@getflip/swirl-components 0.31.2 → 0.33.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.
@@ -6,7 +6,7 @@ const index = require('./index-83363034.js');
6
6
  const index$1 = require('./index-2ddd0598.js');
7
7
  const utils = require('./utils-f1b4e064.js');
8
8
 
9
- const swirlShellLayoutCss = ":host{--extended-sidebar-width:17rem;--collapsed-sidebar-width:4rem;display:flex;width:100%;height:100%}:host *{box-sizing:border-box}.shell-layout{display:grid;width:100%;min-height:100%;transition:grid-template-columns 0.2s;grid-template-columns:0 1fr;grid-template-rows:auto 1fr;grid-template-areas:\"banner banner\"\n \"sidebar main\"}@media (min-width: 992px){.shell-layout{grid-template-columns:var(--extended-sidebar-width) 1fr}}.shell-layout--collapsed-sidebar{grid-template-columns:0 1fr}@media (min-width: 992px){.shell-layout--collapsed-sidebar:not(.shell-layout--collapsing) .shell-layout__sidebar-wrapper.shell-layout__sidebar-wrapper--hovered .shell-layout__sidebar,.shell-layout--collapsed-sidebar:not(.shell-layout--collapsing) .shell-layout__sidebar-wrapper:focus-within .shell-layout__sidebar{width:var(--extended-sidebar-width);box-shadow:0 0.75rem 2rem rgba(25, 26, 28, 0.12),\n 0 0.25rem 0.75rem rgba(25, 26, 28, 0.08)}}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper{transform:translate3d(-100%, 0, 0)}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper .shell-layout__sidebar{width:100%;box-shadow:none}@media (min-width: 992px){.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper{max-width:var(--collapsed-sidebar-width);flex-basis:var(--collapsed-sidebar-width);transform:none}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__sidebar{box-shadow:none}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__collapsed-logo{display:inline-flex;justify-content:center;align-items:center}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__expanded-logo{display:none}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__toggle{display:none}}@media (min-width: 992px){.shell-layout--collapsed-sidebar{grid-template-columns:var(--collapsed-sidebar-width) 1fr}}.shell-layout__banner{grid-area:banner}.shell-layout__sidebar-wrapper{position:absolute;z-index:2;top:0;bottom:0;left:0;width:100%;max-width:var(--extended-sidebar-width);min-height:0;flex-basis:var(--extended-sidebar-width);flex-shrink:0;transition:max-width 0.2s, transform 0.2s;grid-area:sidebar}@media (min-width: 992px){.shell-layout__sidebar-wrapper{position:relative;inset:auto}}.shell-layout__sidebar{display:flex;width:var(--extended-sidebar-width);height:100%;border-right:var(--s-border-width-default) solid var(--s-border-default);flex-direction:column;transition:box-shadow 0.2s, width 0.2s;box-shadow:0 0.75rem 2rem rgba(25, 26, 28, 0.12),\n 0 0.25rem 0.75rem rgba(25, 26, 28, 0.08)}@media (min-width: 992px){.shell-layout__sidebar{box-shadow:none}}.shell-layout__header{flex-shrink:0;border-bottom:var(--s-border-width-default) solid var(--s-border-default);background-color:var(--s-background-default)}.shell-layout__logo-bar{display:flex;overflow:hidden;align-items:center;height:4.5rem}.shell-layout__expanded-logo{padding-right:var(--s-space-12);padding-left:var(--s-space-12);flex-grow:1}.shell-layout__collapsed-logo{display:none;padding-right:var(--s-space-12);padding-left:var(--s-space-12);flex-grow:1}.shell-layout__toggle{padding-right:var(--s-space-16);padding-left:var(--s-space-12);flex-grow:0;flex-shrink:0}.shell-layout__mobile-toggle{position:absolute;z-index:2;top:var(--s-space-12);left:calc(100% + var(--s-space-16))}@media (min-width: 992px){.shell-layout__mobile-toggle{display:none}}.shell-layout__main-navigation{overflow:auto;flex-grow:1;background-color:var(--s-background-default)}.shell-layout__main{min-height:0;background-color:var(--s-background-default);grid-area:main}.shell-layout__main>*,.shell-layout__main ::slotted(*){height:100%}.shell-layout__backdrop{position:fixed;z-index:1;background-color:rgba(0, 0, 0, 0.4);-webkit-animation:shell-layout-backdrop-fade-in 0.1s;animation:shell-layout-backdrop-fade-in 0.1s;inset:0}@media (min-width: 992px){.shell-layout__backdrop{display:none}}.shell-layout__backdrop--fading{-webkit-animation:shell-layout-backdrop-fade-out 0.2s;animation:shell-layout-backdrop-fade-out 0.2s}@-webkit-keyframes shell-layout-backdrop-fade-in{from{opacity:0}to{opacity:1}}@keyframes shell-layout-backdrop-fade-in{from{opacity:0}to{opacity:1}}@-webkit-keyframes shell-layout-backdrop-fade-out{from{opacity:1}to{opacity:0}}@keyframes shell-layout-backdrop-fade-out{from{opacity:1}to{opacity:0}}";
9
+ const swirlShellLayoutCss = ":host{--extended-sidebar-width:17rem;--collapsed-sidebar-width:4rem;display:flex;width:100%;height:100%}:host *{box-sizing:border-box}.shell-layout{display:grid;width:100%;min-height:100%;transition:grid-template-columns 0.2s;grid-template-columns:0 1fr;grid-template-rows:auto 1fr;grid-template-areas:\"banner banner\"\n \"sidebar main\"}@media (min-width: 992px){.shell-layout{grid-template-columns:var(--extended-sidebar-width) 1fr}}.shell-layout--collapsed-sidebar{grid-template-columns:0 1fr}@media (min-width: 992px){.shell-layout--collapsed-sidebar:not(.shell-layout--collapsing) .shell-layout__sidebar-wrapper.shell-layout__sidebar-wrapper--hovered .shell-layout__sidebar,.shell-layout--collapsed-sidebar:not(.shell-layout--collapsing) .shell-layout__sidebar-wrapper:focus-within .shell-layout__sidebar{width:var(--extended-sidebar-width);box-shadow:0 0.75rem 2rem rgba(25, 26, 28, 0.12),\n 0 0.25rem 0.75rem rgba(25, 26, 28, 0.08)}}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper{transform:translate3d(-100%, 0, 0)}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper .shell-layout__sidebar{width:100%;box-shadow:none}@media (min-width: 992px){.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper{max-width:var(--collapsed-sidebar-width);flex-basis:var(--collapsed-sidebar-width);transform:none}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__sidebar{box-shadow:none}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__collapsed-logo{display:inline-flex;justify-content:center;align-items:center}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__expanded-logo{display:none}.shell-layout--collapsed-sidebar .shell-layout__sidebar-wrapper:not(.shell-layout__sidebar-wrapper--hovered):not(:focus-within) .shell-layout__toggle{display:none}}@media (min-width: 992px){.shell-layout--collapsed-sidebar{grid-template-columns:var(--collapsed-sidebar-width) 1fr}}.shell-layout--hide-sidebar{grid-template-columns:1fr;grid-template-areas:\"banner\"\n \"main\"}@media (min-width: 992px){.shell-layout--hide-sidebar{grid-template-columns:1fr}}.shell-layout__banner{grid-area:banner}.shell-layout__sidebar-wrapper{position:absolute;z-index:2;top:0;bottom:0;left:0;width:100%;max-width:var(--extended-sidebar-width);min-height:0;flex-basis:var(--extended-sidebar-width);flex-shrink:0;transition:max-width 0.2s, transform 0.2s;grid-area:sidebar}@media (min-width: 992px){.shell-layout__sidebar-wrapper{position:relative;inset:auto}}.shell-layout__sidebar{display:flex;width:var(--extended-sidebar-width);height:100%;border-right:var(--s-border-width-default) solid var(--s-border-default);flex-direction:column;transition:box-shadow 0.2s, width 0.2s;box-shadow:0 0.75rem 2rem rgba(25, 26, 28, 0.12),\n 0 0.25rem 0.75rem rgba(25, 26, 28, 0.08)}@media (min-width: 992px){.shell-layout__sidebar{box-shadow:none}}.shell-layout__header{flex-shrink:0;border-bottom:var(--s-border-width-default) solid var(--s-border-default);background-color:var(--s-background-default)}.shell-layout__logo-bar{display:flex;overflow:hidden;align-items:center;height:4.5rem}.shell-layout__expanded-logo{padding-right:var(--s-space-12);padding-left:var(--s-space-12);flex-grow:1}.shell-layout__collapsed-logo{display:none;padding-right:var(--s-space-12);padding-left:var(--s-space-12);flex-grow:1}.shell-layout__toggle{padding-right:var(--s-space-16);padding-left:var(--s-space-12);flex-grow:0;flex-shrink:0}.shell-layout__mobile-toggle{position:absolute;z-index:2;top:var(--s-space-12);left:calc(100% + var(--s-space-16))}@media (min-width: 992px){.shell-layout__mobile-toggle{display:none}}.shell-layout__main-navigation{overflow:auto;flex-grow:1;background-color:var(--s-background-default)}.shell-layout__main{min-height:0;background-color:var(--s-background-default);grid-area:main}.shell-layout__main>*,.shell-layout__main ::slotted(*){height:100%}.shell-layout__backdrop{position:fixed;z-index:1;background-color:rgba(0, 0, 0, 0.4);-webkit-animation:shell-layout-backdrop-fade-in 0.1s;animation:shell-layout-backdrop-fade-in 0.1s;inset:0}@media (min-width: 992px){.shell-layout__backdrop{display:none}}.shell-layout__backdrop--fading{-webkit-animation:shell-layout-backdrop-fade-out 0.2s;animation:shell-layout-backdrop-fade-out 0.2s}@-webkit-keyframes shell-layout-backdrop-fade-in{from{opacity:0}to{opacity:1}}@keyframes shell-layout-backdrop-fade-in{from{opacity:0}to{opacity:1}}@-webkit-keyframes shell-layout-backdrop-fade-out{from{opacity:1}to{opacity:0}}@keyframes shell-layout-backdrop-fade-out{from{opacity:1}to{opacity:0}}";
10
10
 
