@svar-ui/svelte-toolbar 2.6.0 → 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.
Files changed (35) hide show
  1. package/dist/buttons/ButtonList.svelte +35 -0
  2. package/dist/buttons/ButtonList.svelte.d.ts +13 -0
  3. package/{src → dist}/buttons/Icon.svelte +7 -8
  4. package/dist/buttons/Icon.svelte.d.ts +16 -0
  5. package/{src → dist}/buttons/Item.svelte +5 -6
  6. package/dist/buttons/Item.svelte.d.ts +13 -0
  7. package/{src → dist}/buttons/Label.svelte +2 -2
  8. package/dist/buttons/Label.svelte.d.ts +9 -0
  9. package/{src → dist}/buttons/Separator.svelte +1 -2
  10. package/dist/buttons/Separator.svelte.d.ts +6 -0
  11. package/dist/buttons/Spacer.svelte.d.ts +26 -0
  12. package/dist/components/BarComponent.svelte +69 -0
  13. package/dist/components/BarComponent.svelte.d.ts +11 -0
  14. package/{src → dist}/components/Group.svelte +12 -18
  15. package/dist/components/Group.svelte.d.ts +12 -0
  16. package/{src → dist}/components/Menu.svelte +16 -21
  17. package/dist/components/Menu.svelte.d.ts +12 -0
  18. package/dist/components/Toolbar.svelte +160 -0
  19. package/dist/components/Toolbar.svelte.d.ts +14 -0
  20. package/dist/env.d.ts +7 -0
  21. package/dist/helpers.d.ts +6 -0
  22. package/dist/helpers.js +41 -0
  23. package/dist/index.d.ts +5 -0
  24. package/{src → dist}/index.js +5 -6
  25. package/dist/types.d.ts +39 -0
  26. package/dist/types.js +1 -0
  27. package/package.json +56 -53
  28. package/readme.md +5 -16
  29. package/whatsnew.md +46 -27
  30. package/src/buttons/Button.svelte +0 -39
  31. package/src/components/BarComponent.svelte +0 -86
  32. package/src/components/Toolbar.svelte +0 -190
  33. package/src/helpers.js +0 -32
  34. package/types/index.d.ts +0 -37
  35. /package/{src → dist}/buttons/Spacer.svelte +0 -0
@@ -0,0 +1,35 @@
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
+ }
7
+ </script>
8
+
9
+ <div class="wx-button-list {css}">
10
+ {#each options as option}
11
+ <Button
12
+ type={value === option.id ? "primary" : undefined}
13
+ {disabled}
14
+ text={option.label}
15
+ onclick={() => onClickHandler(option.id)}
16
+ />
17
+ {/each}
18
+ </div>
19
+
20
+ <style>
21
+ .wx-button-list {
22
+ line-height: normal;
23
+ }
24
+ .wx-button-list :global(button) {
25
+ width: 100%;
26
+ }
27
+ .wx-button-list :global(button:not(:first-child)) {
28
+ border-top-left-radius: 0;
29
+ border-top-right-radius: 0;
30
+ }
31
+ .wx-button-list :global(button:not(:last-child)) {
32
+ border-bottom-left-radius: 0;
33
+ border-bottom-right-radius: 0;
34
+ }
35
+ </style>
@@ -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,15 +1,12 @@
1
- <script>
2
- import { Button } from "@svar-ui/svelte-core";
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" {onclick}>
12
- {#if icon}<i class="{icon} {css}"></i>{/if}
8
+ <div class="wx-item" class:wx-text-icon={!!text} {onclick}>
9
+ <i class="{icon || 'wxi-empty'} {css || ''}"></i>
13
10
  {text}
14
11
  </div>
15
12
  {:else}
@@ -18,10 +15,12 @@
18
15
 
19
16
  <style>
20
17
  i {
21
- margin-right: 8px;
22
18
  font-size: var(--wx-icon-size);
23
19
  color: var(--wx-color-font);
24
20
  }
21
+ .wx-text-icon i {
22
+ margin-right: 8px;
23
+ }
25
24
  .wx-item {
26
25
  cursor: pointer;
27
26
  white-space: nowrap;
@@ -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
- let { id = "", text = "", css = "", icon = "", onclick } = $props();
3
-
4
- function handleClick() {
5
- onclick && onclick({ id });
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;
@@ -1,5 +1,5 @@
1
- <script>
2
- const { text, value, children } = $props();
1
+ <script lang="ts">const { text, value, children } = $props();
2
+ export {};
3
3
  </script>
4
4
 
5
5
  {#if children}
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from "svelte";
2
+ type Props = {
3
+ text?: string;
4
+ value?: any;
5
+ children?: Snippet;
6
+ };
7
+ declare const Label: import("svelte").Component<Props, {}, "">;
8
+ type Label = ReturnType<typeof Label>;
9
+ export default Label;
@@ -1,5 +1,4 @@
1
- <script>
2
- let { menu = false } = $props();
1
+ <script lang="ts">let { menu = false } = $props();
3
2
  </script>
4
3
 
5
4
  <div class="wx-separator{menu ? '-menu' : ''}">&nbsp;</div>
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ menu?: boolean;
3
+ };
4
+ declare const Separator: import("svelte").Component<Props, {}, "">;
5
+ type Separator = ReturnType<typeof Separator>;
6
+ export default Separator;
@@ -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
+ }
@@ -0,0 +1,69 @@
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);
20
+ </script>
21
+
22
+ {#if item.comp == "spacer"}
23
+ <Spacer />
24
+ {:else if item.comp == "separator"}
25
+ <Separator {menu} />
26
+ {:else}
27
+ {@const SvelteComponent = itemComponent}
28
+ <div
29
+ class="wx-tb-element {item.css || ''}"
30
+ class:wx-spacer={item.spacer}
31
+ class:wx-menu={menu}
32
+ data-id={setID(item.id as TID)}
33
+ >
34
+ <SvelteComponent
35
+ {value}
36
+ onchange={detectChange}
37
+ onclick={onClick}
38
+ {menu}
39
+ {...item}
40
+ {text}
41
+ />
42
+ </div>
43
+ {/if}
44
+
45
+ <style>
46
+ .wx-spacer {
47
+ flex: 1;
48
+ }
49
+ .wx-tb-element {
50
+ padding: 4px;
51
+ flex-shrink: 0;
52
+ align-self: center;
53
+ display: flex;
54
+ }
55
+ .wx-menu.wx-tb-element {
56
+ line-height: 36px;
57
+ padding: 2px 8px;
58
+ background-color: var(--wx-background);
59
+ }
60
+ .wx-menu :global(button) {
61
+ width: 100%;
62
+ }
63
+ .wx-menu :global(.wx-tb-element) {
64
+ align-self: stretch;
65
+ }
66
+ .wx-menu.wx-tb-element:hover {
67
+ background: var(--wx-background-alt);
68
+ }
69
+ </style>
@@ -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
- import Group from "./Group.svelte";
3
-
4
- import BarComponent from "./BarComponent.svelte";
5
- import { Dropdown } from "@svar-ui/svelte-core";
6
- import { collapseSeparators } from "../helpers";
7
-
8
- let { item, values = null, menu = false, onchange, onclick } = $props();
9
-
10
- let collapsedState = $state(true);
11
-
12
- const onClick = ev => {
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
- import BarComponent from "./BarComponent.svelte";
3
- import Group from "./Group.svelte";
4
- import { Dropdown, Button } from "@svar-ui/svelte-core";
5
-
6
- let { items = [], css, values, width, onclick, onchange } = $props();
7
-
8
- let popup = $state();
9
- let div = $state();
10
-
11
- function oncancel() {
12
- popup = null;
13
- }
14
- function showMenu() {
15
- popup = true;
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 || ''}" bind:this={div} data-id="$menu">
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,7 @@
1
+ /// <reference types="svelte" />
2
+
3
+ declare module "*.svelte" {
4
+ import type { Component } from "svelte";
5
+ const component: Component<any>;
6
+ export default component;
7
+ }
@@ -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[];
@@ -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
+ }
@@ -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";
@@ -1,18 +1,17 @@
1
+ import { Button } from "@svar-ui/svelte-core";
1
2
  import Toolbar from "./components/Toolbar.svelte";
2
- import { registerToolbarItem } from "./helpers.js";
3
-
3
+ import { registerToolbarItem } from "./helpers";
4
4
  import Separator from "./buttons/Separator.svelte";
5
5
  import Spacer from "./buttons/Spacer.svelte";
6
- import Button from "./buttons/Button.svelte";
6
+ import ButtonList from "./buttons/ButtonList.svelte";
7
7
  import Label from "./buttons/Label.svelte";
8
8
  import Icon from "./buttons/Icon.svelte";
9
9
  import Item from "./buttons/Item.svelte";
10
-
11
10
  registerToolbarItem("button", Button);
11
+ registerToolbarItem("button", Icon, { menu: true });
12
12
  registerToolbarItem("separator", Separator);
13
13
  registerToolbarItem("spacer", Spacer);
14
14
  registerToolbarItem("label", Label);
15
15
  registerToolbarItem("item", Item);
16
16
  registerToolbarItem("icon", Icon);
17
-
18
- export { Toolbar, registerToolbarItem };
17
+ export { Toolbar, ButtonList, registerToolbarItem };