@coyalabs/bts-style 1.0.7 → 1.0.9
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/dist/Base/BaseContainer.svelte +76 -0
- package/dist/Base/BaseContainer.svelte.d.ts +49 -0
- package/dist/Base/BaseIcon.svelte +42 -0
- package/dist/Base/BaseIcon.svelte.d.ts +30 -0
- package/dist/Base/BasePage.svelte +51 -0
- package/dist/Base/BasePage.svelte.d.ts +31 -0
- package/dist/Base/BaseText.svelte +44 -0
- package/dist/{BaseContainer.svelte.d.ts → Base/BaseText.svelte.d.ts} +7 -5
- package/dist/Components/Button.svelte +127 -0
- package/dist/Components/Button.svelte.d.ts +63 -0
- package/dist/Components/IconButton.svelte +44 -0
- package/dist/Components/IconButton.svelte.d.ts +34 -0
- package/dist/Components/InputBox.svelte +103 -0
- package/dist/Components/InputBox.svelte.d.ts +56 -0
- package/dist/Components/Popup/AlertPopup.svelte +27 -0
- package/dist/Components/Popup/AlertPopup.svelte.d.ts +28 -0
- package/dist/Components/Popup/ConfirmPopup.svelte +39 -0
- package/dist/Components/Popup/ConfirmPopup.svelte.d.ts +32 -0
- package/dist/Components/Popup/Popup.svelte +67 -0
- package/dist/{BasePage.svelte.d.ts → Components/Popup/Popup.svelte.d.ts} +15 -9
- package/dist/Components/Popup/PromptPopup.svelte +61 -0
- package/dist/Components/Popup/PromptPopup.svelte.d.ts +36 -0
- package/dist/Components/Separator.svelte +61 -0
- package/dist/Components/Separator.svelte.d.ts +30 -0
- package/dist/Components/TabBar.svelte +128 -0
- package/dist/Components/TabBar.svelte.d.ts +40 -0
- package/dist/Components/Toggle.svelte +59 -0
- package/dist/{Testing.svelte.d.ts → Components/Toggle.svelte.d.ts} +5 -9
- package/dist/Components/Tooltip.svelte +132 -0
- package/dist/Components/Tooltip.svelte.d.ts +28 -0
- package/dist/Components/TreeDirectory.svelte +148 -0
- package/dist/Components/TreeDirectory.svelte.d.ts +58 -0
- package/dist/Components/popupStore.d.ts +31 -0
- package/dist/Components/popupStore.js +99 -0
- package/dist/Structure/TextHeader.svelte +32 -0
- package/dist/Structure/TextHeader.svelte.d.ts +28 -0
- package/dist/icons.d.ts +10 -0
- package/dist/icons.js +10 -0
- package/dist/index.d.ts +19 -2
- package/dist/index.js +24 -2
- package/package.json +2 -1
- package/public/favicon.png +0 -0
- package/README.md +0 -35
- package/dist/BaseContainer.svelte +0 -43
- package/dist/BasePage.svelte +0 -30
- package/dist/Testing.svelte +0 -26
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Button from './Button.svelte';
|
|
3
|
+
import BaseText from '../Base/BaseText.svelte';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @type {Array<{id?: string, label: string, icon?: string, type?: 'tab' | 'separator'}>}
|
|
7
|
+
*/
|
|
8
|
+
export let tabs = [];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @type {string}
|
|
12
|
+
*/
|
|
13
|
+
export let activeTab = '';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type {(tabId: string) => void}
|
|
17
|
+
*/
|
|
18
|
+
export let onTabChange = () => {};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} tabId
|
|
22
|
+
*/
|
|
23
|
+
function selectTab(tabId) {
|
|
24
|
+
activeTab = tabId;
|
|
25
|
+
onTabChange(tabId);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {number} index - The index in the full tabs array
|
|
30
|
+
*/
|
|
31
|
+
function getCornerRadius(index) {
|
|
32
|
+
// Check if previous item is a separator or start of array
|
|
33
|
+
const prevItem = tabs[index - 1];
|
|
34
|
+
const isFirstInGroup = index === 0 || prevItem?.type === 'separator';
|
|
35
|
+
|
|
36
|
+
// Check if next item is a separator or end of array
|
|
37
|
+
const nextItem = tabs[index + 1];
|
|
38
|
+
const isLastInGroup = index === tabs.length - 1 || nextItem?.type === 'separator';
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
topLeft: isFirstInGroup ? '25px' : '18px',
|
|
42
|
+
topRight: isFirstInGroup ? '25px' : '18px',
|
|
43
|
+
bottomLeft: isLastInGroup ? '25px' : '18px',
|
|
44
|
+
bottomRight: isLastInGroup ? '25px' : '18px'
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Group tabs into categories based on separators
|
|
50
|
+
* @typedef {{label: string | null, tabs: Array<{tab: {id?: string, label: string, icon?: string, type?: 'tab' | 'separator'}, originalIndex: number}>}} Category
|
|
51
|
+
* @type {Category[]}
|
|
52
|
+
*/
|
|
53
|
+
$: categories = tabs.reduce((/** @type {Category[]} */ acc, tab, index) => {
|
|
54
|
+
if (tab.type === 'separator') {
|
|
55
|
+
acc.push({ label: tab.label, tabs: [] });
|
|
56
|
+
} else {
|
|
57
|
+
if (acc.length === 0) {
|
|
58
|
+
acc.push({ label: null, tabs: [] });
|
|
59
|
+
}
|
|
60
|
+
acc[acc.length - 1].tabs.push({ tab, originalIndex: index });
|
|
61
|
+
}
|
|
62
|
+
return acc;
|
|
63
|
+
}, /** @type {Category[]} */ ([]));
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<div class="tab-bar">
|
|
67
|
+
{#each categories as category}
|
|
68
|
+
<div class="category">
|
|
69
|
+
{#if category.label}
|
|
70
|
+
<div class="separator">
|
|
71
|
+
<BaseText variant="content">{category.label}</BaseText>
|
|
72
|
+
</div>
|
|
73
|
+
{/if}
|
|
74
|
+
<div class="category-buttons">
|
|
75
|
+
{#each category.tabs as {tab, originalIndex}}
|
|
76
|
+
{@const corners = getCornerRadius(originalIndex)}
|
|
77
|
+
<div class="tab-button">
|
|
78
|
+
<Button
|
|
79
|
+
theme={activeTab === tab.id ? 'primary' : 'secondary'}
|
|
80
|
+
icon={tab.icon}
|
|
81
|
+
actionIcon={null}
|
|
82
|
+
borderRadiusTopLeft={corners.topLeft}
|
|
83
|
+
borderRadiusTopRight={corners.topRight}
|
|
84
|
+
borderRadiusBottomLeft={corners.bottomLeft}
|
|
85
|
+
borderRadiusBottomRight={corners.bottomRight}
|
|
86
|
+
on:click={() => tab.id && selectTab(tab.id)}
|
|
87
|
+
>
|
|
88
|
+
{tab.label}
|
|
89
|
+
</Button>
|
|
90
|
+
</div>
|
|
91
|
+
{/each}
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
{/each}
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<style>
|
|
98
|
+
.tab-bar {
|
|
99
|
+
display: flex;
|
|
100
|
+
flex-direction: column;
|
|
101
|
+
gap: 1rem;
|
|
102
|
+
width: 250px;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.category {
|
|
106
|
+
display: flex;
|
|
107
|
+
flex-direction: column;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.category-buttons {
|
|
111
|
+
display: flex;
|
|
112
|
+
flex-direction: column;
|
|
113
|
+
gap: 4px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.tab-button {
|
|
117
|
+
width: 100%;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.separator {
|
|
121
|
+
opacity: 0.6;
|
|
122
|
+
padding-bottom: 1rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.tab-button :global(button) {
|
|
126
|
+
width: 100%;
|
|
127
|
+
}
|
|
128
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export default TabBar;
|
|
2
|
+
type TabBar = SvelteComponent<{
|
|
3
|
+
tabs?: {
|
|
4
|
+
id?: string | undefined;
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: string | undefined;
|
|
7
|
+
type?: "separator" | "tab" | undefined;
|
|
8
|
+
}[] | undefined;
|
|
9
|
+
activeTab?: string | undefined;
|
|
10
|
+
onTabChange?: ((tabId: string) => void) | undefined;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}> & {
|
|
14
|
+
$$bindings?: string | undefined;
|
|
15
|
+
};
|
|
16
|
+
declare const TabBar: $$__sveltets_2_IsomorphicComponent<{
|
|
17
|
+
tabs?: {
|
|
18
|
+
id?: string;
|
|
19
|
+
label: string;
|
|
20
|
+
icon?: string;
|
|
21
|
+
type?: "tab" | "separator";
|
|
22
|
+
}[] | undefined;
|
|
23
|
+
activeTab?: string | undefined;
|
|
24
|
+
onTabChange?: ((tabId: string) => void) | undefined;
|
|
25
|
+
}, {
|
|
26
|
+
[evt: string]: CustomEvent<any>;
|
|
27
|
+
}, {}, {}, string>;
|
|
28
|
+
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> {
|
|
29
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
30
|
+
$$bindings?: Bindings;
|
|
31
|
+
} & Exports;
|
|
32
|
+
(internal: unknown, props: Props & {
|
|
33
|
+
$$events?: Events;
|
|
34
|
+
$$slots?: Slots;
|
|
35
|
+
}): Exports & {
|
|
36
|
+
$set?: any;
|
|
37
|
+
$on?: any;
|
|
38
|
+
};
|
|
39
|
+
z_$$bindings?: Bindings;
|
|
40
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/**
|
|
3
|
+
* @type {boolean}
|
|
4
|
+
*/
|
|
5
|
+
export let checked = false;
|
|
6
|
+
|
|
7
|
+
function toggle() {
|
|
8
|
+
checked = !checked;
|
|
9
|
+
}
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<button class="toggle" class:checked on:click={toggle} aria-label="Toggle switch">
|
|
13
|
+
<div class="pill"></div>
|
|
14
|
+
</button>
|
|
15
|
+
|
|
16
|
+
<style>
|
|
17
|
+
.toggle {
|
|
18
|
+
all: unset;
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
position: relative;
|
|
21
|
+
width: 50px;
|
|
22
|
+
height: 25px;
|
|
23
|
+
border-radius: 25px;
|
|
24
|
+
border: 2px solid rgba(255, 255, 255, 0.13);
|
|
25
|
+
box-sizing: border-box;
|
|
26
|
+
transition: all 0.3s ease;
|
|
27
|
+
user-select: none;
|
|
28
|
+
-webkit-user-select: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Off state */
|
|
32
|
+
.toggle {
|
|
33
|
+
background: rgba(121, 92, 105, 0.25);
|
|
34
|
+
box-shadow: inset 0px 0px 9px 2px rgba(102, 88, 128, 0.48);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* On state */
|
|
38
|
+
.toggle.checked {
|
|
39
|
+
background: #ffa1cb6c;
|
|
40
|
+
box-shadow:
|
|
41
|
+
0px 0px 13px 0px rgba(255, 255, 255, 0.07),
|
|
42
|
+
inset 0px 0px 9px 2px rgba(193, 182, 212, 0.5);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.pill {
|
|
46
|
+
position: absolute;
|
|
47
|
+
width: calc(50% - 4px);
|
|
48
|
+
height: calc(100% - 4px);
|
|
49
|
+
background: #FFEFF6;
|
|
50
|
+
border-radius: 25px;
|
|
51
|
+
top: 2px;
|
|
52
|
+
left: 2px;
|
|
53
|
+
transition: transform 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.toggle.checked .pill {
|
|
57
|
+
transform: translateX(calc(100% + 4px));
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
export default
|
|
2
|
-
type
|
|
3
|
-
|
|
1
|
+
export default Toggle;
|
|
2
|
+
type Toggle = SvelteComponent<{
|
|
3
|
+
checked?: boolean | undefined;
|
|
4
4
|
}, {
|
|
5
|
-
ping: CustomEvent<any>;
|
|
6
|
-
} & {
|
|
7
5
|
[evt: string]: CustomEvent<any>;
|
|
8
6
|
}, {}> & {
|
|
9
7
|
$$bindings?: string | undefined;
|
|
10
8
|
};
|
|
11
|
-
declare const
|
|
12
|
-
|
|
9
|
+
declare const Toggle: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
checked?: boolean | undefined;
|
|
13
11
|
}, {
|
|
14
|
-
ping: CustomEvent<any>;
|
|
15
|
-
} & {
|
|
16
12
|
[evt: string]: CustomEvent<any>;
|
|
17
13
|
}, {}, {}, string>;
|
|
18
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> {
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import BaseContainer from '../Base/BaseContainer.svelte';
|
|
3
|
+
import BaseIcon from '../Base/BaseIcon.svelte';
|
|
4
|
+
import BaseText from '../Base/BaseText.svelte';
|
|
5
|
+
import { icons } from '../icons.js';
|
|
6
|
+
/**
|
|
7
|
+
* @type {string}
|
|
8
|
+
*/
|
|
9
|
+
export let text;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @type {string}
|
|
13
|
+
*/
|
|
14
|
+
export let iconSize = '12px';
|
|
15
|
+
|
|
16
|
+
let showTooltip = false;
|
|
17
|
+
/**
|
|
18
|
+
* @type {HTMLDivElement}
|
|
19
|
+
*/
|
|
20
|
+
let tooltipElement;
|
|
21
|
+
/**
|
|
22
|
+
* @type {HTMLDivElement}
|
|
23
|
+
*/
|
|
24
|
+
let iconElement;
|
|
25
|
+
let positionBelow = false;
|
|
26
|
+
|
|
27
|
+
function handleMouseEnter() {
|
|
28
|
+
showTooltip = true;
|
|
29
|
+
|
|
30
|
+
// Check position after tooltip is rendered
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
if (tooltipElement && iconElement) {
|
|
33
|
+
const iconRect = iconElement.getBoundingClientRect();
|
|
34
|
+
const tooltipRect = tooltipElement.getBoundingClientRect();
|
|
35
|
+
|
|
36
|
+
// Check if there's enough space above
|
|
37
|
+
const spaceAbove = iconRect.top;
|
|
38
|
+
const spaceBelow = window.innerHeight - iconRect.bottom;
|
|
39
|
+
|
|
40
|
+
positionBelow = spaceAbove < tooltipRect.height + 10;
|
|
41
|
+
}
|
|
42
|
+
}, 0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function handleMouseLeave() {
|
|
46
|
+
showTooltip = false;
|
|
47
|
+
}
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<div class="tooltip-wrapper">
|
|
51
|
+
<div
|
|
52
|
+
class="icon-trigger"
|
|
53
|
+
bind:this={iconElement}
|
|
54
|
+
on:mouseenter={handleMouseEnter}
|
|
55
|
+
on:mouseleave={handleMouseLeave}
|
|
56
|
+
role="tooltip"
|
|
57
|
+
>
|
|
58
|
+
<BaseIcon variant="toned" svg={icons.help} size={iconSize} />
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
{#if showTooltip}
|
|
62
|
+
<div
|
|
63
|
+
class="tooltip"
|
|
64
|
+
class:below={positionBelow}
|
|
65
|
+
bind:this={tooltipElement}
|
|
66
|
+
>
|
|
67
|
+
<BaseContainer theme="filled" padding="0.75rem" borderRadiusTopLeft="15px" borderRadiusTopRight="15px" borderRadiusBottomLeft="15px" borderRadiusBottomRight="15px">
|
|
68
|
+
<BaseText textModifier="-5px">{text}</BaseText>
|
|
69
|
+
</BaseContainer>
|
|
70
|
+
</div>
|
|
71
|
+
{/if}
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<style>
|
|
75
|
+
.tooltip-wrapper {
|
|
76
|
+
position: relative;
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.icon-trigger {
|
|
81
|
+
cursor: help;
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
padding: 8px;
|
|
86
|
+
margin: -8px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.tooltip {
|
|
90
|
+
position: absolute;
|
|
91
|
+
bottom: calc(100% + 8px);
|
|
92
|
+
left: 50%;
|
|
93
|
+
transform: translateX(-50%);
|
|
94
|
+
min-width: 150px;
|
|
95
|
+
max-width: 500px;
|
|
96
|
+
white-space: normal;
|
|
97
|
+
z-index: 1000;
|
|
98
|
+
pointer-events: none;
|
|
99
|
+
animation: fadeIn 0.2s ease;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.tooltip.below {
|
|
103
|
+
bottom: auto;
|
|
104
|
+
top: calc(100% + 8px);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@keyframes fadeIn {
|
|
108
|
+
from {
|
|
109
|
+
opacity: 0;
|
|
110
|
+
transform: translateX(-50%) translateY(-5px);
|
|
111
|
+
}
|
|
112
|
+
to {
|
|
113
|
+
opacity: 1;
|
|
114
|
+
transform: translateX(-50%) translateY(0);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.tooltip.below {
|
|
119
|
+
animation: fadeInBelow 0.2s ease;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@keyframes fadeInBelow {
|
|
123
|
+
from {
|
|
124
|
+
opacity: 0;
|
|
125
|
+
transform: translateX(-50%) translateY(5px);
|
|
126
|
+
}
|
|
127
|
+
to {
|
|
128
|
+
opacity: 1;
|
|
129
|
+
transform: translateX(-50%) translateY(0);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default Tooltip;
|
|
2
|
+
type Tooltip = SvelteComponent<{
|
|
3
|
+
text: string;
|
|
4
|
+
iconSize?: string | undefined;
|
|
5
|
+
}, {
|
|
6
|
+
[evt: string]: CustomEvent<any>;
|
|
7
|
+
}, {}> & {
|
|
8
|
+
$$bindings?: string | undefined;
|
|
9
|
+
};
|
|
10
|
+
declare const Tooltip: $$__sveltets_2_IsomorphicComponent<{
|
|
11
|
+
text: string;
|
|
12
|
+
iconSize?: string | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
}, {}, {}, string>;
|
|
16
|
+
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> {
|
|
17
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
18
|
+
$$bindings?: Bindings;
|
|
19
|
+
} & Exports;
|
|
20
|
+
(internal: unknown, props: Props & {
|
|
21
|
+
$$events?: Events;
|
|
22
|
+
$$slots?: Slots;
|
|
23
|
+
}): Exports & {
|
|
24
|
+
$set?: any;
|
|
25
|
+
$on?: any;
|
|
26
|
+
};
|
|
27
|
+
z_$$bindings?: Bindings;
|
|
28
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { slide } from 'svelte/transition';
|
|
3
|
+
import Button from './Button.svelte';
|
|
4
|
+
import { icons } from '../icons.js';
|
|
5
|
+
|
|
6
|
+
/** @type {{ name: string, type: 'file' | 'folder', children?: any[] }[]} */
|
|
7
|
+
export let items = [];
|
|
8
|
+
|
|
9
|
+
/** @type {boolean} */
|
|
10
|
+
export let showCount = true;
|
|
11
|
+
|
|
12
|
+
/** @type {string | null} */
|
|
13
|
+
export let itemIcon = null;
|
|
14
|
+
|
|
15
|
+
/** @type {number} */
|
|
16
|
+
export let level = 0;
|
|
17
|
+
|
|
18
|
+
let expanded = new Set();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} id
|
|
22
|
+
*/
|
|
23
|
+
function toggle(id) {
|
|
24
|
+
if (expanded.has(id)) expanded.delete(id);
|
|
25
|
+
else expanded.add(id);
|
|
26
|
+
expanded = expanded;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the current expanded state
|
|
31
|
+
* @returns {string[]}
|
|
32
|
+
*/
|
|
33
|
+
export function getState() {
|
|
34
|
+
return Array.from(expanded);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Set the expanded state
|
|
39
|
+
* @param {string[]} state
|
|
40
|
+
*/
|
|
41
|
+
export function setState(state) {
|
|
42
|
+
expanded = new Set(state);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Expand all folders
|
|
47
|
+
*/
|
|
48
|
+
export function expandAll() {
|
|
49
|
+
/** @type {string[]} */
|
|
50
|
+
const allIds = [];
|
|
51
|
+
/**
|
|
52
|
+
* @param {any[]} items
|
|
53
|
+
* @param {number} lvl
|
|
54
|
+
*/
|
|
55
|
+
function collectIds(items, lvl) {
|
|
56
|
+
items.forEach((/** @type {any} */ item, /** @type {number} */ i) => {
|
|
57
|
+
if (item.type === 'folder') {
|
|
58
|
+
const id = `${lvl}-${i}`;
|
|
59
|
+
allIds.push(id);
|
|
60
|
+
if (item.children) collectIds(item.children, lvl + 1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
collectIds(items, level);
|
|
65
|
+
expanded = new Set(allIds);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Collapse all folders
|
|
70
|
+
*/
|
|
71
|
+
export function collapseAll() {
|
|
72
|
+
expanded = new Set();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Count total items recursively in a folder
|
|
77
|
+
* @param {any[]} children
|
|
78
|
+
* @returns {number}
|
|
79
|
+
*/
|
|
80
|
+
function countItems(children) {
|
|
81
|
+
if (!children) return 0;
|
|
82
|
+
let count = 0;
|
|
83
|
+
children.forEach((/** @type {any} */ child) => {
|
|
84
|
+
count++;
|
|
85
|
+
if (child.type === 'folder' && child.children) {
|
|
86
|
+
count += countItems(child.children);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return count;
|
|
90
|
+
}
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<div class="tree" style="padding-left: {level === 0 ? level * 30 : level * 20}px;">
|
|
94
|
+
{#each items as item, i}
|
|
95
|
+
{@const id = `${level}-${i}`}
|
|
96
|
+
{@const open = expanded.has(id)}
|
|
97
|
+
{@const isLast = i === items.length - 1}
|
|
98
|
+
{@const isNested = level > 0}
|
|
99
|
+
|
|
100
|
+
{#if item.type === 'folder'}
|
|
101
|
+
<div class="folder" on:click={() => toggle(id)} on:keydown={() => {}} role="button" tabindex="0">
|
|
102
|
+
<Button
|
|
103
|
+
theme="primary"
|
|
104
|
+
icon={icons.folder}
|
|
105
|
+
actionIcon={icons.icon_expand}
|
|
106
|
+
actionIconSize="15px"
|
|
107
|
+
actionIconRotation={open ? 0 : -90}
|
|
108
|
+
borderRadiusTopLeft={isNested ? '15px' : '25px'}
|
|
109
|
+
borderRadiusTopRight={isNested ? '15px' : '25px'}
|
|
110
|
+
borderRadiusBottomRight="15px"
|
|
111
|
+
>
|
|
112
|
+
{item.name}{#if showCount && item.children} <span class="count">({countItems(item.children)})</span>{/if}
|
|
113
|
+
</Button>
|
|
114
|
+
</div>
|
|
115
|
+
{#if open && item.children}
|
|
116
|
+
<div transition:slide={{ duration: 150 }}>
|
|
117
|
+
<svelte:self items={item.children} {showCount} {itemIcon} level={level + 1} />
|
|
118
|
+
</div>
|
|
119
|
+
{/if}
|
|
120
|
+
{:else}
|
|
121
|
+
<Button
|
|
122
|
+
theme="secondary"
|
|
123
|
+
icon={itemIcon}
|
|
124
|
+
borderRadiusTopLeft={isNested ? '15px' : '25px'}
|
|
125
|
+
borderRadiusTopRight={isNested ? '15px' : '25px'}
|
|
126
|
+
borderRadiusBottomLeft={isNested && !isLast ? '15px' : '25px'}
|
|
127
|
+
borderRadiusBottomRight={isNested && !isLast ? '15px' : '25px'}
|
|
128
|
+
>
|
|
129
|
+
{item.name}
|
|
130
|
+
</Button>
|
|
131
|
+
{/if}
|
|
132
|
+
{/each}
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<style>
|
|
136
|
+
.tree {
|
|
137
|
+
display: flex;
|
|
138
|
+
flex-direction: column;
|
|
139
|
+
gap: 8px;
|
|
140
|
+
}
|
|
141
|
+
.folder {
|
|
142
|
+
cursor: pointer;
|
|
143
|
+
}
|
|
144
|
+
.folder :global(.count) {
|
|
145
|
+
margin-left: 5px;
|
|
146
|
+
opacity: 0.5;
|
|
147
|
+
}
|
|
148
|
+
</style>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export default TreeDirectory;
|
|
2
|
+
type TreeDirectory = SvelteComponent<{
|
|
3
|
+
items?: {
|
|
4
|
+
name: string;
|
|
5
|
+
type: "file" | "folder";
|
|
6
|
+
children?: any[] | undefined;
|
|
7
|
+
}[] | undefined;
|
|
8
|
+
showCount?: boolean | undefined;
|
|
9
|
+
itemIcon?: string | null | undefined;
|
|
10
|
+
level?: number | undefined;
|
|
11
|
+
getState?: (() => string[]) | undefined;
|
|
12
|
+
setState?: ((state: string[]) => void) | undefined;
|
|
13
|
+
expandAll?: (() => void) | undefined;
|
|
14
|
+
collapseAll?: (() => void) | undefined;
|
|
15
|
+
}, {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
}, {}> & {
|
|
18
|
+
$$bindings?: string | undefined;
|
|
19
|
+
} & {
|
|
20
|
+
getState: () => string[];
|
|
21
|
+
setState: (state: string[]) => void;
|
|
22
|
+
expandAll: () => void;
|
|
23
|
+
collapseAll: () => void;
|
|
24
|
+
};
|
|
25
|
+
declare const TreeDirectory: $$__sveltets_2_IsomorphicComponent<{
|
|
26
|
+
items?: {
|
|
27
|
+
name: string;
|
|
28
|
+
type: "file" | "folder";
|
|
29
|
+
children?: any[];
|
|
30
|
+
}[] | undefined;
|
|
31
|
+
showCount?: boolean | undefined;
|
|
32
|
+
itemIcon?: string | null | undefined;
|
|
33
|
+
level?: number | undefined;
|
|
34
|
+
getState?: (() => string[]) | undefined;
|
|
35
|
+
setState?: ((state: string[]) => void) | undefined;
|
|
36
|
+
expandAll?: (() => void) | undefined;
|
|
37
|
+
collapseAll?: (() => void) | undefined;
|
|
38
|
+
}, {
|
|
39
|
+
[evt: string]: CustomEvent<any>;
|
|
40
|
+
}, {}, {
|
|
41
|
+
getState: () => string[];
|
|
42
|
+
setState: (state: string[]) => void;
|
|
43
|
+
expandAll: () => void;
|
|
44
|
+
collapseAll: () => void;
|
|
45
|
+
}, string>;
|
|
46
|
+
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> {
|
|
47
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
48
|
+
$$bindings?: Bindings;
|
|
49
|
+
} & Exports;
|
|
50
|
+
(internal: unknown, props: Props & {
|
|
51
|
+
$$events?: Events;
|
|
52
|
+
$$slots?: Slots;
|
|
53
|
+
}): Exports & {
|
|
54
|
+
$set?: any;
|
|
55
|
+
$on?: any;
|
|
56
|
+
};
|
|
57
|
+
z_$$bindings?: Bindings;
|
|
58
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export namespace popupStore {
|
|
2
|
+
export { subscribe };
|
|
3
|
+
export function open(title: any, component: any, props?: {}, subtitle?: string): void;
|
|
4
|
+
export function close(): void;
|
|
5
|
+
export function confirm(title: string, message: string, options?: {
|
|
6
|
+
onConfirm?: (() => void) | undefined;
|
|
7
|
+
onCancel?: (() => void) | undefined;
|
|
8
|
+
confirmText?: string | undefined;
|
|
9
|
+
cancelText?: string | undefined;
|
|
10
|
+
}): void;
|
|
11
|
+
export function alert(title: string, message: string, options?: {
|
|
12
|
+
onOk?: (() => void) | undefined;
|
|
13
|
+
okText?: string | undefined;
|
|
14
|
+
}): void;
|
|
15
|
+
export function prompt(title: string, message: string, options?: {
|
|
16
|
+
onSubmit?: ((value: string) => void) | undefined;
|
|
17
|
+
onCancel?: (() => void) | undefined;
|
|
18
|
+
placeholder?: string | undefined;
|
|
19
|
+
submitText?: string | undefined;
|
|
20
|
+
cancelText?: string | undefined;
|
|
21
|
+
label?: string | undefined;
|
|
22
|
+
}): void;
|
|
23
|
+
}
|
|
24
|
+
declare const subscribe: (this: void, run: import("svelte/store").Subscriber<{
|
|
25
|
+
isOpen: boolean;
|
|
26
|
+
title: string;
|
|
27
|
+
subtitle?: string;
|
|
28
|
+
component: any;
|
|
29
|
+
props: any;
|
|
30
|
+
}>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
31
|
+
export {};
|