aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/App.vue217
-rw-r--r--src/components/AncestryBar.vue50
-rw-r--r--src/components/SearchModal.vue2
-rw-r--r--src/components/TutorialPane.vue25
-rw-r--r--src/lib.ts18
5 files changed, 105 insertions, 207 deletions
diff --git a/src/App.vue b/src/App.vue
index 4cc7aa0..e9db4c9 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -18,7 +18,7 @@ import type {TolMap} from './tol';
import {TolNode} from './tol';
import {LayoutNode, initLayoutTree, initLayoutMap, tryLayout} from './layout';
import type {LayoutOptions, LayoutTreeChg} from './layout';
-import {arraySum, randWeightedChoice, getScrollBarWidth} from './lib';
+import {arraySum, randWeightedChoice} from './lib';
import type {Action} from './lib';
// Note: Import paths lack a .ts or .js extension because .ts makes vue-tsc complain, and .js makes vite complain
@@ -78,8 +78,7 @@ const defaultUiOpts = {
// For other components
appBgColor: '#292524',
tileAreaOffset: 5, //px (space between root tile and display boundary)
- scrollGap: getScrollBarWidth(), //px (gap for overflown-root and ancestry-bar scrollbars, used to prevent overlap)
- ancestryBarSz: defaultLytOpts.minTileSz * 2, //px (breadth of ancestry-bar area)
+ ancestryBarImgSz: defaultLytOpts.minTileSz * 2, //px
ancestryBarBgColor: '#44403c',
ancestryTileMargin: 5, //px (gap between detached-ancestor tiles)
infoModalImgSz: 200,
@@ -123,18 +122,15 @@ export default defineComponent({
// Options
lytOpts: this.getLytOpts(),
uiOpts: this.getUiOpts(),
- // For window-resize handling
- width: document.documentElement.clientWidth,
- height: document.documentElement.clientHeight,
+ // For layout and resize-handling
+ mainAreaDims: [0, 0] as [number, number],
+ tileAreaDims: [0, 0] as [number, number],
pendingResizeHdlr: 0, // Set to a setTimeout() value
// Other
excessTolNodeThreshold: 1000, // Threshold where excess tolMap entries are removed (done on tile collapse)
};
},
computed: {
- wideArea(): boolean {
- return this.width >= this.height;
- },
// Nodes to show in ancestry-bar, with tol root first
detachedAncestors(): LayoutNode[] | null {
if (this.activeRoot == this.layoutTree){
@@ -148,59 +144,6 @@ export default defineComponent({
}
return ancestors.reverse();
},
- // Placement info for Tile and AncestryBar
- tileAreaPos(){
- let pos = [this.uiOpts.tileAreaOffset, this.uiOpts.tileAreaOffset] as [number, number];
- if (this.detachedAncestors != null){
- if (this.wideArea){
- pos[0] += this.uiOpts.ancestryBarSz;
- } else {
- pos[1] += this.uiOpts.ancestryBarSz;
- }
- }
- if (this.tutorialOpen){
- pos[1] += this.uiOpts.tutorialPaneSz;
- }
- return pos;
- },
- tileAreaDims(){
- let dims = [
- this.width - this.uiOpts.tileAreaOffset*2,
- this.height - this.uiOpts.tileAreaOffset*2
- ] as [number, number];
- if (this.detachedAncestors != null){
- if (this.wideArea){
- dims[0] -= this.uiOpts.ancestryBarSz;
- } else {
- dims[1] -= this.uiOpts.ancestryBarSz;
- }
- }
- if (this.tutorialOpen){
- dims[1] -= this.uiOpts.tutorialPaneSz;
- }
- return dims;
- },
- ancestryBarPos(): [number, number] {
- let pos = [0, 0] as [number, number];
- if (this.tutorialOpen){
- pos[1] += this.uiOpts.tutorialPaneSz;
- }
- return pos;
- },
- ancestryBarDims(): [number, number] {
- if (this.wideArea){
- let dims = [this.uiOpts.ancestryBarSz, this.height] as [number, number];
- if (this.tutorialOpen){
- dims[1] -= this.uiOpts.tutorialPaneSz;
- }
- return dims;
- } else {
- return [this.width, this.uiOpts.ancestryBarSz];
- }
- },
- tutorialPaneDims(): [number, number] {
- return [this.width, this.uiOpts.tutorialPaneSz];
- },
},
methods: {
// For tile expand/collapse events
@@ -221,12 +164,10 @@ export default defineComponent({
chg: {type: 'expand', node: layoutNode, tolMap: this.tolMap} as LayoutTreeChg,
layoutMap: this.layoutMap
};
- let success = tryLayout(
- this.activeRoot, this.tileAreaPos, this.tileAreaDims, this.lytOpts, lytFnOpts);
+ let success = tryLayout(this.activeRoot, [0,0], this.tileAreaDims, this.lytOpts, lytFnOpts);
// If expanding active-root with too many children to fit, allow overflow
if (!success && layoutNode == this.activeRoot){
- success = tryLayout(this.activeRoot, this.tileAreaPos,
- [this.tileAreaDims[0] - this.uiOpts.scrollGap, this.tileAreaDims[1]],
+ success = tryLayout(this.activeRoot, [0,0], this.tileAreaDims,
{...this.lytOpts, layoutType: 'flex-sqr'}, lytFnOpts);
if (success){
this.overflownRoot = true;
@@ -261,7 +202,7 @@ export default defineComponent({
return false;
}
this.setLastFocused(null);
- let success = tryLayout(this.activeRoot, this.tileAreaPos, this.tileAreaDims, this.lytOpts, {
+ let success = tryLayout(this.activeRoot, [0,0], this.tileAreaDims, this.lytOpts, {
allowCollapse: false,
chg: {type: 'collapse', node: layoutNode, tolMap: this.tolMap},
layoutMap: this.layoutMap
@@ -301,27 +242,27 @@ export default defineComponent({
let doExpansion = () => {
LayoutNode.hideUpward(layoutNode, this.layoutMap);
this.activeRoot = layoutNode;
- this.overflownRoot = false;
- let lytFnOpts = {
- allowCollapse: false,
- chg: {type: 'expand', node: layoutNode, tolMap: this.tolMap} as LayoutTreeChg,
- layoutMap: this.layoutMap
- };
- let success = tryLayout(
- this.activeRoot, this.tileAreaPos, this.tileAreaDims, this.lytOpts, lytFnOpts);
- if (!success){
- success = tryLayout(this.activeRoot, this.tileAreaPos,
- [this.tileAreaDims[0] - this.uiOpts.scrollGap, this.tileAreaDims[1]],
- {...this.lytOpts, layoutType: 'flex-sqr'}, lytFnOpts);
- if (success){
- this.overflownRoot = true;
+ return this.updateAreaDims().then(() => {
+ this.overflownRoot = false;
+ let lytFnOpts = {
+ allowCollapse: false,
+ chg: {type: 'expand', node: layoutNode, tolMap: this.tolMap} as LayoutTreeChg,
+ layoutMap: this.layoutMap
+ };
+ let success = tryLayout(this.activeRoot, [0,0], this.tileAreaDims, this.lytOpts, lytFnOpts);
+ if (!success){
+ success = tryLayout(this.activeRoot, [0,0], this.tileAreaDims,
+ {...this.lytOpts, layoutType: 'flex-sqr'}, lytFnOpts);
+ if (success){
+ this.overflownRoot = true;
+ }
}
- }
- // Check for failure
- if (!success){
- layoutNode.failFlag = !layoutNode.failFlag; // Triggers failure animation
- }
- return success;
+ // Check for failure
+ if (!success){
+ layoutNode.failFlag = !layoutNode.failFlag; // Triggers failure animation
+ }
+ return success;
+ });
};
// Check if data for node-to-expand exists, getting from server if needed
let tolNode = this.tolMap.get(layoutNode.name)!;
@@ -330,15 +271,13 @@ export default defineComponent({
urlPath += this.uiOpts.useReducedTree ? '&tree=reduced' : '';
return fetch(urlPath)
.then(response => response.json())
- .then(obj => {
- Object.getOwnPropertyNames(obj).forEach(key => {this.tolMap.set(key, obj[key])});
- doExpansion();
- })
+ .then(obj => {Object.getOwnPropertyNames(obj).forEach(key => {this.tolMap.set(key, obj[key])})})
+ .then(doExpansion)
.catch(error => {
console.log('ERROR loading tolnode data', error);
});
} else {
- return new Promise((resolve, reject) => resolve(doExpansion()));
+ return doExpansion();
}
},
onNonleafClickHeld(layoutNode: LayoutNode){
@@ -352,7 +291,7 @@ export default defineComponent({
}
LayoutNode.hideUpward(layoutNode, this.layoutMap);
this.activeRoot = layoutNode;
- this.relayoutWithCollapse();
+ this.updateAreaDims().then(() => this.relayoutWithCollapse());
},
onDetachedAncestorClick(layoutNode: LayoutNode){
if (!this.handleActionForTutorial('unhideAncestor')){
@@ -361,8 +300,7 @@ export default defineComponent({
this.setLastFocused(null);
LayoutNode.showDownward(layoutNode);
this.activeRoot = layoutNode;
- this.relayoutWithCollapse();
- this.overflownRoot = false;
+ this.updateAreaDims().then(() => this.relayoutWithCollapse());
},
// For tile-info events
onInfoIconClick(nodeName: string){
@@ -618,14 +556,14 @@ export default defineComponent({
onStartTutorial(){
if (this.tutorialOpen == false){
this.tutorialOpen = true;
- this.relayoutWithCollapse();
+ this.updateAreaDims().then(() => this.relayoutWithCollapse());
}
},
onTutorialClose(){
this.tutorialOpen = false;
this.welcomeOpen = false;
this.disabledActions.clear();
- this.relayoutWithCollapse();
+ this.updateAreaDims().then(() => this.relayoutWithCollapse());
},
onTutStageChg(disabledActions: Set<Action>, triggerAction: Action | null){
this.welcomeOpen = false;
@@ -651,12 +589,10 @@ export default defineComponent({
onResize(){
if (this.pendingResizeHdlr == 0){
this.pendingResizeHdlr = setTimeout(() => {
- this.width = document.documentElement.clientWidth;
- this.height = document.documentElement.clientHeight;
- this.uiOpts.scrollGap = getScrollBarWidth();
- this.relayoutWithCollapse();
- this.overflownRoot = false;
- this.pendingResizeHdlr = 0;
+ this.updateAreaDims().then(() => {
+ this.relayoutWithCollapse();
+ this.pendingResizeHdlr = 0;
+ });
}, 100);
}
},
@@ -683,7 +619,7 @@ export default defineComponent({
this.layoutTree = initLayoutTree(this.tolMap, this.layoutTree.name, 0);
this.activeRoot = this.layoutTree;
this.layoutMap = initLayoutMap(this.layoutTree);
- this.relayoutWithCollapse();
+ this.updateAreaDims().then(() => this.relayoutWithCollapse());
})
.catch(error => {
console.log('ERROR loading initial tolnode data', error);
@@ -737,17 +673,27 @@ export default defineComponent({
}
},
relayoutWithCollapse(){
- tryLayout(this.activeRoot, this.tileAreaPos, this.tileAreaDims, this.lytOpts,
+ tryLayout(this.activeRoot, [0,0], this.tileAreaDims, this.lytOpts,
{allowCollapse: true, layoutMap: this.layoutMap});
// Relayout again to allocate remaining tiles 'evenly'
- tryLayout(this.activeRoot, this.tileAreaPos, this.tileAreaDims, this.lytOpts,
+ tryLayout(this.activeRoot, [0,0], this.tileAreaDims, this.lytOpts,
{allowCollapse: false, layoutMap: this.layoutMap});
+ this.overflownRoot = false;
+ },
+ updateAreaDims(){
+ console.log('updating dims')
+ let mainAreaEl = this.$refs.mainArea as HTMLElement;
+ this.mainAreaDims = [mainAreaEl.offsetWidth, mainAreaEl.offsetHeight];
+ // Need to wait until ancestor-bar is laid-out before computing tileAreaDims
+ return this.$nextTick(() => {
+ let tileAreaEl = this.$refs.tileArea as HTMLElement;
+ this.tileAreaDims = [tileAreaEl.offsetWidth, tileAreaEl.offsetHeight];
+ });
},
},
created(){
window.addEventListener('resize', this.onResize);
window.addEventListener('keyup', this.onKeyUp);
- this.relayoutWithCollapse();
this.initTreeFromServer();
},
unmounted(){
@@ -763,33 +709,36 @@ export default defineComponent({
</script>
<template>
-<div class="absolute left-0 top-0 w-screen h-screen overflow-hidden" :style="{backgroundColor: uiOpts.appBgColor}">
- <!-- Note: Making the above enclosing div's width/height dynamic seems to cause white flashes when resizing -->
- <tile :layoutNode="layoutTree" :tolMap="tolMap" :lytOpts="lytOpts" :uiOpts="uiOpts"
- :overflownDim="overflownRoot ? tileAreaDims[1] : 0"
- @leaf-click="onLeafClick" @nonleaf-click="onNonleafClick"
- @leaf-click-held="onLeafClickHeld" @nonleaf-click-held="onNonleafClickHeld"
- @info-icon-click="onInfoIconClick"/>
- <ancestry-bar v-if="detachedAncestors != null"
- :pos="ancestryBarPos" :dims="ancestryBarDims" :nodes="detachedAncestors"
- :tolMap="tolMap" :lytOpts="lytOpts" :uiOpts="uiOpts"
- @detached-ancestor-click="onDetachedAncestorClick" @info-icon-click="onInfoIconClick"/>
- <tutorial-pane v-if="tutorialOpen"
- :pos="[0,0]" :dims="tutorialPaneDims" :uiOpts="uiOpts" :triggerFlag="tutTriggerFlag"
- :skipWelcome="!welcomeOpen" @tutorial-close="onTutorialClose" @tutorial-stage-chg="onTutStageChg"/>
- <!-- Icons -->
- <search-icon @click="onSearchIconClick"
- class="absolute bottom-[6px] right-[78px] w-[18px] h-[18px]
- text-white/40 hover:text-white hover:cursor-pointer"/>
- <play-icon @click="onPlayIconClick"
- class="absolute bottom-[6px] right-[54px] w-[18px] h-[18px]
- text-white/40 hover:text-white hover:cursor-pointer"/>
- <settings-icon @click="onSettingsIconClick"
- class="absolute bottom-[6px] right-[30px] w-[18px] h-[18px]
- text-white/40 hover:text-white hover:cursor-pointer"/>
- <help-icon @click="onHelpIconClick"
- class="absolute bottom-[6px] right-[6px] w-[18px] h-[18px]
- text-white/40 hover:text-white hover:cursor-pointer"/>
+<div class="absolute left-0 top-0 w-screen h-screen overflow-hidden flex flex-col"
+ :style="{backgroundColor: uiOpts.appBgColor}">
+ <div class="flex bg-black">
+ <h1 class="text-white text-bold px-2">Title</h1>
+ <!-- Icons -->
+ <search-icon @click="onSearchIconClick"
+ class="ml-auto mr-[6px] my-[6px] w-[18px] h-[18px] text-white/40 hover:text-white hover:cursor-pointer"/>
+ <play-icon @click="onPlayIconClick"
+ class="mr-[6px] my-[6px] w-[18px] h-[18px] text-white/40 hover:text-white hover:cursor-pointer"/>
+ <settings-icon @click="onSettingsIconClick"
+ class="mr-[6px] my-[6px] w-[18px] h-[18px] text-white/40 hover:text-white hover:cursor-pointer"/>
+ <help-icon @click="onHelpIconClick"
+ class="mr-[6px] my-[6px] w-[18px] h-[18px] text-white/40 hover:text-white hover:cursor-pointer"/>
+ </div>
+ <tutorial-pane v-if="tutorialOpen" :height="uiOpts.tutorialPaneSz + 'px'" class="grow-0 shrink-0"
+ :uiOpts="uiOpts" :triggerFlag="tutTriggerFlag" :skipWelcome="!welcomeOpen"
+ @tutorial-close="onTutorialClose" @tutorial-stage-chg="onTutStageChg"/>
+ <div :class="['flex', mainAreaDims[0] > mainAreaDims[1] ? 'flex-row' : 'flex-col', 'grow', 'min-h-0']" ref="mainArea">
+ <ancestry-bar v-if="detachedAncestors != null"
+ :nodes="detachedAncestors" :vert="mainAreaDims[0] > mainAreaDims[1]"
+ :tolMap="tolMap" :lytOpts="lytOpts" :uiOpts="uiOpts"
+ @detached-ancestor-click="onDetachedAncestorClick" @info-icon-click="onInfoIconClick"/>
+ <div class="relative m-[5px] grow" ref="tileArea">
+ <tile :layoutNode="layoutTree" :tolMap="tolMap" :lytOpts="lytOpts" :uiOpts="uiOpts"
+ :overflownDim="overflownRoot ? mainAreaDims[1] : 0"
+ @leaf-click="onLeafClick" @nonleaf-click="onNonleafClick"
+ @leaf-click-held="onLeafClickHeld" @nonleaf-click-held="onNonleafClickHeld"
+ @info-icon-click="onInfoIconClick"/>
+ </div>
+ </div>
<!-- Modals -->
<transition name="fade">
<tile-info-modal v-if="infoModalNodeName != null"
diff --git a/src/components/AncestryBar.vue b/src/components/AncestryBar.vue
index 66c1b13..8f31900 100644
--- a/src/components/AncestryBar.vue
+++ b/src/components/AncestryBar.vue
@@ -8,57 +8,29 @@ import type {TolMap} from '../tol';
// Displays a sequence of nodes, representing ancestors from a tree-of-life root to a currently-active root
export default defineComponent({
props: {
- // For absolute positioning
- pos: {type: Array as unknown as PropType<[number,number]>, required: true},
- dims: {type: Array as unknown as PropType<[number,number]>, required: true},
- // The ancestors to display
nodes: {type: Array as PropType<LayoutNode[]>, required: true},
+ vert: {type: Boolean, default: false},
// Other
tolMap: {type: Object as PropType<TolMap>, required: true},
lytOpts: {type: Object as PropType<LayoutOptions>, required: true},
uiOpts: {type: Object, required: true},
},
computed: {
- wideArea(){
- return this.dims[0] >= this.dims[1];
- },
- tileSz(){
- return (this.wideArea ? this.dims[1] : this.dims[0]) -
- (this.uiOpts.ancestryTileMargin * 2) - this.uiOpts.scrollGap;
- },
usedNodes(){ // Childless versions of 'nodes' used to parameterise <tile>
return this.nodes.map(n => {
let newNode = new LayoutNode(n.name, []);
- newNode.dims = [this.tileSz, this.tileSz];
+ newNode.dims = [this.uiOpts.ancestryBarImgSz, this.uiOpts.ancestryBarImgSz];
return newNode;
});
},
- overflowing(){
- let len = this.uiOpts.ancestryTileMargin +
- (this.tileSz + this.uiOpts.ancestryTileMargin) * this.nodes.length;
- return len > (this.wideArea ? this.dims[0] : this.dims[1]);
- },
- width(){
- return this.dims[0] + (this.wideArea || this.overflowing ? 0 : -this.uiOpts.scrollGap);
- },
- height(){
- return this.dims[1] + (!this.wideArea || this.overflowing ? 0 : -this.uiOpts.scrollGap);
- },
styles(): Record<string,string> {
return {
- position: 'absolute',
- left: this.pos[0] + 'px',
- top: this.pos[1] + 'px',
- width: this.width + 'px',
- height: this.height + 'px',
- overflowX: this.wideArea ? 'auto' : 'hidden',
- overflowY: this.wideArea ? 'hidden' : 'auto',
- // Extra padding for scrollbar inclusion
- paddingRight: (this.overflowing && !this.wideArea ? this.uiOpts.scrollGap : 0) + 'px',
- paddingBottom: (this.overflowing && this.wideArea ? this.uiOpts.scrollGap : 0) + 'px',
+ overflowX: this.vert ? 'hidden' : 'auto',
+ overflowY: this.vert ? 'auto' : 'hidden',
+ maxHeight: '100vh',
// For child layout
display: 'flex',
- flexDirection: this.wideArea ? 'row' : 'column',
+ flexDirection: this.vert ? 'column' : 'row',
gap: this.uiOpts.ancestryTileMargin + 'px',
padding: this.uiOpts.ancestryTileMargin + 'px',
// Other
@@ -71,7 +43,7 @@ export default defineComponent({
nodes(){
setTimeout(() => this.scrollToEnd(), 0); // Without timeout, seems to run before new tiles are added
},
- wideArea(){
+ vert(){
setTimeout(() => this.scrollToEnd(), 0);
},
},
@@ -84,15 +56,15 @@ export default defineComponent({
},
onWheelEvt(evt: WheelEvent){
// Possibly convert vertical scroll to horizontal
- if (this.wideArea && Math.abs(evt.deltaX) < Math.abs(evt.deltaY)){
+ if (!this.vert && Math.abs(evt.deltaX) < Math.abs(evt.deltaY)){
this.$el.scrollLeft -= (evt.deltaY > 0 ? 30 : -30);
}
},
scrollToEnd(){
- if (this.wideArea){
- this.$el.scrollLeft = this.$el.scrollWidth;
- } else {
+ if (this.vert){
this.$el.scrollTop = this.$el.scrollHeight;
+ } else {
+ this.$el.scrollLeft = this.$el.scrollWidth;
}
},
},
diff --git a/src/components/SearchModal.vue b/src/components/SearchModal.vue
index 35efb55..e5e8596 100644
--- a/src/components/SearchModal.vue
+++ b/src/components/SearchModal.vue
@@ -16,7 +16,7 @@ export default defineComponent({
searchHasMoreSuggs: false,
focusedSuggIdx: null as null | number, // Denotes a search-suggestion selected using the arrow keys
pendingSuggReq: 0, // Set via setTimeout() upon a search-suggestion request
- pendingSuggReqUrl: null, // Used by a pendingSuggReq callback to use the latest user input
+ pendingSuggReqUrl: '', // Used by a pendingSuggReq callback to use the latest user input
};
},
props: {
diff --git a/src/components/TutorialPane.vue b/src/components/TutorialPane.vue
index c04aeee..d5f681c 100644
--- a/src/components/TutorialPane.vue
+++ b/src/components/TutorialPane.vue
@@ -5,11 +5,10 @@ import {Action} from '../lib';
export default defineComponent({
props: {
- pos: {type: Array as unknown as PropType<[number,number]>, required: true},
- dims: {type: Array as unknown as PropType<[number,number]>, required: true},
uiOpts: {type: Object, required: true},
triggerFlag: {type: Boolean, required: true},
skipWelcome: {type: Boolean, default: false},
+ height: {type: String, default: 'auto'},
},
data(){
return {
@@ -20,13 +19,9 @@ export default defineComponent({
computed: {
styles(): Record<string,string> {
return {
- position: 'absolute',
- left: this.pos[0] + 'px',
- top: this.pos[1] + 'px',
- width: this.dims[0] + 'px',
- height: this.dims[1] + 'px',
backgroundColor: this.uiOpts.tutorialPaneBgColor,
color: this.uiOpts.tutorialPaneTextColor,
+ height: this.height,
};
},
contentStyles(): Record<string,string> {
@@ -98,18 +93,20 @@ export default defineComponent({
</script>
<template>
-<div :style="styles" class="flex flex-col justify-evenly">
- <close-icon @click.stop="onClose"
- class="block absolute top-2 right-2 w-6 h-6 hover:cursor-pointer"/>
+<div :style="styles" class="p-2 flex flex-col justify-between">
+ <div class="flex">
+ <h2 class="text-center mb-2">{{stage == 0 ? 'Welcome' : 'Tutorial'}}</h2>
+ <close-icon @click.stop="onClose"
+ class="block ml-auto w-6 h-6 hover:cursor-pointer"/>
+ </div>
<template v-if="stage == 0">
- <h2 class="text-center">Welcome</h2>
<div :style="contentStyles">
Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore
et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco.
</div>
- <div class="w-full flex justify-evenly">
+ <div class="w-full flex justify-evenly mt-2">
<button :style="buttonStyles" class="hover:brightness-125" @click="onStartTutorial">
Start Tutorial
</button>
@@ -119,8 +116,6 @@ export default defineComponent({
</div>
</template>
<template v-else>
- <h2 class="text-center">Tutorial</h2>
- <!-- Text content -->
<div v-if="stage == 1" :style="contentStyles">
Click/touch on the tile to expand it and see it's children. <br/>
A green title means the tile has children. Orange and red mean 100+ or 1000+ children.
@@ -170,7 +165,7 @@ export default defineComponent({
And finally, the help icon provides summarised usage information.
</div>
<!-- Buttons -->
- <div class="w-full flex justify-evenly">
+ <div class="w-full flex justify-evenly mt-2">
<button :style="buttonStyles"
:disabled="stage == 1" :class="stage == 1 ? ['brightness-75'] : ['hover:brightness-125']"
@click="onPrevClick">
diff --git a/src/lib.ts b/src/lib.ts
index c13992c..69fac57 100644
--- a/src/lib.ts
+++ b/src/lib.ts
@@ -111,21 +111,3 @@ export function capitalizeWords(str: string){
return str.replace(/\b\w/g, x => x.toUpperCase());
// '\b' matches word boundary, '\w' is like [a-zA-Z0-9_],
}
-// Dynamically obtains scroll bar width
-// From stackoverflow.com/questions/13382516/getting-scroll-bar-width-using-javascript
-export function getScrollBarWidth(){
- // Create hidden outer div
- let outer = document.createElement('div');
- outer.style.visibility = 'hidden';
- outer.style.overflow = 'scroll';
- document.body.appendChild(outer);
- // Create inner div
- let inner = document.createElement('div');
- outer.appendChild(inner);
- // Get width difference
- let scrollBarWidth = outer.offsetWidth - inner.offsetWidth;
- // Remove temporary divs
- outer.parentNode!.removeChild(outer);
- //
- return scrollBarWidth;
-}