@streamscloud/kit 0.2.29 → 0.2.31
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/ui/grouped-sidebar/cmp.grouped-sidebar-section.svelte +127 -0
- package/dist/ui/grouped-sidebar/cmp.grouped-sidebar-section.svelte.d.ts +27 -0
- package/dist/ui/grouped-sidebar/cmp.grouped-sidebar.svelte +116 -0
- package/dist/ui/grouped-sidebar/cmp.grouped-sidebar.svelte.d.ts +17 -0
- package/dist/ui/grouped-sidebar/index.d.ts +4 -0
- package/dist/ui/grouped-sidebar/index.js +3 -0
- package/dist/ui/grouped-sidebar/types.svelte.d.ts +64 -0
- package/dist/ui/grouped-sidebar/types.svelte.js +76 -0
- package/package.json +5 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script lang="ts">import { DynamicComponent, DynamicComponentModel } from '../dynamic-component';
|
|
2
|
+
import { Icon } from '../icon';
|
|
3
|
+
import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_20_regular.svg?raw';
|
|
4
|
+
import IconChevronRight from '@fluentui/svg-icons/icons/chevron_right_20_regular.svg?raw';
|
|
5
|
+
let { section, showSectionCollapser = true, expandToFill = true, on } = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="grouped-sidebar-section">
|
|
9
|
+
{#if showSectionCollapser}
|
|
10
|
+
<button type="button" class="grouped-sidebar-section__trigger" onclick={() => on?.toggleSection?.(section)}>
|
|
11
|
+
<span class="grouped-sidebar-section__title" class:grouped-sidebar-section__title--invalid={!section.isValid}>{section.name}</span>
|
|
12
|
+
<span class="grouped-sidebar-section__expand-icon">
|
|
13
|
+
{#if section.expanded}
|
|
14
|
+
<Icon src={IconChevronDown} />
|
|
15
|
+
{:else}
|
|
16
|
+
<Icon src={IconChevronRight} />
|
|
17
|
+
{/if}
|
|
18
|
+
</span>
|
|
19
|
+
</button>
|
|
20
|
+
{/if}
|
|
21
|
+
|
|
22
|
+
<div
|
|
23
|
+
class="grouped-sidebar-section__content"
|
|
24
|
+
class:grouped-sidebar-section__content--expanded={section.expanded}
|
|
25
|
+
class:grouped-sidebar-section__content--fill={section.expanded && expandToFill}
|
|
26
|
+
class:grouped-sidebar-section__content--without-paddings={section.withoutPaddings}>
|
|
27
|
+
{#if section.expanded && section.component}
|
|
28
|
+
{#if typeof section.component === 'function'}
|
|
29
|
+
{@render section.component()}
|
|
30
|
+
{:else if section.component instanceof DynamicComponentModel}
|
|
31
|
+
<DynamicComponent model={section.component} />
|
|
32
|
+
{/if}
|
|
33
|
+
{/if}
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<!--
|
|
38
|
+
@component
|
|
39
|
+
A collapsible section within a GroupedSidebar. Renders a trigger button with chevron and expandable content area.
|
|
40
|
+
|
|
41
|
+
### CSS Custom Properties
|
|
42
|
+
| Property | Description | Default |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `--sc-kit--grouped-sidebar-section--trigger--background` | Trigger row background | `light-dark(neutral-50, dark-700)` |
|
|
45
|
+
| `--sc-kit--grouped-sidebar-section--trigger--color` | Trigger text color | `light-dark(gray-800, white)` |
|
|
46
|
+
| `--sc-kit--grouped-sidebar-section--error-color` | Invalid section title color | `light-dark(destructive-500, destructive-400)` |
|
|
47
|
+
| `--sc-kit--grouped-sidebar-section--padding-block` | Content vertical padding | `1rem` |
|
|
48
|
+
| `--sc-kit--grouped-sidebar-section--padding-inline` | Content horizontal padding | `1rem` |
|
|
49
|
+
| `--sc-kit--grouped-sidebar-section--content--display` | Content display mode | `block` |
|
|
50
|
+
-->
|
|
51
|
+
|
|
52
|
+
<style>.grouped-sidebar-section {
|
|
53
|
+
--_grouped-sidebar-section--trigger--background: var(
|
|
54
|
+
--sc-kit--grouped-sidebar-section--trigger--background,
|
|
55
|
+
light-dark(#f9fafb, #222222)
|
|
56
|
+
);
|
|
57
|
+
--_grouped-sidebar-section--trigger--color: var(
|
|
58
|
+
--sc-kit--grouped-sidebar-section--trigger--color,
|
|
59
|
+
light-dark(#2e2e2e, #ffffff)
|
|
60
|
+
);
|
|
61
|
+
--_grouped-sidebar-section--error-color: var(
|
|
62
|
+
--sc-kit--grouped-sidebar-section--error-color,
|
|
63
|
+
light-dark(#e71d36, #f17e8b)
|
|
64
|
+
);
|
|
65
|
+
--_grouped-sidebar-section--padding-block: var(--sc-kit--grouped-sidebar-section--padding-block, 1rem);
|
|
66
|
+
--_grouped-sidebar-section--padding-inline: var(--sc-kit--grouped-sidebar-section--padding-inline, 1rem);
|
|
67
|
+
--_grouped-sidebar-section--content--display: var(--sc-kit--grouped-sidebar-section--content--display, block);
|
|
68
|
+
display: contents;
|
|
69
|
+
}
|
|
70
|
+
.grouped-sidebar-section__trigger {
|
|
71
|
+
display: flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
width: 100%;
|
|
74
|
+
padding: 0.375rem 1rem;
|
|
75
|
+
background-color: var(--_grouped-sidebar-section--trigger--background);
|
|
76
|
+
margin-bottom: 1px;
|
|
77
|
+
color: var(--_grouped-sidebar-section--trigger--color);
|
|
78
|
+
}
|
|
79
|
+
.grouped-sidebar-section__title {
|
|
80
|
+
font-size: 0.875rem;
|
|
81
|
+
}
|
|
82
|
+
.grouped-sidebar-section__title--invalid {
|
|
83
|
+
color: var(--_grouped-sidebar-section--error-color);
|
|
84
|
+
}
|
|
85
|
+
.grouped-sidebar-section__expand-icon {
|
|
86
|
+
margin-left: auto;
|
|
87
|
+
}
|
|
88
|
+
.grouped-sidebar-section__content {
|
|
89
|
+
display: var(--_grouped-sidebar-section--content--display);
|
|
90
|
+
transition: flex 250ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
91
|
+
flex: 0 0 0;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
}
|
|
94
|
+
.grouped-sidebar-section__content--expanded {
|
|
95
|
+
flex: 0 0 auto;
|
|
96
|
+
padding: var(--_grouped-sidebar-section--padding-block) var(--_grouped-sidebar-section--padding-inline);
|
|
97
|
+
padding-bottom: 0;
|
|
98
|
+
margin-bottom: var(--_grouped-sidebar-section--padding-block);
|
|
99
|
+
}
|
|
100
|
+
.grouped-sidebar-section__content--fill {
|
|
101
|
+
flex: 1;
|
|
102
|
+
overflow-y: auto;
|
|
103
|
+
--_cross-browser-scrollbar--thumb-color: transparent;
|
|
104
|
+
--_cross-browser-scrollbar--track-color: transparent;
|
|
105
|
+
}
|
|
106
|
+
.grouped-sidebar-section__content--fill:hover {
|
|
107
|
+
--_cross-browser-scrollbar--thumb-color: var(--scrollbar--thumb-color, light-dark(#d1d5db, #4b5563));
|
|
108
|
+
--_cross-browser-scrollbar--track-color: var(--scrollbar--track-color, transparent);
|
|
109
|
+
}
|
|
110
|
+
.grouped-sidebar-section__content--fill::-webkit-scrollbar {
|
|
111
|
+
width: 6px;
|
|
112
|
+
height: 6px;
|
|
113
|
+
}
|
|
114
|
+
.grouped-sidebar-section__content--fill::-webkit-scrollbar-track {
|
|
115
|
+
background: var(--_cross-browser-scrollbar--track-color);
|
|
116
|
+
border-radius: 100vw;
|
|
117
|
+
}
|
|
118
|
+
.grouped-sidebar-section__content--fill::-webkit-scrollbar-thumb {
|
|
119
|
+
background: var(--_cross-browser-scrollbar--thumb-color);
|
|
120
|
+
border-radius: 100vw;
|
|
121
|
+
}
|
|
122
|
+
@supports (scrollbar-color: transparent transparent) {
|
|
123
|
+
.grouped-sidebar-section__content--fill {
|
|
124
|
+
scrollbar-color: var(--_cross-browser-scrollbar--thumb-color) var(--_cross-browser-scrollbar--track-color);
|
|
125
|
+
scrollbar-width: thin;
|
|
126
|
+
}
|
|
127
|
+
}</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SidebarGroupSectionModel } from './types.svelte';
|
|
2
|
+
type Props = {
|
|
3
|
+
section: SidebarGroupSectionModel;
|
|
4
|
+
/** @default true */
|
|
5
|
+
showSectionCollapser?: boolean;
|
|
6
|
+
/** When true, expanded sections stretch to fill available space @default true */
|
|
7
|
+
expandToFill?: boolean;
|
|
8
|
+
on?: {
|
|
9
|
+
toggleSection?: (section: SidebarGroupSectionModel) => void;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A collapsible section within a GroupedSidebar. Renders a trigger button with chevron and expandable content area.
|
|
14
|
+
*
|
|
15
|
+
* ### CSS Custom Properties
|
|
16
|
+
* | Property | Description | Default |
|
|
17
|
+
* |---|---|---|
|
|
18
|
+
* | `--sc-kit--grouped-sidebar-section--trigger--background` | Trigger row background | `light-dark(neutral-50, dark-700)` |
|
|
19
|
+
* | `--sc-kit--grouped-sidebar-section--trigger--color` | Trigger text color | `light-dark(gray-800, white)` |
|
|
20
|
+
* | `--sc-kit--grouped-sidebar-section--error-color` | Invalid section title color | `light-dark(destructive-500, destructive-400)` |
|
|
21
|
+
* | `--sc-kit--grouped-sidebar-section--padding-block` | Content vertical padding | `1rem` |
|
|
22
|
+
* | `--sc-kit--grouped-sidebar-section--padding-inline` | Content horizontal padding | `1rem` |
|
|
23
|
+
* | `--sc-kit--grouped-sidebar-section--content--display` | Content display mode | `block` |
|
|
24
|
+
*/
|
|
25
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
26
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
27
|
+
export default Cmp;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script lang="ts">import { SegmentedControl } from '../segmented-control';
|
|
2
|
+
import { default as Section } from './cmp.grouped-sidebar-section.svelte';
|
|
3
|
+
let { settings } = $props();
|
|
4
|
+
const handleSelectGroup = (id) => {
|
|
5
|
+
settings.selectedGroupId = id;
|
|
6
|
+
if (selectedGroup?.onSelected) {
|
|
7
|
+
selectedGroup.onSelected();
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const handleToggleSection = (section) => {
|
|
11
|
+
if (!selectedGroup) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const nextStateExpanded = !section.expanded;
|
|
15
|
+
if (!nextStateExpanded && !settings.allowCloseAllSections) {
|
|
16
|
+
const currentlyExpandedSectionsCount = selectedGroup.sections.filter((x) => x.expanded).length;
|
|
17
|
+
if (currentlyExpandedSectionsCount <= 1) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (nextStateExpanded && !settings.allowMultipleExpandedSections) {
|
|
22
|
+
section.onExpandedChanged(true);
|
|
23
|
+
selectedGroup.sections.forEach((x) => {
|
|
24
|
+
if (x.id !== section.id) {
|
|
25
|
+
x.onExpandedChanged(false);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
section.onExpandedChanged(nextStateExpanded);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const selectedGroup = $derived(settings.groups.find((d) => d.id === settings.selectedGroupId));
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<div class="grouped-sidebar">
|
|
37
|
+
{#if (settings.groups.length > 1 || settings.alwaysShowAllGroups) && selectedGroup}
|
|
38
|
+
<div class="grouped-sidebar__header">
|
|
39
|
+
<SegmentedControl
|
|
40
|
+
segments={settings.groups.map((g) => ({ id: g.id, label: g.name, invalid: !g.isValid }))}
|
|
41
|
+
selected={selectedGroup.id}
|
|
42
|
+
on={{ change: handleSelectGroup }} />
|
|
43
|
+
</div>
|
|
44
|
+
{/if}
|
|
45
|
+
<div class="grouped-sidebar__sections">
|
|
46
|
+
{#if selectedGroup}
|
|
47
|
+
{#each selectedGroup.sections as section (section.id)}
|
|
48
|
+
<Section
|
|
49
|
+
section={section}
|
|
50
|
+
expandToFill={settings.expandToFill}
|
|
51
|
+
showSectionCollapser={selectedGroup.sections.length > 1 || settings.alwaysShowAllSections}
|
|
52
|
+
on={{ toggleSection: handleToggleSection }} />
|
|
53
|
+
{/each}
|
|
54
|
+
{/if}
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!--
|
|
59
|
+
@component
|
|
60
|
+
A sidebar with tabbed groups and collapsible sections. Supports accordion (single expanded) and multi-expand modes, with optional auto-height sections.
|
|
61
|
+
|
|
62
|
+
### CSS Custom Properties
|
|
63
|
+
| Property | Description | Default |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `--sc-kit--grouped-sidebar--background` | Sidebar background | `light-dark(white, dark-800)` |
|
|
66
|
+
| `--sc-kit--grouped-sidebar--padding-block` | Header vertical padding | `1rem` |
|
|
67
|
+
| `--sc-kit--grouped-sidebar--padding-inline` | Header horizontal padding | `1rem` |
|
|
68
|
+
-->
|
|
69
|
+
|
|
70
|
+
<style>.grouped-sidebar {
|
|
71
|
+
--_grouped-sidebar--background: var(--sc-kit--grouped-sidebar--background, light-dark(#ffffff, #1e1e1e));
|
|
72
|
+
--_grouped-sidebar--padding-block: var(--sc-kit--grouped-sidebar--padding-block, 1rem);
|
|
73
|
+
--_grouped-sidebar--padding-inline: var(--sc-kit--grouped-sidebar--padding-inline, 1rem);
|
|
74
|
+
--sc-kit--grouped-sidebar-section--padding-block: var(--_grouped-sidebar--padding-block);
|
|
75
|
+
--sc-kit--grouped-sidebar-section--padding-inline: var(--_grouped-sidebar--padding-inline);
|
|
76
|
+
--sc-kit--segmented-control--background: light-dark(#f2f2f3, #222222);
|
|
77
|
+
--sc-kit--segmented-control--selected--background: light-dark(#ffffff, #242424);
|
|
78
|
+
--sc-kit--segmented-control--border-color: light-dark(#f2f2f3, #222222);
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
height: 100%;
|
|
82
|
+
background: var(--_grouped-sidebar--background);
|
|
83
|
+
}
|
|
84
|
+
.grouped-sidebar__header {
|
|
85
|
+
padding: var(--_grouped-sidebar--padding-block) var(--_grouped-sidebar--padding-inline);
|
|
86
|
+
}
|
|
87
|
+
.grouped-sidebar__sections {
|
|
88
|
+
display: flex;
|
|
89
|
+
overflow-y: auto;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
flex: 1;
|
|
92
|
+
--_cross-browser-scrollbar--thumb-color: transparent;
|
|
93
|
+
--_cross-browser-scrollbar--track-color: transparent;
|
|
94
|
+
}
|
|
95
|
+
.grouped-sidebar__sections:hover {
|
|
96
|
+
--_cross-browser-scrollbar--thumb-color: var(--scrollbar--thumb-color, light-dark(#d1d5db, #4b5563));
|
|
97
|
+
--_cross-browser-scrollbar--track-color: var(--scrollbar--track-color, transparent);
|
|
98
|
+
}
|
|
99
|
+
.grouped-sidebar__sections::-webkit-scrollbar {
|
|
100
|
+
width: 6px;
|
|
101
|
+
height: 6px;
|
|
102
|
+
}
|
|
103
|
+
.grouped-sidebar__sections::-webkit-scrollbar-track {
|
|
104
|
+
background: var(--_cross-browser-scrollbar--track-color);
|
|
105
|
+
border-radius: 100vw;
|
|
106
|
+
}
|
|
107
|
+
.grouped-sidebar__sections::-webkit-scrollbar-thumb {
|
|
108
|
+
background: var(--_cross-browser-scrollbar--thumb-color);
|
|
109
|
+
border-radius: 100vw;
|
|
110
|
+
}
|
|
111
|
+
@supports (scrollbar-color: transparent transparent) {
|
|
112
|
+
.grouped-sidebar__sections {
|
|
113
|
+
scrollbar-color: var(--_cross-browser-scrollbar--thumb-color) var(--_cross-browser-scrollbar--track-color);
|
|
114
|
+
scrollbar-width: thin;
|
|
115
|
+
}
|
|
116
|
+
}</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GroupedSidebarSettings } from './types.svelte';
|
|
2
|
+
type Props = {
|
|
3
|
+
settings: GroupedSidebarSettings;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* A sidebar with tabbed groups and collapsible sections. Supports accordion (single expanded) and multi-expand modes, with optional auto-height sections.
|
|
7
|
+
*
|
|
8
|
+
* ### CSS Custom Properties
|
|
9
|
+
* | Property | Description | Default |
|
|
10
|
+
* |---|---|---|
|
|
11
|
+
* | `--sc-kit--grouped-sidebar--background` | Sidebar background | `light-dark(white, dark-800)` |
|
|
12
|
+
* | `--sc-kit--grouped-sidebar--padding-block` | Header vertical padding | `1rem` |
|
|
13
|
+
* | `--sc-kit--grouped-sidebar--padding-inline` | Header horizontal padding | `1rem` |
|
|
14
|
+
*/
|
|
15
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
17
|
+
export default Cmp;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as GroupedSidebar } from './cmp.grouped-sidebar.svelte';
|
|
2
|
+
export { default as GroupedSidebarSection } from './cmp.grouped-sidebar-section.svelte';
|
|
3
|
+
export { GroupedSidebarSettings, SidebarGroupModel, SidebarGroupSectionModel } from './types.svelte';
|
|
4
|
+
export type { SidebarGroupInit, SidebarSectionInit, SidebarValidator } from './types.svelte';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DynamicComponentModel } from '../dynamic-component';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
export declare class GroupedSidebarSettings {
|
|
4
|
+
groups: ReadonlyArray<SidebarGroupModel>;
|
|
5
|
+
selectedGroupId: string;
|
|
6
|
+
allowMultipleExpandedSections: boolean;
|
|
7
|
+
allowCloseAllSections: boolean;
|
|
8
|
+
alwaysShowAllSections: boolean;
|
|
9
|
+
alwaysShowAllGroups: boolean;
|
|
10
|
+
expandToFill: boolean;
|
|
11
|
+
constructor(init: {
|
|
12
|
+
groups: SidebarGroupInit[];
|
|
13
|
+
initiallySelectedGroupId?: string;
|
|
14
|
+
allowMultipleExpandedSections?: boolean;
|
|
15
|
+
allowCloseAllSections?: boolean;
|
|
16
|
+
alwaysShowAllGroups?: boolean;
|
|
17
|
+
alwaysShowAllSections?: boolean;
|
|
18
|
+
expandToFill?: boolean;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export declare class SidebarGroupModel {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
sections: ReadonlyArray<SidebarGroupSectionModel>;
|
|
25
|
+
onSelected: () => void;
|
|
26
|
+
readonly isValid: boolean;
|
|
27
|
+
private _validator;
|
|
28
|
+
constructor(init: SidebarGroupInit);
|
|
29
|
+
get validator(): SidebarValidator;
|
|
30
|
+
updateValidator: (validator: SidebarValidator) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare class SidebarGroupSectionModel {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
expanded: boolean;
|
|
36
|
+
component: DynamicComponentModel | Snippet;
|
|
37
|
+
withoutPaddings: boolean;
|
|
38
|
+
readonly isValid: boolean;
|
|
39
|
+
private _validator;
|
|
40
|
+
private _onExpandedCallback;
|
|
41
|
+
constructor(init: SidebarSectionInit);
|
|
42
|
+
get validator(): SidebarValidator | null;
|
|
43
|
+
onExpandedChanged: (val: boolean) => void;
|
|
44
|
+
updateValidator: (validator: SidebarValidator) => void;
|
|
45
|
+
}
|
|
46
|
+
export interface SidebarGroupInit {
|
|
47
|
+
id?: string;
|
|
48
|
+
name: string;
|
|
49
|
+
sections: SidebarSectionInit[];
|
|
50
|
+
onSelected?: () => void;
|
|
51
|
+
validator?: SidebarValidator;
|
|
52
|
+
}
|
|
53
|
+
export interface SidebarSectionInit {
|
|
54
|
+
id?: string;
|
|
55
|
+
name: string;
|
|
56
|
+
expanded?: boolean;
|
|
57
|
+
withoutPaddings?: boolean;
|
|
58
|
+
component: DynamicComponentModel | Snippet;
|
|
59
|
+
onExpandedChanged?: (val: boolean) => void;
|
|
60
|
+
validator?: SidebarValidator;
|
|
61
|
+
}
|
|
62
|
+
export type SidebarValidator = {
|
|
63
|
+
isValid: boolean;
|
|
64
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { randomNanoid } from '../../core/utils';
|
|
2
|
+
import { DynamicComponentModel } from '../dynamic-component';
|
|
3
|
+
export class GroupedSidebarSettings {
|
|
4
|
+
groups = $state.raw([]);
|
|
5
|
+
selectedGroupId = $state('');
|
|
6
|
+
allowMultipleExpandedSections = $state(false);
|
|
7
|
+
allowCloseAllSections = $state(false);
|
|
8
|
+
alwaysShowAllSections = $state(false);
|
|
9
|
+
alwaysShowAllGroups = $state(false);
|
|
10
|
+
expandToFill = $state(true);
|
|
11
|
+
constructor(init) {
|
|
12
|
+
this.groups = init.groups.map((g) => new SidebarGroupModel(g));
|
|
13
|
+
this.selectedGroupId = init.initiallySelectedGroupId ?? '';
|
|
14
|
+
this.allowMultipleExpandedSections = init.allowMultipleExpandedSections ?? false;
|
|
15
|
+
this.allowCloseAllSections = init.allowCloseAllSections ?? false;
|
|
16
|
+
this.alwaysShowAllGroups = init.alwaysShowAllGroups ?? false;
|
|
17
|
+
this.alwaysShowAllSections = init.alwaysShowAllSections ?? false;
|
|
18
|
+
this.expandToFill = init.expandToFill ?? true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class SidebarGroupModel {
|
|
22
|
+
id;
|
|
23
|
+
name;
|
|
24
|
+
sections = $state.raw([]);
|
|
25
|
+
onSelected;
|
|
26
|
+
isValid = $derived.by(() => (this.validator?.isValid ?? true) && this.sections.every((s) => s.isValid));
|
|
27
|
+
_validator = $state.raw(null);
|
|
28
|
+
constructor(init) {
|
|
29
|
+
this.id = init.id ?? randomNanoid();
|
|
30
|
+
this.name = init.name;
|
|
31
|
+
this.sections = init.sections.map((s) => new SidebarGroupSectionModel(s));
|
|
32
|
+
this.onSelected = init.onSelected ?? (() => void 0);
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
34
|
+
const that = this;
|
|
35
|
+
this._validator = init.validator || {
|
|
36
|
+
get isValid() {
|
|
37
|
+
return that.sections.every((s) => s.isValid);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
get validator() {
|
|
42
|
+
return this._validator;
|
|
43
|
+
}
|
|
44
|
+
updateValidator = (validator) => {
|
|
45
|
+
this._validator = validator;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export class SidebarGroupSectionModel {
|
|
49
|
+
id;
|
|
50
|
+
name;
|
|
51
|
+
expanded = $state(false);
|
|
52
|
+
component;
|
|
53
|
+
withoutPaddings;
|
|
54
|
+
isValid = $derived.by(() => this.validator?.isValid ?? true);
|
|
55
|
+
_validator = $state.raw(null);
|
|
56
|
+
_onExpandedCallback;
|
|
57
|
+
constructor(init) {
|
|
58
|
+
this.id = init.id ?? randomNanoid();
|
|
59
|
+
this.name = init.name;
|
|
60
|
+
this.expanded = init.expanded ?? false;
|
|
61
|
+
this.component = init.component;
|
|
62
|
+
this._onExpandedCallback = init.onExpandedChanged ?? null;
|
|
63
|
+
this.withoutPaddings = init.withoutPaddings ?? false;
|
|
64
|
+
this._validator = init.validator ?? null;
|
|
65
|
+
}
|
|
66
|
+
get validator() {
|
|
67
|
+
return this._validator;
|
|
68
|
+
}
|
|
69
|
+
onExpandedChanged = (val) => {
|
|
70
|
+
this.expanded = val;
|
|
71
|
+
this._onExpandedCallback?.(val);
|
|
72
|
+
};
|
|
73
|
+
updateValidator = (validator) => {
|
|
74
|
+
this._validator = validator;
|
|
75
|
+
};
|
|
76
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/kit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -141,6 +141,10 @@
|
|
|
141
141
|
"types": "./dist/ui/form-group/index.d.ts",
|
|
142
142
|
"svelte": "./dist/ui/form-group/index.js"
|
|
143
143
|
},
|
|
144
|
+
"./ui/grouped-sidebar": {
|
|
145
|
+
"types": "./dist/ui/grouped-sidebar/index.d.ts",
|
|
146
|
+
"svelte": "./dist/ui/grouped-sidebar/index.js"
|
|
147
|
+
},
|
|
144
148
|
"./ui/html-block": {
|
|
145
149
|
"types": "./dist/ui/html-block/index.d.ts",
|
|
146
150
|
"svelte": "./dist/ui/html-block/index.js"
|