🚧 First svelte component
This commit is contained in:
parent
1c1df43bf9
commit
203d1b6b34
10 changed files with 809 additions and 668 deletions
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"printWidth": 100
|
"printWidth": 100,
|
||||||
|
"plugins": ["prettier-plugin-svelte"],
|
||||||
|
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||||
}
|
}
|
||||||
|
|
51
UI/Base/SubtleButton.svelte
Normal file
51
UI/Base/SubtleButton.svelte
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import { Store } from "../../Logic/UIEventSource"
|
||||||
|
import BaseUIElement from "../BaseUIElement"
|
||||||
|
import Img from "./Img"
|
||||||
|
import Translations from "../i18n/Translations"
|
||||||
|
|
||||||
|
export let imageUrl: string | BaseUIElement
|
||||||
|
export let message: string | BaseUIElement
|
||||||
|
export let options: { url?: string | Store<string>; newTab?: boolean; imgSize?: string, extraClasses?: string }
|
||||||
|
|
||||||
|
let element: HTMLElement
|
||||||
|
let href = typeof options?.url == "string" ? options.url : ""
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (typeof options?.url != "string" && options?.url != undefined) {
|
||||||
|
options.url.addCallbackAndRun((data) => {
|
||||||
|
href = data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let img: BaseUIElement
|
||||||
|
const imgClasses = "block justify-center flex-none mr-4 " + (options?.imgSize ?? "h-11 w-11")
|
||||||
|
if ((imageUrl ?? "") === "") {
|
||||||
|
img = undefined
|
||||||
|
} else if (typeof imageUrl === "string") {
|
||||||
|
img = new Img(imageUrl)?.SetClass(imgClasses)
|
||||||
|
} else {
|
||||||
|
img = imageUrl?.SetClass(imgClasses)
|
||||||
|
}
|
||||||
|
if (img != undefined) element.appendChild(img.ConstructElement())
|
||||||
|
|
||||||
|
let msg = Translations.W(message)?.SetClass("block text-ellipsis no-images flex-shrink")
|
||||||
|
element.appendChild(msg.ConstructElement())
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if options?.url == undefined}
|
||||||
|
<span bind:this={element} class="{options.extraClasses}"/>
|
||||||
|
{:else}
|
||||||
|
<a {href} class="no-underline" bind:this={element} target={options?.newTab ? "_blank" : ""} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
span,
|
||||||
|
a {
|
||||||
|
@apply flex p-3 my-2 rounded-lg hover:shadow-xl transition-colors transition-shadow;
|
||||||
|
@apply items-center w-full;
|
||||||
|
@apply bg-subtle text-black hover:bg-unsubtle;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,13 +1,11 @@
|
||||||
import Translations from "../i18n/Translations"
|
|
||||||
import Combine from "./Combine"
|
|
||||||
import BaseUIElement from "../BaseUIElement"
|
import BaseUIElement from "../BaseUIElement"
|
||||||
import Link from "./Link"
|
|
||||||
import Img from "./Img"
|
|
||||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||||
import { UIElement } from "../UIElement"
|
import { UIElement } from "../UIElement"
|
||||||
import { VariableUiElement } from "./VariableUIElement"
|
import { VariableUiElement } from "./VariableUIElement"
|
||||||
import Lazy from "./Lazy"
|
import Lazy from "./Lazy"
|
||||||
import Loading from "./Loading"
|
import Loading from "./Loading"
|
||||||
|
import SubtleButtonSvelte from "./SubtleButton.svelte"
|
||||||
|
import SvelteUIElement from "./SvelteUIElement"
|
||||||
|
|
||||||
export class SubtleButton extends UIElement {
|
export class SubtleButton extends UIElement {
|
||||||
private readonly imageUrl: string | BaseUIElement
|
private readonly imageUrl: string | BaseUIElement
|
||||||
|
@ -15,7 +13,7 @@ export class SubtleButton extends UIElement {
|
||||||
private readonly options: {
|
private readonly options: {
|
||||||
url?: string | Store<string>
|
url?: string | Store<string>
|
||||||
newTab?: boolean
|
newTab?: boolean
|
||||||
imgSize?: string
|
imgSize?: string,
|
||||||
extraClasses?: string
|
extraClasses?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +23,9 @@ export class SubtleButton extends UIElement {
|
||||||
options: {
|
options: {
|
||||||
url?: string | Store<string>
|
url?: string | Store<string>
|
||||||
newTab?: boolean
|
newTab?: boolean
|
||||||
imgSize?: "h-11 w-11" | string
|
imgSize?: "h-11 w-11" | string,
|
||||||
extraClasses?: string
|
extraClasses?: string
|
||||||
} = undefined
|
} = {}
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.imageUrl = imageUrl
|
this.imageUrl = imageUrl
|
||||||
|
@ -36,30 +34,11 @@ export class SubtleButton extends UIElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected InnerRender(): string | BaseUIElement {
|
protected InnerRender(): string | BaseUIElement {
|
||||||
const classes =
|
return new SvelteUIElement(SubtleButtonSvelte, {
|
||||||
"block flex p-3 my-2 bg-subtle rounded-lg hover:shadow-xl hover:bg-unsubtle transition-colors transition-shadow link-no-underline " +
|
imageUrl: this?.imageUrl ?? undefined,
|
||||||
(this?.options?.extraClasses ?? "")
|
message: this?.message ?? "",
|
||||||
const message = Translations.W(this.message)?.SetClass(
|
options: this?.options ?? {},
|
||||||
"block text-ellipsis no-images flex-shrink"
|
})
|
||||||
)
|
|
||||||
let img
|
|
||||||
const imgClasses =
|
|
||||||
"block justify-center flex-none mr-4 " + (this.options?.imgSize ?? "h-11 w-11")
|
|
||||||
if ((this.imageUrl ?? "") === "") {
|
|
||||||
img = undefined
|
|
||||||
} else if (typeof this.imageUrl === "string") {
|
|
||||||
img = new Img(this.imageUrl)?.SetClass(imgClasses)
|
|
||||||
} else {
|
|
||||||
img = this.imageUrl?.SetClass(imgClasses)
|
|
||||||
}
|
|
||||||
const button = new Combine([img, message]).SetClass("flex items-center group w-full")
|
|
||||||
|
|
||||||
if (this.options?.url == undefined) {
|
|
||||||
this.SetClass(classes)
|
|
||||||
return button
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Link(button, this.options.url, this.options.newTab ?? false).SetClass(classes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnClickWithLoading(
|
public OnClickWithLoading(
|
||||||
|
|
21
UI/Base/SvelteUIElement.ts
Normal file
21
UI/Base/SvelteUIElement.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import BaseUIElement from "../BaseUIElement"
|
||||||
|
|
||||||
|
export default class SvelteUIElement extends BaseUIElement {
|
||||||
|
private readonly _svelteComponent
|
||||||
|
private readonly _props: Record<string, any>
|
||||||
|
|
||||||
|
constructor(svelteElement, props: Record<string, any>) {
|
||||||
|
super()
|
||||||
|
this._svelteComponent = svelteElement
|
||||||
|
this._props = props
|
||||||
|
}
|
||||||
|
|
||||||
|
protected InnerConstructElement(): HTMLElement {
|
||||||
|
const el = document.createElement("div")
|
||||||
|
new this._svelteComponent({
|
||||||
|
target: el,
|
||||||
|
props: this._props,
|
||||||
|
})
|
||||||
|
return el
|
||||||
|
}
|
||||||
|
}
|
1317
package-lock.json
generated
1317
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -6,6 +6,7 @@
|
||||||
"bugs": "https://github.com/pietervdvn/MapComplete/issues",
|
"bugs": "https://github.com/pietervdvn/MapComplete/issues",
|
||||||
"homepage": "https://mapcomplete.osm.be",
|
"homepage": "https://mapcomplete.osm.be",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run generate:layeroverview && npm run strt",
|
"start": "npm run generate:layeroverview && npm run strt",
|
||||||
"strt": "vite",
|
"strt": "vite",
|
||||||
|
@ -108,6 +109,8 @@
|
||||||
"@babel/preset-env": "7.13.8",
|
"@babel/preset-env": "7.13.8",
|
||||||
"@parcel/service-worker": "^2.6.0",
|
"@parcel/service-worker": "^2.6.0",
|
||||||
"@rollup/plugin-json": "^6.0.0",
|
"@rollup/plugin-json": "^6.0.0",
|
||||||
|
"@sveltejs/vite-plugin-svelte": "^2.0.2",
|
||||||
|
"@tsconfig/svelte": "^3.0.0",
|
||||||
"@types/chai": "^4.3.0",
|
"@types/chai": "^4.3.0",
|
||||||
"@types/geojson": "^7946.0.10",
|
"@types/geojson": "^7946.0.10",
|
||||||
"@types/leaflet-markercluster": "^1.0.3",
|
"@types/leaflet-markercluster": "^1.0.3",
|
||||||
|
@ -125,10 +128,15 @@
|
||||||
"fs": "0.0.1-security",
|
"fs": "0.0.1-security",
|
||||||
"mocha": "^9.2.2",
|
"mocha": "^9.2.2",
|
||||||
"prettier": "2.7.1",
|
"prettier": "2.7.1",
|
||||||
|
"prettier-plugin-svelte": "^2.9.0",
|
||||||
"read-file": "^0.2.0",
|
"read-file": "^0.2.0",
|
||||||
|
"sass": "^1.57.1",
|
||||||
"sharp": "^0.30.5",
|
"sharp": "^0.30.5",
|
||||||
|
"svelte": "^3.55.1",
|
||||||
|
"svelte-check": "^3.0.2",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"ts2json-schema": "^1.4.0",
|
"ts2json-schema": "^1.4.0",
|
||||||
|
"tslib": "^2.4.1",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"tslint-no-circular-imports": "^0.7.0",
|
"tslint-no-circular-imports": "^0.7.0",
|
||||||
"typescript": "^4.7.4",
|
"typescript": "^4.7.4",
|
||||||
|
|
5
postcss.config.cjs
Normal file
5
postcss.config.cjs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const tailwindcss = require("tailwindcss")
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
plugins: [tailwindcss("./tailwind.config.cjs")],
|
||||||
|
}
|
7
svelte.config.js
Normal file
7
svelte.config.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
||||||
|
// for more information about preprocessors
|
||||||
|
preprocess: vitePreprocess(),
|
||||||
|
}
|
|
@ -1,23 +1,27 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
const plugin = require("tailwindcss/plugin");
|
const plugin = require("tailwindcss/plugin")
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ["./**/*.html", "./**/*.ts"],
|
content: ["./**/*.{html,ts,svelte}"],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
maxHeight: {
|
maxHeight: {
|
||||||
"65vh": "65vh",
|
"65vh": "65vh",
|
||||||
"20vh": "20vh",
|
"20vh": "20vh",
|
||||||
},
|
},
|
||||||
|
colors: {
|
||||||
|
subtle: "#dbeafe",
|
||||||
|
unsubtle: "#bfdbfe",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
plugin(function ({ addVariant, e }) {
|
plugin(function ({ addVariant, e }) {
|
||||||
addVariant("landscape", ({ modifySelectors, separator }) => {
|
addVariant("landscape", ({ modifySelectors, separator }) => {
|
||||||
modifySelectors(({ className }) => {
|
modifySelectors(({ className }) => {
|
||||||
return `.${e(`landscape${separator}${className}`)}:landscape`;
|
return `.${e(`landscape${separator}${className}`)}:landscape`
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
const { defineConfig } = require("vite")
|
import { defineConfig } from "vite"
|
||||||
|
import { svelte } from "@sveltejs/vite-plugin-svelte"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
|
|
||||||
const allHtmlFiles = fs.readdirSync(".").filter((f) => f.endsWith(".html"))
|
const allHtmlFiles = fs.readdirSync(".").filter((f) => f.endsWith(".html"))
|
||||||
const input = {}
|
const input = {}
|
||||||
const ASSET_URL = process.env.ASSET_URL || ""
|
const ASSET_URL = process.env.ASSET_URL || ""
|
||||||
|
@ -9,13 +11,14 @@ for (const html of allHtmlFiles) {
|
||||||
input[name] = "./" + html
|
input[name] = "./" + html
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = defineConfig({
|
export default defineConfig({
|
||||||
build: {
|
build: {
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input,
|
input,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
base: `${ASSET_URL}`,
|
base: `${ASSET_URL}`,
|
||||||
|
plugins: [svelte()],
|
||||||
server: {
|
server: {
|
||||||
port: 1234,
|
port: 1234,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue