mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-02 00:32:33 +00:00
accessibility improvements
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body data-sveltekit-preload-data="hover">
|
<body data-sveltekit-preload-data="hover">
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@@ -16,7 +16,7 @@
|
|||||||
const { verticalFileView, elevationProfile, bottomPanelSize, rightPanelSize } = settings;
|
const { verticalFileView, elevationProfile, bottomPanelSize, rightPanelSize } = settings;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="fixed flex flex-row w-screen h-screen">
|
<div class="fixed flex flex-row w-screen h-dvh">
|
||||||
<div class="flex flex-col grow h-full min-w-0">
|
<div class="flex flex-col grow h-full min-w-0">
|
||||||
<div class="grow relative">
|
<div class="grow relative">
|
||||||
<Menu />
|
<Menu />
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as ToggleGroup from '$lib/components/ui/toggle-group';
|
import * as ToggleGroup from '$lib/components/ui/toggle-group';
|
||||||
import Tooltip from '$lib/components/Tooltip.svelte';
|
import Tooltip from '$lib/components/Tooltip.svelte';
|
||||||
import { Separator } from '$lib/components/ui/separator';
|
|
||||||
|
|
||||||
import Chart from 'chart.js/auto';
|
import Chart from 'chart.js/auto';
|
||||||
import mapboxgl from 'mapbox-gl';
|
import mapboxgl from 'mapbox-gl';
|
||||||
@@ -281,13 +280,16 @@
|
|||||||
return points[0].index;
|
return points[0].index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
canvas.addEventListener('pointerdown', (evt) => {
|
|
||||||
dragging = true;
|
let dragStarted = false;
|
||||||
|
function onMouseDown(evt) {
|
||||||
|
dragStarted = true;
|
||||||
canvas.style.cursor = 'col-resize';
|
canvas.style.cursor = 'col-resize';
|
||||||
startIndex = getIndex(evt);
|
startIndex = getIndex(evt);
|
||||||
});
|
}
|
||||||
canvas.addEventListener('pointermove', (evt) => {
|
function onMouseMove(evt) {
|
||||||
if (dragging) {
|
if (dragStarted) {
|
||||||
|
dragging = true;
|
||||||
endIndex = getIndex(evt);
|
endIndex = getIndex(evt);
|
||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
slicedGPXStatistics.set([
|
slicedGPXStatistics.set([
|
||||||
@@ -300,15 +302,19 @@
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
canvas.addEventListener('pointerup', (evt) => {
|
function onMouseUp(evt) {
|
||||||
|
dragStarted = false;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
canvas.style.cursor = '';
|
canvas.style.cursor = '';
|
||||||
endIndex = getIndex(evt);
|
endIndex = getIndex(evt);
|
||||||
if (startIndex === endIndex) {
|
if (startIndex === endIndex) {
|
||||||
slicedGPXStatistics.set(undefined);
|
slicedGPXStatistics.set(undefined);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
canvas.addEventListener('pointerdown', onMouseDown);
|
||||||
|
canvas.addEventListener('pointermove', onMouseMove);
|
||||||
|
canvas.addEventListener('pointerup', onMouseUp);
|
||||||
});
|
});
|
||||||
|
|
||||||
$: if (chart && $distanceUnits && $velocityUnits && $temperatureUnits) {
|
$: if (chart && $distanceUnits && $velocityUnits && $temperatureUnits) {
|
||||||
|
@@ -5,12 +5,12 @@
|
|||||||
export let minAfter: number = 0;
|
export let minAfter: number = 0;
|
||||||
export let maxAfter: number = Number.MAX_SAFE_INTEGER;
|
export let maxAfter: number = Number.MAX_SAFE_INTEGER;
|
||||||
|
|
||||||
function handleMouseDown(event: MouseEvent) {
|
function handleMouseDown(event: PointerEvent) {
|
||||||
const startX = event.clientX;
|
const startX = event.clientX;
|
||||||
const startY = event.clientY;
|
const startY = event.clientY;
|
||||||
const startAfter = after;
|
const startAfter = after;
|
||||||
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: PointerEvent) => {
|
||||||
const newAfter =
|
const newAfter =
|
||||||
startAfter + (orientation === 'col' ? startX - event.clientX : startY - event.clientY);
|
startAfter + (orientation === 'col' ? startX - event.clientX : startY - event.clientY);
|
||||||
if (newAfter >= minAfter && newAfter <= maxAfter) {
|
if (newAfter >= minAfter && newAfter <= maxAfter) {
|
||||||
@@ -23,12 +23,12 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
window.removeEventListener('mousemove', handleMouseMove);
|
window.removeEventListener('pointermove', handleMouseMove);
|
||||||
window.removeEventListener('mouseup', handleMouseUp);
|
window.removeEventListener('pointerup', handleMouseUp);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('mousemove', handleMouseMove);
|
window.addEventListener('pointermove', handleMouseMove);
|
||||||
window.addEventListener('mouseup', handleMouseUp);
|
window.addEventListener('pointerup', handleMouseUp);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -37,5 +37,5 @@
|
|||||||
class="{orientation === 'col'
|
class="{orientation === 'col'
|
||||||
? 'w-1 h-full cursor-col-resize'
|
? 'w-1 h-full cursor-col-resize'
|
||||||
: 'w-full h-1 cursor-row-resize'} {orientation}"
|
: 'w-full h-1 cursor-row-resize'} {orientation}"
|
||||||
on:mousedown={handleMouseDown}
|
on:pointerdown={handleMouseDown}
|
||||||
/>
|
/>
|
||||||
|
@@ -42,7 +42,9 @@
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
class="w-full flex flex-row {side === 'right'
|
class="w-full flex flex-row {side === 'right'
|
||||||
? 'justify-between'
|
? 'justify-between'
|
||||||
: 'justify-start'} py-0 px-1 h-fit {nohover ? 'hover:bg-background' : ''}"
|
: 'justify-start'} py-0 px-1 h-fit {nohover
|
||||||
|
? 'hover:bg-background'
|
||||||
|
: ''} pointer-events-none"
|
||||||
>
|
>
|
||||||
{#if side === 'left'}
|
{#if side === 'left'}
|
||||||
{#if $open[fullId]}
|
{#if $open[fullId]}
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={container}
|
bind:this={container}
|
||||||
class="{$$props.class ||
|
class="{$$props.class ||
|
||||||
''} clear-both translate-0 m-[10px] mb-0 pointer-events-auto bg-background rounded shadow-md hidden"
|
''} clear-both translate-0 m-[10px] mb-0 last:mb-[10px] pointer-events-auto bg-background rounded shadow-md hidden"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -332,6 +332,7 @@
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
$selection.toggle(item);
|
$selection.toggle(item);
|
||||||
|
$selection = $selection;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
on:mouseenter={() => {
|
on:mouseenter={() => {
|
||||||
@@ -360,7 +361,7 @@
|
|||||||
{:else if item.level === ListLevel.WAYPOINT}
|
{:else if item.level === ListLevel.WAYPOINT}
|
||||||
<MapPin size="16" class="mr-1 shrink-0" />
|
<MapPin size="16" class="mr-1 shrink-0" />
|
||||||
{/if}
|
{/if}
|
||||||
<span class="grow truncate {$verticalFileView ? 'mr-2' : ''}">
|
<span class="grow select-none truncate {$verticalFileView ? 'mr-2' : ''}">
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -207,8 +207,10 @@ export class GPXLayer {
|
|||||||
} else {
|
} else {
|
||||||
selectItem(new ListWaypointItem(this.fileId, marker._waypoint._data.index));
|
selectItem(new ListWaypointItem(this.fileId, marker._waypoint._data.index));
|
||||||
}
|
}
|
||||||
} else {
|
} else if (get(currentTool) === Tool.WAYPOINT) {
|
||||||
selectedWaypoint.set([marker._waypoint, this.fileId]);
|
selectedWaypoint.set([marker._waypoint, this.fileId]);
|
||||||
|
} else {
|
||||||
|
this.showWaypointPopup(marker._waypoint);
|
||||||
}
|
}
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
import { get, writable } from 'svelte/store';
|
import { get, writable } from 'svelte/store';
|
||||||
import { getLayers } from './utils';
|
import { getLayers } from './utils';
|
||||||
|
|
||||||
|
let container: HTMLDivElement;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
currentBasemap,
|
currentBasemap,
|
||||||
previousBasemap,
|
previousBasemap,
|
||||||
@@ -95,16 +97,45 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let open = false;
|
||||||
|
function openLayerControl() {
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
function closeLayerControl() {
|
||||||
|
open = false;
|
||||||
|
}
|
||||||
|
let cancelEvents = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<CustomControl class="group min-w-[29px] min-h-[29px] overflow-hidden">
|
<CustomControl class="group min-w-[29px] min-h-[29px] overflow-hidden">
|
||||||
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div
|
<div
|
||||||
class="flex flex-row justify-center items-center w-[29px] h-[29px] delay-100 transition-[opacity height] duration-0 group-hover:opacity-0 group-hover:h-0 group-hover:delay-0"
|
bind:this={container}
|
||||||
|
class="h-full w-full"
|
||||||
|
on:mouseenter={openLayerControl}
|
||||||
|
on:mouseleave={closeLayerControl}
|
||||||
|
on:pointerenter={() => {
|
||||||
|
if (!open) {
|
||||||
|
cancelEvents = true;
|
||||||
|
openLayerControl();
|
||||||
|
setTimeout(() => {
|
||||||
|
cancelEvents = false;
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex flex-row justify-center items-center delay-100 transition-[opacity] duration-0 {open
|
||||||
|
? 'opacity-0 w-0 h-0 delay-0'
|
||||||
|
: 'w-[29px] h-[29px]'}"
|
||||||
>
|
>
|
||||||
<Layers size="20" />
|
<Layers size="20" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="transition-[grid-template-rows grid-template-cols] grid grid-rows-[0fr] grid-cols-[0fr] duration-150 group-hover:grid-rows-[1fr] group-hover:grid-cols-[1fr] h-full"
|
class="transition-[grid-template-rows grid-template-cols] grid grid-rows-[0fr] grid-cols-[0fr] duration-150 h-full {open
|
||||||
|
? 'grid-rows-[1fr] grid-cols-[1fr]'
|
||||||
|
: ''} {cancelEvents ? 'pointer-events-none' : ''}"
|
||||||
>
|
>
|
||||||
<ScrollArea>
|
<ScrollArea>
|
||||||
<div class="h-fit">
|
<div class="h-fit">
|
||||||
@@ -129,4 +160,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</CustomControl>
|
</CustomControl>
|
||||||
|
|
||||||
|
<svelte:window
|
||||||
|
on:click={(e) => {
|
||||||
|
if (open && !cancelEvents && !container.contains(e.target)) {
|
||||||
|
closeLayerControl();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
@@ -120,7 +120,7 @@
|
|||||||
<Accordion.Item value="item-1" class="flex flex-col overflow-hidden">
|
<Accordion.Item value="item-1" class="flex flex-col overflow-hidden">
|
||||||
<Accordion.Trigger>{$_('layers.selection')}</Accordion.Trigger>
|
<Accordion.Trigger>{$_('layers.selection')}</Accordion.Trigger>
|
||||||
<Accordion.Content class="grow flex flex-col border rounded">
|
<Accordion.Content class="grow flex flex-col border rounded">
|
||||||
<ScrollArea class="py-2 pr-2">
|
<ScrollArea class="py-2 pl-1 pr-2 min-h-9">
|
||||||
<LayerTree
|
<LayerTree
|
||||||
layerTree={basemapTree}
|
layerTree={basemapTree}
|
||||||
name="basemapSettings"
|
name="basemapSettings"
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
/>
|
/>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
<Separator />
|
<Separator />
|
||||||
<ScrollArea class="py-2 pr-2">
|
<ScrollArea class="py-2 pl-1 pr-2 min-h-9">
|
||||||
<LayerTree
|
<LayerTree
|
||||||
layerTree={overlayTree}
|
layerTree={overlayTree}
|
||||||
name="overlaySettings"
|
name="overlaySettings"
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<CustomControl class="w-[29px] h-[29px]">
|
<CustomControl class="w-[29px] h-[29px] shrink-0">
|
||||||
<Toggle bind:pressed={$streetViewEnabled} class="w-full h-full rounded p-0">
|
<Toggle bind:pressed={$streetViewEnabled} class="w-full h-full rounded p-0">
|
||||||
<PersonStanding size="22" />
|
<PersonStanding size="22" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
|
@@ -98,6 +98,9 @@
|
|||||||
$map.on('mousedown', onMouseDown);
|
$map.on('mousedown', onMouseDown);
|
||||||
$map.on('mousemove', onMouseMove);
|
$map.on('mousemove', onMouseMove);
|
||||||
$map.on('mouseup', onMouseUp);
|
$map.on('mouseup', onMouseUp);
|
||||||
|
$map.on('touchstart', onMouseDown);
|
||||||
|
$map.on('touchmove', onMouseMove);
|
||||||
|
$map.on('touchend', onMouseUp);
|
||||||
$map.dragPan.disable();
|
$map.dragPan.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +110,9 @@
|
|||||||
$map.off('mousedown', onMouseDown);
|
$map.off('mousedown', onMouseDown);
|
||||||
$map.off('mousemove', onMouseMove);
|
$map.off('mousemove', onMouseMove);
|
||||||
$map.off('mouseup', onMouseUp);
|
$map.off('mouseup', onMouseUp);
|
||||||
|
$map.off('touchstart', onMouseDown);
|
||||||
|
$map.off('touchmove', onMouseMove);
|
||||||
|
$map.off('touchend', onMouseUp);
|
||||||
$map.dragPan.enable();
|
$map.dragPan.enable();
|
||||||
|
|
||||||
if ($map.getLayer('rectangle')) {
|
if ($map.getLayer('rectangle')) {
|
||||||
|
Reference in New Issue
Block a user