mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 15:32:23 -04:00
Add ButtonToolbarItem as interface for modifying button groups
This commit is contained in:
parent
4a6b3b3786
commit
928f486867
11 changed files with 145 additions and 14 deletions
|
@ -63,7 +63,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const hideButton = (id: Identifier) =>
|
const hideButton = (id: Identifier) =>
|
||||||
updateRegistration(({ detach }) => detach.set(true), id);
|
updateRegistration(({ detach }) => detach.set(true), id);
|
||||||
const toggleButton = (id: Identifier) =>
|
const toggleButton = (id: Identifier) =>
|
||||||
updateRegistration(({ detach }) => detach.update((old) => !old), id);
|
updateRegistration(
|
||||||
|
({ detach }) => detach.update((old: boolean): boolean => !old),
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
Object.assign(api, {
|
Object.assign(api, {
|
||||||
insertButton,
|
insertButton,
|
||||||
|
|
|
@ -3,13 +3,76 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
|
import { setContext } from "svelte";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import ButtonToolbarItem from "./ButtonToolbarItem.svelte";
|
||||||
|
import type { ButtonGroupRegistration } from "./buttons";
|
||||||
|
import { buttonToolbarKey } from "./contextKeys";
|
||||||
|
import type { Identifier } from "./identifier";
|
||||||
|
import { insert, add } from "./identifier";
|
||||||
|
import type { SvelteComponent } from "./registration";
|
||||||
|
import { makeInterface } from "./registration";
|
||||||
|
|
||||||
export let id: string | undefined = undefined;
|
export let id: string | undefined = undefined;
|
||||||
let className: string | undefined;
|
let className: string = "";
|
||||||
export { className as class };
|
export { className as class };
|
||||||
|
|
||||||
export let nowrap = false;
|
export let nowrap = false;
|
||||||
|
|
||||||
|
function makeRegistration(): ButtonGroupRegistration {
|
||||||
|
const detach = writable(false);
|
||||||
|
return { detach };
|
||||||
|
}
|
||||||
|
|
||||||
|
const { registerComponent, dynamicItems, getDynamicInterface } = makeInterface(
|
||||||
|
makeRegistration
|
||||||
|
);
|
||||||
|
|
||||||
|
setContext(buttonToolbarKey, registerComponent);
|
||||||
|
|
||||||
|
export let api = {};
|
||||||
|
let buttonToolbarRef: HTMLDivElement;
|
||||||
|
|
||||||
|
$: if (buttonToolbarRef) {
|
||||||
|
const { addComponent, updateRegistration } = getDynamicInterface(
|
||||||
|
buttonToolbarRef
|
||||||
|
);
|
||||||
|
|
||||||
|
const insertGroup = (button: SvelteComponent, position: Identifier = 0) =>
|
||||||
|
addComponent(button, (added, parent) => insert(added, parent, position));
|
||||||
|
const appendGroup = (button: SvelteComponent, position: Identifier = -1) =>
|
||||||
|
addComponent(button, (added, parent) => add(added, parent, position));
|
||||||
|
|
||||||
|
const showGroup = (id: Identifier) =>
|
||||||
|
updateRegistration(({ detach }) => detach.set(false), id);
|
||||||
|
const hideGroup = (id: Identifier) =>
|
||||||
|
updateRegistration(({ detach }) => detach.set(true), id);
|
||||||
|
const toggleGroup = (id: Identifier) =>
|
||||||
|
updateRegistration(
|
||||||
|
({ detach }) => detach.update((old: boolean): boolean => !old),
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
|
Object.assign(api, {
|
||||||
|
insertGroup,
|
||||||
|
appendGroup,
|
||||||
|
showGroup,
|
||||||
|
hideGroup,
|
||||||
|
toggleGroup,
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div {id} class={`btn-toolbar ${className}`} class:flex-nowrap={nowrap} role="toolbar">
|
<div
|
||||||
|
bind:this={buttonToolbarRef}
|
||||||
|
{id}
|
||||||
|
class={`btn-toolbar ${className}`}
|
||||||
|
class:flex-nowrap={nowrap}
|
||||||
|
role="toolbar">
|
||||||
<slot />
|
<slot />
|
||||||
|
{#each $dynamicItems as item}
|
||||||
|
<ButtonToolbarItem id={item[0].id} registration={item[1]}>
|
||||||
|
<svelte:component this={item[0].component} {...item[0].props} />
|
||||||
|
</ButtonToolbarItem>
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
44
ts/components/ButtonToolbarItem.svelte
Normal file
44
ts/components/ButtonToolbarItem.svelte
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<!--
|
||||||
|
Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
-->
|
||||||
|
<script lang="typescript">
|
||||||
|
import Detachable from "components/Detachable.svelte";
|
||||||
|
|
||||||
|
import type { ButtonGroupRegistration } from "./buttons";
|
||||||
|
import type { Register } from "./registration";
|
||||||
|
|
||||||
|
import { getContext, hasContext } from "svelte";
|
||||||
|
import { buttonToolbarKey } from "./contextKeys";
|
||||||
|
|
||||||
|
export let id: string | undefined = undefined;
|
||||||
|
export let registration: ButtonGroupRegistration | undefined = undefined;
|
||||||
|
|
||||||
|
let detach_: boolean;
|
||||||
|
|
||||||
|
if (registration) {
|
||||||
|
const { detach } = registration;
|
||||||
|
detach.subscribe((value: boolean) => (detach_ = value));
|
||||||
|
} else if (hasContext(buttonToolbarKey)) {
|
||||||
|
const registerComponent = getContext<Register<ButtonGroupRegistration>>(
|
||||||
|
buttonToolbarKey
|
||||||
|
);
|
||||||
|
const { detach } = registerComponent();
|
||||||
|
detach.subscribe((value: boolean) => (detach_ = value));
|
||||||
|
} else {
|
||||||
|
detach_ = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
div {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- div is necessary to preserve item position -->
|
||||||
|
<div {id}>
|
||||||
|
<Detachable detach={detach_}>
|
||||||
|
<slot />
|
||||||
|
</Detachable>
|
||||||
|
</div>
|
|
@ -13,3 +13,7 @@ export interface ButtonRegistration {
|
||||||
detach: Writable<boolean>;
|
detach: Writable<boolean>;
|
||||||
position: Writable<ButtonPosition>;
|
position: Writable<ButtonPosition>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ButtonGroupRegistration {
|
||||||
|
detach: Writable<boolean>;
|
||||||
|
}
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
export const nightModeKey = Symbol("nightMode");
|
export const nightModeKey = Symbol("nightMode");
|
||||||
export const disabledKey = Symbol("disabled");
|
export const disabledKey = Symbol("disabled");
|
||||||
|
|
||||||
|
export const buttonToolbarKey = Symbol("buttonToolbar");
|
||||||
export const buttonGroupKey = Symbol("buttonGroup");
|
export const buttonGroupKey = Symbol("buttonGroup");
|
||||||
export const dropdownKey = Symbol("dropdown");
|
export const dropdownKey = Symbol("dropdown");
|
||||||
|
|
|
@ -34,7 +34,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ButtonGroup id="color" {api}>
|
<ButtonGroup {api}>
|
||||||
<ButtonGroupItem>
|
<ButtonGroupItem>
|
||||||
<WithShortcut shortcut="F7" let:createShortcut let:shortcutLabel>
|
<WithShortcut shortcut="F7" let:createShortcut let:shortcutLabel>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
|
@ -48,6 +48,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import WithTheming from "components/WithTheming.svelte";
|
import WithTheming from "components/WithTheming.svelte";
|
||||||
import StickyBar from "components/StickyBar.svelte";
|
import StickyBar from "components/StickyBar.svelte";
|
||||||
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
||||||
|
import ButtonToolbarItem from "components/ButtonToolbarItem.svelte";
|
||||||
|
|
||||||
import NoteTypeButtons from "./NoteTypeButtons.svelte";
|
import NoteTypeButtons from "./NoteTypeButtons.svelte";
|
||||||
import FormatInlineButtons from "./FormatInlineButtons.svelte";
|
import FormatInlineButtons from "./FormatInlineButtons.svelte";
|
||||||
|
@ -55,6 +56,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import ColorButtons from "./ColorButtons.svelte";
|
import ColorButtons from "./ColorButtons.svelte";
|
||||||
import TemplateButtons from "./TemplateButtons.svelte";
|
import TemplateButtons from "./TemplateButtons.svelte";
|
||||||
|
|
||||||
|
export const toolbar = {};
|
||||||
export const notetypeButtons = {};
|
export const notetypeButtons = {};
|
||||||
export const formatInlineButtons = {};
|
export const formatInlineButtons = {};
|
||||||
export const formatBlockButtons = {};
|
export const formatBlockButtons = {};
|
||||||
|
@ -76,12 +78,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
<WithTheming {style}>
|
<WithTheming {style}>
|
||||||
<StickyBar>
|
<StickyBar>
|
||||||
<ButtonToolbar>
|
<ButtonToolbar api={toolbar}>
|
||||||
<NoteTypeButtons api={notetypeButtons} />
|
<ButtonToolbarItem id="notetype">
|
||||||
<FormatInlineButtons api={formatInlineButtons} />
|
<NoteTypeButtons api={notetypeButtons} />
|
||||||
<FormatBlockButtons api={formatBlockButtons} />
|
</ButtonToolbarItem>
|
||||||
<ColorButtons api={colorButtons} />
|
|
||||||
<TemplateButtons api={templateButtons} />
|
<ButtonToolbarItem id="inlineFormatting">
|
||||||
|
<FormatInlineButtons api={formatInlineButtons} />
|
||||||
|
</ButtonToolbarItem>
|
||||||
|
|
||||||
|
<ButtonToolbarItem id="blockFormatting">
|
||||||
|
<FormatBlockButtons api={formatBlockButtons} />
|
||||||
|
</ButtonToolbarItem>
|
||||||
|
|
||||||
|
<ButtonToolbarItem id="color">
|
||||||
|
<ColorButtons api={colorButtons} />
|
||||||
|
</ButtonToolbarItem>
|
||||||
|
|
||||||
|
<ButtonToolbarItem id="template">
|
||||||
|
<TemplateButtons api={templateButtons} />
|
||||||
|
</ButtonToolbarItem>
|
||||||
</ButtonToolbar>
|
</ButtonToolbar>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
</WithTheming>
|
</WithTheming>
|
||||||
|
|
|
@ -43,7 +43,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ButtonGroup id="blockFormatting" {api}>
|
<ButtonGroup {api}>
|
||||||
<ButtonGroupItem>
|
<ButtonGroupItem>
|
||||||
<WithState
|
<WithState
|
||||||
key="insertUnorderedList"
|
key="insertUnorderedList"
|
||||||
|
|
|
@ -24,7 +24,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export let api = {};
|
export let api = {};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ButtonGroup id="notetype" {api}>
|
<ButtonGroup {api}>
|
||||||
<ButtonGroupItem>
|
<ButtonGroupItem>
|
||||||
<WithShortcut shortcut="Control+KeyB" let:createShortcut let:shortcutLabel>
|
<WithShortcut shortcut="Control+KeyB" let:createShortcut let:shortcutLabel>
|
||||||
<WithState
|
<WithState
|
||||||
|
|
|
@ -14,7 +14,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export let api = {};
|
export let api = {};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ButtonGroup id="notetype" {api}>
|
<ButtonGroup {api}>
|
||||||
<ButtonGroupItem>
|
<ButtonGroupItem>
|
||||||
<LabelButton
|
<LabelButton
|
||||||
disables={false}
|
disables={false}
|
||||||
|
|
|
@ -34,7 +34,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ButtonGroup id="template" {api}>
|
<ButtonGroup {api}>
|
||||||
<ButtonGroupItem>
|
<ButtonGroupItem>
|
||||||
<WithShortcut shortcut="F3" let:createShortcut let:shortcutLabel>
|
<WithShortcut shortcut="F3" let:createShortcut let:shortcutLabel>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
Loading…
Reference in a new issue