mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Activate FormatBlockButtons
This commit is contained in:
parent
baff3df381
commit
bd31a19852
8 changed files with 162 additions and 115 deletions
|
@ -3,17 +3,18 @@ Copyright: Ankitects Pty Ltd and contributors
|
|||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type { ToolbarItem } from "./types";
|
||||
import { setContext } from "svelte";
|
||||
import { dropdownKey } from "./contextKeys";
|
||||
|
||||
import ButtonGroup from "./ButtonGroup.svelte";
|
||||
|
||||
export let id: string;
|
||||
export let className = "";
|
||||
export let id: string | undefined;
|
||||
let className = "";
|
||||
export { className as class };
|
||||
|
||||
function extendClassName(className: string): string {
|
||||
return `dropdown-menu btn-dropdown-menu ${className}`;
|
||||
}
|
||||
export let api = {};
|
||||
|
||||
export let items: ToolbarItem[];
|
||||
setContext(dropdownKey, null);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -28,4 +29,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
</style>
|
||||
|
||||
<ButtonGroup {id} className={extendClassName(className)} {items} />
|
||||
<ButtonGroup {id} class={`dropdown-menu btn-dropdown-menu ${className}`} {api}>
|
||||
<slot />
|
||||
</ButtonGroup>
|
||||
|
|
|
@ -7,12 +7,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import { nightModeKey } from "./contextKeys";
|
||||
|
||||
export let id: string;
|
||||
export let className = "";
|
||||
export let tooltip: string;
|
||||
export let label: string;
|
||||
export let shortcutLabel: string | undefined;
|
||||
let className = "";
|
||||
export { className as class };
|
||||
|
||||
export let onClick: (event: MouseEvent) => void;
|
||||
export let tooltip: string;
|
||||
|
||||
let buttonRef: HTMLButtonElement;
|
||||
|
||||
|
@ -28,6 +26,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
button {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
font-size: calc(var(--toolbar-size) / 2.3);
|
||||
}
|
||||
|
||||
.btn-day {
|
||||
|
@ -52,15 +52,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: calc(var(--toolbar-size) / 2.3);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.monospace {
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
|
||||
<button
|
||||
|
@ -70,8 +61,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
class:btn-day={!nightMode}
|
||||
class:btn-night={nightMode}
|
||||
title={tooltip}
|
||||
on:click={onClick}
|
||||
on:click
|
||||
on:mousedown|preventDefault>
|
||||
<span class:me-3={shortcutLabel}>{label}</span>
|
||||
{#if shortcutLabel}<span class="monospace">{shortcutLabel}</span>{/if}
|
||||
<slot />
|
||||
</button>
|
||||
|
|
|
@ -3,23 +3,21 @@ Copyright: Ankitects Pty Ltd and contributors
|
|||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type { ToolbarItem } from "./types";
|
||||
import { setContext } from "svelte";
|
||||
import { dropdownKey } from "./contextKeys";
|
||||
|
||||
export let id: string;
|
||||
export let items: ToolbarItem[];
|
||||
export let id: string | undefined;
|
||||
|
||||
setContext(dropdownKey, null);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
ul {
|
||||
div {
|
||||
background-color: var(--frame-bg);
|
||||
border-color: var(--medium-border);
|
||||
}
|
||||
</style>
|
||||
|
||||
<ul {id} class="dropdown-menu">
|
||||
{#each items as menuItem}
|
||||
<li>
|
||||
<svelte:component this={menuItem.component} {...menuItem} />
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<div {id}>
|
||||
<slot />
|
||||
</div>
|
||||
|
|
|
@ -4,8 +4,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
-->
|
||||
<script lang="typescript">
|
||||
import type { Readable } from "svelte/store";
|
||||
import { getContext, onMount, createEventDispatcher } from "svelte";
|
||||
import { disabledKey, nightModeKey } from "./contextKeys";
|
||||
import { hasContext, getContext, onMount, createEventDispatcher } from "svelte";
|
||||
import { disabledKey, nightModeKey, dropdownKey } from "./contextKeys";
|
||||
|
||||
export let id: string;
|
||||
let className = "";
|
||||
|
@ -14,14 +14,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
export let tooltip: string | undefined;
|
||||
export let active = false;
|
||||
export let disables = true;
|
||||
export let dropdownToggle = false;
|
||||
|
||||
$: extraProps = dropdownToggle
|
||||
? {
|
||||
"data-bs-toggle": "dropdown",
|
||||
"aria-expanded": "false",
|
||||
}
|
||||
: {};
|
||||
|
||||
let buttonRef: HTMLButtonElement;
|
||||
|
||||
|
@ -30,6 +22,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
const nightMode = getContext<boolean>(nightModeKey);
|
||||
|
||||
const dropdown = getContext(dropdownKey);
|
||||
const dropdownProps = dropdown?.getDropdownTriggerProps() ?? {};
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
onMount(() => dispatch("mount", { button: buttonRef }));
|
||||
</script>
|
||||
|
@ -71,13 +66,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
{id}
|
||||
class={`btn ${className}`}
|
||||
class:active
|
||||
class:dropdown-toggle={dropdownToggle}
|
||||
class:btn-day={!nightMode}
|
||||
class:btn-night={nightMode}
|
||||
tabindex="-1"
|
||||
title={tooltip}
|
||||
disabled={_disabled}
|
||||
{...extraProps}
|
||||
class:dropdown-toggle={Boolean(dropdown)}
|
||||
{...dropdownProps}
|
||||
on:click
|
||||
on:mousedown|preventDefault>
|
||||
<span class="p-1"><slot /></span>
|
||||
|
|
|
@ -3,39 +3,33 @@ Copyright: Ankitects Pty Ltd and contributors
|
|||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type { DynamicSvelteComponent } from "sveltelib/dynamicComponent";
|
||||
import type { ToolbarItem } from "./types";
|
||||
|
||||
import Dropdown from "bootstrap/js/dist/dropdown";
|
||||
|
||||
/* Bootstrap dropdown are normally declared alongside the associated button
|
||||
* However we cannot do that, as the menus cannot be declared in sticky-positioned elements
|
||||
*/
|
||||
export let button: ToolbarItem;
|
||||
export let menuId: string;
|
||||
import { setContext } from "svelte";
|
||||
import { dropdownKey } from "./contextKeys";
|
||||
|
||||
function extend({
|
||||
className,
|
||||
...rest
|
||||
}: DynamicSvelteComponent): DynamicSvelteComponent {
|
||||
return {
|
||||
dropdownToggle: true,
|
||||
...rest,
|
||||
};
|
||||
}
|
||||
setContext(dropdownKey, {
|
||||
getDropdownTriggerProps: () => ({
|
||||
"data-bs-toggle": "dropdown",
|
||||
"aria-expanded": "false",
|
||||
}),
|
||||
});
|
||||
|
||||
function createDropdown({ detail }: CustomEvent): void {
|
||||
const button: HTMLButtonElement = detail.button;
|
||||
const menuId = Math.random().toString(36).substring(2);
|
||||
|
||||
/* Normally dropdown and trigger are associated with a
|
||||
/* common ancestor with .dropdown class */
|
||||
function createDropdown(button: HTMLElement): void {
|
||||
/* Prevent focus on menu activation */
|
||||
const noop = () => {};
|
||||
Object.defineProperty(button, "focus", { value: noop });
|
||||
|
||||
/* Set custom menu without using .dropdown
|
||||
* Rendering the menu here would cause the menu to
|
||||
* be displayed outside of the visible area
|
||||
*/
|
||||
* be displayed outside of the visible area */
|
||||
|
||||
const dropdown = new Dropdown(button);
|
||||
|
||||
const menu = (button.getRootNode() as Document) /* or shadow root */
|
||||
.getElementById(menuId);
|
||||
|
||||
|
@ -47,7 +41,4 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
</script>
|
||||
|
||||
<svelte:component
|
||||
this={button.component}
|
||||
{...extend(button)}
|
||||
on:mount={createDropdown} />
|
||||
<slot {createDropdown} {menuId} />
|
||||
|
|
|
@ -4,3 +4,4 @@ export const nightModeKey = Symbol("nightMode");
|
|||
export const disabledKey = Symbol("disabled");
|
||||
|
||||
export const buttonGroupKey = Symbol("buttonGroup");
|
||||
export const dropdownKey = Symbol("dropdown");
|
||||
|
|
|
@ -57,5 +57,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<StickyBar>
|
||||
<NoteTypeButtons />
|
||||
<FormatInlineButtons />
|
||||
<FormatBlockButtons />
|
||||
</StickyBar>
|
||||
</WithTheming>
|
||||
|
|
|
@ -42,27 +42,109 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
</script>
|
||||
|
||||
<ButtonDropdown id="listFormatting">
|
||||
<ButtonGroup id="blockFormatting" {api}>
|
||||
<WithState
|
||||
key="insertUnorderedList"
|
||||
update={() => document.queryCommandState('insertUnorderedList')}
|
||||
let:state={active}
|
||||
let:updateState>
|
||||
<IconButton
|
||||
tooltip={tr.editingUnorderedList()}
|
||||
{active}
|
||||
on:click={(event) => {
|
||||
document.execCommand('insertUnorderedList');
|
||||
updateState(event);
|
||||
}}>
|
||||
{@html ulIcon}
|
||||
</IconButton>
|
||||
</WithState>
|
||||
|
||||
<WithState
|
||||
key="insertOrderedList"
|
||||
update={() => document.queryCommandState('insertOrderedList')}
|
||||
let:state={active}
|
||||
let:updateState>
|
||||
<IconButton
|
||||
tooltip={tr.editingOrderedList()}
|
||||
{active}
|
||||
on:click={(event) => {
|
||||
document.execCommand('insertOrderedList');
|
||||
updateState(event);
|
||||
}}>
|
||||
{@html olIcon}
|
||||
</IconButton>
|
||||
</WithState>
|
||||
|
||||
<WithDropdownMenu let:createDropdown let:menuId>
|
||||
<IconButton on:mount={(event) => createDropdown(event.detail.button)}>
|
||||
{@html listOptionsIcon}
|
||||
</IconButton>
|
||||
|
||||
<ButtonDropdown id={menuId}>
|
||||
<ButtonGroup id="justify" {api}>
|
||||
<IconButton command="justifyLeft" tooltip={tr.editingAlignLeft()}>
|
||||
<WithState
|
||||
key="justifyLeft"
|
||||
update={() => document.queryCommandState('justifyLeft')}
|
||||
let:state={active}
|
||||
let:updateState>
|
||||
<IconButton
|
||||
tooltip={tr.editingAlignLeft()}
|
||||
{active}
|
||||
on:click={(event) => {
|
||||
document.execCommand('justifyLeft');
|
||||
updateState(event);
|
||||
}}>
|
||||
{@html justifyLeftIcon}
|
||||
</IconButton>
|
||||
</WithState>
|
||||
|
||||
<IconButton command="justifyCenter" tooltip={tr.editingCenter()}>
|
||||
<WithState
|
||||
key="justifyCenter"
|
||||
update={() => document.queryCommandState('justifyCenter')}
|
||||
let:state={active}
|
||||
let:updateState>
|
||||
<IconButton
|
||||
tooltip={tr.editingCenter()}
|
||||
{active}
|
||||
on:click={(event) => {
|
||||
document.execCommand('justifyCenter');
|
||||
updateState(event);
|
||||
}}>
|
||||
{@html justifyCenterIcon}
|
||||
</IconButton>
|
||||
</WithState>
|
||||
|
||||
<IconButton command="justifyCenter" tooltip={tr.editingCenter()}>
|
||||
{@html justifyCenterIcon}
|
||||
</IconButton>
|
||||
|
||||
<IconButton command="justifyRight" tooltip={tr.editingAlignRight()}>
|
||||
<WithState
|
||||
key="justifyRight"
|
||||
update={() => document.queryCommandState('justifyRight')}
|
||||
let:state={active}
|
||||
let:updateState>
|
||||
<IconButton
|
||||
tooltip={tr.editingAlignRight()}
|
||||
{active}
|
||||
on:click={(event) => {
|
||||
document.execCommand('justifyRight');
|
||||
updateState(event);
|
||||
}}>
|
||||
{@html justifyRightIcon}
|
||||
</IconButton>
|
||||
</WithState>
|
||||
|
||||
<IconButton command="justifyFull" tooltip={tr.editingJustify()}>
|
||||
<WithState
|
||||
key="justifyFull"
|
||||
update={() => document.queryCommandState('justifyFull')}
|
||||
let:state={active}
|
||||
let:updateState>
|
||||
<IconButton
|
||||
tooltip={tr.editingJustify()}
|
||||
{active}
|
||||
on:click={(event) => {
|
||||
document.execCommand('justifyFull');
|
||||
updateState(event);
|
||||
}}>
|
||||
{@html justifyFullIcon}
|
||||
</IconButton>
|
||||
</WithState>
|
||||
</ButtonGroup>
|
||||
|
||||
<ButtonGroup id="indentation" {api}>
|
||||
|
@ -75,19 +157,5 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
</IconButton>
|
||||
</ButtonGroup>
|
||||
</ButtonDropdown>
|
||||
|
||||
<ButtonGroup id="blockFormatting" {api}>
|
||||
<IconButton command="insertUnorderedList" tooltip={tr.editingUnorderedList()}>
|
||||
{@html ulIcon}
|
||||
</IconButton>
|
||||
|
||||
<IconButton command="insertOrderedList" tooltip={tr.editingOrderedList()}>
|
||||
{@html olIcon}
|
||||
</IconButton>
|
||||
|
||||
<WithDropdownMenu menuId="listFormatting">
|
||||
<IconButton>
|
||||
{@html listOptionsIcon}
|
||||
</IconButton>
|
||||
</WithDropdownMenu>
|
||||
</ButtonGroup>
|
||||
|
|
Loading…
Reference in a new issue