mirror of
https://github.com/maputnik/editor.git
synced 2026-08-24 05:57:25 +00:00
Add global state modal (#1377)
## Launch Checklist This adds the ability to edit the global state. I think it deserves a modal of its own since I don't think it should be part of other modals... Here are some images: <img width="1274" height="254" alt="image" src="https://github.com/user-attachments/assets/4b6f2564-6c71-47da-9f8c-3bd2b97e1163" /> Initial dialog with no variable: <img width="640" height="254" alt="image" src="https://github.com/user-attachments/assets/b813b540-cae9-4c80-b2c0-4d965c022cb8" /> After you click add a few times: <img width="640" height="254" alt="image" src="https://github.com/user-attachments/assets/125cb978-90dc-4047-9694-b0ffc6eaa469" /> The state is updated as you change thing in the dialog. I didn't complicated it to select the type of the variable, but this can be added later of if there's a requirement to do so, I meant to keep it simple for now. - [x] Briefly describe the changes in this PR. - [x] Include before/after visuals or gifs if this PR includes visual changes. - [x] Write tests for all new functionality. - [x] Add an entry to `CHANGELOG.md` under the `## main` section. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
- Add support for hillshade's color arrays and relief-color elevation expression
|
- Add support for hillshade's color arrays and relief-color elevation expression
|
||||||
- Change layers icons to make them a bit more distinct
|
- Change layers icons to make them a bit more distinct
|
||||||
- Remove `@mdi` packages in favor of `react-icons`
|
- Remove `@mdi` packages in favor of `react-icons`
|
||||||
|
- Added global state modal to allow editing the global state
|
||||||
- _...Add new stuff here..._
|
- _...Add new stuff here..._
|
||||||
|
|
||||||
### 🐞 Bug fixes
|
### 🐞 Bug fixes
|
||||||
|
|||||||
@@ -304,6 +304,57 @@ describe("modals", () => {
|
|||||||
it("toggle");
|
it("toggle");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("global state", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
when.click("nav:global-state");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("add variable", () => {
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
|
state: { key1: { default: "value" } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("add multiple variables", () => {
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
|
state: { key1: { default: "value" }, key2: { default: "value" }, key3: { default: "value" } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("remove variable", () => {
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
when.click("global-state-remove-variable", 0);
|
||||||
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
|
state: { key2: { default: "value" }, key3: { default: "value" } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("edit variable key", () => {
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
when.setValue("global-state-variable-key:0", "mykey");
|
||||||
|
when.typeKeys("{enter}");
|
||||||
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
|
state: { mykey: { default: "value" } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("edit variable value", () => {
|
||||||
|
when.click("global-state-add-variable");
|
||||||
|
when.setValue("global-state-variable-value:0", "myvalue");
|
||||||
|
when.typeKeys("{enter}");
|
||||||
|
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
|
||||||
|
state: { key1: { default: "myvalue" } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("Handle localStorage QuotaExceededError", () => {
|
describe("Handle localStorage QuotaExceededError", () => {
|
||||||
it("handles quota exceeded error when opening style from URL", () => {
|
it("handles quota exceeded error when opening style from URL", () => {
|
||||||
// Clear localStorage to start fresh
|
// Clear localStorage to start fresh
|
||||||
|
|||||||
+21
-6
@@ -25,6 +25,7 @@ import ModalSources from "./modals/ModalSources";
|
|||||||
import ModalOpen from "./modals/ModalOpen";
|
import ModalOpen from "./modals/ModalOpen";
|
||||||
import ModalShortcuts from "./modals/ModalShortcuts";
|
import ModalShortcuts from "./modals/ModalShortcuts";
|
||||||
import ModalDebug from "./modals/ModalDebug";
|
import ModalDebug from "./modals/ModalDebug";
|
||||||
|
import ModalGlobalState from "./modals/ModalGlobalState";
|
||||||
|
|
||||||
import {downloadGlyphsMetadata, downloadSpriteMetadata} from "../libs/metadata";
|
import {downloadGlyphsMetadata, downloadSpriteMetadata} from "../libs/metadata";
|
||||||
import style from "../libs/style";
|
import style from "../libs/style";
|
||||||
@@ -126,6 +127,7 @@ type AppState = {
|
|||||||
shortcuts: boolean
|
shortcuts: boolean
|
||||||
export: boolean
|
export: boolean
|
||||||
debug: boolean
|
debug: boolean
|
||||||
|
globalState: boolean
|
||||||
}
|
}
|
||||||
fileHandle: FileSystemFileHandle | null
|
fileHandle: FileSystemFileHandle | null
|
||||||
};
|
};
|
||||||
@@ -164,6 +166,7 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
shortcuts: false,
|
shortcuts: false,
|
||||||
export: false,
|
export: false,
|
||||||
debug: false,
|
debug: false,
|
||||||
|
globalState: false,
|
||||||
},
|
},
|
||||||
maplibreGlDebugOptions: {
|
maplibreGlDebugOptions: {
|
||||||
showTileBoundaries: false,
|
showTileBoundaries: false,
|
||||||
@@ -213,6 +216,12 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
this.toggleModal("settings");
|
this.toggleModal("settings");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "g",
|
||||||
|
handler: () => {
|
||||||
|
this.toggleModal("globalState");
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "i",
|
key: "i",
|
||||||
handler: () => {
|
handler: () => {
|
||||||
@@ -911,39 +920,45 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
onChangeMaplibreGlDebug={this.onChangeMaplibreGlDebug}
|
onChangeMaplibreGlDebug={this.onChangeMaplibreGlDebug}
|
||||||
onChangeOpenlayersDebug={this.onChangeOpenlayersDebug}
|
onChangeOpenlayersDebug={this.onChangeOpenlayersDebug}
|
||||||
isOpen={this.state.isOpen.debug}
|
isOpen={this.state.isOpen.debug}
|
||||||
onOpenToggle={this.toggleModal.bind(this, "debug")}
|
onOpenToggle={() => this.toggleModal("debug")}
|
||||||
mapView={this.state.mapView}
|
mapView={this.state.mapView}
|
||||||
/>
|
/>
|
||||||
<ModalShortcuts
|
<ModalShortcuts
|
||||||
isOpen={this.state.isOpen.shortcuts}
|
isOpen={this.state.isOpen.shortcuts}
|
||||||
onOpenToggle={this.toggleModal.bind(this, "shortcuts")}
|
onOpenToggle={() => this.toggleModal("shortcuts")}
|
||||||
/>
|
/>
|
||||||
<ModalSettings
|
<ModalSettings
|
||||||
mapStyle={this.state.mapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
onStyleChanged={this.onStyleChanged}
|
onStyleChanged={this.onStyleChanged}
|
||||||
onChangeMetadataProperty={this.onChangeMetadataProperty}
|
onChangeMetadataProperty={this.onChangeMetadataProperty}
|
||||||
isOpen={this.state.isOpen.settings}
|
isOpen={this.state.isOpen.settings}
|
||||||
onOpenToggle={this.toggleModal.bind(this, "settings")}
|
onOpenToggle={() => this.toggleModal("settings")}
|
||||||
/>
|
/>
|
||||||
<ModalExport
|
<ModalExport
|
||||||
mapStyle={this.state.mapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
onStyleChanged={this.onStyleChanged}
|
onStyleChanged={this.onStyleChanged}
|
||||||
isOpen={this.state.isOpen.export}
|
isOpen={this.state.isOpen.export}
|
||||||
onOpenToggle={this.toggleModal.bind(this, "export")}
|
onOpenToggle={() => this.toggleModal("export")}
|
||||||
fileHandle={this.state.fileHandle}
|
fileHandle={this.state.fileHandle}
|
||||||
onSetFileHandle={this.onSetFileHandle}
|
onSetFileHandle={this.onSetFileHandle}
|
||||||
/>
|
/>
|
||||||
<ModalOpen
|
<ModalOpen
|
||||||
isOpen={this.state.isOpen.open}
|
isOpen={this.state.isOpen.open}
|
||||||
onStyleOpen={this.openStyle}
|
onStyleOpen={this.openStyle}
|
||||||
onOpenToggle={this.toggleModal.bind(this, "open")}
|
onOpenToggle={() => this.toggleModal("open")}
|
||||||
fileHandle={this.state.fileHandle}
|
fileHandle={this.state.fileHandle}
|
||||||
/>
|
/>
|
||||||
<ModalSources
|
<ModalSources
|
||||||
mapStyle={this.state.mapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
onStyleChanged={this.onStyleChanged}
|
onStyleChanged={this.onStyleChanged}
|
||||||
isOpen={this.state.isOpen.sources}
|
isOpen={this.state.isOpen.sources}
|
||||||
onOpenToggle={this.toggleModal.bind(this, "sources")}
|
onOpenToggle={() => this.toggleModal("sources")}
|
||||||
|
/>
|
||||||
|
<ModalGlobalState
|
||||||
|
mapStyle={this.state.mapStyle}
|
||||||
|
onStyleChanged={this.onStyleChanged}
|
||||||
|
isOpen={this.state.isOpen.globalState}
|
||||||
|
onOpenToggle={() => this.toggleModal("globalState")}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import {
|
|||||||
MdHelpOutline,
|
MdHelpOutline,
|
||||||
MdFindInPage,
|
MdFindInPage,
|
||||||
MdLanguage,
|
MdLanguage,
|
||||||
MdSave
|
MdSave,
|
||||||
|
MdPublic
|
||||||
} from "react-icons/md";
|
} from "react-icons/md";
|
||||||
import pkgJson from "../../package.json";
|
import pkgJson from "../../package.json";
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
@@ -236,6 +237,10 @@ class AppToolbarInternal extends React.Component<AppToolbarInternalProps> {
|
|||||||
<MdSettings />
|
<MdSettings />
|
||||||
<IconText>{t("Style Settings")}</IconText>
|
<IconText>{t("Style Settings")}</IconText>
|
||||||
</ToolbarAction>
|
</ToolbarAction>
|
||||||
|
<ToolbarAction wdKey="nav:global-state" onClick={this.props.onToggleModal.bind(this, "globalState")}>
|
||||||
|
<MdPublic />
|
||||||
|
<IconText>{t("Global State")}</IconText>
|
||||||
|
</ToolbarAction>
|
||||||
|
|
||||||
<ToolbarSelect wdKey="nav:inspect">
|
<ToolbarSelect wdKey="nav:inspect">
|
||||||
<MdFindInPage />
|
<MdFindInPage />
|
||||||
|
|||||||
+10
-3
@@ -3,8 +3,7 @@ import React from "react";
|
|||||||
const headers = {
|
const headers = {
|
||||||
js: "JS",
|
js: "JS",
|
||||||
android: "Android",
|
android: "Android",
|
||||||
ios: "iOS",
|
ios: "iOS"
|
||||||
macos: "macOS",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type DocProps = {
|
type DocProps = {
|
||||||
@@ -37,6 +36,14 @@ export default class Doc extends React.Component<DocProps> {
|
|||||||
!Array.isArray(values)
|
!Array.isArray(values)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sdkSupportToJsx = (value: string) => {
|
||||||
|
const supportValue = value.toLowerCase();
|
||||||
|
if (supportValue.startsWith("https://")) {
|
||||||
|
return <a href={supportValue} target="_blank" rel="noreferrer">{"#" + supportValue.split("/").pop()}</a>;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{doc &&
|
{doc &&
|
||||||
@@ -74,7 +81,7 @@ export default class Doc extends React.Component<DocProps> {
|
|||||||
<td>{key}</td>
|
<td>{key}</td>
|
||||||
{Object.keys(headers).map((k) => {
|
{Object.keys(headers).map((k) => {
|
||||||
if (Object.prototype.hasOwnProperty.call(supportObj, k)) {
|
if (Object.prototype.hasOwnProperty.call(supportObj, k)) {
|
||||||
return <td key={k}>{supportObj[k as keyof typeof headers]}</td>;
|
return <td key={k}>{sdkSupportToJsx(supportObj[k as keyof typeof headers])}</td>;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return <td key={k}>no</td>;
|
return <td key={k}>no</td>;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ type ModalInternalProps = PropsWithChildren & {
|
|||||||
"data-wd-key"?: string
|
"data-wd-key"?: string
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
title: string
|
title: string
|
||||||
onOpenToggle(value: boolean): unknown
|
onOpenToggle(): void
|
||||||
underlayClickExits?: boolean
|
underlayClickExits?: boolean
|
||||||
className?: string
|
className?: string
|
||||||
} & WithTranslation;
|
} & WithTranslation;
|
||||||
@@ -26,7 +26,7 @@ class ModalInternal extends React.Component<ModalInternalProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.props.onOpenToggle(false);
|
this.props.onOpenToggle();
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ type ModalAddInternalProps = {
|
|||||||
layers: LayerSpecification[]
|
layers: LayerSpecification[]
|
||||||
onLayersChange(layers: LayerSpecification[]): unknown
|
onLayersChange(layers: LayerSpecification[]): unknown
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onOpenToggle(open: boolean): unknown
|
onOpenToggle(): void
|
||||||
// A dict of source id's and the available source layers
|
// A dict of source id's and the available source layers
|
||||||
sources: Record<string, SourceSpecification & {layers: string[]}>;
|
sources: Record<string, SourceSpecification & {layers: string[]}>;
|
||||||
} & WithTranslation;
|
} & WithTranslation;
|
||||||
@@ -50,7 +50,7 @@ class ModalAddInternal extends React.Component<ModalAddInternalProps, ModalAddSt
|
|||||||
changedLayers.push(layer as LayerSpecification);
|
changedLayers.push(layer as LayerSpecification);
|
||||||
this.setState({ error: null }, () => {
|
this.setState({ error: null }, () => {
|
||||||
this.props.onLayersChange(changedLayers);
|
this.props.onLayersChange(changedLayers);
|
||||||
this.props.onOpenToggle(false);
|
this.props.onOpenToggle();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type ModalDebugInternalProps = {
|
|||||||
renderer: string
|
renderer: string
|
||||||
onChangeMaplibreGlDebug(key: string, checked: boolean): unknown
|
onChangeMaplibreGlDebug(key: string, checked: boolean): unknown
|
||||||
onChangeOpenlayersDebug(key: string, checked: boolean): unknown
|
onChangeOpenlayersDebug(key: string, checked: boolean): unknown
|
||||||
onOpenToggle(value: boolean): unknown
|
onOpenToggle(): void
|
||||||
maplibreGlDebugOptions?: object
|
maplibreGlDebugOptions?: object
|
||||||
openlayersDebugOptions?: object
|
openlayersDebugOptions?: object
|
||||||
mapView: {
|
mapView: {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type ModalExportInternalProps = {
|
|||||||
mapStyle: StyleSpecificationWithId
|
mapStyle: StyleSpecificationWithId
|
||||||
onStyleChanged: OnStyleChangedCallback
|
onStyleChanged: OnStyleChangedCallback
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onOpenToggle(...args: unknown[]): unknown
|
onOpenToggle(): void
|
||||||
onSetFileHandle(fileHandle: FileSystemFileHandle | null): unknown
|
onSetFileHandle(fileHandle: FileSystemFileHandle | null): unknown
|
||||||
fileHandle: FileSystemFileHandle | null
|
fileHandle: FileSystemFileHandle | null
|
||||||
} & WithTranslation;
|
} & WithTranslation;
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { withTranslation, type WithTranslation } from "react-i18next";
|
||||||
|
import { MdDelete } from "react-icons/md";
|
||||||
|
import latest from "@maplibre/maplibre-gl-style-spec/dist/latest.json";
|
||||||
|
|
||||||
|
import Modal from "./Modal";
|
||||||
|
import FieldString from "../FieldString";
|
||||||
|
import InputButton from "../InputButton";
|
||||||
|
import { PiListPlusBold } from "react-icons/pi";
|
||||||
|
import { type StyleSpecificationWithId } from "../../libs/definitions";
|
||||||
|
import { type SchemaSpecification } from "maplibre-gl";
|
||||||
|
import Doc from "../Doc";
|
||||||
|
|
||||||
|
type ModalGlobalStateInternalProps = {
|
||||||
|
mapStyle: StyleSpecificationWithId;
|
||||||
|
isOpen: boolean;
|
||||||
|
onStyleChanged(style: StyleSpecificationWithId): void;
|
||||||
|
onOpenToggle(): void
|
||||||
|
} & WithTranslation;
|
||||||
|
|
||||||
|
type GlobalStateVariable = {
|
||||||
|
key: string;
|
||||||
|
value: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModalGlobalStateInternal: React.FC<ModalGlobalStateInternalProps> = (props) => {
|
||||||
|
const getGlobalStateVariables = (): GlobalStateVariable[] => {
|
||||||
|
const style = props.mapStyle;
|
||||||
|
const globalState = style.state || {};
|
||||||
|
|
||||||
|
return Object.entries(globalState).map(([key, value]) => ({
|
||||||
|
key,
|
||||||
|
value: value.default
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const setGlobalStateVariables = (variables: GlobalStateVariable[]) => {
|
||||||
|
const style = { ...props.mapStyle };
|
||||||
|
|
||||||
|
// Create the globalState object from the variables array
|
||||||
|
const globalState: Record<string, SchemaSpecification> = {};
|
||||||
|
for (const variable of variables) {
|
||||||
|
if (variable.key.trim() !== "") {
|
||||||
|
globalState[variable.key] = {
|
||||||
|
default: variable.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
style.state = Object.keys(globalState).length > 0 ? globalState : undefined;
|
||||||
|
|
||||||
|
props.onStyleChanged(style);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAddVariable = () => {
|
||||||
|
const variables = getGlobalStateVariables();
|
||||||
|
let index = 1;
|
||||||
|
while (variables.find(v => v.key === `key${index}`)) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
variables.push({ key: `key${index}`, value: "value" });
|
||||||
|
setGlobalStateVariables(variables);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRemoveVariable = (index: number) => {
|
||||||
|
const variables = getGlobalStateVariables();
|
||||||
|
variables.splice(index, 1);
|
||||||
|
setGlobalStateVariables(variables);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeVariableKey = (index: number, newKey: string) => {
|
||||||
|
const variables = getGlobalStateVariables();
|
||||||
|
variables[index].key = newKey || "";
|
||||||
|
setGlobalStateVariables(variables);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeVariableValue = (index: number, newValue: string) => {
|
||||||
|
const variables = getGlobalStateVariables();
|
||||||
|
|
||||||
|
variables[index].value = newValue || "";
|
||||||
|
setGlobalStateVariables(variables);
|
||||||
|
};
|
||||||
|
|
||||||
|
const variables = getGlobalStateVariables();
|
||||||
|
|
||||||
|
const variableFields = variables.map((variable, index) => (
|
||||||
|
<tr key={index}>
|
||||||
|
<td>
|
||||||
|
<FieldString
|
||||||
|
label={props.t("Key")}
|
||||||
|
value={variable.key}
|
||||||
|
onChange={(value) => onChangeVariableKey(index, value || "")}
|
||||||
|
data-wd-key={"global-state-variable-key:" + index}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<FieldString
|
||||||
|
label={props.t("Value")}
|
||||||
|
value={variable.value}
|
||||||
|
onChange={(value) => onChangeVariableValue(index, value || "")}
|
||||||
|
data-wd-key={"global-state-variable-value:" + index}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td style={{ verticalAlign: "middle"}}>
|
||||||
|
<InputButton
|
||||||
|
onClick={() => onRemoveVariable(index)}
|
||||||
|
title={props.t("Remove variable")}
|
||||||
|
data-wd-key="global-state-remove-variable"
|
||||||
|
>
|
||||||
|
<MdDelete />
|
||||||
|
</InputButton>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
data-wd-key="modal:global-state"
|
||||||
|
isOpen={props.isOpen}
|
||||||
|
onOpenToggle={props.onOpenToggle}
|
||||||
|
title={props.t("Global State Variables")}
|
||||||
|
>
|
||||||
|
|
||||||
|
{variables.length === 0 &&
|
||||||
|
<div>
|
||||||
|
<p>{props.t("No global state variables defined. Add variables to create reusable values in your style.")}</p>
|
||||||
|
<div key="doc" className="maputnik-doc-inline">
|
||||||
|
<Doc fieldSpec={latest.$root.state} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{variables.length > 0 &&
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{variableFields}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
<div>
|
||||||
|
<InputButton
|
||||||
|
onClick={onAddVariable}
|
||||||
|
data-wd-key="global-state-add-variable"
|
||||||
|
>
|
||||||
|
<PiListPlusBold />
|
||||||
|
{props.t("Add Variable")}
|
||||||
|
</InputButton>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModalGlobalState = withTranslation()(ModalGlobalStateInternal);
|
||||||
|
export default ModalGlobalState;
|
||||||
@@ -45,7 +45,7 @@ class PublicStyle extends React.Component<PublicStyleProps> {
|
|||||||
|
|
||||||
type ModalOpenInternalProps = {
|
type ModalOpenInternalProps = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onOpenToggle(...args: unknown[]): unknown
|
onOpenToggle(): void
|
||||||
onStyleOpen(...args: unknown[]): unknown
|
onStyleOpen(...args: unknown[]): unknown
|
||||||
fileHandle: FileSystemFileHandle | null
|
fileHandle: FileSystemFileHandle | null
|
||||||
} & WithTranslation;
|
} & WithTranslation;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ type ModalSettingsInternalProps = {
|
|||||||
onStyleChanged: OnStyleChangedCallback
|
onStyleChanged: OnStyleChangedCallback
|
||||||
onChangeMetadataProperty(...args: unknown[]): unknown
|
onChangeMetadataProperty(...args: unknown[]): unknown
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onOpenToggle(...args: unknown[]): unknown
|
onOpenToggle(): void
|
||||||
} & WithTranslation;
|
} & WithTranslation;
|
||||||
|
|
||||||
class ModalSettingsInternal extends React.Component<ModalSettingsInternalProps> {
|
class ModalSettingsInternal extends React.Component<ModalSettingsInternalProps> {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Modal from "./Modal";
|
|||||||
|
|
||||||
type ModalShortcutsInternalProps = {
|
type ModalShortcutsInternalProps = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onOpenToggle(...args: unknown[]): unknown
|
onOpenToggle(): void
|
||||||
} & WithTranslation;
|
} & WithTranslation;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ class AddSource extends React.Component<AddSourceProps, AddSourceState> {
|
|||||||
type ModalSourcesInternalProps = {
|
type ModalSourcesInternalProps = {
|
||||||
mapStyle: StyleSpecificationWithId
|
mapStyle: StyleSpecificationWithId
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onOpenToggle(...args: unknown[]): unknown
|
onOpenToggle(): void
|
||||||
onStyleChanged: OnStyleChangedCallback
|
onStyleChanged: OnStyleChangedCallback
|
||||||
} & WithTranslation;
|
} & WithTranslation;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user