11
11
  const SwirlShellLayout = class {
12
12
  constructor(hostRef) {
@@ -14,13 +14,13 @@ const SwirlShellLayout = class {
14
14
  this.desktopMediaQuery = utils.getDesktopMediaQuery();
15
15
  this.desktopMediaQueryHandler = (event) => {
16
16
  if (event.matches) {
17
- this.showSidebar();
17
+ this.expandLeftSidebar();
18
18
  }
19
19
  else {
20
- this.hideSidebar();
20
+ this.collapseLeftSidebar();
21
21
  }
22
22
  };
23
- this.hideSidebar = () => {
23
+ this.collapseLeftSidebar = () => {
24
24
  this.collapsedSidebar = true;
25
25
  this.collapsing = true;
26
26
  setTimeout(() => {
@@ -31,20 +31,23 @@ const SwirlShellLayout = class {
31
31
  this.sidebarHovered = false;
32
32
  }, 200);
33
33
  };
34
- this.showSidebar = () => {
34
+ this.expandLeftSidebar = () => {
35
+ if (this.hideSidebar) {
36
+ return;
37
+ }
35
38
  this.collapsedSidebar = false;
36
39
  };
37
40
  this.toggleSidebar = () => {
38
41
  if (this.collapsedSidebar) {
39
- this.showSidebar();
42
+ this.expandLeftSidebar();
40
43
  }
41
44
  else {
42
- this.hideSidebar();
45
+ this.collapseLeftSidebar();
43
46
  }
44
47
  };
45
48
  this.onBackdropClick = () => {
46
49
  if (!this.collapsedSidebar) {
47
- this.hideSidebar();
50
+ this.collapseLeftSidebar();
48
51
  }
49
52
  };
50
53
  this.onSidebarClick = () => {
@@ -60,6 +63,7 @@ const SwirlShellLayout = class {
60
63
  this.onSidebarMouseLeave = () => {
61
64
  this.sidebarHovered = false;
62
65
  };
66
+ this.hideSidebar = undefined;
63
67
  this.mainNavigationLabel = "Main";
64
68
  this.sidebarToggleLabel = "Toggle sidebar";
65
69
  this.collapsedSidebar = undefined;
@@ -69,7 +73,7 @@ const SwirlShellLayout = class {
69
73
  componentWillLoad() {
70
74
  var _a, _b;
71
75
  if (!this.desktopMediaQuery.matches) {
72
- this.hideSidebar();
76
+ this.collapseLeftSidebar();
73
77
  }
74
78
  (_b = (_a = this.desktopMediaQuery).addEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, "change", this.desktopMediaQueryHandler);
75
79
  }
@@ -77,18 +81,19 @@ const SwirlShellLayout = class {
77
81
  * Collapse the left sidebar.
78
82
  */
79
83
  async collapseSidebar() {
80
- this.hideSidebar();
84
+ this.collapseLeftSidebar();
81
85
  }
82
86
  /**
83
87
  * Extend the left sidebar.
84
88
  */
85
89
  async extendSidebar() {
86
- this.showSidebar();
90
+ this.expandLeftSidebar();
87
91
  }
88
92
  render() {
89
93
  const className = index$1.classnames("shell-layout", {
90
94
  "shell-layout--collapsed-sidebar": this.collapsedSidebar,
91
95
  "shell-layout--collapsing": this.collapsing,
96
+ "shell-layout--hide-sidebar": this.hideSidebar,
92
97
  });
93
98
  const sidebarWrapperClassName = index$1.classnames("shell-layout__sidebar-wrapper", {
94
99
  "shell-layout__sidebar-wrapper--hovered": this.sidebarHovered,
@@ -96,9 +101,9 @@ const SwirlShellLayout = class {
96
101
  const backdropClassName = index$1.classnames("shell-layout__backdrop", {
97
102
  "shell-layout__backdrop--fading": this.collapsing,
98
103
  });
99
- return (index.h(index.Host, null, index.h("div", { class: className }, index.h("div", { class: "shell-layout__banner" }, index.h("slot", { name: "banner" })), index.h("div", { class: sidebarWrapperClassName, onClick: this.onSidebarClick, onMouseEnter: this.onSidebarMouseEnter, onMouseLeave: this.onSidebarMouseLeave }, index.h("div", { class: "shell-layout__sidebar" }, index.h("header", { class: "shell-layout__header" }, index.h("div", { class: "shell-layout__logo-bar" }, index.h("div", { class: "shell-layout__expanded-logo" }, index.h("slot", { name: "logo-expanded" })), index.h("div", { class: "shell-layout__collapsed-logo" }, index.h("slot", { name: "logo-collapsed" })), index.h("div", { class: "shell-layout__toggle" }, index.h("swirl-button", { swirlAriaExpanded: String(!this.collapsedSidebar), hideLabel: true, icon: this.collapsedSidebar
104
+ return (index.h(index.Host, null, index.h("div", { class: className }, index.h("div", { class: "shell-layout__banner" }, index.h("slot", { name: "banner" })), index.h("div", { class: sidebarWrapperClassName, onClick: this.onSidebarClick, onMouseEnter: this.onSidebarMouseEnter, onMouseLeave: this.onSidebarMouseLeave }, !this.hideSidebar && (index.h("div", { class: "shell-layout__sidebar" }, index.h("header", { class: "shell-layout__header" }, index.h("div", { class: "shell-layout__logo-bar" }, index.h("div", { class: "shell-layout__expanded-logo" }, index.h("slot", { name: "logo-expanded" })), index.h("div", { class: "shell-layout__collapsed-logo" }, index.h("slot", { name: "logo-collapsed" })), index.h("div", { class: "shell-layout__toggle" }, index.h("swirl-button", { swirlAriaExpanded: String(!this.collapsedSidebar), hideLabel: true, icon: this.collapsedSidebar
100
105
  ? "<swirl-icon-double-arrow-right></swirl-icon-double-arrow-right>"
101
- : "<swirl-icon-double-arrow-left></swirl-icon-double-arrow-left>", label: this.sidebarToggleLabel, onClick: this.toggleSidebar }))), index.h("div", { class: "shell-layout__tools" }, index.h("slot", { name: "tools" }))), index.h("nav", { "aria-label": this.mainNavigationLabel, class: "shell-layout__main-navigation" }, index.h("slot", { name: "main-navigation" })))), index.h("main", { class: "shell-layout__main" }, index.h("slot", { name: "main" })), (!this.collapsedSidebar || this.collapsing) && (index.h("div", { class: backdropClassName, onClick: this.onBackdropClick })))));
106
+ : "<swirl-icon-double-arrow-left></swirl-icon-double-arrow-left>", label: this.sidebarToggleLabel, onClick: this.toggleSidebar }))), index.h("div", { class: "shell-layout__tools" }, index.h("slot", { name: "tools" }))), index.h("nav", { "aria-label": this.mainNavigationLabel, class: "shell-layout__main-navigation" }, index.h("slot", { name: "main-navigation" }))))), index.h("main", { class: "shell-layout__main" }, index.h("slot", { name: "main" })), (!this.collapsedSidebar || this.collapsing) && (index.h("div", { class: backdropClassName, onClick: this.onBackdropClick })))));
102
107
  }
103
108
  };
104
109
  SwirlShellLayout.style = swirlShellLayoutCss;
@@ -33,66 +33,83 @@
33
33
  overflow-x: auto;
34
34
  overflow-y: hidden;
35
35
  width: 100%;
36
- padding: var(--s-space-24) 0 var(--s-space-24) var(--s-space-16);
36
+ padding: var(--s-space-24) var(--s-space-16) var(--s-space-24)
37
+ var(--s-space-16);
38
+ scroll-padding: var(--s-space-16);
37
39
  scrollbar-width: none;
38
40
  scroll-snap-type: x mandatory;
39
41
  scroll-behavior: smooth;
40
42
  }
41
43
 
42
- @media (min-width: 768px) {
43
-
44
- .carousel__slides {
45
- padding-left: var(--s-space-24)
46
- }
47
- }
48
-
49
44
  .carousel__slides::-webkit-scrollbar {
50
45
  display: none;
51
46
  }
52
47
 
53
48
  .carousel__slides ::slotted(*) {
49
+ margin-left: var(--s-space-16);
54
50
  flex-grow: 0;
55
51
  flex-shrink: 0;
56
- scroll-snap-align: start;
57
- padding-left: var(--s-space-16);
52
+ scroll-snap-align: center;
58
53
  }
59
54
 
60
55
  @media (min-width: 768px) {
61
56
 
62
57
  .carousel__slides ::slotted(*) {
63
- padding-left: var(--s-space-24)
58
+ margin-left: var(--s-space-24)
64
59
  }
65
60
  }
66
61
 
67
- .carousel__slides ::slotted(*:last-child) {
68
- margin-right: var(--s-space-16);
62
+ .carousel__slides ::slotted(*:first-of-type) {
63
+ scroll-snap-align: start;
64
+ }
65
+
66
+ .carousel__slides ::slotted(*:last-of-type) {
67
+ scroll-snap-align: end;
69
68
  }
70
69
 
71
70
  @media (min-width: 768px) {
72
71
 
73
- .carousel__slides ::slotted(*:last-child) {
74
- margin-right: var(--s-space-24)
72
+ .carousel__slides {
73
+ padding-right: var(--s-space-24);
74
+ padding-left: var(--s-space-24);
75
+ scroll-padding: var(--s-space-24)
76
+ }
75
77
  }
76
- }
77
78
 
78
79
  .carousel__previous-slide-button {
79
80
  position: absolute;
80
81
  z-index: 1;
81
82
  top: calc(50% - var(--s-space-12));
82
- left: var(--s-space-16);
83
+ left: var(--s-space-4);
84
+ display: none;
83
85
  transition: opacity 0.2s;
84
86
  transform: translateY(-50%) scale(0.72);
85
87
  pointer-events: none;
86
88
  opacity: 0;
87
89
  }
88
90
 
91
+ @media (min-width: 768px) {
92
+
93
+ .carousel__previous-slide-button {
94
+ display: inline-block
95
+ }
96
+ }
97
+
89
98
  .carousel__next-slide-button {
90
99
  position: absolute;
91
100
  z-index: 1;
92
101
  top: calc(50% - var(--s-space-12));
93
- right: var(--s-space-16);
102
+ right: var(--s-space-4);
103
+ display: none;
94
104
  transition: opacity 0.2s;
95
105
  transform: translateY(-50%) scale(0.72);
96
106
  pointer-events: none;
97
107
  opacity: 0;
98
108
  }
109
+
110
+ @media (min-width: 768px) {
111
+
112
+ .carousel__next-slide-button {
113
+ display: inline-block
114
+ }
115
+ }
@@ -10,10 +10,15 @@ export class SwirlCarousel {
10
10
  this.onNextSlideButtonClick = () => {
11
11
  this.nextSlide();
12
12
  };
13
+ this.onScroll = () => {
14
+ this.checkScrollPosition();
15
+ };
13
16
  this.label = undefined;
14
17
  this.nextSlideButtonLabel = "Next slide";
15
18
  this.previousSlideButtonLabel = "Previous slide";
16
19
  this.loopAround = false;
20
+ this.isAtEnd = undefined;
21
+ this.isAtStart = undefined;
17
22
  this.isScrollable = undefined;
18
23
  }
19
24
  onWindowResize() {
@@ -22,11 +27,19 @@ export class SwirlCarousel {
22
27
  componentDidLoad() {
23
28
  queueMicrotask(() => {
24
29
  this.checkScrollStatus();
30
+ this.checkScrollPosition();
25
31
  });
26
32
  }
27
- checkScrollStatus() {
28
- this.isScrollable =
29
- this.slidesContainer.scrollWidth > this.slidesContainer.offsetWidth;
33
+ /**
34
+ * Scroll to slide with id.
35
+ */
36
+ async scrollToSlide(id) {
37
+ const slides = this.getSlides();
38
+ const slide = slides.find((slide) => slide.id === id);
39
+ if (!Boolean(slide)) {
40
+ return;
41
+ }
42
+ slide.scrollIntoView({ block: "nearest", inline: "start" });
30
43
  }
31
44
  previousSlide() {
32
45
  const slides = this.getSlides();
@@ -51,6 +64,22 @@ export class SwirlCarousel {
51
64
  const slides = this.getSlides();
52
65
  return slides.filter((slide) => this.checkInView(slide));
53
66
  }
67
+ checkScrollStatus() {
68
+ this.isScrollable =
69
+ this.slidesContainer.scrollWidth > this.slidesContainer.offsetWidth;
70
+ }
71
+ checkScrollPosition() {
72
+ const slides = this.getSlides();
73
+ const activeSlides = this.getActiveSlides();
74
+ const isAtStart = activeSlides[0] === slides[0];
75
+ const isAtEnd = activeSlides[activeSlides.length - 1] === slides[slides.length - 1];
76
+ if (isAtStart !== this.isAtStart) {
77
+ this.isAtStart = isAtStart;
78
+ }
79
+ if (isAtEnd !== this.isAtEnd) {
80
+ this.isAtEnd = isAtEnd;
81
+ }
82
+ }
54
83
  checkInView(element) {
55
84
  let containerLeft = this.slidesContainer.scrollLeft;
56
85
  let containerRight = containerLeft + this.slidesContainer.clientWidth;
@@ -60,7 +89,7 @@ export class SwirlCarousel {
60
89
  return inInView;
61
90
  }
62
91
  render() {
63
- return (h(Host, { "aria-label": this.label, "aria-roledescription": "carousel", role: "group" }, h("div", { class: "carousel" }, this.isScrollable && (h("swirl-button", { class: "carousel__previous-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-back></swirl-icon-arrow-back>", label: this.previousSlideButtonLabel, onClick: this.onPreviousSlideButtonClick, pill: true, variant: "floating" })), this.isScrollable && (h("swirl-button", { class: "carousel__next-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-forward></swirl-icon-arrow-forward>", label: this.nextSlideButtonLabel, onClick: this.onNextSlideButtonClick, pill: true, variant: "floating" })), h("div", { "aria-live": "polite", class: "carousel__slides", ref: (el) => (this.slidesContainer = el) }, h("slot", null)))));
92
+ return (h(Host, { "aria-label": this.label, "aria-roledescription": "carousel", role: "group" }, h("div", { class: "carousel" }, this.isScrollable && !this.isAtStart && (h("swirl-button", { class: "carousel__previous-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-back></swirl-icon-arrow-back>", label: this.previousSlideButtonLabel, onClick: this.onPreviousSlideButtonClick, pill: true, variant: "floating" })), this.isScrollable && !this.isAtEnd && (h("swirl-button", { class: "carousel__next-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-forward></swirl-icon-arrow-forward>", label: this.nextSlideButtonLabel, onClick: this.onNextSlideButtonClick, pill: true, variant: "floating" })), h("div", { "aria-live": "polite", class: "carousel__slides", onScroll: this.onScroll, ref: (el) => (this.slidesContainer = el) }, h("slot", null)))));
64
93
  }
65
94
  static get is() { return "swirl-carousel"; }
66
95
  static get encapsulation() { return "shadow"; }
@@ -151,9 +180,34 @@ export class SwirlCarousel {
151
180
  }
152
181
  static get states() {
153
182
  return {
183
+ "isAtEnd": {},
184
+ "isAtStart": {},
154
185
  "isScrollable": {}
155
186
  };
156
187
  }
188
+ static get methods() {
189
+ return {
190
+ "scrollToSlide": {
191
+ "complexType": {
192
+ "signature": "(id: string) => Promise<void>",
193
+ "parameters": [{
194
+ "tags": [],
195
+ "text": ""
196
+ }],
197
+ "references": {
198
+ "Promise": {
199
+ "location": "global"
200
+ }
201
+ },
202
+ "return": "Promise<void>"
203
+ },
204
+ "docs": {
205
+ "text": "Scroll to slide with id.",
206
+ "tags": []
207
+ }
208
+ }
209
+ };
210
+ }
157
211
  static get elementRef() { return "el"; }
158
212
  static get listeners() {
159
213
  return [{
@@ -83,6 +83,20 @@
83
83
  }
84
84
  }
85
85
 
86
+ .shell-layout--hide-sidebar {
87
+ grid-template-columns: 1fr;
88
+ grid-template-areas:
89
+ "banner"
90
+ "main";
91
+ }
92
+
93
+ @media (min-width: 992px) {
94
+
95
+ .shell-layout--hide-sidebar {
96
+ grid-template-columns: 1fr
97
+ }
98
+ }
99
+
86
100
  .shell-layout__banner {
87
101
  grid-area: banner;
88
102
  }
@@ -14,13 +14,13 @@ export class SwirlShellLayout {
14
14
  this.desktopMediaQuery = getDesktopMediaQuery();
15
15
  this.desktopMediaQueryHandler = (event) => {
16
16
  if (event.matches) {
17
- this.showSidebar();
17
+ this.expandLeftSidebar();
18
18
  }
19
19
  else {
20
- this.hideSidebar();
20
+ this.collapseLeftSidebar();
21
21
  }
22
22
  };
23
- this.hideSidebar = () => {
23
+ this.collapseLeftSidebar = () => {
24
24
  this.collapsedSidebar = true;
25
25
  this.collapsing = true;
26
26
  setTimeout(() => {
@@ -31,20 +31,23 @@ export class SwirlShellLayout {
31
31
  this.sidebarHovered = false;
32
32
  }, 200);
33
33
  };
34
- this.showSidebar = () => {
34
+ this.expandLeftSidebar = () => {
35
+ if (this.hideSidebar) {
36
+ return;
37
+ }
35
38
  this.collapsedSidebar = false;
36
39
  };
37
40
  this.toggleSidebar = () => {
38
41
  if (this.collapsedSidebar) {
39
- this.showSidebar();
42
+ this.expandLeftSidebar();
40
43
  }
41
44
  else {
42
- this.hideSidebar();
45
+ this.collapseLeftSidebar();
43
46
  }
44
47
  };
45
48
  this.onBackdropClick = () => {
46
49
  if (!this.collapsedSidebar) {
47
- this.hideSidebar();
50
+ this.collapseLeftSidebar();
48
51
  }
49
52
  };
50
53
  this.onSidebarClick = () => {
@@ -60,6 +63,7 @@ export class SwirlShellLayout {
60
63
  this.onSidebarMouseLeave = () => {
61
64
  this.sidebarHovered = false;
62
65
  };
66
+ this.hideSidebar = undefined;
63
67
  this.mainNavigationLabel = "Main";
64
68
  this.sidebarToggleLabel = "Toggle sidebar";
65
69
  this.collapsedSidebar = undefined;
@@ -69,7 +73,7 @@ export class SwirlShellLayout {
69
73
  componentWillLoad() {
70
74
  var _a, _b;
71
75
  if (!this.desktopMediaQuery.matches) {
72
- this.hideSidebar();
76
+ this.collapseLeftSidebar();
73
77
  }
74
78
  (_b = (_a = this.desktopMediaQuery).addEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, "change", this.desktopMediaQueryHandler);
75
79
  }
@@ -77,18 +81,19 @@ export class SwirlShellLayout {
77
81
  * Collapse the left sidebar.
78
82
  */
79
83
  async collapseSidebar() {
80
- this.hideSidebar();
84
+ this.collapseLeftSidebar();
81
85
  }
82
86
  /**
83
87
  * Extend the left sidebar.
84
88
  */
85
89
  async extendSidebar() {
86
- this.showSidebar();
90
+ this.expandLeftSidebar();
87
91
  }
88
92
  render() {
89
93
  const className = classnames("shell-layout", {
90
94
  "shell-layout--collapsed-sidebar": this.collapsedSidebar,
91
95
  "shell-layout--collapsing": this.collapsing,
96
+ "shell-layout--hide-sidebar": this.hideSidebar,
92
97
  });
93
98
  const sidebarWrapperClassName = classnames("shell-layout__sidebar-wrapper", {
94
99
  "shell-layout__sidebar-wrapper--hovered": this.sidebarHovered,
@@ -96,9 +101,9 @@ export class SwirlShellLayout {
96
101
  const backdropClassName = classnames("shell-layout__backdrop", {
97
102
  "shell-layout__backdrop--fading": this.collapsing,
98
103
  });
99
- return (h(Host, null, h("div", { class: className }, h("div", { class: "shell-layout__banner" }, h("slot", { name: "banner" })), h("div", { class: sidebarWrapperClassName, onClick: this.onSidebarClick, onMouseEnter: this.onSidebarMouseEnter, onMouseLeave: this.onSidebarMouseLeave }, h("div", { class: "shell-layout__sidebar" }, h("header", { class: "shell-layout__header" }, h("div", { class: "shell-layout__logo-bar" }, h("div", { class: "shell-layout__expanded-logo" }, h("slot", { name: "logo-expanded" })), h("div", { class: "shell-layout__collapsed-logo" }, h("slot", { name: "logo-collapsed" })), h("div", { class: "shell-layout__toggle" }, h("swirl-button", { swirlAriaExpanded: String(!this.collapsedSidebar), hideLabel: true, icon: this.collapsedSidebar
104
+ return (h(Host, null, h("div", { class: className }, h("div", { class: "shell-layout__banner" }, h("slot", { name: "banner" })), h("div", { class: sidebarWrapperClassName, onClick: this.onSidebarClick, onMouseEnter: this.onSidebarMouseEnter, onMouseLeave: this.onSidebarMouseLeave }, !this.hideSidebar && (h("div", { class: "shell-layout__sidebar" }, h("header", { class: "shell-layout__header" }, h("div", { class: "shell-layout__logo-bar" }, h("div", { class: "shell-layout__expanded-logo" }, h("slot", { name: "logo-expanded" })), h("div", { class: "shell-layout__collapsed-logo" }, h("slot", { name: "logo-collapsed" })), h("div", { class: "shell-layout__toggle" }, h("swirl-button", { swirlAriaExpanded: String(!this.collapsedSidebar), hideLabel: true, icon: this.collapsedSidebar
100
105
  ? "<swirl-icon-double-arrow-right></swirl-icon-double-arrow-right>"
101
- : "<swirl-icon-double-arrow-left></swirl-icon-double-arrow-left>", label: this.sidebarToggleLabel, onClick: this.toggleSidebar }))), h("div", { class: "shell-layout__tools" }, h("slot", { name: "tools" }))), h("nav", { "aria-label": this.mainNavigationLabel, class: "shell-layout__main-navigation" }, h("slot", { name: "main-navigation" })))), h("main", { class: "shell-layout__main" }, h("slot", { name: "main" })), (!this.collapsedSidebar || this.collapsing) && (h("div", { class: backdropClassName, onClick: this.onBackdropClick })))));
106
+ : "<swirl-icon-double-arrow-left></swirl-icon-double-arrow-left>", label: this.sidebarToggleLabel, onClick: this.toggleSidebar }))), h("div", { class: "shell-layout__tools" }, h("slot", { name: "tools" }))), h("nav", { "aria-label": this.mainNavigationLabel, class: "shell-layout__main-navigation" }, h("slot", { name: "main-navigation" }))))), h("main", { class: "shell-layout__main" }, h("slot", { name: "main" })), (!this.collapsedSidebar || this.collapsing) && (h("div", { class: backdropClassName, onClick: this.onBackdropClick })))));
102
107
  }
103
108
  static get is() { return "swirl-shell-layout"; }
104
109
  static get encapsulation() { return "shadow"; }
@@ -114,6 +119,23 @@ export class SwirlShellLayout {
114
119
  }
115
120
  static get properties() {
116
121
  return {
122
+ "hideSidebar": {
123
+ "type": "boolean",
124
+ "mutable": false,
125
+ "complexType": {
126
+ "original": "boolean",
127
+ "resolved": "boolean",
128
+ "references": {}
129
+ },
130
+ "required": false,
131
+ "optional": true,
132
+ "docs": {
133
+ "tags": [],
134
+ "text": ""
135
+ },
136
+ "attribute": "hide-sidebar",
137
+ "reflect": false
138
+ },
117
139
  "mainNavigationLabel": {
118
140
  "type": "string",
119
141
  "mutable": false,
@@ -1,7 +1,7 @@
1
1
  import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';
2
2
  import { d as defineCustomElement$2 } from './swirl-button2.js';
3
3
 
4
- const swirlCarouselCss = ":host{position:relative;display:block;overflow:hidden;width:100%;margin-top:calc(-1 * var(--s-space-24));margin-bottom:calc(-1 * var(--s-space-24))}:host(:hover) .carousel__previous-slide-button{pointer-events:auto;opacity:1}:host(:hover) .carousel__next-slide-button{pointer-events:auto;opacity:1}:host *{box-sizing:border-box}.carousel{position:relative;overflow:hidden;width:100%}.carousel__slides{position:relative;display:flex;overflow-x:auto;overflow-y:hidden;width:100%;padding:var(--s-space-24) 0 var(--s-space-24) var(--s-space-16);scrollbar-width:none;scroll-snap-type:x mandatory;scroll-behavior:smooth}@media (min-width: 768px){.carousel__slides{padding-left:var(--s-space-24)}}.carousel__slides::-webkit-scrollbar{display:none}.carousel__slides ::slotted(*){flex-grow:0;flex-shrink:0;scroll-snap-align:start;padding-left:var(--s-space-16)}@media (min-width: 768px){.carousel__slides ::slotted(*){padding-left:var(--s-space-24)}}.carousel__slides ::slotted(*:last-child){margin-right:var(--s-space-16)}@media (min-width: 768px){.carousel__slides ::slotted(*:last-child){margin-right:var(--s-space-24)}}.carousel__previous-slide-button{position:absolute;z-index:1;top:calc(50% - var(--s-space-12));left:var(--s-space-16);transition:opacity 0.2s;transform:translateY(-50%) scale(0.72);pointer-events:none;opacity:0}.carousel__next-slide-button{position:absolute;z-index:1;top:calc(50% - var(--s-space-12));right:var(--s-space-16);transition:opacity 0.2s;transform:translateY(-50%) scale(0.72);pointer-events:none;opacity:0}";
4
+ const swirlCarouselCss = ":host{position:relative;display:block;overflow:hidden;width:100%;margin-top:calc(-1 * var(--s-space-24));margin-bottom:calc(-1 * var(--s-space-24))}:host(:hover) .carousel__previous-slide-button{pointer-events:auto;opacity:1}:host(:hover) .carousel__next-slide-button{pointer-events:auto;opacity:1}:host *{box-sizing:border-box}.carousel{position:relative;overflow:hidden;width:100%}.carousel__slides{position:relative;display:flex;overflow-x:auto;overflow-y:hidden;width:100%;padding:var(--s-space-24) var(--s-space-16) var(--s-space-24)\n var(--s-space-16);scroll-padding:var(--s-space-16);scrollbar-width:none;scroll-snap-type:x mandatory;scroll-behavior:smooth}.carousel__slides::-webkit-scrollbar{display:none}.carousel__slides ::slotted(*){margin-left:var(--s-space-16);flex-grow:0;flex-shrink:0;scroll-snap-align:center}@media (min-width: 768px){.carousel__slides ::slotted(*){margin-left:var(--s-space-24)}}.carousel__slides ::slotted(*:first-of-type){scroll-snap-align:start}.carousel__slides ::slotted(*:last-of-type){scroll-snap-align:end}@media (min-width: 768px){.carousel__slides{padding-right:var(--s-space-24);padding-left:var(--s-space-24);scroll-padding:var(--s-space-24)}}.carousel__previous-slide-button{position:absolute;z-index:1;top:calc(50% - var(--s-space-12));left:var(--s-space-4);display:none;transition:opacity 0.2s;transform:translateY(-50%) scale(0.72);pointer-events:none;opacity:0}@media (min-width: 768px){.carousel__previous-slide-button{display:inline-block}}.carousel__next-slide-button{position:absolute;z-index:1;top:calc(50% - var(--s-space-12));right:var(--s-space-4);display:none;transition:opacity 0.2s;transform:translateY(-50%) scale(0.72);pointer-events:none;opacity:0}@media (min-width: 768px){.carousel__next-slide-button{display:inline-block}}";
5
5
 
6
6
  const SwirlCarousel$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
7
7
  constructor() {
@@ -14,10 +14,15 @@ const SwirlCarousel$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
14
14
  this.onNextSlideButtonClick = () => {
15
15
  this.nextSlide();
16
16
  };
17
+ this.onScroll = () => {
18
+ this.checkScrollPosition();
19
+ };
17
20
  this.label = undefined;
18
21
  this.nextSlideButtonLabel = "Next slide";
19
22
  this.previousSlideButtonLabel = "Previous slide";
20
23
  this.loopAround = false;
24
+ this.isAtEnd = undefined;
25
+ this.isAtStart = undefined;
21
26
  this.isScrollable = undefined;
22
27
  }
23
28
  onWindowResize() {
@@ -26,11 +31,19 @@ const SwirlCarousel$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
26
31
  componentDidLoad() {
27
32
  queueMicrotask(() => {
28
33
  this.checkScrollStatus();
34
+ this.checkScrollPosition();
29
35
  });
30
36
  }
31
- checkScrollStatus() {
32
- this.isScrollable =
33
- this.slidesContainer.scrollWidth > this.slidesContainer.offsetWidth;
37
+ /**
38
+ * Scroll to slide with id.
39
+ */
40
+ async scrollToSlide(id) {
41
+ const slides = this.getSlides();
42
+ const slide = slides.find((slide) => slide.id === id);
43
+ if (!Boolean(slide)) {
44
+ return;
45
+ }
46
+ slide.scrollIntoView({ block: "nearest", inline: "start" });
34
47
  }
35
48
  previousSlide() {
36
49
  const slides = this.getSlides();
@@ -55,6 +68,22 @@ const SwirlCarousel$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
55
68
  const slides = this.getSlides();
56
69
  return slides.filter((slide) => this.checkInView(slide));
57
70
  }
71
+ checkScrollStatus() {
72
+ this.isScrollable =
73
+ this.slidesContainer.scrollWidth > this.slidesContainer.offsetWidth;
74
+ }
75
+ checkScrollPosition() {
76
+ const slides = this.getSlides();
77
+ const activeSlides = this.getActiveSlides();
78
+ const isAtStart = activeSlides[0] === slides[0];
79
+ const isAtEnd = activeSlides[activeSlides.length - 1] === slides[slides.length - 1];
80
+ if (isAtStart !== this.isAtStart) {
81
+ this.isAtStart = isAtStart;
82
+ }
83
+ if (isAtEnd !== this.isAtEnd) {
84
+ this.isAtEnd = isAtEnd;
85
+ }
86
+ }
58
87
  checkInView(element) {
59
88
  let containerLeft = this.slidesContainer.scrollLeft;
60
89
  let containerRight = containerLeft + this.slidesContainer.clientWidth;
@@ -64,7 +93,7 @@ const SwirlCarousel$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
64
93
  return inInView;
65
94
  }
66
95
  render() {
67
- return (h(Host, { "aria-label": this.label, "aria-roledescription": "carousel", role: "group" }, h("div", { class: "carousel" }, this.isScrollable && (h("swirl-button", { class: "carousel__previous-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-back></swirl-icon-arrow-back>", label: this.previousSlideButtonLabel, onClick: this.onPreviousSlideButtonClick, pill: true, variant: "floating" })), this.isScrollable && (h("swirl-button", { class: "carousel__next-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-forward></swirl-icon-arrow-forward>", label: this.nextSlideButtonLabel, onClick: this.onNextSlideButtonClick, pill: true, variant: "floating" })), h("div", { "aria-live": "polite", class: "carousel__slides", ref: (el) => (this.slidesContainer = el) }, h("slot", null)))));
96
+ return (h(Host, { "aria-label": this.label, "aria-roledescription": "carousel", role: "group" }, h("div", { class: "carousel" }, this.isScrollable && !this.isAtStart && (h("swirl-button", { class: "carousel__previous-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-back></swirl-icon-arrow-back>", label: this.previousSlideButtonLabel, onClick: this.onPreviousSlideButtonClick, pill: true, variant: "floating" })), this.isScrollable && !this.isAtEnd && (h("swirl-button", { class: "carousel__next-slide-button", hideLabel: true, icon: "<swirl-icon-arrow-forward></swirl-icon-arrow-forward>", label: this.nextSlideButtonLabel, onClick: this.onNextSlideButtonClick, pill: true, variant: "floating" })), h("div", { "aria-live": "polite", class: "carousel__slides", onScroll: this.onScroll, ref: (el) => (this.slidesContainer = el) }, h("slot", null)))));
68
97
  }
69
98
  get el() { return this; }
70
99
  static get style() { return swirlCarouselCss; }
@@ -73,7 +102,10 @@ const SwirlCarousel$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
73
102
  "nextSlideButtonLabel": [1, "next-slide-button-label"],
74
103
  "previousSlideButtonLabel": [1, "previous-slide-button-label"],
75
104
  "loopAround": [4, "loop-around"],
76
- "isScrollable": [32]
105
+ "isAtEnd": [32],
106
+ "isAtStart": [32],
107
+ "isScrollable": [32],
108
+ "scrollToSlide": [64]
77
109
  }, [[9, "resize", "onWindowResize"]]]);
78
110
  function defineCustomElement$1() {
79
111
  if (typeof customElements === "undefined") {