Merge branch 'master' into mousewheelevents

This commit is contained in:
Hakim El Hattab
2023-10-27 09:42:32 +02:00
committed by GitHub
45 changed files with 2108 additions and 370 deletions

View File

@@ -5,7 +5,7 @@
* https://revealjs.com/pdf-export/ * https://revealjs.com/pdf-export/
*/ */
html.print-pdf { html.reveal-print {
* { * {
-webkit-print-color-adjust: exact; -webkit-print-color-adjust: exact;
} }
@@ -70,6 +70,10 @@ html.print-pdf {
page-break-after: always; page-break-after: always;
} }
.reveal .slides .pdf-page:last-of-type {
page-break-after: avoid;
}
.reveal .slides section { .reveal .slides section {
visibility: visible !important; visibility: visible !important;
display: block !important; display: block !important;
@@ -145,6 +149,7 @@ html.print-pdf {
display: block; display: block;
position: absolute; position: absolute;
font-size: 14px; font-size: 14px;
visibility: visible;
} }
/* This accessibility tool is not useful in PDF and breaks it visually */ /* This accessibility tool is not useful in PDF and breaks it visually */

View File

@@ -19,6 +19,7 @@ html.reveal-full-page {
height: 100%; height: 100%;
height: 100vh; height: 100vh;
height: calc( var(--vh, 1vh) * 100 ); height: calc( var(--vh, 1vh) * 100 );
height: 100svh;
overflow: hidden; overflow: hidden;
} }
@@ -31,6 +32,8 @@ html.reveal-full-page {
background-color: #fff; background-color: #fff;
color: #000; color: #000;
--r-controls-spacing: 12px;
} }
// Force the presentation to cover the full viewport when we // Force the presentation to cover the full viewport when we
@@ -271,13 +274,11 @@ $controlsArrowAngleActive: 36deg;
} }
.reveal .controls { .reveal .controls {
$spacing: 12px;
display: none; display: none;
position: absolute; position: absolute;
top: auto; top: auto;
bottom: $spacing; bottom: var(--r-controls-spacing);
right: $spacing; right: var(--r-controls-spacing);
left: auto; left: auto;
z-index: 11; z-index: 11;
color: #000; color: #000;
@@ -509,7 +510,9 @@ $controlsArrowAngleActive: 36deg;
// Edge aligned controls layout // Edge aligned controls layout
@media screen and (min-width: 500px) { @media screen and (min-width: 500px) {
$spacing: 0.8em; .reveal-viewport {
--r-controls-spacing: 0.8em;
}
.reveal .controls[data-controls-layout="edges"] { .reveal .controls[data-controls-layout="edges"] {
& { & {
@@ -529,24 +532,24 @@ $controlsArrowAngleActive: 36deg;
.navigate-left { .navigate-left {
top: 50%; top: 50%;
left: $spacing; left: var(--r-controls-spacing);
margin-top: -$controlArrowSize*0.5; margin-top: -$controlArrowSize*0.5;
} }
.navigate-right { .navigate-right {
top: 50%; top: 50%;
right: $spacing; right: var(--r-controls-spacing);
margin-top: -$controlArrowSize*0.5; margin-top: -$controlArrowSize*0.5;
} }
.navigate-up { .navigate-up {
top: $spacing; top: var(--r-controls-spacing);
left: 50%; left: 50%;
margin-left: -$controlArrowSize*0.5; margin-left: -$controlArrowSize*0.5;
} }
.navigate-down { .navigate-down {
bottom: $spacing - $controlArrowSpacing + 0.3em; bottom: calc(var(--r-controls-spacing) - #{$controlArrowSpacing} + 0.3em);
left: 50%; left: 50%;
margin-left: -$controlArrowSize*0.5; margin-left: -$controlArrowSize*0.5;
} }
@@ -1864,6 +1867,234 @@ $notesWidthPercent: 25%;
} }
/*********************************************
* SCROLL VIEW
*********************************************/
.reveal-viewport.loading-scroll-mode {
visibility: hidden;
}
.reveal-viewport.reveal-scroll {
& {
margin: 0 auto;
overflow: auto;
overflow-x: hidden;
overflow-y: auto;
z-index: 1;
--r-scrollbar-width: 7px;
--r-scrollbar-trigger-size: 5px;
--r-controls-spacing: 8px;
}
@media screen and (max-width: 500px) {
--r-scrollbar-width: 3px;
--r-scrollbar-trigger-size: 3px;
}
.controls,
.progress,
.playback,
.backgrounds,
.slide-number,
.speaker-notes {
display: none !important;
}
.reveal {
overflow: visible;
touch-action: manipulation;
}
.slides {
position: static;
pointer-events: initial;
left: auto;
top: auto;
width: 100% !important;
margin: 0;
padding: 0;
overflow: visible;
display: block;
perspective: none;
perspective-origin: 50% 50%;
}
.scroll-page {
position: relative;
width: 100%;
height: calc(var(--page-height) + var(--page-scroll-padding));
z-index: 1;
overflow: visible;
}
.scroll-page-sticky {
position: sticky;
height: var(--page-height);
top: 0px;
}
.scroll-page-content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.scroll-page section {
visibility: visible !important;
display: block !important;
position: absolute !important;
width: var(--slide-width) !important;
height: var(--slide-height) !important;
top: 50% !important;
left: 50% !important;
opacity: 1 !important;
transform: scale(var(--slide-scale)) translate(-50%, -50%) !important;
transform-style: flat !important;
transform-origin: 0 0 !important;
}
.slide-background {
display: block !important;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: auto !important;
visibility: visible;
opacity: 1;
touch-action: manipulation;
}
}
// Chromium
.reveal-viewport.reveal-scroll[data-scrollbar="true"]::-webkit-scrollbar,
.reveal-viewport.reveal-scroll[data-scrollbar="auto"]::-webkit-scrollbar {
display: none;
}
// Firefox
.reveal-viewport.reveal-scroll[data-scrollbar="true"],
.reveal-viewport.reveal-scroll[data-scrollbar="auto"] {
scrollbar-width: none;
}
.reveal.has-dark-background,
.reveal-viewport.has-dark-background {
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal.has-light-background,
.reveal-viewport.has-light-background {
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport.reveal-scroll .scrollbar {
position: sticky;
top: 50%;
z-index: 20;
opacity: 0;
transition: all 0.3s ease;
&.visible,
&:hover {
opacity: 1;
}
.scrollbar-inner {
position: absolute;
width: var(--r-scrollbar-width);
height: calc(var(--viewport-height) - var(--r-controls-spacing) * 2);
right: var(--r-controls-spacing);
top: 0;
transform: translateY(-50%);
border-radius: var(--r-scrollbar-width);
z-index: 10;
}
.scrollbar-playhead {
position: absolute;
width: var(--r-scrollbar-width);
height: var(--r-scrollbar-width);
top: 0;
left: 0;
border-radius: var(--r-scrollbar-width);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
z-index: 11;
transition: background-color 0.2s ease;
}
.scrollbar-slide {
position: absolute;
width: 100%;
background-color: rgba(var(--r-overlay-element-bg-color), 0.2);
box-shadow: 0 0 0px 1px rgba(var(--r-overlay-element-fg-color), 0.1);
border-radius: var(--r-scrollbar-width);
transition: background-color 0.2s ease;
}
// Hit area
.scrollbar-slide:after {
content: '';
position: absolute;
width: 200%;
height: 100%;
top: 0;
left: -50%;
background: rgba( 0, 0, 0, 0 );
z-index: -1;
}
.scrollbar-slide:hover,
.scrollbar-slide.active {
background-color: rgba(var(--r-overlay-element-bg-color), 0.4);
}
.scrollbar-trigger {
position: absolute;
width: 100%;
transition: background-color 0.2s ease;
}
.scrollbar-slide.active.has-triggers {
background-color: rgba(var(--r-overlay-element-bg-color), 0.4);
z-index: 10;
}
.scrollbar-slide.active .scrollbar-trigger:after {
content: '';
position: absolute;
width: var(--r-scrollbar-trigger-size);
height: var(--r-scrollbar-trigger-size);
border-radius: 20px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
transition: transform 0.2s ease, opacity 0.2s ease;
opacity: 0.4;
}
.scrollbar-slide.active .scrollbar-trigger.active:after,
.scrollbar-slide.active .scrollbar-trigger.active ~ .scrollbar-trigger:after {
opacity: 1;
}
.scrollbar-slide.active .scrollbar-trigger ~ .scrollbar-trigger.active:after {
transform: translate(calc( var(--r-scrollbar-width) * -2), 0);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
}
}
/********************************************* /*********************************************
* PRINT STYLES * PRINT STYLES
*********************************************/ *********************************************/

View File

@@ -27,6 +27,9 @@ $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: rgba(79, 64, 28, 0.99); $selectionBackgroundColor: rgba(79, 64, 28, 0.99);
$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); $heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Background generator // Background generator
@mixin bodyBackground() { @mixin bodyBackground() {
@include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) ); @include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) );

View File

@@ -25,6 +25,9 @@ $linkColor: #51483D;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #26351C; $selectionBackgroundColor: #26351C;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
.reveal a { .reveal a {
line-height: 1.3em; line-height: 1.3em;
} }

View File

@@ -31,6 +31,9 @@ $linkColor: #00008B;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: rgba(0, 0, 0, 0.99); $selectionBackgroundColor: rgba(0, 0, 0, 0.99);
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds // Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff); @include dark-bg-text-color(#fff);

View File

@@ -29,6 +29,9 @@ $linkColor: #3b759e;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #134674; $selectionBackgroundColor: #134674;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Fix links so they are not cut off // Fix links so they are not cut off
.reveal a { .reveal a {
line-height: 1.3em; line-height: 1.3em;

View File

@@ -51,6 +51,9 @@ $linkColor: $blue;
$linkColorHover: lighten( $linkColor, 20% ); $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: $magenta; $selectionBackgroundColor: $magenta;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Background generator // Background generator
// @mixin bodyBackground() { // @mixin bodyBackground() {
// @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) ); // @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) );

View File

@@ -40,6 +40,9 @@ $heading2Size: 1.6em;
$heading3Size: 1.3em; $heading3Size: 1.3em;
$heading4Size: 1.0em; $heading4Size: 1.0em;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds // Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff); @include dark-bg-text-color(#fff);

View File

@@ -37,6 +37,9 @@ $heading2Size: 1.6em;
$heading3Size: 1.3em; $heading3Size: 1.3em;
$heading4Size: 1.0em; $heading4Size: 1.0em;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds // Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff); @include dark-bg-text-color(#fff);

View File

@@ -25,4 +25,6 @@
--r-link-color-hover: #{$linkColorHover}; --r-link-color-hover: #{$linkColorHover};
--r-selection-background-color: #{$selectionBackgroundColor}; --r-selection-background-color: #{$selectionBackgroundColor};
--r-selection-color: #{$selectionColor}; --r-selection-color: #{$selectionColor};
--r-overlay-element-bg-color: #{$overlayElementBgColor};
--r-overlay-element-fg-color: #{$overlayElementFgColor};
} }

View File

@@ -38,6 +38,11 @@ $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #FF5E99; $selectionBackgroundColor: #FF5E99;
$selectionColor: #fff; $selectionColor: #fff;
// Colors used for UI elements that are overlaid on top of
// the presentation
$overlayElementBgColor: 240, 240, 240;
$overlayElementFgColor: 0, 0, 0;
// Generates the presentation background, can be overridden // Generates the presentation background, can be overridden
// to return a background image or gradient // to return a background image or gradient
@mixin bodyBackground() { @mixin bodyBackground() {

2
dist/reveal.css vendored

File diff suppressed because one or more lines are too long

2
dist/reveal.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/reveal.js vendored

File diff suppressed because one or more lines are too long

2
dist/reveal.js.map vendored

File diff suppressed because one or more lines are too long

View File

@@ -37,6 +37,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #c0a86e; --r-link-color-hover: #c0a86e;
--r-selection-background-color: rgba(79, 64, 28, 0.99); --r-selection-background-color: rgba(79, 64, 28, 0.99);
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -39,6 +39,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8dcffc; --r-link-color-hover: #8dcffc;
--r-selection-background-color: #bee4fd; --r-selection-background-color: #bee4fd;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -36,6 +36,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8dcffc; --r-link-color-hover: #8dcffc;
--r-selection-background-color: rgba(66, 175, 250, 0.75); --r-selection-background-color: rgba(66, 175, 250, 0.75);
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -42,6 +42,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #dd5566; --r-link-color-hover: #dd5566;
--r-selection-background-color: #a23; --r-selection-background-color: #a23;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -43,6 +43,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8BE9FD; --r-link-color-hover: #8BE9FD;
--r-selection-background-color: #44475A; --r-selection-background-color: #44475A;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -39,6 +39,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #71e9f4; --r-link-color-hover: #71e9f4;
--r-selection-background-color: #FF5E99; --r-selection-background-color: #FF5E99;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {

2
dist/theme/moon.css vendored
View File

@@ -44,6 +44,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #78b9e6; --r-link-color-hover: #78b9e6;
--r-selection-background-color: #d33682; --r-selection-background-color: #d33682;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -37,6 +37,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #f3d7ac; --r-link-color-hover: #f3d7ac;
--r-selection-background-color: #e7ad52; --r-selection-background-color: #e7ad52;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -40,6 +40,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #8b7c69; --r-link-color-hover: #8b7c69;
--r-selection-background-color: #26351C; --r-selection-background-color: #26351C;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -39,6 +39,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #0000f1; --r-link-color-hover: #0000f1;
--r-selection-background-color: rgba(0, 0, 0, 0.99); --r-selection-background-color: rgba(0, 0, 0, 0.99);
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {

2
dist/theme/sky.css vendored
View File

@@ -41,6 +41,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #74a7cb; --r-link-color-hover: #74a7cb;
--r-selection-background-color: #134674; --r-selection-background-color: #134674;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -40,6 +40,8 @@ html * {
--r-link-color-hover: #78b9e6; --r-link-color-hover: #78b9e6;
--r-selection-background-color: #d33682; --r-selection-background-color: #d33682;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -39,6 +39,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #6ca0e8; --r-link-color-hover: #6ca0e8;
--r-selection-background-color: #98bdef; --r-selection-background-color: #98bdef;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {

View File

@@ -36,6 +36,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #6ca0e8; --r-link-color-hover: #6ca0e8;
--r-selection-background-color: #98bdef; --r-selection-background-color: #98bdef;
--r-selection-color: #fff; --r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
} }
.reveal-viewport { .reveal-viewport {

122
examples/scroll.html Normal file
View File

@@ -0,0 +1,122 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - Scroll View</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="../dist/reset.css">
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../dist/theme/black.css" id="theme">
<link rel="stylesheet" href="../plugin/highlight/monokai.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section><h1>Scroll View</h1></section>
<section data-background="indigo">
<h2>Scroll triggers</h2>
<ul>
<li class="fragment fade-left">Step one</li>
<li class="fragment fade-left">Step two</li>
<li class="fragment fade-left">Step three</li>
</ul>
</section>
<section data-background-color="#fff"><h2>Scroll bar inverts<br>based on slide bg</h2></section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<h2>Auto-Animate</h2>
<p>Automatically animate matching elements across slides with <a href="https://revealjs.com/auto-animate/">Auto-Animate</a>.</p>
<div class="r-hstack justify-center">
<div data-id="box1" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
<div data-id="box2" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
<div data-id="box3" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
</div>
</section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<div class="r-hstack justify-center">
<div data-id="box1" data-auto-animate-delay="0" style="background: cyan; width: 150px; height: 100px; margin: 10px;"></div>
<div data-id="box2" data-auto-animate-delay="0.1" style="background: magenta; width: 150px; height: 100px; margin: 10px;"></div>
<div data-id="box3" data-auto-animate-delay="0.2" style="background: yellow; width: 150px; height: 100px; margin: 10px;"></div>
</div>
<h2 style="margin-top: 20px;">Auto-Animate</h2>
</section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<div class="r-stack">
<div data-id="box1" style="background: cyan; width: 300px; height: 300px; border-radius: 200px;"></div>
<div data-id="box2" style="background: magenta; width: 200px; height: 200px; border-radius: 200px;"></div>
<div data-id="box3" style="background: yellow; width: 100px; height: 100px; border-radius: 200px;"></div>
</div>
<h2 style="margin-top: 20px;">Auto-Animate</h2>
</section>
<section data-background-gradient="linear-gradient(to bottom, #283b95, #17b2c3)" id="gradient-bg">
<h2>Gradient Backgrounds</h2>
</section>
<section data-auto-animate>
<h2 data-id="code-title">Scroll triggered code highlights</h2>
<pre data-id="code-animation"><code class="hljs javascript" data-trim data-line-numbers="|4,8-11|17|22-24"><script type="text/template">
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
function SecondExample() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
</script></code></pre>
</section>
<section class="stack">
<section data-background="https://static.slid.es/reveal/image-placeholder.png" id="image-bg">
<h2>Image Backgrounds</h2>
<pre><code class="hljs html">&lt;section data-background="image.png"&gt;</code></pre>
</section>
<section data-background-video="https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.mp4,https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.webm">
<h2>Video background</h2>
</section>
</section>
<section><h2>The end</h2></section>
</div>
</div>
<script src="../dist/reveal.js"></script>
<script src="../plugin/notes/notes.js"></script>
<script src="../plugin/markdown/markdown.js"></script>
<script src="../plugin/highlight/highlight.js"></script>
<script>
Reveal.initialize({
view: 'scroll',
hash: true,
plugins: [ RevealMarkdown, RevealHighlight, RevealNotes ]
});
</script>
</body>
</html>

View File

@@ -256,6 +256,36 @@ export default {
parallaxBackgroundHorizontal: null, parallaxBackgroundHorizontal: null,
parallaxBackgroundVertical: null, parallaxBackgroundVertical: null,
// Can be used to initialize reveal.js in one of the following views:
// - print: Render the presentation so that it can be printed to PDF
// - scroll: Show the presentation as a tall scrollable page with scroll
// triggered animations
view: null,
// Adjusts the height of each slide in the scroll view.
// - full: Each slide is as tall as the viewport
// - compact: Slides are as small as possible, allowing multiple slides
// to be visible in parallel on tall devices
scrollLayout: 'full',
// Control how scroll snapping works in the scroll view.
// - false: No snapping, scrolling is continuous
// - proximity: Snap when close to a slide
// - mandatory: Always snap to the closest slide
//
// Only applies to presentations in scroll view.
scrollSnap: 'mandatory',
// Enables and configure the scroll view progress bar.
// - 'auto': Show the scrollbar while scrolling, hide while idle
// - true: Always show the scrollbar
// - false: Never show the scrollbar
scrollProgress: 'auto',
// Automatically activate the scroll view when we the viewport falls
// below the given width.
scrollActivationWidth: 435,
// The maximum number of pages a single slide can expand onto when printing // The maximum number of pages a single slide can expand onto when printing
// to PDF, unlimited by default // to PDF, unlimited by default
pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
@@ -287,7 +317,7 @@ export default {
// Time before the cursor is hidden (in ms) // Time before the cursor is hidden (in ms)
hideCursorTime: 5000, hideCursorTime: 5000,
// Should we automatmically sort and set indices for fragments // Should we automatically sort and set indices for fragments
// at each sync? (See Reveal.sync) // at each sync? (See Reveal.sync)
sortFragmentsOnSync: true, sortFragmentsOnSync: true,

View File

@@ -190,10 +190,30 @@ export default class Backgrounds {
if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition; if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition;
if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity; if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity;
const contrastClass = this.getContrastClass( slide );
if( typeof contrastClass === 'string' ) {
slide.classList.add( contrastClass );
}
}
/**
* Returns a class name that can be applied to a slide to indicate
* if it has a light or dark background.
*
* @param {*} slide
*
* @returns {string|null}
*/
getContrastClass( slide ) {
const element = slide.slideBackgroundElement;
// If this slide has a background color, we add a class that // If this slide has a background color, we add a class that
// signals if it is light or dark. If the slide has no background // signals if it is light or dark. If the slide has no background
// color, no class will be added // color, no class will be added
let contrastColor = data.backgroundColor; let contrastColor = slide.getAttribute( 'data-background-color' );
// If no bg color was found, or it cannot be converted by colorToRgb, check the computed background // If no bg color was found, or it cannot be converted by colorToRgb, check the computed background
if( !contrastColor || !colorToRgb( contrastColor ) ) { if( !contrastColor || !colorToRgb( contrastColor ) ) {
@@ -211,14 +231,32 @@ export default class Backgrounds {
// an element with no background // an element with no background
if( rgb && rgb.a !== 0 ) { if( rgb && rgb.a !== 0 ) {
if( colorBrightness( contrastColor ) < 128 ) { if( colorBrightness( contrastColor ) < 128 ) {
slide.classList.add( 'has-dark-background' ); return 'has-dark-background';
} }
else { else {
slide.classList.add( 'has-light-background' ); return 'has-light-background';
} }
} }
} }
return null;
}
/**
* Bubble the 'has-light-background'/'has-dark-background' classes.
*/
bubbleSlideContrastClassToElement( slide, target ) {
[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => {
if( slide.classList.contains( classToBubble ) ) {
target.classList.add( classToBubble );
}
else {
target.classList.remove( classToBubble );
}
}, this );
} }
/** /**
@@ -322,14 +360,7 @@ export default class Backgrounds {
// If there's a background brightness flag for this slide, // If there's a background brightness flag for this slide,
// bubble it to the .reveal container // bubble it to the .reveal container
if( currentSlide ) { if( currentSlide ) {
[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => { this.bubbleSlideContrastClassToElement( currentSlide, this.Reveal.getRevealElement() );
if( currentSlide.classList.contains( classToBubble ) ) {
this.Reveal.getRevealElement().classList.add( classToBubble );
}
else {
this.Reveal.getRevealElement().classList.remove( classToBubble );
}
}, this );
} }
// Allow the first background to apply without transition // Allow the first background to apply without transition

View File

@@ -174,24 +174,23 @@ export default class Fragments {
* *
* @return {{shown: array, hidden: array}} * @return {{shown: array, hidden: array}}
*/ */
update( index, fragments ) { update( index, fragments, slide = this.Reveal.getCurrentSlide() ) {
let changedFragments = { let changedFragments = {
shown: [], shown: [],
hidden: [] hidden: []
}; };
let currentSlide = this.Reveal.getCurrentSlide(); if( slide && this.Reveal.getConfig().fragments ) {
if( currentSlide && this.Reveal.getConfig().fragments ) {
fragments = fragments || this.sort( currentSlide.querySelectorAll( '.fragment' ) ); fragments = fragments || this.sort( slide.querySelectorAll( '.fragment' ) );
if( fragments.length ) { if( fragments.length ) {
let maxIndex = 0; let maxIndex = 0;
if( typeof index !== 'number' ) { if( typeof index !== 'number' ) {
let currentFragment = this.sort( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop(); let currentFragment = this.sort( slide.querySelectorAll( '.fragment.visible' ) ).pop();
if( currentFragment ) { if( currentFragment ) {
index = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 ); index = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );
} }
@@ -252,7 +251,7 @@ export default class Fragments {
// the current fragment index. // the current fragment index.
index = typeof index === 'number' ? index : -1; index = typeof index === 'number' ? index : -1;
index = Math.max( Math.min( index, maxIndex ), -1 ); index = Math.max( Math.min( index, maxIndex ), -1 );
currentSlide.setAttribute( 'data-fragment', index ); slide.setAttribute( 'data-fragment', index );
} }

View File

@@ -17,7 +17,6 @@ export default class Keyboard {
this.bindings = {}; this.bindings = {};
this.onDocumentKeyDown = this.onDocumentKeyDown.bind( this ); this.onDocumentKeyDown = this.onDocumentKeyDown.bind( this );
this.onDocumentKeyPress = this.onDocumentKeyPress.bind( this );
} }
@@ -54,7 +53,6 @@ export default class Keyboard {
bind() { bind() {
document.addEventListener( 'keydown', this.onDocumentKeyDown, false ); document.addEventListener( 'keydown', this.onDocumentKeyDown, false );
document.addEventListener( 'keypress', this.onDocumentKeyPress, false );
} }
@@ -64,7 +62,6 @@ export default class Keyboard {
unbind() { unbind() {
document.removeEventListener( 'keydown', this.onDocumentKeyDown, false ); document.removeEventListener( 'keydown', this.onDocumentKeyDown, false );
document.removeEventListener( 'keypress', this.onDocumentKeyPress, false );
} }
@@ -135,20 +132,6 @@ export default class Keyboard {
} }
/**
* Handler for the document level 'keypress' event.
*
* @param {object} event
*/
onDocumentKeyPress( event ) {
// Check if the pressed key is question mark
if( event.shiftKey && event.charCode === 63 ) {
this.Reveal.toggleHelp();
}
}
/** /**
* Handler for the document level 'keydown' event. * Handler for the document level 'keydown' event.
* *
@@ -184,10 +167,10 @@ export default class Keyboard {
let activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className); let activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className);
// Whitelist certain modifiers for slide navigation shortcuts // Whitelist certain modifiers for slide navigation shortcuts
let isNavigationKey = [32, 37, 38, 39, 40, 78, 80].indexOf( event.keyCode ) !== -1; let keyCodeUsesModifier = [32, 37, 38, 39, 40, 78, 80, 191].indexOf( event.keyCode ) !== -1;
// Prevent all other events when a modifier is pressed // Prevent all other events when a modifier is pressed
let unusedModifier = !( isNavigationKey && event.shiftKey || event.altKey ) && let unusedModifier = !( keyCodeUsesModifier && event.shiftKey || event.altKey ) &&
( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ); ( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey );
// Disregard the event if there's a focused element or a // Disregard the event if there's a focused element or a
@@ -351,7 +334,7 @@ export default class Keyboard {
} }
} }
// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON // TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON
else if( keyCode === 58 || keyCode === 59 || keyCode === 66 || keyCode === 86 || keyCode === 190 || keyCode === 191 ) { else if( [58, 59, 66, 86, 190].includes( keyCode ) || ( keyCode === 191 && !event.shiftKey ) ) {
this.Reveal.togglePause(); this.Reveal.togglePause();
} }
// F // F
@@ -360,16 +343,20 @@ export default class Keyboard {
} }
// A // A
else if( keyCode === 65 ) { else if( keyCode === 65 ) {
if ( config.autoSlideStoppable ) { if( config.autoSlideStoppable ) {
this.Reveal.toggleAutoSlide( autoSlideWasPaused ); this.Reveal.toggleAutoSlide( autoSlideWasPaused );
} }
} }
// G // G
else if( keyCode === 71 ) { else if( keyCode === 71 ) {
if ( config.jumpToSlide ) { if( config.jumpToSlide ) {
this.Reveal.toggleJumpToSlide(); this.Reveal.toggleJumpToSlide();
} }
} }
// ?
else if( keyCode === 191 && event.shiftKey ) {
this.Reveal.toggleHelp();
}
else { else {
triggered = false; triggered = false;
} }

View File

@@ -64,7 +64,7 @@ export default class Location {
try { try {
slide = document slide = document
.getElementById( decodeURIComponent( name ) ) .getElementById( decodeURIComponent( name ) )
.closest('.slides>section, .slides>section>section'); .closest('.slides section');
} }
catch ( error ) { } catch ( error ) { }

View File

@@ -38,10 +38,12 @@ export default class Notes {
*/ */
update() { update() {
if( this.Reveal.getConfig().showNotes && this.element && this.Reveal.getCurrentSlide() && !this.Reveal.print.isPrintingPDF() ) { if( this.Reveal.getConfig().showNotes &&
this.element && this.Reveal.getCurrentSlide() &&
!this.Reveal.isScrollView() &&
!this.Reveal.isPrintView()
) {
this.element.innerHTML = this.getSlideNotes() || '<span class="notes-placeholder">No notes on this slide.</span>'; this.element.innerHTML = this.getSlideNotes() || '<span class="notes-placeholder">No notes on this slide.</span>';
} }
} }
@@ -54,7 +56,11 @@ export default class Notes {
*/ */
updateVisibility() { updateVisibility() {
if( this.Reveal.getConfig().showNotes && this.hasNotes() && !this.Reveal.print.isPrintingPDF() ) { if( this.Reveal.getConfig().showNotes &&
this.hasNotes() &&
!this.Reveal.isScrollView() &&
!this.Reveal.isPrintView()
) {
this.Reveal.getRevealElement().classList.add( 'show-notes' ); this.Reveal.getRevealElement().classList.add( 'show-notes' );
} }
else { else {

View File

@@ -24,7 +24,7 @@ export default class Overview {
activate() { activate() {
// Only proceed if enabled in config // Only proceed if enabled in config
if( this.Reveal.getConfig().overview && !this.isActive() ) { if( this.Reveal.getConfig().overview && !this.Reveal.isScrollView() && !this.isActive() ) {
this.active = true; this.active = true;

View File

@@ -4,7 +4,7 @@ import { queryAll, createStyleSheet } from '../utils/util.js'
/** /**
* Setups up our presentation for printing/exporting to PDF. * Setups up our presentation for printing/exporting to PDF.
*/ */
export default class Print { export default class PrintView {
constructor( Reveal ) { constructor( Reveal ) {
@@ -16,7 +16,7 @@ export default class Print {
* Configures the presentation for printing to a static * Configures the presentation for printing to a static
* PDF. * PDF.
*/ */
async setupPDF() { async activate() {
const config = this.Reveal.getConfig(); const config = this.Reveal.getConfig();
const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ) const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR )
@@ -42,11 +42,11 @@ export default class Print {
// Limit the size of certain elements to the dimensions of the slide // Limit the size of certain elements to the dimensions of the slide
createStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' ); createStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );
document.documentElement.classList.add( 'print-pdf' ); document.documentElement.classList.add( 'reveal-print', 'print-pdf' );
document.body.style.width = pageWidth + 'px'; document.body.style.width = pageWidth + 'px';
document.body.style.height = pageHeight + 'px'; document.body.style.height = pageHeight + 'px';
const viewportElement = document.querySelector( '.reveal-viewport' ); const viewportElement = this.Reveal.getViewportElement();
let presentationBackground; let presentationBackground;
if( viewportElement ) { if( viewportElement ) {
const viewportStyles = window.getComputedStyle( viewportElement ); const viewportStyles = window.getComputedStyle( viewportElement );
@@ -226,11 +226,11 @@ export default class Print {
} }
/** /**
* Checks if this instance is being used to print a PDF. * Checks if the print mode is/should be activated.
*/ */
isPrintingPDF() { isActive() {
return ( /print-pdf/gi ).test( window.location.search ); return this.Reveal.getConfig().view === 'print';
} }

View File

@@ -0,0 +1,888 @@
import { HORIZONTAL_SLIDES_SELECTOR } from '../utils/constants.js'
import { queryAll } from '../utils/util.js'
const HIDE_SCROLLBAR_TIMEOUT = 500;
const MAX_PROGRESS_SPACING = 4;
const MIN_PROGRESS_SEGMENT_HEIGHT = 6;
const MIN_PLAYHEAD_HEIGHT = 8;
/**
* The scroll view lets you read a reveal.js presentation
* as a linear scrollable page.
*/
export default class ScrollView {
constructor( Reveal ) {
this.Reveal = Reveal;
this.active = false;
this.activatedCallbacks = [];
this.onScroll = this.onScroll.bind( this );
}
/**
* Activates the scroll view. This rearranges the presentation DOM
* by—among other things—wrapping each slide in a page element.
*/
activate() {
if( this.active ) return;
const stateBeforeActivation = this.Reveal.getState();
this.active = true;
// Store the full presentation HTML so that we can restore it
// when/if the scroll view is deactivated
this.slideHTMLBeforeActivation = this.Reveal.getSlidesElement().innerHTML;
const horizontalSlides = queryAll( this.Reveal.getRevealElement(), HORIZONTAL_SLIDES_SELECTOR );
this.viewportElement.classList.add( 'loading-scroll-mode', 'reveal-scroll' );
let presentationBackground;
const viewportStyles = window.getComputedStyle( this.viewportElement );
if( viewportStyles && viewportStyles.background ) {
presentationBackground = viewportStyles.background;
}
const pageElements = [];
const pageContainer = horizontalSlides[0].parentNode;
let previousSlide;
// Creates a new page element and appends the given slide/bg
// to it.
const createPageElement = ( slide, h, v ) => {
let contentContainer;
// If this slide is part of an auto-animation sequence, we
// group it under the same page element as the previous slide
if( previousSlide && this.Reveal.shouldAutoAnimateBetween( previousSlide, slide ) ) {
contentContainer = document.createElement( 'div' );
contentContainer.className = 'scroll-page-content scroll-auto-animate-page';
contentContainer.style.display = 'none';
previousSlide.closest( '.scroll-page-content' ).parentNode.appendChild( contentContainer );
}
else {
// Wrap the slide in a page element and hide its overflow
// so that no page ever flows onto another
const page = document.createElement( 'div' );
page.className = 'scroll-page';
pageElements.push( page );
// Copy the presentation-wide background to each page
if( presentationBackground ) {
page.style.background = presentationBackground;
}
const stickyContainer = document.createElement( 'div' );
stickyContainer.className = 'scroll-page-sticky';
page.appendChild( stickyContainer );
contentContainer = document.createElement( 'div' );
contentContainer.className = 'scroll-page-content';
stickyContainer.appendChild( contentContainer );
}
contentContainer.appendChild( slide );
slide.classList.remove( 'past', 'future' );
slide.setAttribute( 'data-index-h', h );
slide.setAttribute( 'data-index-v', v );
if( slide.slideBackgroundElement ) {
slide.slideBackgroundElement.remove( 'past', 'future' );
contentContainer.insertBefore( slide.slideBackgroundElement, slide );
}
previousSlide = slide;
}
// Slide and slide background layout
horizontalSlides.forEach( ( horizontalSlide, h ) => {
if( this.Reveal.isVerticalStack( horizontalSlide ) ) {
horizontalSlide.querySelectorAll( 'section' ).forEach( ( verticalSlide, v ) => {
createPageElement( verticalSlide, h, v );
});
}
else {
createPageElement( horizontalSlide, h, 0 );
}
}, this );
this.createProgressBar();
// Remove leftover stacks
queryAll( this.Reveal.getRevealElement(), '.stack' ).forEach( stack => stack.remove() );
// Add our newly created pages to the DOM
pageElements.forEach( page => pageContainer.appendChild( page ) );
// Re-run JS-based content layout after the slide is added to page DOM
this.Reveal.slideContent.layout( this.Reveal.getSlidesElement() );
this.Reveal.layout();
this.Reveal.setState( stateBeforeActivation );
this.activatedCallbacks.forEach( callback => callback() );
this.activatedCallbacks = [];
this.restoreScrollPosition();
this.viewportElement.classList.remove( 'loading-scroll-mode' );
this.viewportElement.addEventListener( 'scroll', this.onScroll, { passive: true } );
}
/**
* Deactivates the scroll view and restores the standard slide-based
* presentation.
*/
deactivate() {
if( !this.active ) return;
const stateBeforeDeactivation = this.Reveal.getState();
this.active = false;
this.viewportElement.removeEventListener( 'scroll', this.onScroll );
this.viewportElement.classList.remove( 'reveal-scroll' );
this.removeProgressBar();
this.Reveal.getSlidesElement().innerHTML = this.slideHTMLBeforeActivation;
this.Reveal.sync();
this.Reveal.setState( stateBeforeDeactivation );
this.slideHTMLBeforeActivation = null;
}
toggle( override ) {
if( typeof override === 'boolean' ) {
override ? this.activate() : this.deactivate();
}
else {
this.isActive() ? this.deactivate() : this.activate();
}
}
/**
* Checks if the scroll view is currently active.
*/
isActive() {
return this.active;
}
/**
* Renders the progress bar component.
*/
createProgressBar() {
this.progressBar = document.createElement( 'div' );
this.progressBar.className = 'scrollbar';
this.progressBarInner = document.createElement( 'div' );
this.progressBarInner.className = 'scrollbar-inner';
this.progressBar.appendChild( this.progressBarInner );
this.progressBarPlayhead = document.createElement( 'div' );
this.progressBarPlayhead.className = 'scrollbar-playhead';
this.progressBarInner.appendChild( this.progressBarPlayhead );
this.viewportElement.insertBefore( this.progressBar, this.viewportElement.firstChild );
const handleDocumentMouseMove = ( event ) => {
let progress = ( event.clientY - this.progressBarInner.getBoundingClientRect().top ) / this.progressBarHeight;
progress = Math.max( Math.min( progress, 1 ), 0 );
this.viewportElement.scrollTop = progress * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
};
const handleDocumentMouseUp = ( event ) => {
this.draggingProgressBar = false;
this.showProgressBar();
document.removeEventListener( 'mousemove', handleDocumentMouseMove );
document.removeEventListener( 'mouseup', handleDocumentMouseUp );
};
const handleMouseDown = ( event ) => {
event.preventDefault();
this.draggingProgressBar = true;
document.addEventListener( 'mousemove', handleDocumentMouseMove );
document.addEventListener( 'mouseup', handleDocumentMouseUp );
handleDocumentMouseMove( event );
};
this.progressBarInner.addEventListener( 'mousedown', handleMouseDown );
}
removeProgressBar() {
if( this.progressBar ) {
this.progressBar.remove();
this.progressBar = null;
}
}
layout() {
if( this.isActive() ) {
this.syncPages();
this.syncScrollPosition();
}
}
/**
* Updates our pages to match the latest configuration and
* presentation size.
*/
syncPages() {
const config = this.Reveal.getConfig();
const slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );
const scale = this.Reveal.getScale();
const useCompactLayout = config.scrollLayout === 'compact';
const viewportHeight = this.viewportElement.offsetHeight;
const compactHeight = slideSize.height * scale;
const pageHeight = useCompactLayout ? compactHeight : viewportHeight;
// The height that needs to be scrolled between scroll triggers
const scrollTriggerHeight = useCompactLayout ? compactHeight : viewportHeight;
this.viewportElement.style.setProperty( '--page-height', pageHeight + 'px' );
this.viewportElement.style.scrollSnapType = typeof config.scrollSnap === 'string' ? `y ${config.scrollSnap}` : '';
// This will hold all scroll triggers used to show/hide slides
this.slideTriggers = [];
const pageElements = Array.from( this.Reveal.getRevealElement().querySelectorAll( '.scroll-page' ) );
this.pages = pageElements.map( pageElement => {
const page = this.createPage({
pageElement,
slideElement: pageElement.querySelector( 'section' ),
stickyElement: pageElement.querySelector( '.scroll-page-sticky' ),
contentElement: pageElement.querySelector( '.scroll-page-content' ),
backgroundElement: pageElement.querySelector( '.slide-background' ),
autoAnimateElements: pageElement.querySelectorAll( '.scroll-auto-animate-page' ),
autoAnimatePages: []
});
page.pageElement.style.setProperty( '--slide-height', config.center === true ? 'auto' : slideSize.height + 'px' );
this.slideTriggers.push({
page: page,
activate: () => this.activatePage( page ),
deactivate: () => this.deactivatePage( page )
});
// Create scroll triggers that show/hide fragments
this.createFragmentTriggersForPage( page );
// Create scroll triggers for triggering auto-animate steps
if( page.autoAnimateElements.length > 0 ) {
this.createAutoAnimateTriggersForPage( page );
}
let totalScrollTriggerCount = Math.max( page.scrollTriggers.length - 1, 0 );
// Each auto-animate step may include its own scroll triggers
// for fragments, ensure we count those as well
totalScrollTriggerCount += page.autoAnimatePages.reduce( ( total, page ) => {
return total + Math.max( page.scrollTriggers.length - 1, 0 );
}, page.autoAnimatePages.length );
// Clean up from previous renders
page.pageElement.querySelectorAll( '.scroll-snap-point' ).forEach( el => el.remove() );
// Create snap points for all scroll triggers
// - Can't be absolute in FF
// - Can't be 0-height in Safari
// - Can't use snap-align on parent in Safari because then
// inner triggers won't work
for( let i = 0; i < totalScrollTriggerCount + 1; i++ ) {
const triggerStick = document.createElement( 'div' );
triggerStick.className = 'scroll-snap-point';
triggerStick.style.height = scrollTriggerHeight + 'px';
triggerStick.style.scrollSnapAlign = useCompactLayout ? 'center' : 'start';
page.pageElement.appendChild( triggerStick );
if( i === 0 ) {
triggerStick.style.marginTop = -scrollTriggerHeight + 'px';
}
}
// In the compact layout, only slides with scroll triggers cover the
// full viewport height. This helps avoid empty gaps before or after
// a sticky slide.
if( useCompactLayout && page.scrollTriggers.length > 0 ) {
page.pageHeight = viewportHeight;
page.pageElement.style.setProperty( '--page-height', viewportHeight + 'px' );
}
else {
page.pageHeight = pageHeight;
page.pageElement.style.removeProperty( '--page-height' );
}
// Add scroll padding based on how many scroll triggers we have
page.scrollPadding = scrollTriggerHeight * totalScrollTriggerCount;
// The total height including scrollable space
page.totalHeight = page.pageHeight + page.scrollPadding;
// This is used to pad the height of our page in CSS
page.pageElement.style.setProperty( '--page-scroll-padding', page.scrollPadding + 'px' );
// If this is a sticky page, stick it to the vertical center
if( totalScrollTriggerCount > 0 ) {
page.stickyElement.style.position = 'sticky';
page.stickyElement.style.top = Math.max( ( viewportHeight - page.pageHeight ) / 2, 0 ) + 'px';
}
else {
page.stickyElement.style.position = 'relative';
page.pageElement.style.scrollSnapAlign = page.pageHeight < viewportHeight ? 'center' : 'start';
}
return page;
} );
this.setTriggerRanges();
/*
console.log(this.slideTriggers.map( t => {
return {
range: `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`,
triggers: t.page.scrollTriggers.map( t => {
return `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`
}).join( ', ' ),
}
}))
*/
this.viewportElement.setAttribute( 'data-scrollbar', config.scrollProgress );
if( config.scrollProgress && this.totalScrollTriggerCount > 1 ) {
// Create the progress bar if it doesn't already exist
if( !this.progressBar ) this.createProgressBar();
this.syncProgressBar();
}
else {
this.removeProgressBar();
}
}
/**
* Calculates and sets the scroll range for all of our scroll
* triggers.
*/
setTriggerRanges() {
// Calculate the total number of scroll triggers
this.totalScrollTriggerCount = this.slideTriggers.reduce( ( total, trigger ) => {
return total + Math.max( trigger.page.scrollTriggers.length, 1 );
}, 0 );
let rangeStart = 0;
// Calculate the scroll range of each scroll trigger on a scale
// of 0-1
this.slideTriggers.forEach( ( trigger, i ) => {
trigger.range = [
rangeStart,
rangeStart + Math.max( trigger.page.scrollTriggers.length, 1 ) / this.totalScrollTriggerCount
];
const scrollTriggerSegmentSize = ( trigger.range[1] - trigger.range[0] ) / trigger.page.scrollTriggers.length;
// Set the range for each inner scroll trigger
trigger.page.scrollTriggers.forEach( ( scrollTrigger, i ) => {
scrollTrigger.range = [
rangeStart + i * scrollTriggerSegmentSize,
rangeStart + ( i + 1 ) * scrollTriggerSegmentSize
];
} );
rangeStart = trigger.range[1];
} );
}
/**
* Creates one scroll trigger for each fragments in the given page.
*
* @param {*} page
*/
createFragmentTriggersForPage( page, slideElement ) {
slideElement = slideElement || page.slideElement;
// Each fragment 'group' is an array containing one or more
// fragments. Multiple fragments that appear at the same time
// are part of the same group.
const fragmentGroups = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment' ), true );
// Create scroll triggers that show/hide fragments
if( fragmentGroups.length ) {
page.fragments = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment:not(.disabled)' ) );
page.scrollTriggers.push(
// Trigger for the initial state with no fragments visible
{
activate: () => {
this.Reveal.fragments.update( -1, page.fragments, slideElement );
}
},
// Triggers for each fragment group
...fragmentGroups.map( ( fragments, i ) => ({
activate: () => {
this.Reveal.fragments.update( i, page.fragments, slideElement );
}
})
)
);
}
return page.scrollTriggers.length;
}
/**
* Creates scroll triggers for the auto-animate steps in the
* given page.
*
* @param {*} page
*/
createAutoAnimateTriggersForPage( page ) {
if( page.autoAnimateElements.length > 0 ) {
// Triggers for each subsequent auto-animate slide
this.slideTriggers.push( ...Array.from( page.autoAnimateElements ).map( ( autoAnimateElement, i ) => {
let autoAnimatePage = this.createPage({
slideElement: autoAnimateElement.querySelector( 'section' ),
contentElement: autoAnimateElement,
backgroundElement: autoAnimateElement.querySelector( '.slide-background' )
});
// Create fragment scroll triggers for the auto-animate slide
this.createFragmentTriggersForPage( autoAnimatePage, autoAnimatePage.slideElement );
page.autoAnimatePages.push( autoAnimatePage );
// Return our slide trigger
return {
page: autoAnimatePage,
activate: () => this.activatePage( autoAnimatePage ),
deactivate: () => this.deactivatePage( autoAnimatePage )
};
}));
}
}
/**
* Helper method for creating a page definition and adding
* required fields. A "page" is a slide or auto-animate step.
*/
createPage( page ) {
page.scrollTriggers = [];
page.indexh = parseInt( page.slideElement.getAttribute( 'data-index-h' ), 10 );
page.indexv = parseInt( page.slideElement.getAttribute( 'data-index-v' ), 10 );
return page;
}
/**
* Rerenders progress bar segments so that they match the current
* reveal.js config and size.
*/
syncProgressBar() {
this.progressBarInner.querySelectorAll( '.scrollbar-slide' ).forEach( slide => slide.remove() );
const scrollHeight = this.viewportElement.scrollHeight;
const viewportHeight = this.viewportElement.offsetHeight;
const viewportHeightFactor = viewportHeight / scrollHeight;
this.progressBarHeight = this.progressBarInner.offsetHeight;
this.playheadHeight = Math.max( viewportHeightFactor * this.progressBarHeight, MIN_PLAYHEAD_HEIGHT );
this.progressBarScrollableHeight = this.progressBarHeight - this.playheadHeight;
const progressSegmentHeight = viewportHeight / scrollHeight * this.progressBarHeight;
const spacing = Math.min( progressSegmentHeight / 8, MAX_PROGRESS_SPACING );
this.progressBarPlayhead.style.height = this.playheadHeight - spacing + 'px';
// Don't show individual segments if they're too small
if( progressSegmentHeight > MIN_PROGRESS_SEGMENT_HEIGHT ) {
this.slideTriggers.forEach( slideTrigger => {
const { page } = slideTrigger;
// Visual representation of a slide
page.progressBarSlide = document.createElement( 'div' );
page.progressBarSlide.className = 'scrollbar-slide';
page.progressBarSlide.style.top = slideTrigger.range[0] * this.progressBarHeight + 'px';
page.progressBarSlide.style.height = ( slideTrigger.range[1] - slideTrigger.range[0] ) * this.progressBarHeight - spacing + 'px';
page.progressBarSlide.classList.toggle( 'has-triggers', page.scrollTriggers.length > 0 );
this.progressBarInner.appendChild( page.progressBarSlide );
// Visual representations of each scroll trigger
page.scrollTriggerElements = page.scrollTriggers.map( ( trigger, i ) => {
const triggerElement = document.createElement( 'div' );
triggerElement.className = 'scrollbar-trigger';
triggerElement.style.top = ( trigger.range[0] - slideTrigger.range[0] ) * this.progressBarHeight + 'px';
triggerElement.style.height = ( trigger.range[1] - trigger.range[0] ) * this.progressBarHeight - spacing + 'px';
page.progressBarSlide.appendChild( triggerElement );
if( i === 0 ) triggerElement.style.display = 'none';
return triggerElement;
} );
} );
}
else {
this.pages.forEach( page => page.progressBarSlide = null );
}
}
/**
* Reads the current scroll position and updates our active
* trigger states accordingly.
*/
syncScrollPosition() {
const viewportHeight = this.viewportElement.offsetHeight;
const viewportHeightFactor = viewportHeight / this.viewportElement.scrollHeight;
const scrollTop = this.viewportElement.scrollTop;
const scrollHeight = this.viewportElement.scrollHeight - viewportHeight
const scrollProgress = Math.max( Math.min( scrollTop / scrollHeight, 1 ), 0 );
const scrollProgressMid = Math.max( Math.min( ( scrollTop + viewportHeight / 2 ) / this.viewportElement.scrollHeight, 1 ), 0 );
let activePage;
this.slideTriggers.forEach( ( trigger ) => {
const { page } = trigger;
const shouldPreload = scrollProgress >= trigger.range[0] - viewportHeightFactor*2 &&
scrollProgress <= trigger.range[1] + viewportHeightFactor*2;
// Load slides that are within the preload range
if( shouldPreload && !page.loaded ) {
page.loaded = true;
this.Reveal.slideContent.load( page.slideElement );
}
else if( page.loaded ) {
page.loaded = false;
this.Reveal.slideContent.unload( page.slideElement );
}
// If we're within this trigger range, activate it
if( scrollProgress >= trigger.range[0] && scrollProgress <= trigger.range[1] ) {
this.activateTrigger( trigger );
activePage = trigger.page;
}
// .. otherwise deactivate
else if( trigger.active ) {
this.deactivateTrigger( trigger );
}
} );
// Each page can have its own scroll triggers, check if any of those
// need to be activated/deactivated
if( activePage ) {
activePage.scrollTriggers.forEach( ( trigger ) => {
if( scrollProgressMid >= trigger.range[0] && scrollProgressMid <= trigger.range[1] ) {
this.activateTrigger( trigger );
}
else if( trigger.active ) {
this.deactivateTrigger( trigger );
}
} );
}
// Update our visual progress indication
this.setProgressBarValue( scrollTop / ( this.viewportElement.scrollHeight - viewportHeight ) );
}
/**
* Moves the progress bar playhead to the specified position.
*
* @param {number} progress 0-1
*/
setProgressBarValue( progress ) {
if( this.progressBar ) {
this.progressBarPlayhead.style.transform = `translateY(${progress * this.progressBarScrollableHeight}px)`;
this.getAllPages()
.filter( page => page.progressBarSlide )
.forEach( ( page ) => {
page.progressBarSlide.classList.toggle( 'active', page.active === true );
page.scrollTriggers.forEach( ( trigger, i ) => {
page.scrollTriggerElements[i].classList.toggle( 'active', page.active === true && trigger.active === true );
} );
} );
this.showProgressBar();
}
}
/**
* Show the progress bar and, if configured, automatically hide
* it after a delay.
*/
showProgressBar() {
this.progressBar.classList.add( 'visible' );
clearTimeout( this.hideProgressBarTimeout );
if( this.Reveal.getConfig().scrollProgress === 'auto' && !this.draggingProgressBar ) {
this.hideProgressBarTimeout = setTimeout( () => {
if( this.progressBar ) {
this.progressBar.classList.remove( 'visible' );
}
}, HIDE_SCROLLBAR_TIMEOUT );
}
}
/**
* Scrolls the given slide element into view.
*
* @param {HTMLElement} slideElement
*/
scrollToSlide( slideElement ) {
// If the scroll view isn't active yet, queue this action
if( !this.active ) {
this.activatedCallbacks.push( () => this.scrollToSlide( slideElement ) );
}
else {
// Find the trigger for this slide
const trigger = this.getScrollTriggerBySlide( slideElement );
if( trigger ) {
// Use the trigger's range to calculate the scroll position
this.viewportElement.scrollTop = trigger.range[0] * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
}
}
}
/**
* Persists the current scroll position to session storage
* so that it can be restored.
*/
storeScrollPosition() {
clearTimeout( this.storeScrollPositionTimeout );
this.storeScrollPositionTimeout = setTimeout( () => {
sessionStorage.setItem( 'reveal-scroll-top', this.viewportElement.scrollTop );
sessionStorage.setItem( 'reveal-scroll-origin', location.origin + location.pathname );
this.storeScrollPositionTimeout = null;
}, 50 );
}
/**
* Restores the scroll position when a deck is reloader.
*/
restoreScrollPosition() {
const scrollPosition = sessionStorage.getItem( 'reveal-scroll-top' );
const scrollOrigin = sessionStorage.getItem( 'reveal-scroll-origin' );
if( scrollPosition && scrollOrigin === location.origin + location.pathname ) {
this.viewportElement.scrollTop = parseInt( scrollPosition, 10 );
}
}
/**
* Activates the given page and starts its embedded conten
* if there is any.
*
* @param {object} page
*/
activatePage( page ) {
if( !page.active ) {
page.active = true;
const { slideElement, backgroundElement, contentElement, indexh, indexv } = page;
contentElement.style.display = 'block';
slideElement.classList.add( 'present' );
if( backgroundElement ) {
backgroundElement.classList.add( 'present' );
}
this.Reveal.setCurrentScrollPage( slideElement, indexh, indexv );
this.Reveal.backgrounds.bubbleSlideContrastClassToElement( slideElement, this.viewportElement );
// If this page is part of an auto-animation there will be one
// content element per auto-animated page. We need to show the
// current page and hide all others.
Array.from( contentElement.parentNode.querySelectorAll( '.scroll-page-content' ) ).forEach( sibling => {
if( sibling !== contentElement ) {
sibling.style.display = 'none';
}
});
}
}
/**
* Deactivates the page after it has been visible.
*
* @param {object} page
*/
deactivatePage( page ) {
if( page.active ) {
page.active = false;
page.slideElement.classList.remove( 'present' );
page.backgroundElement.classList.remove( 'present' );
}
}
activateTrigger( trigger ) {
if( !trigger.active ) {
trigger.active = true;
trigger.activate();
}
}
deactivateTrigger( trigger ) {
if( trigger.active ) {
trigger.active = false;
if( trigger.deactivate ) {
trigger.deactivate();
}
}
}
/**
* Retrieve a slide by its original h/v index (i.e. the indices the
* slide had before being linearized).
*
* @param {number} h
* @param {number} v
* @returns {HTMLElement}
*/
getSlideByIndices( h, v ) {
const page = this.getAllPages().find( page => {
return page.indexh === h && page.indexv === v;
} );
return page ? page.slideElement : null;
}
/**
* Retrieve a list of all scroll triggers for the given slide
* DOM element.
*
* @param {HTMLElement} slide
* @returns {Array}
*/
getScrollTriggerBySlide( slide ) {
return this.slideTriggers.find( trigger => trigger.page.slideElement === slide );
}
/**
* Get a list of all pages in the scroll view. This includes
* both top-level slides and auto-animate steps.
*
* @returns {Array}
*/
getAllPages() {
return this.pages.flatMap( page => [page, ...(page.autoAnimatePages || [])] );
}
onScroll() {
this.syncScrollPosition();
this.storeScrollPosition();
}
get viewportElement() {
return this.Reveal.getViewportElement();
}
}

View File

@@ -25,6 +25,10 @@ export default class SlideContent {
*/ */
shouldPreload( element ) { shouldPreload( element ) {
if( this.Reveal.isScrollView() ) {
return true;
}
// Prefer an explicit global preload setting // Prefer an explicit global preload setting
let preload = this.Reveal.getConfig().preloadIframes; let preload = this.Reveal.getConfig().preloadIframes;

View File

@@ -23,7 +23,7 @@ export default class SlideNumber {
configure( config, oldConfig ) { configure( config, oldConfig ) {
let slideNumberDisplay = 'none'; let slideNumberDisplay = 'none';
if( config.slideNumber && !this.Reveal.isPrintingPDF() ) { if( config.slideNumber && !this.Reveal.isPrintView() ) {
if( config.showSlideNumber === 'all' ) { if( config.showSlideNumber === 'all' ) {
slideNumberDisplay = 'block'; slideNumberDisplay = 'block';
} }

View File

@@ -3,6 +3,8 @@ import SlideNumber from './controllers/slidenumber.js'
import JumpToSlide from './controllers/jumptoslide.js' import JumpToSlide from './controllers/jumptoslide.js'
import Backgrounds from './controllers/backgrounds.js' import Backgrounds from './controllers/backgrounds.js'
import AutoAnimate from './controllers/autoanimate.js' import AutoAnimate from './controllers/autoanimate.js'
import ScrollView from './controllers/scrollview.js'
import PrintView from './controllers/printview.js'
import Fragments from './controllers/fragments.js' import Fragments from './controllers/fragments.js'
import Overview from './controllers/overview.js' import Overview from './controllers/overview.js'
import Keyboard from './controllers/keyboard.js' import Keyboard from './controllers/keyboard.js'
@@ -11,7 +13,6 @@ import Controls from './controllers/controls.js'
import Progress from './controllers/progress.js' import Progress from './controllers/progress.js'
import Pointer from './controllers/pointer.js' import Pointer from './controllers/pointer.js'
import Plugins from './controllers/plugins.js' import Plugins from './controllers/plugins.js'
import Print from './controllers/print.js'
import Touch from './controllers/touch.js' import Touch from './controllers/touch.js'
import Focus from './controllers/focus.js' import Focus from './controllers/focus.js'
import Notes from './controllers/notes.js' import Notes from './controllers/notes.js'
@@ -105,6 +106,8 @@ export default function( revealElement, options ) {
jumpToSlide = new JumpToSlide( Reveal ), jumpToSlide = new JumpToSlide( Reveal ),
autoAnimate = new AutoAnimate( Reveal ), autoAnimate = new AutoAnimate( Reveal ),
backgrounds = new Backgrounds( Reveal ), backgrounds = new Backgrounds( Reveal ),
scrollView = new ScrollView( Reveal ),
printView = new PrintView( Reveal ),
fragments = new Fragments( Reveal ), fragments = new Fragments( Reveal ),
overview = new Overview( Reveal ), overview = new Overview( Reveal ),
keyboard = new Keyboard( Reveal ), keyboard = new Keyboard( Reveal ),
@@ -113,7 +116,6 @@ export default function( revealElement, options ) {
progress = new Progress( Reveal ), progress = new Progress( Reveal ),
pointer = new Pointer( Reveal ), pointer = new Pointer( Reveal ),
plugins = new Plugins( Reveal ), plugins = new Plugins( Reveal ),
print = new Print( Reveal ),
focus = new Focus( Reveal ), focus = new Focus( Reveal ),
touch = new Touch( Reveal ), touch = new Touch( Reveal ),
notes = new Notes( Reveal ); notes = new Notes( Reveal );
@@ -140,6 +142,11 @@ export default function( revealElement, options ) {
// 5. Query params // 5. Query params
config = { ...defaultConfig, ...config, ...options, ...initOptions, ...Util.getQueryHash() }; config = { ...defaultConfig, ...config, ...options, ...initOptions, ...Util.getQueryHash() };
// Legacy support for the ?print-pdf query
if( /print-pdf/gi.test( window.location.search ) ) {
config.view = 'print';
}
setViewport(); setViewport();
// Force a layout when the whole page, incl fonts, has loaded // Force a layout when the whole page, incl fonts, has loaded
@@ -201,12 +208,15 @@ export default function( revealElement, options ) {
// Updates the presentation to match the current configuration values // Updates the presentation to match the current configuration values
configure(); configure();
// Read the initial hash
location.readURL();
// Create slide backgrounds // Create slide backgrounds
backgrounds.update( true ); backgrounds.update( true );
// Activate the print/scroll view if configured
activateInitialView();
// Read the initial hash
location.readURL();
// Notify listeners that the presentation is ready but use a 1ms // Notify listeners that the presentation is ready but use a 1ms
// timeout to ensure it's not fired synchronously after #initialize() // timeout to ensure it's not fired synchronously after #initialize()
setTimeout( () => { setTimeout( () => {
@@ -225,19 +235,41 @@ export default function( revealElement, options ) {
}); });
}, 1 ); }, 1 );
// Special setup and config is required when printing to PDF }
if( print.isPrintingPDF() ) {
removeEventListeners();
// The document needs to have loaded for the PDF layout /**
// measurements to be accurate * Activates the correct reveal.js view based on our config.
if( document.readyState === 'complete' ) { * This is only invoked once during initialization.
print.setupPDF(); */
function activateInitialView() {
const activatePrintView = config.view === 'print';
const activateScrollView = config.view === 'scroll' || config.view === 'reader';
if( activatePrintView || activateScrollView ) {
if( activatePrintView ) {
removeEventListeners();
} }
else { else {
window.addEventListener( 'load', () => { touch.unbind();
print.setupPDF(); }
} );
// Avoid content flickering during layout
dom.viewport.classList.add( 'loading-scroll-mode' );
if( activatePrintView ) {
// The document needs to have loaded for the PDF layout
// measurements to be accurate
if( document.readyState === 'complete' ) {
printView.activate();
}
else {
window.addEventListener( 'load', () => printView.activate() );
}
}
else {
scrollView.activate();
} }
} }
@@ -385,7 +417,7 @@ export default function( revealElement, options ) {
function setupScrollPrevention() { function setupScrollPrevention() {
setInterval( () => { setInterval( () => {
if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) { if( !scrollView.isActive() && dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
dom.wrapper.scrollTop = 0; dom.wrapper.scrollTop = 0;
dom.wrapper.scrollLeft = 0; dom.wrapper.scrollLeft = 0;
} }
@@ -452,8 +484,8 @@ export default function( revealElement, options ) {
dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition ); dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
// Expose our configured slide dimensions as custom props // Expose our configured slide dimensions as custom props
dom.viewport.style.setProperty( '--slide-width', typeof config.width == 'string' ? config.width : config.width + 'px' ); dom.viewport.style.setProperty( '--slide-width', typeof config.width === 'string' ? config.width : config.width + 'px' );
dom.viewport.style.setProperty( '--slide-height', typeof config.height == 'string' ? config.height : config.height + 'px' ); dom.viewport.style.setProperty( '--slide-height', typeof config.height === 'string' ? config.height : config.height + 'px' );
if( config.shuffle ) { if( config.shuffle ) {
shuffle(); shuffle();
@@ -689,6 +721,26 @@ export default function( revealElement, options ) {
} }
/**
* Dispatches a slidechanged event.
*
* @param {string} origin Used to identify multiplex clients
*/
function dispatchSlideChanged( origin ) {
dispatchEvent({
type: 'slidechanged',
data: {
indexh,
indexv,
previousSlide,
currentSlide,
origin
}
});
}
/** /**
* Dispatched a postMessage of the given type from our window. * Dispatched a postMessage of the given type from our window.
*/ */
@@ -872,7 +924,10 @@ export default function( revealElement, options ) {
*/ */
function layout() { function layout() {
if( dom.wrapper && !print.isPrintingPDF() ) { if( dom.wrapper && !printView.isActive() ) {
const viewportWidth = dom.viewport.offsetWidth;
const viewportHeight = dom.viewport.offsetHeight;
if( !config.disableLayout ) { if( !config.disableLayout ) {
@@ -886,7 +941,9 @@ export default function( revealElement, options ) {
document.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' ); document.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' );
} }
const size = getComputedSlideSize(); const size = scrollView.isActive() ?
getComputedSlideSize( viewportWidth, viewportHeight ) :
getComputedSlideSize();
const oldScale = scale; const oldScale = scale;
@@ -903,8 +960,9 @@ export default function( revealElement, options ) {
scale = Math.max( scale, config.minScale ); scale = Math.max( scale, config.minScale );
scale = Math.min( scale, config.maxScale ); scale = Math.min( scale, config.maxScale );
// Don't apply any scaling styles if scale is 1 // Don't apply any scaling styles if scale is 1 or we're
if( scale === 1 ) { // in the scroll view
if( scale === 1 || scrollView.isActive() ) {
dom.slides.style.zoom = ''; dom.slides.style.zoom = '';
dom.slides.style.left = ''; dom.slides.style.left = '';
dom.slides.style.top = ''; dom.slides.style.top = '';
@@ -932,7 +990,7 @@ export default function( revealElement, options ) {
continue; continue;
} }
if( config.center || slide.classList.contains( 'center' ) ) { if( ( config.center || slide.classList.contains( 'center' ) ) ) {
// Vertical stacks are not centred since their section // Vertical stacks are not centred since their section
// children will be // children will be
if( slide.classList.contains( 'stack' ) ) { if( slide.classList.contains( 'stack' ) ) {
@@ -958,9 +1016,25 @@ export default function( revealElement, options ) {
} }
}); });
} }
// Responsively turn on the scroll mode if there is an activation
// width configured. Ignore if we're configured to always be in
// scroll mode.
if( typeof config.scrollActivationWidth === 'number' && config.view !== 'scroll' ) {
if( size.presentationWidth > 0 && size.presentationWidth <= config.scrollActivationWidth ) {
if( !scrollView.isActive() ) scrollView.activate();
}
else {
if( scrollView.isActive() ) scrollView.deactivate();
}
}
} }
dom.viewport.style.setProperty( '--slide-scale', scale ); dom.viewport.style.setProperty( '--slide-scale', scale );
dom.viewport.style.setProperty( '--viewport-width', viewportWidth + 'px' );
dom.viewport.style.setProperty( '--viewport-height', viewportHeight + 'px' );
scrollView.layout();
progress.update(); progress.update();
backgrounds.updateParallax(); backgrounds.updateParallax();
@@ -981,7 +1055,6 @@ export default function( revealElement, options ) {
* @param {string|number} height * @param {string|number} height
*/ */
function layoutSlideContents( width, height ) { function layoutSlideContents( width, height ) {
// Handle sizing of elements with the 'r-stretch' class // Handle sizing of elements with the 'r-stretch' class
Util.queryAll( dom.slides, 'section > .stretch, section > .r-stretch' ).forEach( element => { Util.queryAll( dom.slides, 'section > .stretch, section > .r-stretch' ).forEach( element => {
@@ -1017,6 +1090,7 @@ export default function( revealElement, options ) {
* @param {number} [presentationHeight=dom.wrapper.offsetHeight] * @param {number} [presentationHeight=dom.wrapper.offsetHeight]
*/ */
function getComputedSlideSize( presentationWidth, presentationHeight ) { function getComputedSlideSize( presentationWidth, presentationHeight ) {
let width = config.width; let width = config.width;
let height = config.height; let height = config.height;
@@ -1103,6 +1177,19 @@ export default function( revealElement, options ) {
} }
/**
* Checks if the current or specified slide is a stack containing
* vertical slides.
*
* @param {HTMLElement} [slide=currentSlide]
* @return {Boolean}
*/
function isVerticalStack( slide = currentSlide ) {
return slide.classList.contains( '.stack' ) || slide.querySelector( 'section' ) !== null;
}
/** /**
* Returns true if we're on the last slide in the current * Returns true if we're on the last slide in the current
* vertical stack. * vertical stack.
@@ -1288,6 +1375,14 @@ export default function( revealElement, options ) {
// Query all horizontal slides in the deck // Query all horizontal slides in the deck
const horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ); const horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );
// If we're in scroll mode, we scroll the target slide into view
// instead of running our standard slide transition
if( scrollView.isActive() ) {
const scrollToSlide = scrollView.getSlideByIndices( h, v );
if( scrollToSlide ) scrollView.scrollToSlide( scrollToSlide );
return;
}
// Abort if there are no slides // Abort if there are no slides
if( horizontalSlides.length === 0 ) return; if( horizontalSlides.length === 0 ) return;
@@ -1334,6 +1429,9 @@ export default function( revealElement, options ) {
// Detect if we're moving between two auto-animated slides // Detect if we're moving between two auto-animated slides
if( slideChanged && previousSlide && currentSlide && !overview.isActive() ) { if( slideChanged && previousSlide && currentSlide && !overview.isActive() ) {
transition = 'running';
autoAnimateTransition = shouldAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexvBefore );
// If this is an auto-animated transition, we disable the // If this is an auto-animated transition, we disable the
// regular slide transition // regular slide transition
@@ -1341,16 +1439,9 @@ export default function( revealElement, options ) {
// Note 20-03-2020: // Note 20-03-2020:
// This needs to happen before we update slide visibility, // This needs to happen before we update slide visibility,
// otherwise transitions will still run in Safari. // otherwise transitions will still run in Safari.
if( previousSlide.hasAttribute( 'data-auto-animate' ) && currentSlide.hasAttribute( 'data-auto-animate' ) if( autoAnimateTransition ) {
&& previousSlide.getAttribute( 'data-auto-animate-id' ) === currentSlide.getAttribute( 'data-auto-animate-id' ) dom.slides.classList.add( 'disable-slide-transitions' )
&& !( ( indexh > indexhBefore || indexv > indexvBefore ) ? currentSlide : previousSlide ).hasAttribute( 'data-auto-animate-restart' ) ) {
autoAnimateTransition = true;
dom.slides.classList.add( 'disable-slide-transitions' );
} }
transition = 'running';
} }
// Update the visibility of slides now that the indices have changed // Update the visibility of slides now that the indices have changed
@@ -1409,16 +1500,7 @@ export default function( revealElement, options ) {
} }
if( slideChanged ) { if( slideChanged ) {
dispatchEvent({ dispatchSlideChanged( origin );
type: 'slidechanged',
data: {
indexh,
indexv,
previousSlide,
currentSlide,
origin
}
});
} }
// Handle embedded content // Handle embedded content
@@ -1463,6 +1545,71 @@ export default function( revealElement, options ) {
} }
/**
* Checks whether or not an auto-animation should take place between
* the two given slides.
*
* @param {HTMLElement} fromSlide
* @param {HTMLElement} toSlide
* @param {number} indexhBefore
* @param {number} indexvBefore
*
* @returns {boolean}
*/
function shouldAutoAnimateBetween( fromSlide, toSlide, indexhBefore, indexvBefore ) {
return fromSlide.hasAttribute( 'data-auto-animate' ) && toSlide.hasAttribute( 'data-auto-animate' ) &&
fromSlide.getAttribute( 'data-auto-animate-id' ) === toSlide.getAttribute( 'data-auto-animate-id' ) &&
!( ( indexh > indexhBefore || indexv > indexvBefore ) ? toSlide : fromSlide ).hasAttribute( 'data-auto-animate-restart' );
}
/**
* Called anytime a new slide should be activated while in the scroll
* view. The active slide is the page that occupies the most space in
* the scrollable viewport.
*
* @param {number} pageIndex
* @param {HTMLElement} slideElement
*/
function setCurrentScrollPage( slideElement, h, v ) {
let indexhBefore = indexh || 0;
indexh = h;
indexv = v;
const slideChanged = currentSlide !== slideElement;
previousSlide = currentSlide;
currentSlide = slideElement;
if( currentSlide && previousSlide ) {
if( config.autoAnimate && shouldAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexv ) ) {
// Run the auto-animation between our slides
autoAnimate.run( previousSlide, currentSlide );
}
}
// Start or stop embedded content like videos and iframes
if( slideChanged ) {
if( previousSlide ) {
slideContent.stopEmbeddedContent( previousSlide );
slideContent.stopEmbeddedContent( previousSlide.slideBackgroundElement );
}
slideContent.startEmbeddedContent( currentSlide );
slideContent.startEmbeddedContent( currentSlide.slideBackgroundElement );
}
requestAnimationFrame( () => {
announceStatus( getStatusText( currentSlide ) );
});
dispatchSlideChanged();
}
/** /**
* Syncs the presentation with the current DOM. Useful * Syncs the presentation with the current DOM. Useful
* when new slides or control elements are added or when * when new slides or control elements are added or when
@@ -1608,7 +1755,7 @@ export default function( revealElement, options ) {
let slides = Util.queryAll( dom.wrapper, selector ), let slides = Util.queryAll( dom.wrapper, selector ),
slidesLength = slides.length; slidesLength = slides.length;
let printMode = print.isPrintingPDF(); let printMode = scrollView.isActive() || printView.isActive();
let loopedForwards = false; let loopedForwards = false;
let loopedBackwards = false; let loopedBackwards = false;
@@ -1768,7 +1915,7 @@ export default function( revealElement, options ) {
} }
// All slides need to be visible when exporting to PDF // All slides need to be visible when exporting to PDF
if( print.isPrintingPDF() ) { if( printView.isActive() ) {
viewDistance = Number.MAX_VALUE; viewDistance = Number.MAX_VALUE;
} }
@@ -1999,21 +2146,31 @@ export default function( revealElement, options ) {
// If a slide is specified, return the indices of that slide // If a slide is specified, return the indices of that slide
if( slide ) { if( slide ) {
let isVertical = isVerticalSlide( slide ); // In scroll mode the original h/x index is stored on the slide
let slideh = isVertical ? slide.parentNode : slide; if( scrollView.isActive() ) {
h = parseInt( slide.getAttribute( 'data-index-h' ), 10 );
// Select all horizontal slides if( slide.getAttribute( 'data-index-v' ) ) {
let horizontalSlides = getHorizontalSlides(); v = parseInt( slide.getAttribute( 'data-index-v' ), 10 );
}
}
else {
let isVertical = isVerticalSlide( slide );
let slideh = isVertical ? slide.parentNode : slide;
// Now that we know which the horizontal slide is, get its index // Select all horizontal slides
h = Math.max( horizontalSlides.indexOf( slideh ), 0 ); let horizontalSlides = getHorizontalSlides();
// Assume we're not vertical // Now that we know which the horizontal slide is, get its index
v = undefined; h = Math.max( horizontalSlides.indexOf( slideh ), 0 );
// If this is a vertical slide, grab the vertical index // Assume we're not vertical
if( isVertical ) { v = undefined;
v = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );
// If this is a vertical slide, grab the vertical index
if( isVertical ) {
v = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );
}
} }
} }
@@ -2686,6 +2843,9 @@ export default function( revealElement, options ) {
// Toggles the overview mode on/off // Toggles the overview mode on/off
toggleOverview: overview.toggle.bind( overview ), toggleOverview: overview.toggle.bind( overview ),
// Toggles the scroll view on/off
toggleScrollView: scrollView.toggle.bind( scrollView ),
// Toggles the "black screen" mode on/off // Toggles the "black screen" mode on/off
togglePause, togglePause,
@@ -2700,6 +2860,7 @@ export default function( revealElement, options ) {
isLastSlide, isLastSlide,
isLastVerticalSlide, isLastVerticalSlide,
isVerticalSlide, isVerticalSlide,
isVerticalStack,
// State checks // State checks
isPaused, isPaused,
@@ -2707,7 +2868,9 @@ export default function( revealElement, options ) {
isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ), isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
isOverview: overview.isActive.bind( overview ), isOverview: overview.isActive.bind( overview ),
isFocused: focus.isFocused.bind( focus ), isFocused: focus.isFocused.bind( focus ),
isPrintingPDF: print.isPrintingPDF.bind( print ),
isScrollView: scrollView.isActive.bind( scrollView ),
isPrintView: printView.isActive.bind( printView ),
// Checks if reveal.js has been loaded and is ready for use // Checks if reveal.js has been loaded and is ready for use
isReady: () => ready, isReady: () => ready,
@@ -2780,6 +2943,8 @@ export default function( revealElement, options ) {
hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally, hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally,
hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically, hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically,
shouldAutoAnimateBetween,
// Adds/removes a custom key binding // Adds/removes a custom key binding
addKeyBinding: keyboard.addKeyBinding.bind( keyboard ), addKeyBinding: keyboard.addKeyBinding.bind( keyboard ),
removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ), removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),
@@ -2791,6 +2956,7 @@ export default function( revealElement, options ) {
registerKeyboardShortcut: keyboard.registerKeyboardShortcut.bind( keyboard ), registerKeyboardShortcut: keyboard.registerKeyboardShortcut.bind( keyboard ),
getComputedSlideSize, getComputedSlideSize,
setCurrentScrollPage,
// Returns the current scale of the presentation content // Returns the current scale of the presentation content
getScale: () => scale, getScale: () => scale,
@@ -2827,13 +2993,14 @@ export default function( revealElement, options ) {
getStatusText, getStatusText,
// Controllers // Controllers
print,
focus, focus,
scroll: scrollView,
progress, progress,
controls, controls,
location, location,
overview, overview,
fragments, fragments,
backgrounds,
slideContent, slideContent,
slideNumber, slideNumber,

581
package-lock.json generated
View File

@@ -42,12 +42,16 @@
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.12.13", "version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/highlight": "^7.12.13" "@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
},
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
@@ -105,14 +109,18 @@
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.14.3", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.14.2", "@babel/types": "^7.23.0",
"jsesc": "^2.5.1", "@jridgewell/gen-mapping": "^0.3.2",
"source-map": "^0.5.0" "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-annotate-as-pure": { "node_modules/@babel/helper-annotate-as-pure": {
@@ -198,6 +206,15 @@
"@babel/core": "^7.4.0-0" "@babel/core": "^7.4.0-0"
} }
}, },
"node_modules/@babel/helper-environment-visitor": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-explode-assignable-expression": { "node_modules/@babel/helper-explode-assignable-expression": {
"version": "7.13.0", "version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz",
@@ -208,33 +225,28 @@
} }
}, },
"node_modules/@babel/helper-function-name": { "node_modules/@babel/helper-function-name": {
"version": "7.14.2", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-get-function-arity": "^7.12.13", "@babel/template": "^7.22.15",
"@babel/template": "^7.12.13", "@babel/types": "^7.23.0"
"@babel/types": "^7.14.2" },
} "engines": {
}, "node": ">=6.9.0"
"node_modules/@babel/helper-get-function-arity": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
"integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
"dev": true,
"dependencies": {
"@babel/types": "^7.12.13"
} }
}, },
"node_modules/@babel/helper-hoist-variables": { "node_modules/@babel/helper-hoist-variables": {
"version": "7.13.16", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg==", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/traverse": "^7.13.15", "@babel/types": "^7.22.5"
"@babel/types": "^7.13.16" },
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-member-expression-to-functions": { "node_modules/@babel/helper-member-expression-to-functions": {
@@ -328,19 +340,34 @@
} }
}, },
"node_modules/@babel/helper-split-export-declaration": { "node_modules/@babel/helper-split-export-declaration": {
"version": "7.12.13", "version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.12.13" "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.14.0", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true "dev": true,
"engines": {
"node": ">=6.9.0"
}
}, },
"node_modules/@babel/helper-validator-option": { "node_modules/@babel/helper-validator-option": {
"version": "7.12.17", "version": "7.12.17",
@@ -372,20 +399,23 @@
} }
}, },
"node_modules/@babel/highlight": { "node_modules/@babel/highlight": {
"version": "7.14.0", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.14.0", "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.0.0", "chalk": "^2.4.2",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
},
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.14.3", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==", "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true, "dev": true,
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -1300,40 +1330,52 @@
} }
}, },
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.12.13", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.12.13", "@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.12.13", "@babel/parser": "^7.22.15",
"@babel/types": "^7.12.13" "@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.14.2", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.12.13", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.14.2", "@babel/generator": "^7.23.0",
"@babel/helper-function-name": "^7.14.2", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-split-export-declaration": "^7.12.13", "@babel/helper-function-name": "^7.23.0",
"@babel/parser": "^7.14.2", "@babel/helper-hoist-variables": "^7.22.5",
"@babel/types": "^7.14.2", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.0",
"@babel/types": "^7.23.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
},
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.14.2", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.14.0", "@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
},
"engines": {
"node": ">=6.9.0"
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
@@ -2197,26 +2239,35 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.19.3", "version": "4.21.10",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
"integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
"dev": true, "dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001312", "caniuse-lite": "^1.0.30001517",
"electron-to-chromium": "^1.4.71", "electron-to-chromium": "^1.4.477",
"escalade": "^3.1.1", "node-releases": "^2.0.13",
"node-releases": "^2.0.2", "update-browserslist-db": "^1.0.11"
"picocolors": "^1.0.0"
}, },
"bin": { "bin": {
"browserslist": "cli.js" "browserslist": "cli.js"
}, },
"engines": { "engines": {
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
} }
}, },
"node_modules/buffer": { "node_modules/buffer": {
@@ -2337,9 +2388,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001374", "version": "1.0.30001538",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==", "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -2349,6 +2400,10 @@
{ {
"type": "tidelift", "type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite" "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
} }
] ]
}, },
@@ -2854,28 +2909,18 @@
} }
}, },
"node_modules/core-js-compat": { "node_modules/core-js-compat": {
"version": "3.12.1", "version": "3.32.2",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
"integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==", "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"browserslist": "^4.16.6", "browserslist": "^4.21.10"
"semver": "7.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
"url": "https://opencollective.com/core-js" "url": "https://opencollective.com/core-js"
} }
}, },
"node_modules/core-js-compat/node_modules/semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/core-util-is": { "node_modules/core-util-is": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -3155,9 +3200,9 @@
"dev": true "dev": true
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.73", "version": "1.4.526",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.526.tgz",
"integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==", "integrity": "sha512-tjjTMjmZAx1g6COrintLTa2/jcafYKxKoiEkdQOrVdbLaHh2wCt2nsAF8ZHweezkrP+dl/VG9T5nabcYoo0U5Q==",
"dev": true "dev": true
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
@@ -3476,9 +3521,9 @@
} }
}, },
"node_modules/eslint/node_modules/semver": { "node_modules/eslint/node_modules/semver": {
"version": "7.3.5", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -4754,9 +4799,9 @@
} }
}, },
"node_modules/gulp-eslint/node_modules/cross-spawn/node_modules/semver": { "node_modules/gulp-eslint/node_modules/cross-spawn/node_modules/semver": {
"version": "5.7.1", "version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true, "dev": true,
"bin": { "bin": {
"semver": "bin/semver" "semver": "bin/semver"
@@ -6451,10 +6496,16 @@
"dev": true "dev": true
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.1", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true, "dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": { "bin": {
"nanoid": "bin/nanoid.cjs" "nanoid": "bin/nanoid.cjs"
}, },
@@ -6591,9 +6642,9 @@
} }
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.2", "version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true "dev": true
}, },
"node_modules/node-watch": { "node_modules/node-watch": {
@@ -6618,9 +6669,9 @@
} }
}, },
"node_modules/normalize-package-data/node_modules/semver": { "node_modules/normalize-package-data/node_modules/semver": {
"version": "5.7.1", "version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true, "dev": true,
"bin": { "bin": {
"semver": "bin/semver" "semver": "bin/semver"
@@ -7251,21 +7302,31 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.7", "version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true, "dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": { "dependencies": {
"nanoid": "^3.3.1", "nanoid": "^3.3.6",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"source-map-js": "^1.0.2" "source-map-js": "^1.0.2"
}, },
"engines": { "engines": {
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
} }
}, },
"node_modules/postcss-value-parser": { "node_modules/postcss-value-parser": {
@@ -7966,9 +8027,9 @@
} }
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.0", "version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true, "dev": true,
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
@@ -9406,6 +9467,36 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/update-browserslist-db": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.12.tgz",
"integrity": "sha512-tE1smlR58jxbFMtrMpFNRmsrOXlpNXss965T1CrpwuZUzUAg/TBQc94SpyhDLSzrqrJS9xTRBthnZAGcE1oaxg==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
},
"bin": {
"update-browserslist-db": "cli.js"
},
"peerDependencies": {
"browserslist": ">= 4.21.0"
}
},
"node_modules/uri-js": { "node_modules/uri-js": {
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -9629,9 +9720,9 @@
"dev": true "dev": true
}, },
"node_modules/word-wrap": { "node_modules/word-wrap": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@@ -9802,12 +9893,13 @@
}, },
"dependencies": { "dependencies": {
"@babel/code-frame": { "@babel/code-frame": {
"version": "7.12.13", "version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/highlight": "^7.12.13" "@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
} }
}, },
"@babel/compat-data": { "@babel/compat-data": {
@@ -9851,14 +9943,15 @@
} }
}, },
"@babel/generator": { "@babel/generator": {
"version": "7.14.3", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/types": "^7.14.2", "@babel/types": "^7.23.0",
"jsesc": "^2.5.1", "@jridgewell/gen-mapping": "^0.3.2",
"source-map": "^0.5.0" "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
} }
}, },
"@babel/helper-annotate-as-pure": { "@babel/helper-annotate-as-pure": {
@@ -9932,6 +10025,12 @@
"semver": "^6.1.2" "semver": "^6.1.2"
} }
}, },
"@babel/helper-environment-visitor": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true
},
"@babel/helper-explode-assignable-expression": { "@babel/helper-explode-assignable-expression": {
"version": "7.13.0", "version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz",
@@ -9942,33 +10041,22 @@
} }
}, },
"@babel/helper-function-name": { "@babel/helper-function-name": {
"version": "7.14.2", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/helper-get-function-arity": "^7.12.13", "@babel/template": "^7.22.15",
"@babel/template": "^7.12.13", "@babel/types": "^7.23.0"
"@babel/types": "^7.14.2"
}
},
"@babel/helper-get-function-arity": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
"integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
"dev": true,
"requires": {
"@babel/types": "^7.12.13"
} }
}, },
"@babel/helper-hoist-variables": { "@babel/helper-hoist-variables": {
"version": "7.13.16", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg==", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/traverse": "^7.13.15", "@babel/types": "^7.22.5"
"@babel/types": "^7.13.16"
} }
}, },
"@babel/helper-member-expression-to-functions": { "@babel/helper-member-expression-to-functions": {
@@ -10062,18 +10150,24 @@
} }
}, },
"@babel/helper-split-export-declaration": { "@babel/helper-split-export-declaration": {
"version": "7.12.13", "version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/types": "^7.12.13" "@babel/types": "^7.22.5"
} }
}, },
"@babel/helper-string-parser": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"dev": true
},
"@babel/helper-validator-identifier": { "@babel/helper-validator-identifier": {
"version": "7.14.0", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true "dev": true
}, },
"@babel/helper-validator-option": { "@babel/helper-validator-option": {
@@ -10106,20 +10200,20 @@
} }
}, },
"@babel/highlight": { "@babel/highlight": {
"version": "7.14.0", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.14.0", "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.0.0", "chalk": "^2.4.2",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.14.3", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==", "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true "dev": true
}, },
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
@@ -10833,39 +10927,42 @@
} }
}, },
"@babel/template": { "@babel/template": {
"version": "7.12.13", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "^7.12.13", "@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.12.13", "@babel/parser": "^7.22.15",
"@babel/types": "^7.12.13" "@babel/types": "^7.22.15"
} }
}, },
"@babel/traverse": { "@babel/traverse": {
"version": "7.14.2", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "^7.12.13", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.14.2", "@babel/generator": "^7.23.0",
"@babel/helper-function-name": "^7.14.2", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-split-export-declaration": "^7.12.13", "@babel/helper-function-name": "^7.23.0",
"@babel/parser": "^7.14.2", "@babel/helper-hoist-variables": "^7.22.5",
"@babel/types": "^7.14.2", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.0",
"@babel/types": "^7.23.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
} }
}, },
"@babel/types": { "@babel/types": {
"version": "7.14.2", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.14.0", "@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
@@ -11529,16 +11626,15 @@
} }
}, },
"browserslist": { "browserslist": {
"version": "4.19.3", "version": "4.21.10",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
"integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"caniuse-lite": "^1.0.30001312", "caniuse-lite": "^1.0.30001517",
"electron-to-chromium": "^1.4.71", "electron-to-chromium": "^1.4.477",
"escalade": "^3.1.1", "node-releases": "^2.0.13",
"node-releases": "^2.0.2", "update-browserslist-db": "^1.0.11"
"picocolors": "^1.0.0"
} }
}, },
"buffer": { "buffer": {
@@ -11621,9 +11717,9 @@
"dev": true "dev": true
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30001374", "version": "1.0.30001538",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==", "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==",
"dev": true "dev": true
}, },
"chalk": { "chalk": {
@@ -12036,21 +12132,12 @@
"dev": true "dev": true
}, },
"core-js-compat": { "core-js-compat": {
"version": "3.12.1", "version": "3.32.2",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
"integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==", "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"browserslist": "^4.16.6", "browserslist": "^4.21.10"
"semver": "7.0.0"
},
"dependencies": {
"semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true
}
} }
}, },
"core-util-is": { "core-util-is": {
@@ -12277,9 +12364,9 @@
"dev": true "dev": true
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.4.73", "version": "1.4.526",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.526.tgz",
"integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==", "integrity": "sha512-tjjTMjmZAx1g6COrintLTa2/jcafYKxKoiEkdQOrVdbLaHh2wCt2nsAF8ZHweezkrP+dl/VG9T5nabcYoo0U5Q==",
"dev": true "dev": true
}, },
"emoji-regex": { "emoji-regex": {
@@ -12505,9 +12592,9 @@
"peer": true "peer": true
}, },
"semver": { "semver": {
"version": "7.3.5", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"requires": { "requires": {
@@ -13577,9 +13664,9 @@
}, },
"dependencies": { "dependencies": {
"semver": { "semver": {
"version": "5.7.1", "version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true "dev": true
} }
} }
@@ -14919,9 +15006,9 @@
"dev": true "dev": true
}, },
"nanoid": { "nanoid": {
"version": "3.3.1", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true "dev": true
}, },
"nanomatch": { "nanomatch": {
@@ -15023,9 +15110,9 @@
} }
}, },
"node-releases": { "node-releases": {
"version": "2.0.2", "version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true "dev": true
}, },
"node-watch": { "node-watch": {
@@ -15047,9 +15134,9 @@
}, },
"dependencies": { "dependencies": {
"semver": { "semver": {
"version": "5.7.1", "version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true "dev": true
} }
} }
@@ -15520,12 +15607,12 @@
"dev": true "dev": true
}, },
"postcss": { "postcss": {
"version": "8.4.7", "version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"nanoid": "^3.3.1", "nanoid": "^3.3.6",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"source-map-js": "^1.0.2" "source-map-js": "^1.0.2"
} }
@@ -16081,9 +16168,9 @@
} }
}, },
"semver": { "semver": {
"version": "6.3.0", "version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true "dev": true
}, },
"semver-greatest-satisfied-range": { "semver-greatest-satisfied-range": {
@@ -17299,6 +17386,16 @@
} }
} }
}, },
"update-browserslist-db": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.12.tgz",
"integrity": "sha512-tE1smlR58jxbFMtrMpFNRmsrOXlpNXss965T1CrpwuZUzUAg/TBQc94SpyhDLSzrqrJS9xTRBthnZAGcE1oaxg==",
"dev": true,
"requires": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
}
},
"uri-js": { "uri-js": {
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -17487,9 +17584,9 @@
"dev": true "dev": true
}, },
"word-wrap": { "word-wrap": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true "dev": true
}, },
"wrap-ansi": { "wrap-ansi": {

115
test/test-scroll.html Normal file
View File

@@ -0,0 +1,115 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - Test Scroll View</title>
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css">
<script src="../node_modules/qunit/qunit/qunit.js"></script>
</head>
<body style="overflow: auto;">
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<div class="reveal" style="opacity: 0; pointer-events: none;">
<div class="slides">
<section>
<h1>slide 1</h1>
</section>
<section>
<h1>slide 2</h1>
</section>
<section>
<h1>slide 3</h1>
<p class="fragment">fragment 1</p>
<p class="fragment">fragment 2</p>
<p class="fragment">fragment 3</p>
</section>
<section>
<h1>slide 4</h1>
</section>
</div>
</div>
<script src="../dist/reveal.js"></script>
<script>
QUnit.config.testTimeout = 30000;
QUnit.config.reorder = false;
function getScrollHeight() {
return Reveal.getViewportElement().scrollHeight;
}
function getViewportHeight() {
return Reveal.getViewportElement().offsetHeight;
}
Reveal.initialize({ view: 'scroll' }).then( async () => {
QUnit.module( 'Scroll View' );
QUnit.test( 'Activates', assert => {
assert.ok( getScrollHeight() > getViewportHeight(), 'Is overflowing' );
});
QUnit.test( 'Can be toggled via API', assert => {
Reveal.toggleScrollView( false );
assert.ok( getScrollHeight() <= getViewportHeight(), 'Is not overflowing' );
Reveal.toggleScrollView( true );
assert.ok( getScrollHeight() > getViewportHeight(), 'Is overflowing' );
});
QUnit.test( 'Changes present slide when scrolling', assert => {
assert.timeout( 200 );
assert.expect( 2 );
const slides = document.querySelectorAll( '.reveal .slides section' );
assert.ok( slides[0].classList.contains( 'present' ), 'First slide is present' );
Reveal.getViewportElement().scrollTop = getViewportHeight() * 1;
return new Promise( resolve => {
setTimeout(() => {
assert.ok( slides[1].classList.contains( 'present' ), 'Second slide is present' );
resolve();
}, 100);
} );
});
QUnit.test( 'Fires slideschanged event when scrolling', assert => {
assert.timeout( 200 );
assert.expect( 2 );
const slides = document.querySelectorAll( '.reveal .slides section' );
return new Promise( resolve => {
let callback = ( event ) => {
Reveal.off( 'slidechanged', callback );
assert.ok( true, 'slidechanged event fired' );
assert.ok( event.currentSlide.classList.contains( 'present' ), 'slidechanged provides reference to currentSlide' );
resolve();
}
Reveal.on( 'slidechanged', callback );
Reveal.getViewportElement().scrollTop = getViewportHeight() * 2;
});
});
} );
</script>
</body>
</html>