aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.vue116
-rw-r--r--src/components/SettingsModal.vue26
-rw-r--r--src/components/Tile.vue1
-rw-r--r--src/lib.ts12
4 files changed, 95 insertions, 60 deletions
diff --git a/src/App.vue b/src/App.vue
index 0c9a96c..66db8c0 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -21,7 +21,7 @@ import type {TolMap, Action} from './lib';
import {LayoutNode} from './layout';
import type {LayoutOptions, LayoutTreeChg} from './layout';
// Functions
-import {arraySum, randWeightedChoice, getScrollBarWidth} from './lib';
+import {arraySum, randWeightedChoice, getScrollBarWidth, getBreakpoint} from './lib';
import {initLayoutTree, initLayoutMap, tryLayout} from './layout';
// Type representing auto-mode actions
@@ -46,56 +46,62 @@ const initialTolMap: TolMap = new Map();
initialTolMap.set("", new TolNode());
// Configurable options
-const defaultLytOpts: LayoutOptions = {
- tileSpacing: 8, //px
- headerSz: 22, //px
- minTileSz: 50, //px
- maxTileSz: 200, //px
- // Layout-algorithm related
- layoutType: 'sweep', //'sqr' | 'rect' | 'sweep'
- rectMode: 'auto first-row', //'horz' | 'vert' | 'linear' | 'auto' | 'auto first-row'
- sweepMode: 'left', //'left' | 'top' | 'shorter' | 'auto'
- sweptNodesPrio: 'sqrt', //'linear' | 'sqrt' | 'pow-2/3'
- sweepToParent: 'fallback', //'none' | 'prefer' | 'fallback'
-};
-const defaultUiOpts = {
- // For tiles
- borderRadius: 5, //px
- shadowNormal: '0 0 2px black',
- shadowHighlight: '0 0 1px 2px greenyellow',
- shadowFocused: '0 0 1px 2px orange',
- infoIconSz: 18, //px
- infoIconMargin: 2, //px
- childThresholds: [[1, 'greenyellow'], [10, 'orange'], [100, 'red']],
- headerColor: '#fafaf9',
- // For leaf tiles
- leafTilePadding: 4, //px
- leafHeaderFontSz: 15, //px
- // For non-leaf tiles
- nonleafBgColors: ['#44403c', '#57534e'], //tiles at depth N use the Nth color, repeating from the start as needed
- nonleafHeaderFontSz: 15, //px
- nonleafHeaderColor: '#fafaf9',
- nonleafHeaderBgColor: '#1c1917',
- // For other components
- appBgColor: '#292524',
- tileAreaOffset: 5, //px (space between root tile and display boundary)
- scrollGap: getScrollBarWidth(),
- ancestryBarImgSz: defaultLytOpts.minTileSz * 2, //px
- ancestryBarBgColor: '#44403c',
- ancestryTileMargin: 5, //px (gap between detached-ancestor tiles)
- infoModalImgSz: 200,
- searchSuggLimit: 5,
- autoWaitTime: 500, //ms (time to wait between actions (with their transitions))
- tutorialPaneSz: 200,
- tutorialPaneBgColor: '#1c1917',
- tutorialPaneTextColor: 'white',
- // Timing related
- tileChgDuration: 300, //ms (for tile move/expand/collapse)
- clickHoldDuration: 400, //ms (duration after mousedown when a click-and-hold is recognised)
- // Other
- useReducedTree: false,
- jumpToSearchedNode: false,
-};
+function getDefaultLytOpts(): LayoutOptions {
+ let screenSz = getBreakpoint();
+ return {
+ tileSpacing: screenSz == 'sm' ? 6 : 10, //px
+ headerSz: 22, //px
+ minTileSz: 50, //px
+ maxTileSz: 200, //px
+ // Layout-algorithm related
+ layoutType: 'sweep', //'sqr' | 'rect' | 'sweep'
+ rectMode: 'auto first-row', //'horz' | 'vert' | 'linear' | 'auto' | 'auto first-row'
+ sweepMode: 'left', //'left' | 'top' | 'shorter' | 'auto'
+ sweptNodesPrio: 'sqrt', //'linear' | 'sqrt' | 'pow-2/3'
+ sweepToParent: 'fallback', //'none' | 'prefer' | 'fallback'
+ };
+}
+function getDefaultUiOpts(){
+ let screenSz = getBreakpoint();
+ return {
+ // For tiles
+ borderRadius: 5, //px
+ shadowNormal: '0 0 2px black',
+ shadowHighlight: '0 0 1px 2px greenyellow',
+ shadowFocused: '0 0 1px 2px orange',
+ infoIconSz: 18, //px
+ infoIconMargin: 2, //px
+ childThresholds: [[1, 'greenyellow'], [10, 'orange'], [100, 'red']],
+ headerColor: '#fafaf9',
+ // For leaf tiles
+ leafTilePadding: 4, //px
+ leafHeaderFontSz: 15, //px
+ // For non-leaf tiles
+ nonleafBgColors: ['#44403c', '#57534e'], //tiles at depth N use the Nth color, repeating from the start as needed
+ nonleafHeaderFontSz: 15, //px
+ nonleafHeaderColor: '#fafaf9',
+ nonleafHeaderBgColor: '#1c1917',
+ // For other components
+ appBgColor: '#292524',
+ tileAreaOffset: 5, //px (space between root tile and display boundary)
+ scrollGap: getScrollBarWidth(),
+ ancestryBarImgSz: 100, //px
+ ancestryBarBgColor: '#44403c',
+ ancestryTileMargin: 5, //px (gap between detached-ancestor tiles)
+ infoModalImgSz: 200,
+ searchSuggLimit: 5,
+ autoWaitTime: 500, //ms (time to wait between actions (with their transitions))
+ tutorialPaneSz: 200,
+ tutorialPaneBgColor: '#1c1917',
+ tutorialPaneTextColor: 'white',
+ // Timing related
+ tileChgDuration: 300, //ms (for tile move/expand/collapse)
+ clickHoldDuration: 400, //ms (duration after mousedown when a click-and-hold is recognised)
+ // Other
+ useReducedTree: false,
+ jumpToSearchedNode: false,
+ };
+}
export default defineComponent({
data(){
@@ -570,6 +576,8 @@ export default defineComponent({
this.initTreeFromServer();
},
onResetSettings(){
+ let defaultLytOpts = getDefaultLytOpts();
+ let defaultUiOpts = getDefaultUiOpts();
if (this.uiOpts.useReducedTree != defaultUiOpts.useReducedTree){
this.onTreeChange();
}
@@ -671,7 +679,7 @@ export default defineComponent({
// Helper methods
initTreeFromServer(){
let urlPath = '/data/node';
- urlPath += this.uiOpts.useReducedTree ? '&tree=reduced' : '';
+ urlPath += this.uiOpts.useReducedTree ? '?tree=reduced' : '';
fetch(urlPath)
.then(response => response.json())
.then(obj => {
@@ -704,7 +712,7 @@ export default defineComponent({
});
},
getLytOpts(){
- let opts: {[x: string]: boolean|number|string} = {...defaultLytOpts};
+ let opts: {[x: string]: boolean|number|string} = getDefaultLytOpts();
for (let prop of Object.getOwnPropertyNames(opts)){
let item = localStorage.getItem('lyt ' + prop);
if (item != null){
@@ -719,7 +727,7 @@ export default defineComponent({
return opts;
},
getUiOpts(){
- let opts: {[x: string]: boolean|number|string|string[]|(string|number)[][]} = {...defaultUiOpts};
+ let opts: {[x: string]: boolean|number|string|string[]|(string|number)[][]} = getDefaultUiOpts();
for (let prop of Object.getOwnPropertyNames(opts)){
let item = localStorage.getItem('ui ' + prop);
if (item != null){
diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue
index e95dc34..c4f896d 100644
--- a/src/components/SettingsModal.vue
+++ b/src/components/SettingsModal.vue
@@ -10,15 +10,26 @@ export default defineComponent({
lytOpts: {type: Object as PropType<LayoutOptions>, required: true},
uiOpts: {type: Object, required: true},
},
+ data(){
+ return {
+ optChgd: false,
+ };
+ },
methods: {
onCloseClick(evt: Event){
if (evt.target == this.$el || (this.$refs.closeIcon as typeof CloseIcon).$el.contains(evt.target)){
- this.saveSettings();
+ if (this.optChgd){
+ this.saveSettings();
+ }
this.$emit('close');
}
},
+ onOptChg(){
+ this.optChgd = true;
+ },
onLytOptChg(){
this.$emit('layout-setting-chg');
+ this.onOptChg();
},
onMinTileSzChg(){
let minInput = this.$refs.minTileSzInput as HTMLInputElement;
@@ -38,6 +49,7 @@ export default defineComponent({
},
onTreeChg(){
this.$emit('tree-chg');
+ this.onOptChg();
},
saveSettings(){
const savedLytOpts = ['tileSpacing', 'minTileSz', 'maxTileSz', 'layoutType', 'sweepMode', 'sweepToParent', ];
@@ -52,6 +64,7 @@ export default defineComponent({
},
onReset(){
localStorage.clear();
+ this.optChgd = false;
this.$emit('reset');
console.log('Settings reset');
},
@@ -71,21 +84,21 @@ export default defineComponent({
<hr class="border-stone-400"/>
<div>
<label>Tile Spacing <input type="range" min="0" max="20" class="mx-2 w-[3cm]"
- v-model.number="lytOpts.tileSpacing" @input="onLytOptChg"/></label>
+ v-model.number="lytOpts.tileSpacing" @change="onLytOptChg"/></label>
</div>
<hr class="border-stone-400"/>
<div>
<label>
<span class="inline-block w-[3cm]">Min Tile Size</span>
<input type="range" min="0" max="400" v-model.number="lytOpts.minTileSz" class="w-[3cm]"
- @input="onMinTileSzChg" ref="minTileSzInput"/>
+ @change="onMinTileSzChg" ref="minTileSzInput"/>
</label>
</div>
<div>
<label>
<span class="inline-block w-[3cm]">Max Tile Size</span>
<input type="range" min="0" max="400" v-model.number="lytOpts.maxTileSz" class="w-[3cm]"
- @input="onMaxTileSzChg" ref="maxTileSzInput"/>
+ @change="onMaxTileSzChg" ref="maxTileSzInput"/>
</label>
</div>
<hr class="border-stone-400"/>
@@ -149,11 +162,12 @@ export default defineComponent({
<hr class="border-stone-400"/>
<div>
<label>Animation Duration <input type="range" min="0" max="3000" class="mx-2 w-[3cm]"
- v-model.number="uiOpts.tileChgDuration"/></label>
+ v-model.number="uiOpts.tileChgDuration" @change="onOptChg"/></label>
</div>
<hr class="border-stone-400"/>
<div>
- <label> <input type="checkbox" v-model="uiOpts.jumpToSearchedNode"/> Jump to search result</label>
+ <label> <input type="checkbox" v-model="uiOpts.jumpToSearchedNode" @change="onOptChg"/>
+ Jump to search result</label>
</div>
<hr class="border-stone-400"/>
<div>
diff --git a/src/components/Tile.vue b/src/components/Tile.vue
index 7b412b2..3054d46 100644
--- a/src/components/Tile.vue
+++ b/src/components/Tile.vue
@@ -242,6 +242,7 @@ export default defineComponent({
fontSize: this.uiOpts.nonleafHeaderFontSz + 'px',
textAlign: 'center',
color: this.uiOpts.nonleafHeaderColor,
+ paddingLeft: '5px',
// For ellipsis
overflow: 'hidden',
textOverflow: 'ellipsis',
diff --git a/src/lib.ts b/src/lib.ts
index a6c8df1..19bd864 100644
--- a/src/lib.ts
+++ b/src/lib.ts
@@ -47,6 +47,18 @@ export type Action =
* General utility functions
*/
+export type Breakpoint = 'sm' | 'md' | 'lg'; // These represent screen sizes
+export function getBreakpoint(): Breakpoint {
+ let w = window.innerWidth;
+ if (w < 768){
+ return 'sm';
+ } else if (w < 1024){
+ return 'md';
+ } else {
+ return 'lg';
+ }
+}
+
// Returns [0 ... len]
export function range(len: number): number[] {
return [...Array(len).keys()];