Files
editor/src/components/modals/ModalExport.tsx
T
dependabot[bot] 4424276073 chore(deps-dev): Bump vite from 7.3.2 to 8.2.1 (#2081)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite)
from 7.3.2 to 8.2.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/releases">vite's
releases</a>.</em></p>
<blockquote>
<h2>plugin-legacy@8.2.1</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/plugin-legacy@8.2.1/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.2.1</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.2.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>create-vite@8.2.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/create-vite@8.2.0/packages/create-vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>plugin-legacy@8.2.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/plugin-legacy@8.2.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.2.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.2.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.2.0-beta.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.2.0-beta.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.1.5</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.1.5/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.1.4</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.1.4/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.1.3</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.1.3/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.1.2</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.1.2/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.1.1</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.1.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>create-vite@8.1.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/create-vite@8.1.0/packages/create-vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>plugin-legacy@8.1.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/plugin-legacy@8.1.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.1.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.1.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>plugin-legacy@8.1.0-beta.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/plugin-legacy@8.1.0-beta.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.1.0-beta.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.1.0-beta.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.0.16</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.0.16/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md">vite's
changelog</a>.</em></p>
<blockquote>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v8.2.0...v8.2.1">8.2.1</a>
(2026-08-06)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>build:</strong> make client chunkImportMap work with
<code>sharedPlugins: true</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23184">#23184</a>)
(<a
href="https://github.com/vitejs/vite/commit/15f03073c915d6ffb9a1fda447ef66b02bf5cde8">15f0307</a>)</li>
<li><strong>bundled-dev:</strong> inject client script tag before chunk
scripts (<a
href="https://redirect.github.com/vitejs/vite/issues/23161">#23161</a>)
(<a
href="https://github.com/vitejs/vite/commit/eac0cc84aa2472a85a19ee84561c1ba71e381a55">eac0cc8</a>)</li>
<li><strong>css:</strong> don't re-run lightningcss visitor during
minify (fix <a
href="https://redirect.github.com/vitejs/vite/issues/23146">#23146</a>)
(<a
href="https://redirect.github.com/vitejs/vite/issues/23147">#23147</a>)
(<a
href="https://github.com/vitejs/vite/commit/de041a79b05a0be965c874592fe2c1505bcd48df">de041a7</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23136">#23136</a>)
(<a
href="https://github.com/vitejs/vite/commit/14454fd8c9a399bc3fdc193e28465b6fcf001e4d">14454fd</a>)</li>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23070">#23070</a>)
(<a
href="https://github.com/vitejs/vite/commit/7ac6f7f590747bbdab9958e2c016e3dd04f10542">7ac6f7f</a>)</li>
<li>don't mutate the user config when resolving the lib entry from the
top-level <code>input</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23135">#23135</a>)
(<a
href="https://github.com/vitejs/vite/commit/b4bf59686a7ac238929e91a6e1708c739b843a2f">b4bf596</a>)</li>
<li>handle shebang ending with uncommon line terminators (<a
href="https://redirect.github.com/vitejs/vite/issues/23038">#23038</a>)
(<a
href="https://github.com/vitejs/vite/commit/17f7b2f193a110d0b47742ad296d182cb4666ce7">17f7b2f</a>)</li>
<li><strong>server:</strong> use a random port when port is 0 (<a
href="https://redirect.github.com/vitejs/vite/issues/23158">#23158</a>)
(<a
href="https://github.com/vitejs/vite/commit/fddf4ea41de5f7889037a2f957438857ac12a260">fddf4ea</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>css:</strong> look up pure CSS chunks through a Set (<a
href="https://redirect.github.com/vitejs/vite/issues/23114">#23114</a>)
(<a
href="https://github.com/vitejs/vite/commit/1331b0b438b1e7193effb7d2341660bccb9c3155">1331b0b</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li><strong>build:</strong> fix incomplete <code>@default</code> for
build.minify (<a
href="https://redirect.github.com/vitejs/vite/issues/23177">#23177</a>)
(<a
href="https://github.com/vitejs/vite/commit/ef02435114c57d0422028f0e6987f3df8db72969">ef02435</a>)</li>
</ul>
<h3>Miscellaneous Chores</h3>
<ul>
<li><strong>deps:</strong> update dependency rolldown-plugin-dts to
^0.28.0 (<a
href="https://redirect.github.com/vitejs/vite/issues/23137">#23137</a>)
(<a
href="https://github.com/vitejs/vite/commit/4adc1e7931d4beceb4e236d9a271d057c858a06f">4adc1e7</a>)</li>
<li><strong>deps:</strong> update dependency strip-literal to v4 (<a
href="https://redirect.github.com/vitejs/vite/issues/23140">#23140</a>)
(<a
href="https://github.com/vitejs/vite/commit/9db65ce63488ea8f08a3c98dcdc4282b17bd33ff">9db65ce</a>)</li>
</ul>
<h3>Code Refactoring</h3>
<ul>
<li><strong>bundled-dev:</strong> avoid injecting server values in the
bundle (<a
href="https://redirect.github.com/vitejs/vite/issues/22967">#22967</a>)
(<a
href="https://github.com/vitejs/vite/commit/23b8a088dec9dcc3f1c1353f2074f8644b3cc21f">23b8a08</a>)</li>
<li><strong>bundled-dev:</strong> remove rolldown lazy stub module
workaround (<a
href="https://redirect.github.com/vitejs/vite/issues/23129">#23129</a>)
(<a
href="https://github.com/vitejs/vite/commit/e72036eed2e28936ed824971b18aeaa3900857f6">e72036e</a>)</li>
</ul>
<h3>Tests</h3>
<ul>
<li><strong>bundled-dev:</strong> enable sourcemap playgrounds (<a
href="https://redirect.github.com/vitejs/vite/issues/23080">#23080</a>)
(<a
href="https://github.com/vitejs/vite/commit/c2155fe4d5c8d25fba3a7366d367e3296ae669fa">c2155fe</a>)</li>
<li>reduce logs (<a
href="https://redirect.github.com/vitejs/vite/issues/23138">#23138</a>)
(<a
href="https://github.com/vitejs/vite/commit/7673c02e53343ae9356c1f496c1c1da2eb732ac1">7673c02</a>)</li>
</ul>
<h2><a
href="https://github.com/vitejs/vite/compare/v8.2.0-beta.0...v8.2.0">8.2.0</a>
(2026-07-30)</h2>
<h3>Features</h3>
<ul>
<li>add <code>input</code> to <code>server.fs.allow</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/23035">#23035</a>)
(<a
href="https://github.com/vitejs/vite/commit/95a3cdab83e1125b03d2e8dd942fb6b64209e5fa">95a3cda</a>)</li>
<li><strong>bundled-dev:</strong> reload once after rebuild instead of
via the fallback page (<a
href="https://redirect.github.com/vitejs/vite/issues/23106">#23106</a>)
(<a
href="https://github.com/vitejs/vite/commit/b24381d741941b9ce2b1c07db62cc5f4d7bad981">b24381d</a>)</li>
<li><strong>bundled-dev:</strong> support worker file update accepted by
HMR (<a
href="https://redirect.github.com/vitejs/vite/issues/23068">#23068</a>)
(<a
href="https://github.com/vitejs/vite/commit/0d04351fdc12258c75b9f1cda5780fdb836ed0ef">0d04351</a>)</li>
<li><strong>config:</strong> include column in config incompatibility
location (<a
href="https://redirect.github.com/vitejs/vite/issues/23064">#23064</a>)
(<a
href="https://github.com/vitejs/vite/commit/8a245726944ed29225920d49be77c33c6e03afc8">8a24572</a>)</li>
<li><strong>dev:</strong> resolve interface name for explicit host in
network URLs (<a
href="https://redirect.github.com/vitejs/vite/issues/22965">#22965</a>)
(<a
href="https://github.com/vitejs/vite/commit/3ac77d9dd742968961af38a5a91ed6b061ceda7d">3ac77d9</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><strong>bundledDev:</strong> print build errors to the terminal when
an HMR update fails (<a
href="https://redirect.github.com/vitejs/vite/issues/23024">#23024</a>)
(<a
href="https://github.com/vitejs/vite/commit/41c465896e8b11b1eb9c5fbdafbdcc528e189a2c">41c4658</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/23069">#23069</a>)
(<a
href="https://github.com/vitejs/vite/commit/4c07b74416f859d7e8bdace13409ef2d080edf76">4c07b74</a>)</li>
<li><strong>hmr:</strong> preserve environment snapshot during server
restart (<a
href="https://redirect.github.com/vitejs/vite/issues/22992">#22992</a>)
(<a
href="https://github.com/vitejs/vite/commit/b1186c36d06bb94941c58e8272fc4acb8512c93b">b1186c3</a>)</li>
<li><strong>importAnalysis:</strong> interop imports injected into
optimized dep files by plugins (<a
href="https://redirect.github.com/vitejs/vite/issues/23029">#23029</a>)
(<a
href="https://github.com/vitejs/vite/commit/8c2a87d41fb24536e59643351758084cde4d0dd7">8c2a87d</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitejs/vite/commit/421615865dad3ed39137d17281814fc78a41246c"><code>4216158</code></a>
release: v8.2.1</li>
<li><a
href="https://github.com/vitejs/vite/commit/fddf4ea41de5f7889037a2f957438857ac12a260"><code>fddf4ea</code></a>
fix(server): use a random port when port is 0 (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23158">#23158</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/de041a79b05a0be965c874592fe2c1505bcd48df"><code>de041a7</code></a>
fix(css): don't re-run lightningcss visitor during minify (fix <a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23146">#23146</a>)
(<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23147">#23147</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/15f03073c915d6ffb9a1fda447ef66b02bf5cde8"><code>15f0307</code></a>
fix(build): make client chunkImportMap work with <code>sharedPlugins:
true</code> (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23184">#23184</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/c2155fe4d5c8d25fba3a7366d367e3296ae669fa"><code>c2155fe</code></a>
test(bundled-dev): enable sourcemap playgrounds (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23080">#23080</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/ef02435114c57d0422028f0e6987f3df8db72969"><code>ef02435</code></a>
docs(build): fix incomplete <code>@default</code> for build.minify (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23177">#23177</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/eac0cc84aa2472a85a19ee84561c1ba71e381a55"><code>eac0cc8</code></a>
fix(bundled-dev): inject client script tag before chunk scripts (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23161">#23161</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/23b8a088dec9dcc3f1c1353f2074f8644b3cc21f"><code>23b8a08</code></a>
refactor(bundled-dev): avoid injecting server values in the bundle (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22967">#22967</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/e72036eed2e28936ed824971b18aeaa3900857f6"><code>e72036e</code></a>
refactor(bundled-dev): remove rolldown lazy stub module workaround (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23129">#23129</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/14454fd8c9a399bc3fdc193e28465b6fcf001e4d"><code>14454fd</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23136">#23136</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/vitejs/vite/commits/v8.2.1/packages/vite">compare
view</a></li>
</ul>
</details>
<br />

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: HarelM <harel.mazor@gmail.com>
2026-08-19 22:09:14 +00:00

221 lines
6.9 KiB
TypeScript

import React from "react";
import Slugify from "slugify";
import {saveAs} from "file-saver";
import {version} from "maplibre-gl/package.json";
import {format} from "@maplibre/maplibre-gl-style-spec";
import {MdMap, MdSave} from "react-icons/md";
import {type WithTranslation, withTranslation} from "react-i18next";
import { FieldString } from "../FieldString";
import { InputButton } from "../InputButton";
import { Modal } from "./Modal";
import { replaceAccessTokens, stripAccessTokens } from "../../libs/style";
import { spec as fieldSpecAdditional } from "../../libs/field-spec-additional";
import type {OnStyleChangedCallback, StyleSpecificationWithId} from "../../libs/definitions";
const MAPLIBRE_GL_VERSION = version;
const showSaveFilePickerAvailable = typeof window.showSaveFilePicker === "function";
type ModalExportInternalProps = {
mapStyle: StyleSpecificationWithId
onStyleChanged: OnStyleChangedCallback
isOpen: boolean
onOpenToggle(): void
onSetFileHandle(fileHandle: FileSystemFileHandle | null): unknown
fileHandle: FileSystemFileHandle | null
} & WithTranslation;
class ModalExportInternal extends React.Component<ModalExportInternalProps> {
tokenizedStyle() {
return format(
stripAccessTokens(
replaceAccessTokens(this.props.mapStyle)
)
);
}
exportName() {
if (this.props.mapStyle.name) {
return Slugify(this.props.mapStyle.name, {
replacement: "_",
remove: /[*\-+~.()'"!:]/g,
lower: true
});
} else {
return this.props.mapStyle.id;
}
}
createHtml() {
const tokenStyle = this.tokenizedStyle();
const htmlTitle = this.props.mapStyle.name || this.props.t("Map");
const html = `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>${htmlTitle}</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<link href="https://unpkg.com/maplibre-gl@${MAPLIBRE_GL_VERSION}/dist/maplibre-gl.css" rel="stylesheet" />
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script type="module">
import {Map} from 'https://unpkg.com/maplibre-gl@${MAPLIBRE_GL_VERSION}/dist/maplibre-gl.mjs';
const map = new Map({
container: 'map',
style: ${tokenStyle},
});
map.addControl(new maplibregl.NavigationControl());
</script>
</body>
</html>
`;
const blob = new Blob([html], {type: "text/html;charset=utf-8"});
const exportName = this.exportName();
saveAs(blob, exportName + ".html");
}
async saveStyle() {
const tokenStyle = this.tokenizedStyle();
// it is not guaranteed that the File System Access API is available on all
// browsers. If the function is not available, a fallback behavior is used.
if (!showSaveFilePickerAvailable) {
const blob = new Blob([tokenStyle], {type: "application/json;charset=utf-8"});
const exportName = this.exportName();
saveAs(blob, exportName + ".json");
return;
}
let fileHandle = this.props.fileHandle;
if (fileHandle == null) {
fileHandle = await this.createFileHandle();
this.props.onSetFileHandle(fileHandle);
if (fileHandle == null) return;
}
const writable = await fileHandle.createWritable();
await writable.write(tokenStyle);
await writable.close();
this.props.onOpenToggle();
}
async saveStyleAs() {
const tokenStyle = this.tokenizedStyle();
const fileHandle = await this.createFileHandle();
this.props.onSetFileHandle(fileHandle);
if (fileHandle == null) return;
const writable = await fileHandle.createWritable();
await writable.write(tokenStyle);
await writable.close();
this.props.onOpenToggle();
}
async createFileHandle(): Promise<FileSystemFileHandle | null> {
const pickerOpts: SaveFilePickerOptions = {
types: [
{
description: "json",
accept: {"application/json": [".json"]},
},
],
suggestedName: this.exportName(),
};
const fileHandle = await window.showSaveFilePicker(pickerOpts) as FileSystemFileHandle;
this.props.onSetFileHandle(fileHandle);
return fileHandle;
}
changeMetadataProperty(property: string, value: any) {
const changedStyle = {
...this.props.mapStyle,
metadata: {
...this.props.mapStyle.metadata as any,
[property]: value
}
};
this.props.onStyleChanged(changedStyle);
}
render() {
const t = this.props.t;
const fsa = fieldSpecAdditional(t);
return <Modal
data-wd-key="modal:export"
isOpen={this.props.isOpen}
onOpenToggle={this.props.onOpenToggle}
title={t("Save Style")}
className="maputnik-export-modal"
>
<section className="maputnik-modal-section">
<h1>{t("Save Style")}</h1>
<p>
{t("Save the JSON style to your computer.")}
</p>
<div>
<FieldString
label={fsa.maputnik.maptiler_access_token.label}
fieldSpec={fsa.maputnik.maptiler_access_token}
value={(this.props.mapStyle.metadata || {} as any)["maputnik:openmaptiles_access_token"]}
onChange={this.changeMetadataProperty.bind(this, "maputnik:openmaptiles_access_token")}
/>
<FieldString
label={fsa.maputnik.thunderforest_access_token.label}
fieldSpec={fsa.maputnik.thunderforest_access_token}
value={(this.props.mapStyle.metadata || {} as any)["maputnik:thunderforest_access_token"]}
onChange={this.changeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
/>
<FieldString
label={fsa.maputnik.stadia_access_token.label}
fieldSpec={fsa.maputnik.stadia_access_token}
value={(this.props.mapStyle.metadata || {} as any)["maputnik:stadia_access_token"]}
onChange={this.changeMetadataProperty.bind(this, "maputnik:stadia_access_token")}
/>
<FieldString
label={fsa.maputnik.locationiq_access_token.label}
fieldSpec={fsa.maputnik.locationiq_access_token}
value={(this.props.mapStyle.metadata || {} as any)["maputnik:locationiq_access_token"]}
onChange={this.changeMetadataProperty.bind(this, "maputnik:locationiq_access_token")}
/>
</div>
<div className="maputnik-modal-export-buttons">
<InputButton onClick={this.saveStyle.bind(this)}>
<MdSave/>
{t("Save")}
</InputButton>
{showSaveFilePickerAvailable && (
<InputButton onClick={this.saveStyleAs.bind(this)}>
<MdSave/>
{t("Save as")}
</InputButton>
)}
<InputButton onClick={this.createHtml.bind(this)}>
<MdMap/>
{t("Create HTML")}
</InputButton>
</div>
</section>
</Modal>;
}
}
export const ModalExport = withTranslation()(ModalExportInternal);