2021-04-15 15:59:52 +02:00
|
|
|
<!--
|
|
|
|
Copyright: Ankitects Pty Ltd and contributors
|
|
|
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
-->
|
2021-03-30 01:23:39 +02:00
|
|
|
<script lang="typescript">
|
2021-05-05 15:12:02 +02:00
|
|
|
import ButtonGroupItem from "./ButtonGroupItem.svelte";
|
2021-05-05 01:22:51 +02:00
|
|
|
import { setContext } from "svelte";
|
|
|
|
import { writable } from "svelte/store";
|
|
|
|
import { buttonGroupKey } from "./contextKeys";
|
|
|
|
import type { Identifier } from "./identifier";
|
2021-05-06 18:51:44 +02:00
|
|
|
import { insert, add } from "./identifier";
|
2021-05-06 01:22:55 +02:00
|
|
|
import type { ButtonRegistration } from "./buttons";
|
|
|
|
import { ButtonPosition } from "./buttons";
|
2021-05-06 18:51:44 +02:00
|
|
|
import type { SvelteComponent } from "./registration";
|
|
|
|
import { makeInterface } from "./registration";
|
2021-04-08 22:11:50 +02:00
|
|
|
|
2021-04-16 03:10:39 +02:00
|
|
|
export let id: string | undefined = undefined;
|
2021-05-05 01:22:51 +02:00
|
|
|
let className: string = "";
|
2021-04-27 21:01:44 +02:00
|
|
|
export { className as class };
|
|
|
|
|
2021-05-27 17:13:36 +02:00
|
|
|
export let size: number | undefined = undefined;
|
|
|
|
export let wrap: boolean | undefined = undefined;
|
|
|
|
|
|
|
|
$: buttonSize = size ? `--buttons-size: ${size}rem; ` : "";
|
|
|
|
let buttonWrap: string;
|
|
|
|
$: if (wrap === undefined) {
|
|
|
|
buttonWrap = "";
|
|
|
|
} else {
|
|
|
|
buttonWrap = wrap ? `--buttons-wrap: wrap; ` : `--buttons-wrap: nowrap; `;
|
|
|
|
}
|
|
|
|
|
|
|
|
$: style = buttonSize + buttonWrap;
|
|
|
|
|
2021-05-05 15:12:02 +02:00
|
|
|
function makeRegistration(): ButtonRegistration {
|
2021-05-05 01:22:51 +02:00
|
|
|
const detach = writable(false);
|
2021-05-06 01:22:55 +02:00
|
|
|
const position = writable(ButtonPosition.Standalone);
|
|
|
|
return { detach, position };
|
2021-05-05 15:12:02 +02:00
|
|
|
}
|
2021-05-05 01:22:51 +02:00
|
|
|
|
2021-05-26 01:21:33 +02:00
|
|
|
const { registerComponent, items, dynamicItems, getDynamicInterface } =
|
|
|
|
makeInterface(makeRegistration);
|
2021-05-06 18:51:44 +02:00
|
|
|
|
|
|
|
$: for (const [index, item] of $items.entries()) {
|
|
|
|
if ($items.length === 1) {
|
|
|
|
item.position.set(ButtonPosition.Standalone);
|
|
|
|
} else if (index === 0) {
|
|
|
|
item.position.set(ButtonPosition.Leftmost);
|
|
|
|
} else if (index === $items.length - 1) {
|
|
|
|
item.position.set(ButtonPosition.Rightmost);
|
|
|
|
} else {
|
|
|
|
item.position.set(ButtonPosition.Center);
|
|
|
|
}
|
2021-05-06 16:10:26 +02:00
|
|
|
}
|
|
|
|
|
2021-05-06 18:51:44 +02:00
|
|
|
setContext(buttonGroupKey, registerComponent);
|
2021-05-05 01:22:51 +02:00
|
|
|
|
2021-05-06 20:39:52 +02:00
|
|
|
export let api: Record<string, unknown> | undefined = undefined;
|
2021-05-06 18:51:44 +02:00
|
|
|
let buttonGroupRef: HTMLDivElement;
|
2021-05-05 15:12:02 +02:00
|
|
|
|
2021-05-06 20:39:52 +02:00
|
|
|
$: if (api && buttonGroupRef) {
|
2021-05-26 01:21:33 +02:00
|
|
|
const { addComponent, updateRegistration } =
|
|
|
|
getDynamicInterface(buttonGroupRef);
|
2021-05-05 15:12:02 +02:00
|
|
|
|
2021-05-06 18:51:44 +02:00
|
|
|
const insertButton = (button: SvelteComponent, position: Identifier = 0) =>
|
|
|
|
addComponent(button, (added, parent) => insert(added, parent, position));
|
|
|
|
const appendButton = (button: SvelteComponent, position: Identifier = -1) =>
|
|
|
|
addComponent(button, (added, parent) => add(added, parent, position));
|
2021-05-05 15:12:02 +02:00
|
|
|
|
2021-05-06 18:51:44 +02:00
|
|
|
const showButton = (id: Identifier) =>
|
|
|
|
updateRegistration(({ detach }) => detach.set(false), id);
|
|
|
|
const hideButton = (id: Identifier) =>
|
|
|
|
updateRegistration(({ detach }) => detach.set(true), id);
|
|
|
|
const toggleButton = (id: Identifier) =>
|
2021-05-06 19:26:50 +02:00
|
|
|
updateRegistration(
|
|
|
|
({ detach }) => detach.update((old: boolean): boolean => !old),
|
|
|
|
id
|
|
|
|
);
|
2021-05-05 01:22:51 +02:00
|
|
|
|
2021-04-27 22:35:25 +02:00
|
|
|
Object.assign(api, {
|
2021-05-05 01:22:51 +02:00
|
|
|
insertButton,
|
|
|
|
appendButton,
|
|
|
|
showButton,
|
|
|
|
hideButton,
|
|
|
|
toggleButton,
|
2021-05-06 18:51:44 +02:00
|
|
|
});
|
|
|
|
}
|
2021-03-29 21:48:31 +02:00
|
|
|
</script>
|
|
|
|
|
2021-05-06 18:51:44 +02:00
|
|
|
<div
|
|
|
|
bind:this={buttonGroupRef}
|
|
|
|
{id}
|
|
|
|
class={`btn-group ${className}`}
|
2021-05-27 17:13:36 +02:00
|
|
|
{style}
|
2021-05-06 18:51:44 +02:00
|
|
|
dir="ltr"
|
2021-05-26 01:21:33 +02:00
|
|
|
role="group"
|
|
|
|
>
|
2021-04-27 21:01:44 +02:00
|
|
|
<slot />
|
2021-05-06 18:51:44 +02:00
|
|
|
{#each $dynamicItems as item}
|
|
|
|
<ButtonGroupItem id={item[0].id} registration={item[1]}>
|
|
|
|
<svelte:component this={item[0].component} {...item[0].props} />
|
2021-05-05 15:12:02 +02:00
|
|
|
</ButtonGroupItem>
|
2021-05-05 01:22:51 +02:00
|
|
|
{/each}
|
2021-04-27 17:20:13 +02:00
|
|
|
</div>
|
2021-05-26 01:21:33 +02:00
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
div {
|
2021-05-27 17:13:36 +02:00
|
|
|
flex-wrap: var(--buttons-wrap);
|
|
|
|
padding: calc(var(--buttons-size) / 10);
|
2021-05-26 01:21:33 +02:00
|
|
|
margin: 0;
|
|
|
|
}
|
|
|
|
</style>
|