Add CommandIconButton functionality

This commit is contained in:
Henrik Giesel 2021-03-29 21:05:30 +02:00
parent 0963d53e0c
commit ccb7c5d68a
7 changed files with 173 additions and 53 deletions

View File

@ -6,11 +6,19 @@
</script>
<style lang="scss">
span {
button {
display: inline-block;
width: 28px;
height: 28px;
vertical-align: -webkit-baseline-middle;
padding: 0;
}
span {
display: inline-block;
width: 100%;
height: 100%;
}
input {
@ -21,5 +29,7 @@
</style>
<ButtonItem>
<span class={className}> <input type="color" on:change={onChange} /> </span>
<button>
<span class={className}> <input type="color" on:change={onChange} /> </span>
</button>
</ButtonItem>

View File

@ -0,0 +1,57 @@
<script lang="typescript" context="module">
import { writable } from "svelte/store";
export const commandMap = writable(new Map<string, boolean>());
function updateButton(key: string): void {
commandMap.update(
(map: Map<string, boolean>): Map<string, boolean> =>
new Map([...map, [key, document.queryCommandState(key)]])
);
}
export function updateButtons() {
commandMap.update(
(map: Map<string, boolean>): Map<string, boolean> => {
const newMap = new Map<string, boolean>();
for (const key of map.keys()) {
newMap.set(key, document.queryCommandState(key));
}
return newMap;
}
);
}
</script>
<script lang="typescript">
import ButtonItem from "./ButtonItem.svelte";
import IconButtonInner from "./IconButtonInner.svelte";
export let className = "";
export let icon = "";
export let command: string;
export let activatable = true;
let active = false;
if (activatable) {
updateButton(command);
commandMap.subscribe((map: Record<string, boolean>): void => {
active = map.get(command);
return () => map.delete(command);
});
}
function onClick(event: ClickEvent): void {
document.execCommand(command);
}
</script>
<ButtonItem>
<IconButtonInner {className} {active} {onClick}>
{@html icon}
</IconButtonInner>
</ButtonItem>

View File

@ -5,19 +5,20 @@
import LabelButton from "./LabelButton.svelte";
import IconButton from "./IconButton.svelte";
import boldIcon from "./type-bold.svg";
import italicIcon from "./type-italic.svg";
import underlineIcon from "./type-underline.svg";
import superscriptIcon from "./format-superscript.svg";
import subscriptIcon from "./format-subscript.svg";
import bracketsIcon from "./code-brackets.svg";
import eraserIcon from "./eraser.svg";
import paperclipIcon from "./paperclip.svg";
import micIcon from "./mic.svg";
import threeDotsIcon from "./three-dots.svg";
import {
boldButton,
italicButton,
underlineButton,
superscriptButton,
subscriptButton,
eraserButton,
} from "./format";
import { forecolorButton, colorpickerButton } from "./color";
export let leftButtons = [
@ -26,14 +27,12 @@
];
export let rightButtons = [
{ component: IconButton, icon: boldIcon },
{ component: IconButton, icon: italicIcon },
{ component: IconButton, icon: underlineIcon },
{ component: IconButton, icon: superscriptIcon },
{ component: IconButton, icon: subscriptIcon },
{ component: IconButton, icon: eraserIcon },
boldButton,
italicButton,
underlineButton,
superscriptButton,
subscriptButton,
eraserButton,
forecolorButton,
colorpickerButton,

View File

@ -1,31 +1,14 @@
<script lang="typescript">
import ButtonItem from "./ButtonItem.svelte";
import IconButtonInner from "./IconButtonInner.svelte";
export let className: string;
export let icon: string;
export let className = "";
export let icon = "";
export let onClick: (event: ClickEvent) => void;
</script>
<style lang="scss">
span {
display: inline-block;
width: 28px;
height: 28px;
vertical-align: -webkit-baseline-middle;
& > :global(svg),
& > :global(img) {
vertical-align: unset;
width: 100%;
height: 100%;
}
}
</style>
<ButtonItem>
<span class={className} on:click={onClick} on:mousedown|preventDefault>
{#if icon}
{@html icon}
{/if}
</span>
<IconButtonInner {className} active={false} {onClick}>
{@html icon}
</IconButtonInner>
</ButtonItem>

View File

@ -0,0 +1,36 @@
<script lang="typescript">
export let className: string;
export let onClick: (event: ClickEvent) => void;
export let active: boolean;
</script>
<style lang="scss">
button {
display: inline-block;
width: 28px;
height: 28px;
vertical-align: -webkit-baseline-middle;
padding: 2px;
& > :global(svg),
& > :global(img) {
vertical-align: unset;
width: 100%;
height: 100%;
}
}
.active {
border-bottom: 3px solid black;
border-radius: 3px;
:global(.nightMode) & {
border-bottom-color: white;
}
}
</style>
<button class={className} class:active on:click={onClick} on:mousedown|preventDefault>
<slot />
</button>

View File

@ -10,10 +10,6 @@ button.linkb {
opacity: 0.3;
cursor: not-allowed;
}
.nightMode & > img {
filter: invert(180);
}
}
button:focus {
@ -28,13 +24,4 @@ button.highlighted {
background: linear-gradient(0deg, #333333 0%, #434343 100%);
}
}
#topbutsright & {
border-bottom: 3px solid black;
border-radius: 3px;
.nightMode & {
border-bottom-color: white;
}
}
}

View File

@ -0,0 +1,48 @@
// @ts-ignore
import CommandIconButton, { updateButtons } from "./CommandIconButton.svelte";
import boldIcon from "./type-bold.svg";
import italicIcon from "./type-italic.svg";
import underlineIcon from "./type-underline.svg";
import superscriptIcon from "./format-superscript.svg";
import subscriptIcon from "./format-subscript.svg";
import eraserIcon from "./eraser.svg";
export const boldButton = {
component: CommandIconButton,
icon: boldIcon,
command: "bold",
};
export const italicButton = {
component: CommandIconButton,
icon: italicIcon,
command: "italic",
};
export const underlineButton = {
component: CommandIconButton,
icon: underlineIcon,
command: "underline",
};
export const superscriptButton = {
component: CommandIconButton,
icon: superscriptIcon,
command: "superscript",
};
export const subscriptButton = {
component: CommandIconButton,
icon: subscriptIcon,
command: "subscript",
};
export const eraserButton = {
component: CommandIconButton,
icon: eraserIcon,
command: "removeFormat",
highlightable: false,
};
// TODO
setInterval(updateButtons, 2000);