Add CommandIconButton functionality
This commit is contained in:
parent
0963d53e0c
commit
ccb7c5d68a
@ -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>
|
||||
|
57
ts/editor-toolbar/CommandIconButton.svelte
Normal file
57
ts/editor-toolbar/CommandIconButton.svelte
Normal 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>
|
@ -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,
|
||||
|
@ -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>
|
||||
|
36
ts/editor-toolbar/IconButtonInner.svelte
Normal file
36
ts/editor-toolbar/IconButtonInner.svelte
Normal 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>
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
ts/editor-toolbar/format.ts
Normal file
48
ts/editor-toolbar/format.ts
Normal 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);
|
Loading…
Reference in New Issue
Block a user