@svar-ui/svelte-toolbar 2.6.1 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{src → dist}/buttons/ButtonList.svelte +7 -10
- package/dist/buttons/ButtonList.svelte.d.ts +13 -0
- package/{src → dist}/buttons/Icon.svelte +3 -6
- package/dist/buttons/Icon.svelte.d.ts +16 -0
- package/{src → dist}/buttons/Item.svelte +5 -6
- package/dist/buttons/Item.svelte.d.ts +13 -0
- package/{src → dist}/buttons/Label.svelte +2 -2
- package/dist/buttons/Label.svelte.d.ts +9 -0
- package/{src → dist}/buttons/Separator.svelte +1 -2
- package/dist/buttons/Separator.svelte.d.ts +6 -0
- package/dist/buttons/Spacer.svelte.d.ts +26 -0
- package/{src → dist}/components/BarComponent.svelte +20 -22
- package/dist/components/BarComponent.svelte.d.ts +11 -0
- package/{src → dist}/components/Group.svelte +12 -18
- package/dist/components/Group.svelte.d.ts +12 -0
- package/{src → dist}/components/Menu.svelte +16 -21
- package/dist/components/Menu.svelte.d.ts +12 -0
- package/dist/components/Toolbar.svelte +160 -0
- package/dist/components/Toolbar.svelte.d.ts +14 -0
- package/dist/env.d.ts +7 -0
- package/dist/helpers.d.ts +6 -0
- package/dist/helpers.js +41 -0
- package/dist/index.d.ts +5 -0
- package/{src → dist}/index.js +1 -4
- package/dist/types.d.ts +39 -0
- package/dist/types.js +1 -0
- package/package.json +56 -53
- package/readme.md +5 -16
- package/whatsnew.md +41 -29
- package/src/components/Toolbar.svelte +0 -195
- package/src/helpers.js +0 -42
- package/types/index.d.ts +0 -37
- /package/{src → dist}/buttons/Spacer.svelte +0 -0
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
value = id;
|
|
8
|
-
onchange && onchange({ value: id });
|
|
9
|
-
}
|
|
1
|
+
<script lang="ts">import { Button } from "@svar-ui/svelte-core";
|
|
2
|
+
let { css = "", disabled, options = [], onchange, value = $bindable() } = $props();
|
|
3
|
+
function onClickHandler(id) {
|
|
4
|
+
value = id;
|
|
5
|
+
onchange?.({ value: id });
|
|
6
|
+
}
|
|
10
7
|
</script>
|
|
11
8
|
|
|
12
9
|
<div class="wx-button-list {css}">
|
|
13
10
|
{#each options as option}
|
|
14
11
|
<Button
|
|
15
|
-
type={value === option.id ? "primary" :
|
|
12
|
+
type={value === option.id ? "primary" : undefined}
|
|
16
13
|
{disabled}
|
|
17
14
|
text={option.label}
|
|
18
15
|
onclick={() => onClickHandler(option.id)}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IButtonListOption, TID } from "../types";
|
|
2
|
+
type Props = {
|
|
3
|
+
options?: IButtonListOption[];
|
|
4
|
+
value?: TID;
|
|
5
|
+
css?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
onchange?: (ev: {
|
|
8
|
+
value: TID;
|
|
9
|
+
}) => void;
|
|
10
|
+
};
|
|
11
|
+
declare const ButtonList: import("svelte").Component<Props, {}, "value">;
|
|
12
|
+
type ButtonList = ReturnType<typeof ButtonList>;
|
|
13
|
+
export default ButtonList;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
let { icon, title, text, tooltip, css, type, disabled, menu, onclick } =
|
|
5
|
-
$props();
|
|
1
|
+
<script lang="ts">import { Button } from "@svar-ui/svelte-core";
|
|
2
|
+
let { icon, title, text, tooltip, css, type, disabled, menu, onclick } = $props();
|
|
6
3
|
</script>
|
|
7
4
|
|
|
8
5
|
{#if menu}
|
|
9
6
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
10
7
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
11
|
-
<div class="wx-item" class:wx-text-icon={text} {onclick}>
|
|
8
|
+
<div class="wx-item" class:wx-text-icon={!!text} {onclick}>
|
|
12
9
|
<i class="{icon || 'wxi-empty'} {css || ''}"></i>
|
|
13
10
|
{text}
|
|
14
11
|
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentProps } from "svelte";
|
|
2
|
+
import { Button } from "@svar-ui/svelte-core";
|
|
3
|
+
type Props = {
|
|
4
|
+
icon?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
tooltip?: string;
|
|
8
|
+
css?: string;
|
|
9
|
+
type?: ComponentProps<typeof Button>["type"];
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
menu?: boolean;
|
|
12
|
+
onclick?: (ev: MouseEvent) => void;
|
|
13
|
+
};
|
|
14
|
+
declare const Icon: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type Icon = ReturnType<typeof Icon>;
|
|
16
|
+
export default Icon;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
1
|
+
<script lang="ts">let { id = "", text = "", css = "", icon = "", onclick } = $props();
|
|
2
|
+
function handleClick() {
|
|
3
|
+
onclick?.({ id });
|
|
4
|
+
}
|
|
5
|
+
export {};
|
|
7
6
|
</script>
|
|
8
7
|
|
|
9
8
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TID } from "../types";
|
|
2
|
+
type Props = {
|
|
3
|
+
id?: TID;
|
|
4
|
+
text?: string;
|
|
5
|
+
css?: string;
|
|
6
|
+
icon?: string;
|
|
7
|
+
onclick?: (ev: {
|
|
8
|
+
id: TID;
|
|
9
|
+
}) => void;
|
|
10
|
+
};
|
|
11
|
+
declare const Item: import("svelte").Component<Props, {}, "">;
|
|
12
|
+
type Item = ReturnType<typeof Item>;
|
|
13
|
+
export default Item;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default Spacer;
|
|
2
|
+
type Spacer = SvelteComponent<{
|
|
3
|
+
[x: string]: never;
|
|
4
|
+
}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const Spacer: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
+
$$bindings?: Bindings;
|
|
17
|
+
} & Exports;
|
|
18
|
+
(internal: unknown, props: {
|
|
19
|
+
$$events?: Events;
|
|
20
|
+
$$slots?: Slots;
|
|
21
|
+
}): Exports & {
|
|
22
|
+
$set?: any;
|
|
23
|
+
$on?: any;
|
|
24
|
+
};
|
|
25
|
+
z_$$bindings?: Bindings;
|
|
26
|
+
}
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const text = $derived(menu ? item.menuText || item.text : item.text);
|
|
1
|
+
<script lang="ts">import { setID } from "@svar-ui/lib-dom";
|
|
2
|
+
import { getItemHandler } from "../helpers";
|
|
3
|
+
import Separator from "../buttons/Separator.svelte";
|
|
4
|
+
import Spacer from "../buttons/Spacer.svelte";
|
|
5
|
+
let { item = {}, menu = false, values, onclick, onchange } = $props();
|
|
6
|
+
let itemComponent = $derived(getItemHandler(item.comp, { menu }));
|
|
7
|
+
function onClick() {
|
|
8
|
+
if (item.handler) item.handler(item);
|
|
9
|
+
onclick?.({ item });
|
|
10
|
+
}
|
|
11
|
+
let value = $derived(item.key ? values?.[item.key] : undefined);
|
|
12
|
+
function detectChange({ value }) {
|
|
13
|
+
if (item.handler) item.handler(item, value);
|
|
14
|
+
onchange?.({
|
|
15
|
+
value,
|
|
16
|
+
item
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
const text = $derived(menu ? item.menuText || item.text : item.text);
|
|
22
20
|
</script>
|
|
23
21
|
|
|
24
22
|
{#if item.comp == "spacer"}
|
|
@@ -31,7 +29,7 @@
|
|
|
31
29
|
class="wx-tb-element {item.css || ''}"
|
|
32
30
|
class:wx-spacer={item.spacer}
|
|
33
31
|
class:wx-menu={menu}
|
|
34
|
-
data-id={setID(item.id)}
|
|
32
|
+
data-id={setID(item.id as TID)}
|
|
35
33
|
>
|
|
36
34
|
<SvelteComponent
|
|
37
35
|
{value}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IToolbarChangeEvent, IToolbarClickEvent, IToolbarItem, TToolbarValues } from "../types";
|
|
2
|
+
type Props = {
|
|
3
|
+
item?: IToolbarItem;
|
|
4
|
+
menu?: boolean;
|
|
5
|
+
values?: TToolbarValues | null;
|
|
6
|
+
onclick?: (ev: IToolbarClickEvent) => void;
|
|
7
|
+
onchange?: (ev: IToolbarChangeEvent) => void;
|
|
8
|
+
};
|
|
9
|
+
declare const BarComponent: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type BarComponent = ReturnType<typeof BarComponent>;
|
|
11
|
+
export default BarComponent;
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
oncancel();
|
|
14
|
-
onclick && onclick(ev);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const show = () => (collapsedState = false);
|
|
18
|
-
const oncancel = () => (collapsedState = true);
|
|
1
|
+
<script lang="ts">import Group from "./Group.svelte";
|
|
2
|
+
import BarComponent from "./BarComponent.svelte";
|
|
3
|
+
import { Dropdown } from "@svar-ui/svelte-core";
|
|
4
|
+
import { collapseSeparators } from "../helpers";
|
|
5
|
+
let { item, values = null, menu = false, onchange, onclick } = $props();
|
|
6
|
+
let collapsedState = $state(true);
|
|
7
|
+
const onClick = (ev) => {
|
|
8
|
+
oncancel();
|
|
9
|
+
onclick?.(ev);
|
|
10
|
+
};
|
|
11
|
+
const show = () => collapsedState = false;
|
|
12
|
+
const oncancel = () => collapsedState = true;
|
|
19
13
|
</script>
|
|
20
14
|
|
|
21
15
|
<div
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Group from "./Group.svelte";
|
|
2
|
+
import type { IToolbarChangeEvent, IToolbarClickEvent, IToolbarItem, TToolbarValues } from "../types";
|
|
3
|
+
type Props = {
|
|
4
|
+
item: IToolbarItem;
|
|
5
|
+
values?: TToolbarValues | null;
|
|
6
|
+
menu?: boolean;
|
|
7
|
+
onchange?: (ev: IToolbarChangeEvent) => void;
|
|
8
|
+
onclick?: (ev: IToolbarClickEvent) => void;
|
|
9
|
+
};
|
|
10
|
+
declare const Group: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type Group = ReturnType<typeof Group>;
|
|
12
|
+
export default Group;
|
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
function menuClick(ev) {
|
|
18
|
-
oncancel();
|
|
19
|
-
onclick && onclick(ev);
|
|
20
|
-
}
|
|
1
|
+
<script lang="ts">import BarComponent from "./BarComponent.svelte";
|
|
2
|
+
import Group from "./Group.svelte";
|
|
3
|
+
import { Dropdown, Button } from "@svar-ui/svelte-core";
|
|
4
|
+
let { items = [], css, values, width, onclick, onchange } = $props();
|
|
5
|
+
let popup = $state(false);
|
|
6
|
+
function oncancel() {
|
|
7
|
+
popup = false;
|
|
8
|
+
}
|
|
9
|
+
function showMenu() {
|
|
10
|
+
popup = true;
|
|
11
|
+
}
|
|
12
|
+
function menuClick(ev) {
|
|
13
|
+
oncancel();
|
|
14
|
+
onclick?.(ev);
|
|
15
|
+
}
|
|
21
16
|
</script>
|
|
22
17
|
|
|
23
|
-
<div class="wx-menu {css || ''}"
|
|
18
|
+
<div class="wx-menu {css || ''}" data-id="$menu">
|
|
24
19
|
<Button icon="wxi-dots-h" onclick={showMenu} />
|
|
25
20
|
{#if popup}
|
|
26
21
|
<Dropdown width="{width}px" {oncancel}>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IToolbarChangeEvent, IToolbarClickEvent, IToolbarItem, TToolbarValues } from "../types";
|
|
2
|
+
type Props = {
|
|
3
|
+
items?: IToolbarItem[];
|
|
4
|
+
css?: string;
|
|
5
|
+
values?: TToolbarValues | null;
|
|
6
|
+
width?: number;
|
|
7
|
+
onclick?: (ev: IToolbarClickEvent) => void;
|
|
8
|
+
onchange?: (ev: IToolbarChangeEvent) => void;
|
|
9
|
+
};
|
|
10
|
+
declare const Menu: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type Menu = ReturnType<typeof Menu>;
|
|
12
|
+
export default Menu;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<script lang="ts">import Menu from "./Menu.svelte";
|
|
2
|
+
import Group from "./Group.svelte";
|
|
3
|
+
import BarComponent from "./BarComponent.svelte";
|
|
4
|
+
import { onMount, tick } from "svelte";
|
|
5
|
+
import { normalizeToolbarItems } from "../helpers";
|
|
6
|
+
let { items = $bindable([]), menuCss = "", css = "", values = $bindable(null), overflow = "menu", layout = "row", onclick, onchange } = $props();
|
|
7
|
+
function handleChange(ev) {
|
|
8
|
+
if (values && ev.item.key) {
|
|
9
|
+
values[ev.item.key] = ev.value;
|
|
10
|
+
}
|
|
11
|
+
onchange?.(ev);
|
|
12
|
+
}
|
|
13
|
+
let div;
|
|
14
|
+
let menuItems = $state([]);
|
|
15
|
+
const getNodes = () => div.children;
|
|
16
|
+
const barItems = $derived(normalizeToolbarItems(items));
|
|
17
|
+
const vertical = $derived(layout === "column");
|
|
18
|
+
function getTotalWidth() {
|
|
19
|
+
const nodes = getNodes();
|
|
20
|
+
let sum = 0;
|
|
21
|
+
for (let i = 0; i < barItems.length; i++) {
|
|
22
|
+
if (barItems[i].comp != "spacer") {
|
|
23
|
+
sum += nodes[i]?.clientWidth || 0;
|
|
24
|
+
if (barItems[i].comp == "separator") sum += 8;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return sum;
|
|
28
|
+
}
|
|
29
|
+
function collapseGroups() {
|
|
30
|
+
for (let i = barItems.length - 1; i >= 0; i--) {
|
|
31
|
+
// close rightmost open group
|
|
32
|
+
if (barItems[i].items && !barItems[i].collapsed) {
|
|
33
|
+
barItems[i].collapsed = true;
|
|
34
|
+
barItems[i].$width = getNodes()[i].offsetWidth;
|
|
35
|
+
// check after dom update, maybe we need to close more
|
|
36
|
+
tick().then(processOverflow);
|
|
37
|
+
// items are not deep reactive, so we need to trigger the update
|
|
38
|
+
items = [...items];
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function expandGroups(freeSpace) {
|
|
44
|
+
for (let i = 0; i < barItems.length; i++) {
|
|
45
|
+
// open leftmost closed group that was collapsed by overflow
|
|
46
|
+
if (barItems[i].collapsed && barItems[i].$width) {
|
|
47
|
+
// check if group can fit in free space
|
|
48
|
+
if (barItems[i].$width - getNodes()[i].offsetWidth < freeSpace + 10) {
|
|
49
|
+
barItems[i].collapsed = false;
|
|
50
|
+
// items are not deep reactive, so we need to trigger the update
|
|
51
|
+
items = [...items];
|
|
52
|
+
// check after dom update, maybe we can open one more
|
|
53
|
+
tick().then(processOverflow);
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function processOverflow() {
|
|
60
|
+
if (overflow === "wrap" || vertical) return;
|
|
61
|
+
const nodes = getNodes();
|
|
62
|
+
// restore all items so widths can be measured
|
|
63
|
+
for (let i = 0; i < barItems.length; i++) {
|
|
64
|
+
if (nodes[i]) nodes[i].style.display = "";
|
|
65
|
+
}
|
|
66
|
+
const visibleWidth = div.clientWidth;
|
|
67
|
+
const fullWidth = div.scrollWidth;
|
|
68
|
+
const needMenu = fullWidth > visibleWidth;
|
|
69
|
+
if (needMenu) {
|
|
70
|
+
if (overflow === "collapse") return collapseGroups();
|
|
71
|
+
// pinned items always stay visible
|
|
72
|
+
let pinnedWidth = 0;
|
|
73
|
+
for (let i = 0; i < barItems.length; i++) {
|
|
74
|
+
if (barItems[i].pinned) pinnedWidth += nodes[i].clientWidth;
|
|
75
|
+
}
|
|
76
|
+
let sum = 0;
|
|
77
|
+
for (let i = 0; i < barItems.length; i++) {
|
|
78
|
+
if (barItems[i].pinned) continue;
|
|
79
|
+
sum += nodes[i].clientWidth;
|
|
80
|
+
if (barItems[i].comp == "separator") sum += 8;
|
|
81
|
+
if (sum > visibleWidth - 40 - pinnedWidth) {
|
|
82
|
+
// we need to hide nodes[i] and all next non-pinned nodes
|
|
83
|
+
menuItems = [];
|
|
84
|
+
for (let j = i; j < barItems.length; j++) {
|
|
85
|
+
if (barItems[j].pinned) continue;
|
|
86
|
+
menuItems.push(barItems[j]);
|
|
87
|
+
nodes[j].style.display = "none";
|
|
88
|
+
}
|
|
89
|
+
// hide the ending separator
|
|
90
|
+
if (i > 0 && barItems[i - 1].comp == "separator" && !barItems[i - 1].pinned) {
|
|
91
|
+
nodes[i - 1].style.display = "none";
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
const freeWidth = visibleWidth - getTotalWidth();
|
|
98
|
+
if (freeWidth <= 0) return;
|
|
99
|
+
if (overflow === "collapse") return expandGroups(freeWidth);
|
|
100
|
+
if (menuItems.length) menuItems = [];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
onMount(() => {
|
|
104
|
+
const resizeObserver = new ResizeObserver(() => processOverflow());
|
|
105
|
+
resizeObserver.observe(div);
|
|
106
|
+
return () => {
|
|
107
|
+
resizeObserver.unobserve(div);
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<div
|
|
113
|
+
class="wx-toolbar {css}"
|
|
114
|
+
class:wx-wrap={overflow === "wrap"}
|
|
115
|
+
class:wx-column={vertical}
|
|
116
|
+
class:wx-has-menu={menuItems.length > 0}
|
|
117
|
+
bind:this={div}
|
|
118
|
+
>
|
|
119
|
+
{#each barItems as item}
|
|
120
|
+
{#if item.items}
|
|
121
|
+
<Group {item} {values} {onclick} onchange={handleChange} />
|
|
122
|
+
{:else}
|
|
123
|
+
<BarComponent {item} {values} {onclick} onchange={handleChange} />
|
|
124
|
+
{/if}
|
|
125
|
+
{/each}
|
|
126
|
+
{#if menuItems.length}
|
|
127
|
+
<Menu
|
|
128
|
+
items={menuItems}
|
|
129
|
+
css={menuCss}
|
|
130
|
+
{values}
|
|
131
|
+
{onclick}
|
|
132
|
+
onchange={handleChange}
|
|
133
|
+
/>
|
|
134
|
+
{/if}
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<style>
|
|
138
|
+
.wx-toolbar {
|
|
139
|
+
width: 100%;
|
|
140
|
+
flex-wrap: nowrap;
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: stretch;
|
|
143
|
+
padding: 4px;
|
|
144
|
+
position: relative;
|
|
145
|
+
min-height: 48px;
|
|
146
|
+
}
|
|
147
|
+
.wx-toolbar.wx-has-menu {
|
|
148
|
+
padding-right: 48px;
|
|
149
|
+
}
|
|
150
|
+
.wx-toolbar.wx-wrap {
|
|
151
|
+
flex-wrap: wrap;
|
|
152
|
+
}
|
|
153
|
+
.wx-column {
|
|
154
|
+
flex-flow: column;
|
|
155
|
+
width: auto;
|
|
156
|
+
}
|
|
157
|
+
.wx-column > :global(.wx-tb-element) {
|
|
158
|
+
width: 100%;
|
|
159
|
+
}
|
|
160
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IToolbarChangeEvent, IToolbarClickEvent, IToolbarItem, TToolbarValues } from "../types";
|
|
2
|
+
type Props = {
|
|
3
|
+
items?: IToolbarItem[];
|
|
4
|
+
menuCss?: string;
|
|
5
|
+
css?: string;
|
|
6
|
+
values?: TToolbarValues | null;
|
|
7
|
+
overflow?: "collapse" | "wrap" | "menu";
|
|
8
|
+
layout?: "row" | "column";
|
|
9
|
+
onclick?: (ev: IToolbarClickEvent) => void;
|
|
10
|
+
onchange?: (ev: IToolbarChangeEvent) => void;
|
|
11
|
+
};
|
|
12
|
+
declare const Toolbar: import("svelte").Component<Props, {}, "items" | "values">;
|
|
13
|
+
type Toolbar = ReturnType<typeof Toolbar>;
|
|
14
|
+
export default Toolbar;
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Component } from "svelte";
|
|
2
|
+
import type { IItemConfig, IToolbarItem } from "./types";
|
|
3
|
+
export declare function getItemHandler(type: string | Component<any> | undefined, config?: IItemConfig | null): Component<any>;
|
|
4
|
+
export declare function registerToolbarItem(type: string, handler: Component<any>, config?: IItemConfig | null): void;
|
|
5
|
+
export declare function normalizeToolbarItems(items?: IToolbarItem[]): IToolbarItem[];
|
|
6
|
+
export declare function collapseSeparators(items?: IToolbarItem[]): IToolbarItem[];
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { uid } from "@svar-ui/lib-dom";
|
|
2
|
+
const handlers = {};
|
|
3
|
+
export function getItemHandler(type, config = null) {
|
|
4
|
+
// try to get the handler for the config, fallback to the type
|
|
5
|
+
// so we need not register all button types for alternative modes
|
|
6
|
+
const c = typeof type === "string"
|
|
7
|
+
? handlers[getID(type, config)] || handlers[type]
|
|
8
|
+
: type;
|
|
9
|
+
return c || handlers["label"];
|
|
10
|
+
}
|
|
11
|
+
export function registerToolbarItem(type, handler, config = null) {
|
|
12
|
+
handlers[getID(type, config)] = handler;
|
|
13
|
+
}
|
|
14
|
+
// Assign stable ids and collapse consecutive separators
|
|
15
|
+
export function normalizeToolbarItems(items) {
|
|
16
|
+
if (!items?.length)
|
|
17
|
+
return [];
|
|
18
|
+
for (const item of items) {
|
|
19
|
+
if (!item.id)
|
|
20
|
+
item.id = uid();
|
|
21
|
+
}
|
|
22
|
+
return collapseSeparators(items);
|
|
23
|
+
}
|
|
24
|
+
// Keep the first of consecutive separator
|
|
25
|
+
export function collapseSeparators(items) {
|
|
26
|
+
if (!items?.length)
|
|
27
|
+
return items || [];
|
|
28
|
+
const out = [];
|
|
29
|
+
let prevWasSeparator = false;
|
|
30
|
+
for (const item of items) {
|
|
31
|
+
const isSeparator = item.comp === "separator";
|
|
32
|
+
if (isSeparator && prevWasSeparator)
|
|
33
|
+
continue;
|
|
34
|
+
out.push(item);
|
|
35
|
+
prevWasSeparator = isSeparator;
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function getID(type, config = null) {
|
|
40
|
+
return `${type}${config?.menu ? ":menu" : ""}`;
|
|
41
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import Toolbar from "./components/Toolbar.svelte";
|
|
2
|
+
import { registerToolbarItem } from "./helpers";
|
|
3
|
+
import ButtonList from "./buttons/ButtonList.svelte";
|
|
4
|
+
export { Toolbar, ButtonList, registerToolbarItem };
|
|
5
|
+
export type { TID, IToolbarItem, TToolbarValues, IToolbarClickEvent, IToolbarChangeEvent, IButtonListOption, IItemConfig, } from "./types";
|
package/{src → dist}/index.js
RENAMED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Button } from "@svar-ui/svelte-core";
|
|
2
2
|
import Toolbar from "./components/Toolbar.svelte";
|
|
3
|
-
import { registerToolbarItem } from "./helpers
|
|
4
|
-
|
|
3
|
+
import { registerToolbarItem } from "./helpers";
|
|
5
4
|
import Separator from "./buttons/Separator.svelte";
|
|
6
5
|
import Spacer from "./buttons/Spacer.svelte";
|
|
7
6
|
import ButtonList from "./buttons/ButtonList.svelte";
|
|
8
7
|
import Label from "./buttons/Label.svelte";
|
|
9
8
|
import Icon from "./buttons/Icon.svelte";
|
|
10
9
|
import Item from "./buttons/Item.svelte";
|
|
11
|
-
|
|
12
10
|
registerToolbarItem("button", Button);
|
|
13
11
|
registerToolbarItem("button", Icon, { menu: true });
|
|
14
12
|
registerToolbarItem("separator", Separator);
|
|
@@ -16,5 +14,4 @@ registerToolbarItem("spacer", Spacer);
|
|
|
16
14
|
registerToolbarItem("label", Label);
|
|
17
15
|
registerToolbarItem("item", Item);
|
|
18
16
|
registerToolbarItem("icon", Icon);
|
|
19
|
-
|
|
20
17
|
export { Toolbar, ButtonList, registerToolbarItem };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Component } from "svelte";
|
|
2
|
+
export type TID = string | number;
|
|
3
|
+
export interface IToolbarItem {
|
|
4
|
+
id?: TID;
|
|
5
|
+
comp?: string | Component<any>;
|
|
6
|
+
icon?: string;
|
|
7
|
+
css?: string;
|
|
8
|
+
type?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
tooltip?: string;
|
|
12
|
+
menuText?: string;
|
|
13
|
+
key?: string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
spacer?: boolean;
|
|
16
|
+
collapsed?: boolean;
|
|
17
|
+
handler?: (item: IToolbarItem, value?: any) => void;
|
|
18
|
+
layout?: "column";
|
|
19
|
+
items?: IToolbarItem[];
|
|
20
|
+
pinned?: boolean;
|
|
21
|
+
[key: string]: any;
|
|
22
|
+
}
|
|
23
|
+
export type TToolbarValues = {
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
};
|
|
26
|
+
export interface IToolbarClickEvent {
|
|
27
|
+
item: IToolbarItem;
|
|
28
|
+
}
|
|
29
|
+
export interface IToolbarChangeEvent {
|
|
30
|
+
value: any;
|
|
31
|
+
item: IToolbarItem;
|
|
32
|
+
}
|
|
33
|
+
export interface IButtonListOption {
|
|
34
|
+
id: TID;
|
|
35
|
+
label: string;
|
|
36
|
+
}
|
|
37
|
+
export interface IItemConfig {
|
|
38
|
+
menu?: boolean;
|
|
39
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,54 +1,57 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
2
|
+
"name": "@svar-ui/svelte-toolbar",
|
|
3
|
+
"version": "2.6.2",
|
|
4
|
+
"description": "Svelte toolbar component. Lightweight, customizable, easy-to-use.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"buttons panel",
|
|
7
|
+
"svar widgets",
|
|
8
|
+
"svelte",
|
|
9
|
+
"svelte toolbar",
|
|
10
|
+
"toolbar",
|
|
11
|
+
"toolbar component"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://svar.dev/svelte/core/",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://forum.svar.dev"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/svar-widgets/toolbar.git"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"readme.md",
|
|
25
|
+
"whatsnew.md",
|
|
26
|
+
"license.txt"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"svelte": "./dist/index.js",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"svelte": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@svar-ui/lib-dom": "0.14.2",
|
|
40
|
+
"@svar-ui/svelte-core": "2.6.2"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@sveltejs/package": "^2.5.7",
|
|
44
|
+
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
45
|
+
"svelte": "5.56.9",
|
|
46
|
+
"svelte-check": "^4.4.6"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"svelte": "^5.0.0"
|
|
50
|
+
},
|
|
51
|
+
"productTag": "toolbar",
|
|
52
|
+
"scripts": {
|
|
53
|
+
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
54
|
+
"build": "svelte-package -i ./src",
|
|
55
|
+
"dev": "svelte-package -i ./src --watch"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
# SVAR Svelte Toolbar
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@svar-ui/svelte-toolbar)
|
|
@@ -46,21 +46,10 @@ To use the widget, simply import the package and include the component in your S
|
|
|
46
46
|
|
|
47
47
|
Typically, you don't need to modify the code. However, if you wish to do so, follow these steps:
|
|
48
48
|
|
|
49
|
-
1.
|
|
50
|
-
2.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
To run the test:
|
|
55
|
-
|
|
56
|
-
1. Start the test examples with:
|
|
57
|
-
```sh
|
|
58
|
-
yarn start:tests
|
|
59
|
-
```
|
|
60
|
-
2. In a separate console, run the end-to-end tests with:
|
|
61
|
-
```sh
|
|
62
|
-
yarn test:cypress
|
|
63
|
-
```
|
|
49
|
+
1. Install [vite-plus](https://vite.plus) (`curl -fsSL https://vite.plus | bash` on Mac/Linux, `irm https://vite.plus/ps1 | iex` on Windows). The project uses `pnpm` workspaces under the hood, so plain `npm` will not work.
|
|
50
|
+
2. Run `vp i` from the project root to install dependencies.
|
|
51
|
+
3. Run `vp run build` to build all packages.
|
|
52
|
+
4. Start the demo app in development mode with `vp run start`.
|
|
64
53
|
|
|
65
54
|
### Need help?
|
|
66
55
|
|
package/whatsnew.md
CHANGED
|
@@ -1,117 +1,129 @@
|
|
|
1
|
+
## 2.6.2
|
|
2
|
+
|
|
3
|
+
### Updates
|
|
4
|
+
|
|
5
|
+
- Native TypeScript support with types generated from the component sources
|
|
6
|
+
|
|
7
|
+
### Fixes
|
|
8
|
+
|
|
9
|
+
- An item with key throws an error when the Toolbar has no values
|
|
10
|
+
- Changing an item without key writes `values["undefined"]`
|
|
11
|
+
- ButtonList without css gets an undefined CSS class
|
|
12
|
+
|
|
1
13
|
## 2.6.1
|
|
2
14
|
|
|
3
15
|
### Updates
|
|
4
16
|
|
|
5
|
-
-
|
|
6
|
-
-
|
|
17
|
+
- Impossible to render an item differently in the `menu` mode
|
|
18
|
+
- Option based items are not usable in the `menu` mode
|
|
7
19
|
|
|
8
20
|
## 2.6.0
|
|
9
21
|
|
|
10
22
|
### New features
|
|
11
23
|
|
|
12
|
-
-
|
|
24
|
+
- Tooltip for toolbar items
|
|
13
25
|
|
|
14
26
|
### Fixes
|
|
15
27
|
|
|
16
|
-
-
|
|
28
|
+
- Duplicate separators are auto removed
|
|
17
29
|
|
|
18
30
|
## 2.5.3
|
|
19
31
|
|
|
20
32
|
### Fixes
|
|
21
33
|
|
|
22
|
-
-
|
|
23
|
-
-
|
|
34
|
+
- Impossible to arrange first level items as a column
|
|
35
|
+
- Impossible to fix certain items as always visible
|
|
24
36
|
|
|
25
37
|
## 2.5.1
|
|
26
38
|
|
|
27
|
-
-
|
|
39
|
+
- Using Svelte Core v2.5.1
|
|
28
40
|
|
|
29
41
|
## 2.5.0
|
|
30
42
|
|
|
31
|
-
-
|
|
43
|
+
- Using Svelte Core v2.5.0
|
|
32
44
|
|
|
33
45
|
## 2.4.1
|
|
34
46
|
|
|
35
|
-
-
|
|
47
|
+
- Using Svelte Core v2.4.1
|
|
36
48
|
|
|
37
49
|
## 2.4.0
|
|
38
50
|
|
|
39
|
-
-
|
|
51
|
+
- Using Svelte Core v2.4.0
|
|
40
52
|
|
|
41
53
|
## 2.3.0
|
|
42
54
|
|
|
43
55
|
### New features
|
|
44
56
|
|
|
45
|
-
-
|
|
57
|
+
- TypeScript definitions
|
|
46
58
|
|
|
47
59
|
### Fixes
|
|
48
60
|
|
|
49
|
-
-
|
|
61
|
+
- item `menuText` property is not applied
|
|
50
62
|
|
|
51
63
|
## 2.2.1
|
|
52
64
|
|
|
53
65
|
### Fixes
|
|
54
66
|
|
|
55
|
-
-
|
|
67
|
+
- Using in Salesforce environment
|
|
56
68
|
|
|
57
69
|
## 2.2.0
|
|
58
70
|
|
|
59
|
-
-
|
|
71
|
+
- Using core@2.2.0
|
|
60
72
|
|
|
61
73
|
## 2.1.0
|
|
62
74
|
|
|
63
|
-
-
|
|
75
|
+
- Using core@2.1.0
|
|
64
76
|
|
|
65
77
|
## 2.0.1
|
|
66
78
|
|
|
67
79
|
### New features
|
|
68
80
|
|
|
69
|
-
-
|
|
81
|
+
- Svelte 5 support
|
|
70
82
|
|
|
71
83
|
## 1.3.0
|
|
72
84
|
|
|
73
|
-
-
|
|
85
|
+
- Using core@1.3.0
|
|
74
86
|
|
|
75
87
|
## 1.2.3
|
|
76
88
|
|
|
77
89
|
### Fixes
|
|
78
90
|
|
|
79
|
-
-
|
|
80
|
-
-
|
|
91
|
+
- Regression in overflow menu closing
|
|
92
|
+
- Regression in dropdown rendering
|
|
81
93
|
|
|
82
94
|
## 1.2.1
|
|
83
95
|
|
|
84
|
-
-
|
|
96
|
+
- Using core@1.2.0
|
|
85
97
|
|
|
86
98
|
## 1.2.1
|
|
87
99
|
|
|
88
100
|
### New features
|
|
89
101
|
|
|
90
|
-
-
|
|
102
|
+
- Labels can be bound to data
|
|
91
103
|
|
|
92
104
|
## 1.2.0
|
|
93
105
|
|
|
94
106
|
### New features
|
|
95
107
|
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
108
|
+
- Extra demo for the HeaderMenu scenario
|
|
109
|
+
- Ability to use `spacer` on toolbar items
|
|
110
|
+
- Ability to use `item` subtype for the drop-down menus
|
|
99
111
|
|
|
100
112
|
### Fixes
|
|
101
113
|
|
|
102
|
-
-
|
|
103
|
-
-
|
|
114
|
+
- Separator rendering in drop-down menus
|
|
115
|
+
- Names of css classes corrected
|
|
104
116
|
|
|
105
117
|
## 1.1.2
|
|
106
118
|
|
|
107
119
|
### Updates
|
|
108
120
|
|
|
109
|
-
-
|
|
121
|
+
- Inner css classes renamed, "wx" prefix added
|
|
110
122
|
|
|
111
123
|
## 1.1.1
|
|
112
124
|
|
|
113
|
-
-
|
|
125
|
+
- Migrated to vite based toolchain
|
|
114
126
|
|
|
115
127
|
### 1.1.0
|
|
116
128
|
|
|
117
|
-
-
|
|
129
|
+
- Initial version
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import Menu from "./Menu.svelte";
|
|
3
|
-
import Group from "./Group.svelte";
|
|
4
|
-
import BarComponent from "./BarComponent.svelte";
|
|
5
|
-
|
|
6
|
-
import { onMount, tick } from "svelte";
|
|
7
|
-
import { normalizeToolbarItems } from "../helpers";
|
|
8
|
-
|
|
9
|
-
let {
|
|
10
|
-
items = $bindable([]),
|
|
11
|
-
menuCss = "",
|
|
12
|
-
css = "",
|
|
13
|
-
values = $bindable(null),
|
|
14
|
-
overflow = "menu",
|
|
15
|
-
layout = "row",
|
|
16
|
-
onclick,
|
|
17
|
-
onchange,
|
|
18
|
-
} = $props();
|
|
19
|
-
|
|
20
|
-
function handleChange(ev) {
|
|
21
|
-
if (values) {
|
|
22
|
-
values[ev.item.key] = ev.value;
|
|
23
|
-
values = values;
|
|
24
|
-
}
|
|
25
|
-
onchange && onchange(ev);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let div = null;
|
|
29
|
-
let menuItems = $state([]);
|
|
30
|
-
|
|
31
|
-
const barItems = $derived(normalizeToolbarItems(items));
|
|
32
|
-
const vertical = $derived(layout === "column");
|
|
33
|
-
|
|
34
|
-
function getTotalWidth() {
|
|
35
|
-
const nodes = div.children;
|
|
36
|
-
let sum = 0;
|
|
37
|
-
for (let i = 0; i < barItems.length; i++) {
|
|
38
|
-
if (barItems[i].comp != "spacer") {
|
|
39
|
-
sum += nodes[i]?.clientWidth || 0;
|
|
40
|
-
if (barItems[i].comp == "separator") sum += 8;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return sum;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function collapseGroups() {
|
|
47
|
-
for (let i = barItems.length - 1; i >= 0; i--) {
|
|
48
|
-
// close rightmost open group
|
|
49
|
-
if (barItems[i].items && !barItems[i].collapsed) {
|
|
50
|
-
barItems[i].collapsed = true;
|
|
51
|
-
barItems[i].$width = div.children[i].offsetWidth;
|
|
52
|
-
// check after dom update, maybe we need to close more
|
|
53
|
-
tick().then(processOverflow);
|
|
54
|
-
|
|
55
|
-
// items are not deep reactive, so we need to trigger the update
|
|
56
|
-
items = [...items];
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function expandGroups(freeSpace) {
|
|
63
|
-
for (let i = 0; i < barItems.length; i++) {
|
|
64
|
-
// open leftmost closed group that was collapsed by overflow
|
|
65
|
-
if (barItems[i].collapsed && barItems[i].$width) {
|
|
66
|
-
// check if group can fit in free space
|
|
67
|
-
if (
|
|
68
|
-
barItems[i].$width - div.children[i].offsetWidth <
|
|
69
|
-
freeSpace + 10
|
|
70
|
-
) {
|
|
71
|
-
barItems[i].collapsed = false;
|
|
72
|
-
// items are not deep reactive, so we need to trigger the update
|
|
73
|
-
items = [...items];
|
|
74
|
-
// check after dom update, maybe we can open one more
|
|
75
|
-
tick().then(processOverflow);
|
|
76
|
-
}
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function processOverflow() {
|
|
83
|
-
if (overflow === "wrap" || vertical) return;
|
|
84
|
-
|
|
85
|
-
const nodes = div.children;
|
|
86
|
-
// restore all items so widths can be measured
|
|
87
|
-
for (let i = 0; i < barItems.length; i++) {
|
|
88
|
-
if (nodes[i]) nodes[i].style.display = "";
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const visibleWidth = div.clientWidth;
|
|
92
|
-
const fullWidth = div.scrollWidth;
|
|
93
|
-
const needMenu = fullWidth > visibleWidth;
|
|
94
|
-
|
|
95
|
-
if (needMenu) {
|
|
96
|
-
if (overflow === "collapse") return collapseGroups();
|
|
97
|
-
|
|
98
|
-
// pinned items always stay visible
|
|
99
|
-
let pinnedWidth = 0;
|
|
100
|
-
for (let i = 0; i < barItems.length; i++) {
|
|
101
|
-
if (barItems[i].pinned) pinnedWidth += nodes[i].clientWidth;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let sum = 0;
|
|
105
|
-
for (let i = 0; i < barItems.length; i++) {
|
|
106
|
-
if (barItems[i].pinned) continue;
|
|
107
|
-
sum += nodes[i].clientWidth;
|
|
108
|
-
if (barItems[i].comp == "separator") sum += 8;
|
|
109
|
-
if (sum > visibleWidth - 40 - pinnedWidth) {
|
|
110
|
-
// we need to hide nodes[i] and all next non-pinned nodes
|
|
111
|
-
menuItems = [];
|
|
112
|
-
for (let j = i; j < barItems.length; j++) {
|
|
113
|
-
if (barItems[j].pinned) continue;
|
|
114
|
-
menuItems.push(barItems[j]);
|
|
115
|
-
nodes[j].style.display = "none";
|
|
116
|
-
}
|
|
117
|
-
// hide the ending separator
|
|
118
|
-
if (
|
|
119
|
-
i > 0 &&
|
|
120
|
-
barItems[i - 1].comp == "separator" &&
|
|
121
|
-
!barItems[i - 1].pinned
|
|
122
|
-
) {
|
|
123
|
-
nodes[i - 1].style.display = "none";
|
|
124
|
-
}
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
} else {
|
|
129
|
-
const freeWidth = visibleWidth - getTotalWidth();
|
|
130
|
-
if (freeWidth <= 0) return;
|
|
131
|
-
if (overflow === "collapse") return expandGroups(freeWidth);
|
|
132
|
-
|
|
133
|
-
if (menuItems.length) menuItems = [];
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
onMount(() => {
|
|
138
|
-
const resizeObserver = new ResizeObserver(() => processOverflow());
|
|
139
|
-
resizeObserver.observe(div);
|
|
140
|
-
|
|
141
|
-
return () => {
|
|
142
|
-
resizeObserver.unobserve(div);
|
|
143
|
-
};
|
|
144
|
-
});
|
|
145
|
-
</script>
|
|
146
|
-
|
|
147
|
-
<div
|
|
148
|
-
class="wx-toolbar {css}"
|
|
149
|
-
class:wx-wrap={overflow === "wrap"}
|
|
150
|
-
class:wx-column={vertical}
|
|
151
|
-
class:wx-has-menu={menuItems.length}
|
|
152
|
-
bind:this={div}
|
|
153
|
-
>
|
|
154
|
-
{#each barItems as item}
|
|
155
|
-
{#if item.items}
|
|
156
|
-
<Group {item} {values} {onclick} onchange={handleChange} />
|
|
157
|
-
{:else}
|
|
158
|
-
<BarComponent {item} {values} {onclick} onchange={handleChange} />
|
|
159
|
-
{/if}
|
|
160
|
-
{/each}
|
|
161
|
-
{#if menuItems.length}
|
|
162
|
-
<Menu
|
|
163
|
-
items={menuItems}
|
|
164
|
-
css={menuCss}
|
|
165
|
-
{values}
|
|
166
|
-
{onclick}
|
|
167
|
-
onchange={handleChange}
|
|
168
|
-
/>
|
|
169
|
-
{/if}
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<style>
|
|
173
|
-
.wx-toolbar {
|
|
174
|
-
width: 100%;
|
|
175
|
-
flex-wrap: nowrap;
|
|
176
|
-
display: flex;
|
|
177
|
-
align-items: stretch;
|
|
178
|
-
padding: 4px;
|
|
179
|
-
position: relative;
|
|
180
|
-
min-height: 48px;
|
|
181
|
-
}
|
|
182
|
-
.wx-toolbar.wx-has-menu {
|
|
183
|
-
padding-right: 48px;
|
|
184
|
-
}
|
|
185
|
-
.wx-toolbar.wx-wrap {
|
|
186
|
-
flex-wrap: wrap;
|
|
187
|
-
}
|
|
188
|
-
.wx-column {
|
|
189
|
-
flex-flow: column;
|
|
190
|
-
width: auto;
|
|
191
|
-
}
|
|
192
|
-
.wx-column :global(.wx-tb-element) {
|
|
193
|
-
width: 100%;
|
|
194
|
-
}
|
|
195
|
-
</style>
|
package/src/helpers.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { uid } from "@svar-ui/lib-dom";
|
|
2
|
-
|
|
3
|
-
const handlers = {};
|
|
4
|
-
export function getItemHandler(type, config = null) {
|
|
5
|
-
// try to get the handler for the config, fallback to the type
|
|
6
|
-
// so we need not register all button types for alternative modes
|
|
7
|
-
const c =
|
|
8
|
-
typeof type === "string"
|
|
9
|
-
? handlers[getID(type, config)] || handlers[type]
|
|
10
|
-
: type;
|
|
11
|
-
return c || handlers["label"];
|
|
12
|
-
}
|
|
13
|
-
export function registerToolbarItem(type, handler, config = null) {
|
|
14
|
-
handlers[getID(type, config)] = handler;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Assign stable ids and collapse consecutive separators
|
|
18
|
-
export function normalizeToolbarItems(items) {
|
|
19
|
-
if (!items?.length) return [];
|
|
20
|
-
for (const item of items) {
|
|
21
|
-
if (!item.id) item.id = uid();
|
|
22
|
-
}
|
|
23
|
-
return collapseSeparators(items);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Keep the first of consecutive separator
|
|
27
|
-
export function collapseSeparators(items) {
|
|
28
|
-
if (!items?.length) return items || [];
|
|
29
|
-
const out = [];
|
|
30
|
-
let prevWasSeparator = false;
|
|
31
|
-
for (const item of items) {
|
|
32
|
-
const isSeparator = item.comp === "separator";
|
|
33
|
-
if (isSeparator && prevWasSeparator) continue;
|
|
34
|
-
out.push(item);
|
|
35
|
-
prevWasSeparator = isSeparator;
|
|
36
|
-
}
|
|
37
|
-
return out;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function getID(type, config = null) {
|
|
41
|
-
return `${type}${config?.menu ? ":menu" : ""}`;
|
|
42
|
-
}
|
package/types/index.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { Component } from "svelte";
|
|
2
|
-
|
|
3
|
-
export interface IToolbarItem {
|
|
4
|
-
id?: string | number;
|
|
5
|
-
comp?: string | Component<any>;
|
|
6
|
-
icon?: string;
|
|
7
|
-
css?: string;
|
|
8
|
-
type?: string;
|
|
9
|
-
title?: string;
|
|
10
|
-
text?: string;
|
|
11
|
-
tooltip?: string;
|
|
12
|
-
menuText?: string;
|
|
13
|
-
key?: string;
|
|
14
|
-
disabled?: boolean;
|
|
15
|
-
spacer?: boolean;
|
|
16
|
-
collapsed?: boolean;
|
|
17
|
-
handler?: (item: IToolbarItem, value?: any) => void;
|
|
18
|
-
layout?: "column";
|
|
19
|
-
items?: IToolbarItem[];
|
|
20
|
-
pinned?: boolean;
|
|
21
|
-
[key: string]: any;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export declare const Toolbar: Component<{
|
|
25
|
-
items?: IToolbarItem[];
|
|
26
|
-
menuCss?: string;
|
|
27
|
-
css?: string;
|
|
28
|
-
values?: { [key: string]: any };
|
|
29
|
-
overflow?: "collapse" | "wrap" | "menu";
|
|
30
|
-
onclick?: (ev: { item: IToolbarItem }) => void;
|
|
31
|
-
onchange?: (ev: { value: any; item: IToolbarItem }) => void;
|
|
32
|
-
}>;
|
|
33
|
-
|
|
34
|
-
export declare function registerToolbarItem(
|
|
35
|
-
type: string,
|
|
36
|
-
handler: Component<any>
|
|
37
|
-
): void;
|
|
File without changes
|