Compare commits
22 Commits
7e5a034cac
...
v1.15.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
f7c40095d5
|
|||
|
579892067e
|
|||
|
48f87f98d6
|
|||
|
3cd1b32af9
|
|||
|
462404b53e
|
|||
|
e3147caa90
|
|||
|
7c11fefdb7
|
|||
|
9af6636971
|
|||
|
8ae7fd1fd8
|
|||
|
cb3fbade39
|
|||
|
6dfd9765b4
|
|||
|
45eb8f087d
|
|||
|
3630fae133
|
|||
|
1116161e93
|
|||
|
88eb0ac0c1
|
|||
|
6da004e199
|
|||
|
8877a9e1c8
|
|||
|
03d6a86569
|
|||
|
5baebbb846
|
|||
|
dca2991754
|
|||
|
aee7f9d181
|
|||
|
56a077cceb
|
@@ -9,5 +9,5 @@ jobs:
|
||||
steps:
|
||||
- name: Release Drafter
|
||||
uses: https://github.com/raucao/gitea-release-drafter@dev
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { on } from '@ember/modifier';
|
||||
import Icon from '#components/icon';
|
||||
|
||||
<template>
|
||||
{{! template-lint-disable no-nested-interactive }}
|
||||
<div class="sidebar-header">
|
||||
<button type="button" class="back-btn" {{on "click" @onBack}}>
|
||||
<Icon @name="arrow-left" @size={{20}} @color="#333" />
|
||||
@@ -13,7 +14,7 @@ import Icon from '#components/icon';
|
||||
</div>
|
||||
|
||||
<div class="sidebar-content">
|
||||
<section class="settings-section">
|
||||
<section class="about-section">
|
||||
<p>
|
||||
<strong>Marco</strong>
|
||||
(as in
|
||||
@@ -33,31 +34,119 @@ import Icon from '#components/icon';
|
||||
>remote storage</a>
|
||||
to sync place bookmarks across apps and devices.
|
||||
</p>
|
||||
<ul class="link-list">
|
||||
<li>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<Icon @name="gift" @size={{20}} />
|
||||
<span>Open Source</span>
|
||||
</summary>
|
||||
<div class="details-content">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>License</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
href="https://gitea.kosmos.org/raucao/marco"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
Source Code
|
||||
Marco App
|
||||
</a>
|
||||
(<a
|
||||
</td>
|
||||
<td>
|
||||
<a
|
||||
href="https://en.wikipedia.org/wiki/GNU_Affero_General_Public_License"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>AGPL</a>)
|
||||
</li>
|
||||
<li>
|
||||
>
|
||||
<abbr title="GNU Affero General Public License">AGPL</abbr>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
href="https://openstreetmap.org/copyright"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
Map Data © OpenStreetMap
|
||||
Map Data
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<a
|
||||
href="https://opendatacommons.org/licenses/odbl/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<abbr
|
||||
title="Open Data Commons Open Database License"
|
||||
>ODbL</abbr>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
href="https://github.com/feathericons/feather"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
Feather Icons
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a
|
||||
href="https://en.wikipedia.org/wiki/MIT_License"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<abbr title="MIT License">MIT</abbr>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<Icon @name="heart" @size={{20}} @color="#e5533d" />
|
||||
<span>Contribute</span>
|
||||
</summary>
|
||||
<div class="details-content">
|
||||
<p>
|
||||
<strong>Most impactful:</strong>
|
||||
Add and improve data for points of interest in
|
||||
<a
|
||||
href="https://www.openstreetmap.org"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>OpenStreetMap</a>.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Most appreciated:</strong>
|
||||
Use this app as much as you can and
|
||||
<a
|
||||
href="https://community.remotestorage.io/t/marco-an-unhosted-maps-app/941"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>submit feedback</a>
|
||||
about your experience, problems, feature wishes, etc.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Most supportive:</strong>
|
||||
Tell others about this app, on social media, in blog posts,
|
||||
educational videos, etc.
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -17,7 +17,7 @@ export default class AppMenu extends Component {
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="sidebar settings-pane">
|
||||
<div class="sidebar app-menu-pane">
|
||||
{{#if (eq this.currentView "menu")}}
|
||||
<AppMenuHome @onNavigate={{this.setView}} @onClose={{@onClose}} />
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ export default class AppMenuSettings extends Component {
|
||||
this.settings.updateMapKinetic(event.target.value === 'true');
|
||||
}
|
||||
|
||||
@action
|
||||
updatePhotonApi(event) {
|
||||
this.settings.updatePhotonApi(event.target.value);
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="sidebar-header">
|
||||
<button type="button" class="back-btn" {{on "click" @onBack}}>
|
||||
@@ -72,6 +77,23 @@ export default class AppMenuSettings extends Component {
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="photon-api">Photon API Provider</label>
|
||||
<select
|
||||
id="photon-api"
|
||||
class="form-control"
|
||||
{{on "change" this.updatePhotonApi}}
|
||||
>
|
||||
{{#each this.settings.photonApis as |api|}}
|
||||
<option
|
||||
value={{api.url}}
|
||||
selected={{if (eq api.url this.settings.photonApi) "selected"}}
|
||||
>
|
||||
{{api.name}}
|
||||
</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -499,10 +499,9 @@ export default class MapComponent extends Component {
|
||||
}
|
||||
|
||||
if (options.preventZoom) {
|
||||
// If we are preventing zoom (e.g. user clicked a bookmark), we still need to center
|
||||
// but without changing the zoom level.
|
||||
// We use animateToSmartCenter without a second argument (zoom=null).
|
||||
this.animateToSmartCenter(coords);
|
||||
// If we are preventing zoom (e.g. user clicked a bookmark), we rely on visibility check.
|
||||
// This avoids unnecessary panning if the place is already visible.
|
||||
this.handlePinVisibility(coords, { maintainZoom: true });
|
||||
} else if (selected.bbox) {
|
||||
this.zoomToBbox(selected.bbox);
|
||||
} else {
|
||||
@@ -547,7 +546,10 @@ export default class MapComponent extends Component {
|
||||
}
|
||||
// Desktop: Sidebar covers left side (approx 400px)
|
||||
else if (this.args.isSidebarOpen) {
|
||||
const sidebarWidth = 400;
|
||||
const sidebarWidthVar = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--sidebar-width')
|
||||
.trim();
|
||||
const sidebarWidth = parseInt(sidebarWidthVar, 10) || 360;
|
||||
const visibleWidth = size[0] - sidebarWidth;
|
||||
|
||||
// Left padding: Sidebar + 15% of visible width
|
||||
@@ -566,14 +568,15 @@ export default class MapComponent extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
handlePinVisibility(coords) {
|
||||
handlePinVisibility(coords, options = {}) {
|
||||
if (!this.mapInstance) return;
|
||||
|
||||
const view = this.mapInstance.getView();
|
||||
const currentZoom = view.getZoom();
|
||||
|
||||
// If too far out (e.g. world view), zoom in to neighborhood level (16)
|
||||
if (currentZoom < 16) {
|
||||
// UNLESS we want to maintain the current zoom
|
||||
if (!options.maintainZoom && currentZoom < 16) {
|
||||
this.animateToSmartCenter(coords, 16);
|
||||
return;
|
||||
}
|
||||
@@ -590,8 +593,12 @@ export default class MapComponent extends Component {
|
||||
pixel[1] > size[1];
|
||||
|
||||
if (isOffScreen) {
|
||||
this.animateToSmartCenter(coords);
|
||||
// If off-screen, center it smartly (considering sidebar/bottom sheet)
|
||||
// Pass maintainZoom to prevent zoom reset if desired
|
||||
const zoom = options.maintainZoom ? null : 16;
|
||||
this.animateToSmartCenter(coords, zoom);
|
||||
} else {
|
||||
// If on-screen, only pan if obscured by UI
|
||||
this.panIfObscured(coords);
|
||||
}
|
||||
}
|
||||
@@ -627,6 +634,28 @@ export default class MapComponent extends Component {
|
||||
// To move the camera South (Lower Y), we subtract.
|
||||
targetCenter = [coords[0], coords[1] - offsetMapUnits];
|
||||
}
|
||||
// Desktop: Check if sidebar is open
|
||||
else if (this.args.isSidebarOpen) {
|
||||
const sidebarWidthVar = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--sidebar-width')
|
||||
.trim();
|
||||
const sidebarWidth = parseInt(sidebarWidthVar, 10) || 360;
|
||||
|
||||
// We want the pin to be in the center of the remaining space.
|
||||
// Remaining space starts at x = sidebarWidth.
|
||||
// Center of remaining space = sidebarWidth + (totalWidth - sidebarWidth) / 2
|
||||
// = sidebarWidth/2 + totalWidth/2
|
||||
// Map Center is totalWidth/2
|
||||
// Offset = sidebarWidth/2 (to the right)
|
||||
|
||||
const offsetPixels = sidebarWidth / 2;
|
||||
const offsetMapUnits = offsetPixels * resolution;
|
||||
|
||||
// We want pin at center + offset.
|
||||
// So map center must be pin - offset.
|
||||
// X increases to the right.
|
||||
targetCenter = [coords[0] - offsetMapUnits, coords[1]];
|
||||
}
|
||||
|
||||
const animationOptions = {
|
||||
center: targetCenter,
|
||||
@@ -645,33 +674,73 @@ export default class MapComponent extends Component {
|
||||
if (!this.mapInstance) return;
|
||||
|
||||
const size = this.mapInstance.getSize();
|
||||
// Check if mobile (width <= 768px matches CSS)
|
||||
if (size[0] > 768) return;
|
||||
|
||||
const pixel = this.mapInstance.getPixelFromCoordinate(coords);
|
||||
if (!pixel) return;
|
||||
|
||||
const height = size[1];
|
||||
|
||||
// Sidebar covers the bottom 50%
|
||||
const splitPoint = height / 2;
|
||||
|
||||
// If the pin is in the bottom half (y > splitPoint), it is obscured
|
||||
if (pixel[1] > splitPoint) {
|
||||
// Target position: Center of top half = height * 0.25
|
||||
const targetY = height * 0.25;
|
||||
const deltaY = pixel[1] - targetY;
|
||||
|
||||
const view = this.mapInstance.getView();
|
||||
const center = view.getCenter();
|
||||
const resolution = view.getResolution();
|
||||
|
||||
// Move the map center SOUTH (decrease Y) to move the pin UP (decrease pixel Y)
|
||||
const deltaMapUnits = deltaY * resolution;
|
||||
const newCenter = [center[0], center[1] - deltaMapUnits];
|
||||
// Default targets (current position)
|
||||
let targetPixelX = pixel[0];
|
||||
let targetPixelY = pixel[1];
|
||||
let needsPan = false;
|
||||
|
||||
// 1. Mobile Bottom Sheet Logic (Screen <= 768px)
|
||||
if (size[0] <= 768) {
|
||||
const height = size[1];
|
||||
const splitPoint = height / 2;
|
||||
|
||||
// If in bottom half
|
||||
if (pixel[1] > splitPoint) {
|
||||
targetPixelY = height * 0.25; // Target: Center of top half
|
||||
needsPan = true;
|
||||
}
|
||||
}
|
||||
// 2. Desktop Sidebar Logic (Screen > 768px + Sidebar Open)
|
||||
else if (this.args.isSidebarOpen) {
|
||||
const sidebarWidthVar = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--sidebar-width')
|
||||
.trim();
|
||||
const sidebarWidth = parseInt(sidebarWidthVar, 10) || 360;
|
||||
|
||||
// If under sidebar
|
||||
if (pixel[0] < sidebarWidth) {
|
||||
const visibleWidth = size[0] - sidebarWidth;
|
||||
targetPixelX = sidebarWidth + visibleWidth / 2; // Target: Center of visible area
|
||||
needsPan = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Header Logic (Any screen size)
|
||||
// Check if the (potentially new) target Y is under the header
|
||||
const headerHeight = 60;
|
||||
const minTopDistance = headerHeight + 20; // 80px
|
||||
|
||||
if (targetPixelY < minTopDistance) {
|
||||
targetPixelY = minTopDistance + 30; // Move it to ~110px, clear of header
|
||||
needsPan = true;
|
||||
}
|
||||
|
||||
if (needsPan) {
|
||||
const deltaPixelX = pixel[0] - targetPixelX;
|
||||
const deltaPixelY = pixel[1] - targetPixelY;
|
||||
|
||||
// X: Camera moves same direction as we want the world to move? No.
|
||||
// If we want pin to move RIGHT (pixel increases), Camera must move LEFT (X decreases).
|
||||
// deltaPixelX = current - target. If current < target (want move right), delta is negative.
|
||||
// center + negative = decrease. Correct.
|
||||
const newCenterX = center[0] + deltaPixelX * resolution;
|
||||
|
||||
// Y: Camera moves opposite direction to world relative to pixel coords.
|
||||
// Pixel Y increases DOWN. Map Y increases UP.
|
||||
// If we want pin to move DOWN (pixel increases), Camera must move UP (Y increases).
|
||||
// deltaPixelY = current - target. If current < target (want move down), delta is negative.
|
||||
// center - negative = increase. Correct.
|
||||
const newCenterY = center[1] - deltaPixelY * resolution;
|
||||
|
||||
view.animate({
|
||||
center: newCenter,
|
||||
center: [newCenterX, newCenterY],
|
||||
duration: 500,
|
||||
easing: (t) => t * (2 - t), // Ease-out
|
||||
});
|
||||
|
||||
@@ -286,7 +286,7 @@ export default class PlaceDetails extends Component {
|
||||
>
|
||||
<Icon
|
||||
@name="bookmark"
|
||||
@color={{if this.isSaved "currentColor" "#007bff"}}
|
||||
@color={{if this.isSaved "currentColor" "var(--link-color)"}}
|
||||
/>
|
||||
{{if this.isSaved "Saved" "Save"}}
|
||||
</button>
|
||||
@@ -307,7 +307,7 @@ export default class PlaceDetails extends Component {
|
||||
title="Edit"
|
||||
{{on "click" this.startEditing}}
|
||||
>
|
||||
<Icon @name="edit" @color="#007bff" />
|
||||
<Icon @name="edit" @color="var(--link-color)" />
|
||||
Edit
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
@@ -226,7 +226,7 @@ export default class PlacesSidebar extends Component {
|
||||
class="btn btn-outline create-place"
|
||||
{{on "click" this.createNewPlace}}
|
||||
>
|
||||
<Icon @name="plus" @size={{18}} @color="#007bff" />
|
||||
<Icon @name="plus" @size={{18}} @color="var(--link-color)" />
|
||||
Create new place
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import Service from '@ember/service';
|
||||
import Service, { service } from '@ember/service';
|
||||
import { getPlaceType } from '../utils/osm';
|
||||
import { humanizeOsmTag } from '../utils/format-text';
|
||||
|
||||
export default class PhotonService extends Service {
|
||||
baseUrl = 'https://photon.komoot.io/api/';
|
||||
@service settings;
|
||||
|
||||
get baseUrl() {
|
||||
return this.settings.photonApi;
|
||||
}
|
||||
|
||||
async search(query, lat, lon, limit = 10) {
|
||||
if (!query || query.length < 2) return [];
|
||||
|
||||
@@ -4,6 +4,7 @@ import { tracked } from '@glimmer/tracking';
|
||||
export default class SettingsService extends Service {
|
||||
@tracked overpassApi = 'https://overpass-api.de/api/interpreter';
|
||||
@tracked mapKinetic = true;
|
||||
@tracked photonApi = 'https://photon.komoot.io/api/';
|
||||
|
||||
overpassApis = [
|
||||
{
|
||||
@@ -24,6 +25,13 @@ export default class SettingsService extends Service {
|
||||
// },
|
||||
];
|
||||
|
||||
photonApis = [
|
||||
{
|
||||
name: 'photon.komoot.io',
|
||||
url: 'https://photon.komoot.io/api/',
|
||||
},
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.loadSettings();
|
||||
@@ -59,4 +67,8 @@ export default class SettingsService extends Service {
|
||||
this.mapKinetic = enabled;
|
||||
localStorage.setItem('marco:map-kinetic', String(enabled));
|
||||
}
|
||||
|
||||
updatePhotonApi(url) {
|
||||
this.photonApi = url;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
:root {
|
||||
--default-list-color: #fc3;
|
||||
--hover-bg: #f8f9fa;
|
||||
--sidebar-width: 350px;
|
||||
--link-color: #2a7fff;
|
||||
--link-color-visited: #6a4fbf;
|
||||
}
|
||||
|
||||
html,
|
||||
@@ -185,7 +188,7 @@ body {
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: #007bff;
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
@@ -202,7 +205,7 @@ body {
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
width: var(--sidebar-width);
|
||||
background: white;
|
||||
z-index: 3100; /* Higher than Header (3000) */
|
||||
box-shadow: 2px 0 5px rgb(0 0 0 / 10%);
|
||||
@@ -211,12 +214,12 @@ body {
|
||||
overflow: hidden; /* Ensure flex children are contained */
|
||||
}
|
||||
|
||||
.settings-pane.sidebar {
|
||||
.sidebar.app-menu-pane {
|
||||
z-index: 3200; /* Higher than Places Sidebar (3100) */
|
||||
}
|
||||
|
||||
@media (width <= 768px) {
|
||||
.settings-pane.sidebar {
|
||||
.sidebar.app-menu-pane {
|
||||
width: 100%;
|
||||
right: 0;
|
||||
border-radius: 16px 16px 0 0;
|
||||
@@ -252,6 +255,10 @@ body {
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.app-menu-pane .sidebar-content {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.app-menu {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
@@ -285,6 +292,70 @@ body {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.sidebar-content details {
|
||||
margin: 0 -1rem; /* Top margin, negative side margins to span full width */
|
||||
}
|
||||
|
||||
.sidebar-content details summary {
|
||||
list-style: none; /* Hide default triangle */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.8rem;
|
||||
padding: 1rem;
|
||||
padding-left: 1.4rem;
|
||||
cursor: pointer;
|
||||
font-size: 0.95rem;
|
||||
color: #333;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.sidebar-content details summary::-webkit-details-marker {
|
||||
display: none; /* Hide default triangle in WebKit */
|
||||
}
|
||||
|
||||
.sidebar-content details summary:hover {
|
||||
background-color: var(--hover-bg);
|
||||
}
|
||||
|
||||
.sidebar-content details summary .icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.sidebar-content details summary::after {
|
||||
content: '';
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 18 15 12 9 6'/%3E%3C/svg%3E");
|
||||
background-size: 20px 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
margin-left: auto;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.sidebar-content details[open] summary::after {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.sidebar-content details .details-content {
|
||||
padding: 0 1.4rem 1rem;
|
||||
animation: details-slide-down 0.2s ease-out;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@keyframes details-slide-down {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.edit-form {
|
||||
margin: -1rem;
|
||||
margin-bottom: 1rem;
|
||||
@@ -310,14 +381,27 @@ body {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-family: inherit;
|
||||
font-size: 0.95rem;
|
||||
font-size: 1rem;
|
||||
box-sizing: border-box; /* Ensure padding doesn't overflow width */
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
outline: none;
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 2px rgb(0 123 255 / 10%);
|
||||
border-color: var(--link-color);
|
||||
box-shadow: 0 0 0 2px rgb(42 127 255 / 10%);
|
||||
}
|
||||
|
||||
select.form-control {
|
||||
appearance: none;
|
||||
background-color: #fff;
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 0.75rem center;
|
||||
background-size: 16px 16px;
|
||||
padding-right: 2.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-actions {
|
||||
@@ -335,12 +419,20 @@ body {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.settings-section p a {
|
||||
color: #007bff;
|
||||
.about-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.about-section a {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.settings-section p a:hover {
|
||||
.about-section a:visited {
|
||||
color: var(--link-color-visited);
|
||||
}
|
||||
|
||||
.about-section a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@ -349,7 +441,7 @@ body {
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #007bff;
|
||||
background: var(--link-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.75rem;
|
||||
@@ -378,7 +470,7 @@ body {
|
||||
}
|
||||
|
||||
.meta-info a {
|
||||
color: #007bff;
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -386,24 +478,34 @@ body {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
.sidebar-content table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.link-list li {
|
||||
margin-bottom: 0.5rem;
|
||||
.sidebar-content table th,
|
||||
.sidebar-content table td {
|
||||
padding: 0.5rem 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.link-list a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
font-size: 0.95rem;
|
||||
.sidebar-content table th {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: #898989;
|
||||
}
|
||||
|
||||
.link-list a:hover {
|
||||
text-decoration: underline;
|
||||
.sidebar-content table td {
|
||||
border-bottom: 1px solid #f9f9f9;
|
||||
}
|
||||
|
||||
.sidebar-content table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
.places-list {
|
||||
@@ -522,7 +624,7 @@ body {
|
||||
}
|
||||
|
||||
.btn-blue {
|
||||
background: #007bff;
|
||||
background: var(--link-color);
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
@@ -767,15 +869,14 @@ span.icon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Sidebar is open (Desktop: Left 300px) */
|
||||
/* Sidebar is open (Desktop: Left var(--sidebar-width)) */
|
||||
|
||||
/* We want to center in the remaining space (width - 300px) */
|
||||
/* We want to center in the remaining space (width - var(--sidebar-width)) */
|
||||
|
||||
/* Center X = 300 + (width - 300) / 2 = 300 + width/2 - 150 = width/2 + 150 */
|
||||
/* Center X = var(--sidebar-width) + (width - var(--sidebar-width)) / 2 = var(--sidebar-width)/2 + 50% */
|
||||
|
||||
/* So shift left by 150px from center */
|
||||
.map-container.sidebar-open .map-crosshair {
|
||||
left: calc(50% + 150px);
|
||||
left: calc(50% + var(--sidebar-width) / 2);
|
||||
}
|
||||
|
||||
@media (width <= 768px) {
|
||||
@@ -1063,7 +1164,7 @@ button.create-place {
|
||||
}
|
||||
|
||||
.place-lists-manager input[type='checkbox'] {
|
||||
accent-color: #007bff;
|
||||
accent-color: var(--link-color);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -5,7 +5,9 @@ import checkSquare from 'feather-icons/dist/icons/check-square.svg?raw';
|
||||
import clock from 'feather-icons/dist/icons/clock.svg?raw';
|
||||
import edit from 'feather-icons/dist/icons/edit.svg?raw';
|
||||
import facebook from 'feather-icons/dist/icons/facebook.svg?raw';
|
||||
import gift from 'feather-icons/dist/icons/gift.svg?raw';
|
||||
import globe from 'feather-icons/dist/icons/globe.svg?raw';
|
||||
import heart from 'feather-icons/dist/icons/heart.svg?raw';
|
||||
import home from 'feather-icons/dist/icons/home.svg?raw';
|
||||
import info from 'feather-icons/dist/icons/info.svg?raw';
|
||||
import instagram from 'feather-icons/dist/icons/instagram.svg?raw';
|
||||
@@ -35,7 +37,9 @@ const ICONS = {
|
||||
clock,
|
||||
edit,
|
||||
facebook,
|
||||
gift,
|
||||
globe,
|
||||
heart,
|
||||
home,
|
||||
info,
|
||||
instagram,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "marco",
|
||||
"version": "1.14.0",
|
||||
"version": "1.15.4",
|
||||
"private": true,
|
||||
"description": "Unhosted maps app",
|
||||
"repository": {
|
||||
@@ -35,7 +35,7 @@
|
||||
"lint:js:fix": "eslint . --fix",
|
||||
"start": "vite",
|
||||
"test": "vite build --mode development && testem ci --port 0",
|
||||
"preversion": "pnpm test",
|
||||
"preversion": "pnpm lint && pnpm test",
|
||||
"version": "pnpm build && git add release/"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
1
release/assets/main-BOfcjRke.css
Normal file
1
release/assets/main-BOfcjRke.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
release/assets/main-Bzf0iwOa.js
Normal file
2
release/assets/main-Bzf0iwOa.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -39,8 +39,8 @@
|
||||
<meta name="msapplication-TileColor" content="#F6E9A6">
|
||||
<meta name="msapplication-TileImage" content="/icons/icon-144.png">
|
||||
|
||||
<script type="module" crossorigin src="/assets/main-GynTgP18.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/main-BT0n1kYB.css">
|
||||
<script type="module" crossorigin src="/assets/main-Bzf0iwOa.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/main-BOfcjRke.css">
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user