sveltacular 0.0.41 → 0.0.43
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/forms/combo/new-or-existing-combo.svelte +74 -0
- package/dist/forms/combo/new-or-existing-combo.svelte.d.ts +28 -0
- package/dist/forms/list-box/list-box.d.ts +2 -0
- package/dist/forms/list-box/list-box.js +1 -0
- package/dist/forms/list-box/list-box.svelte +14 -10
- package/dist/forms/list-box/list-box.svelte.d.ts +3 -1
- package/dist/forms/radio-group/radio-box.svelte +1 -0
- package/dist/forms/text-box/text-box.svelte +4 -1
- package/dist/generic/empty/empty.svelte +83 -0
- package/dist/generic/empty/empty.svelte.d.ts +22 -0
- package/dist/icons/folder-open-icon.svelte +12 -0
- package/dist/icons/folder-open-icon.svelte.d.ts +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/navigation/pagination/pagination.svelte +109 -0
- package/dist/navigation/pagination/pagination.svelte.d.ts +20 -0
- package/dist/navigation/tabs/tab-group.svelte +4 -4
- package/dist/navigation/wizard/wizard-context.d.ts +1 -0
- package/dist/navigation/wizard/wizard-step.svelte +16 -0
- package/dist/navigation/wizard/wizard.svelte +17 -9
- package/dist/navigation/wizard/wizard.svelte.d.ts +2 -2
- package/dist/tables/data-grid.svelte +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script>import {
|
|
2
|
+
FlexRow,
|
|
3
|
+
ListBox,
|
|
4
|
+
RadioBox,
|
|
5
|
+
TextBox
|
|
6
|
+
} from "../../index.js";
|
|
7
|
+
import FlexCol from "../../layout/flex-col.svelte";
|
|
8
|
+
export let mode = "existing";
|
|
9
|
+
export let newValue = "";
|
|
10
|
+
export let existingValue = "";
|
|
11
|
+
export let items = [];
|
|
12
|
+
export let size = "full";
|
|
13
|
+
export let disabled = false;
|
|
14
|
+
export let required = false;
|
|
15
|
+
export let searchable = false;
|
|
16
|
+
export let search = void 0;
|
|
17
|
+
export let searchPlaceholder = "Search";
|
|
18
|
+
export let newPlaceholder = "New";
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div class="group">
|
|
22
|
+
<FlexRow>
|
|
23
|
+
<div class="labels">
|
|
24
|
+
<FlexCol>
|
|
25
|
+
<div class="radio">
|
|
26
|
+
<RadioBox value="existing" bind:group={mode}>Existing:</RadioBox>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="radio">
|
|
29
|
+
<RadioBox value="new" bind:group={mode}>New:</RadioBox>
|
|
30
|
+
</div>
|
|
31
|
+
</FlexCol>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="inputs">
|
|
34
|
+
<FlexCol>
|
|
35
|
+
<div class="input">
|
|
36
|
+
<ListBox
|
|
37
|
+
bind:value={existingValue}
|
|
38
|
+
{searchable}
|
|
39
|
+
{search}
|
|
40
|
+
{required}
|
|
41
|
+
{items}
|
|
42
|
+
{size}
|
|
43
|
+
placeholder={searchPlaceholder}
|
|
44
|
+
disabled={disabled || mode == 'new'}
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="input">
|
|
48
|
+
<TextBox
|
|
49
|
+
bind:value={newValue}
|
|
50
|
+
{size}
|
|
51
|
+
placeholder={newPlaceholder}
|
|
52
|
+
disabled={disabled || mode == 'existing'}
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
</FlexCol>
|
|
56
|
+
</div>
|
|
57
|
+
</FlexRow>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
.labels {
|
|
62
|
+
flex-shrink: 1;
|
|
63
|
+
}
|
|
64
|
+
.inputs {
|
|
65
|
+
flex-grow: 1;
|
|
66
|
+
}
|
|
67
|
+
.radio,
|
|
68
|
+
.input {
|
|
69
|
+
height: 2.5rem;
|
|
70
|
+
}
|
|
71
|
+
.radio {
|
|
72
|
+
padding-top: 0.1rem;
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import { type DropdownOption, type FormFieldSizeOptions } from '../../index.js';
|
|
3
|
+
import type { SearchFunction } from '../list-box/list-box.js';
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
mode?: "new" | "existing" | undefined;
|
|
7
|
+
newValue?: string | undefined;
|
|
8
|
+
existingValue?: string | undefined;
|
|
9
|
+
items?: DropdownOption[] | undefined;
|
|
10
|
+
size?: FormFieldSizeOptions | undefined;
|
|
11
|
+
disabled?: boolean | undefined;
|
|
12
|
+
required?: boolean | undefined;
|
|
13
|
+
searchable?: boolean | undefined;
|
|
14
|
+
search?: SearchFunction | undefined;
|
|
15
|
+
searchPlaceholder?: string | undefined;
|
|
16
|
+
newPlaceholder?: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
};
|
|
23
|
+
export type NewOrExistingComboProps = typeof __propDef.props;
|
|
24
|
+
export type NewOrExistingComboEvents = typeof __propDef.events;
|
|
25
|
+
export type NewOrExistingComboSlots = typeof __propDef.slots;
|
|
26
|
+
export default class NewOrExistingCombo extends SvelteComponent<NewOrExistingComboProps, NewOrExistingComboEvents, NewOrExistingComboSlots> {
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -13,11 +13,12 @@ export let disabled = false;
|
|
|
13
13
|
export let required = false;
|
|
14
14
|
export let searchable = false;
|
|
15
15
|
export let search = void 0;
|
|
16
|
+
export let placeholder = "";
|
|
16
17
|
const id = uniqueId();
|
|
17
18
|
const dispatch = createEventDispatcher();
|
|
18
19
|
const getText = () => items.find((item) => item.value == value)?.name || "";
|
|
19
20
|
let text = getText();
|
|
20
|
-
let
|
|
21
|
+
let isMenuOpen = false;
|
|
21
22
|
let highlightIndex = -1;
|
|
22
23
|
let filteredItems = [];
|
|
23
24
|
$:
|
|
@@ -27,29 +28,29 @@ const onSelect = (e) => {
|
|
|
27
28
|
dispatch("change", value);
|
|
28
29
|
text = getText();
|
|
29
30
|
applyFilter();
|
|
30
|
-
|
|
31
|
+
isMenuOpen = false;
|
|
31
32
|
};
|
|
32
33
|
const focusOnInput = () => {
|
|
33
34
|
if (browser)
|
|
34
35
|
document.getElementById(id)?.focus();
|
|
35
36
|
};
|
|
36
|
-
const toggle = () =>
|
|
37
|
+
const toggle = () => isMenuOpen = !open;
|
|
37
38
|
const clickArrow = () => {
|
|
38
39
|
if (disabled)
|
|
39
40
|
return;
|
|
40
41
|
toggle();
|
|
41
|
-
if (
|
|
42
|
+
if (isMenuOpen)
|
|
42
43
|
focusOnInput();
|
|
43
44
|
};
|
|
44
45
|
const onInputKeyPress = (e) => {
|
|
45
46
|
if (disabled)
|
|
46
47
|
return;
|
|
47
48
|
if (e.key == "Escape") {
|
|
48
|
-
|
|
49
|
+
isMenuOpen = false;
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
51
52
|
if (e.key == "Enter" || e.key == "Tab") {
|
|
52
|
-
|
|
53
|
+
isMenuOpen = false;
|
|
53
54
|
if (highlightIndex > -1) {
|
|
54
55
|
onSelect(new CustomEvent("select", { detail: filteredItems[highlightIndex] }));
|
|
55
56
|
}
|
|
@@ -57,17 +58,17 @@ const onInputKeyPress = (e) => {
|
|
|
57
58
|
}
|
|
58
59
|
if (e.key == "ArrowDown") {
|
|
59
60
|
highlightIndex = Math.min(highlightIndex + 1, filteredItems.length - 1);
|
|
60
|
-
|
|
61
|
+
isMenuOpen = true;
|
|
61
62
|
return;
|
|
62
63
|
}
|
|
63
64
|
if (e.key == "ArrowUp") {
|
|
64
65
|
highlightIndex = Math.max(highlightIndex - 1, -1);
|
|
65
66
|
if (highlightIndex == -1)
|
|
66
|
-
|
|
67
|
+
isMenuOpen = false;
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
69
70
|
if (e.key.length == 1 || e.key == "Backspace" || e.key == "Delete") {
|
|
70
|
-
|
|
71
|
+
isMenuOpen = true;
|
|
71
72
|
highlightIndex = 0;
|
|
72
73
|
triggerSearch();
|
|
73
74
|
}
|
|
@@ -99,6 +100,8 @@ const updateText = async () => {
|
|
|
99
100
|
}
|
|
100
101
|
};
|
|
101
102
|
triggerSearch();
|
|
103
|
+
$:
|
|
104
|
+
open = isMenuOpen && !disabled;
|
|
102
105
|
</script>
|
|
103
106
|
|
|
104
107
|
<FormField {size}>
|
|
@@ -112,8 +115,9 @@ triggerSearch();
|
|
|
112
115
|
bind:value={text}
|
|
113
116
|
{required}
|
|
114
117
|
{disabled}
|
|
118
|
+
{placeholder}
|
|
115
119
|
readonly={!isSeachable}
|
|
116
|
-
on:focus={() => (
|
|
120
|
+
on:focus={() => (isMenuOpen = true)}
|
|
117
121
|
on:keyup={onInputKeyPress}
|
|
118
122
|
data-value={value}
|
|
119
123
|
data-text={text}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { DropdownOption, FormFieldSizeOptions } from '../../types/form.js';
|
|
3
|
+
import type { SearchFunction } from './list-box.js';
|
|
3
4
|
declare const __propDef: {
|
|
4
5
|
props: {
|
|
5
6
|
value?: string | undefined;
|
|
@@ -8,7 +9,8 @@ declare const __propDef: {
|
|
|
8
9
|
disabled?: boolean | undefined;
|
|
9
10
|
required?: boolean | undefined;
|
|
10
11
|
searchable?: boolean | undefined;
|
|
11
|
-
search?:
|
|
12
|
+
search?: SearchFunction | undefined;
|
|
13
|
+
placeholder?: string | undefined;
|
|
12
14
|
};
|
|
13
15
|
events: {
|
|
14
16
|
change: CustomEvent<string>;
|
|
@@ -46,7 +46,7 @@ const onInput = (e) => {
|
|
|
46
46
|
{#if $$slots.default}
|
|
47
47
|
<FormLabel {id} {required}><slot /></FormLabel>
|
|
48
48
|
{/if}
|
|
49
|
-
<div class="input">
|
|
49
|
+
<div class="input {disabled ? 'disabled' : 'enabled'}">
|
|
50
50
|
{#if prefix}
|
|
51
51
|
<div class="prefix">{prefix}</div>
|
|
52
52
|
{/if}
|
|
@@ -91,6 +91,9 @@ const onInput = (e) => {
|
|
|
91
91
|
user-select: none;
|
|
92
92
|
white-space: nowrap;
|
|
93
93
|
}
|
|
94
|
+
.input.disabled {
|
|
95
|
+
opacity: 0.5;
|
|
96
|
+
}
|
|
94
97
|
.input input {
|
|
95
98
|
background-color: transparent;
|
|
96
99
|
border: none;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script>export let text = "No data to display";
|
|
2
|
+
export let size = "md";
|
|
3
|
+
export let orientation = "vertical";
|
|
4
|
+
export let reverse = false;
|
|
5
|
+
export let align = "center";
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="empty {size} {orientation} {reverse ? 'reverse' : ''} {align}">
|
|
9
|
+
{#if $$slots.default}
|
|
10
|
+
<div class="icon">
|
|
11
|
+
<slot />
|
|
12
|
+
</div>
|
|
13
|
+
{/if}
|
|
14
|
+
<div class="text">
|
|
15
|
+
{text}
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<style>.empty {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
text-align: center;
|
|
25
|
+
color: var(--color-text-secondary, rgba(150, 150, 150, 0.5));
|
|
26
|
+
font-weight: 500;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.start {
|
|
30
|
+
justify-content: flex-start;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.end {
|
|
34
|
+
justify-content: flex-end;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.horizontal {
|
|
38
|
+
flex-direction: row;
|
|
39
|
+
gap: 1rem;
|
|
40
|
+
}
|
|
41
|
+
.horizontal.reverse {
|
|
42
|
+
flex-direction: row-reverse;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.vertical.reverse {
|
|
46
|
+
flex-direction: column-reverse;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.sm {
|
|
50
|
+
font-size: 1rem;
|
|
51
|
+
line-height: 1.5rem;
|
|
52
|
+
}
|
|
53
|
+
.sm .icon {
|
|
54
|
+
height: 1.5rem;
|
|
55
|
+
width: 1.5rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.md {
|
|
59
|
+
font-size: 1.25rem;
|
|
60
|
+
line-height: 1.75rem;
|
|
61
|
+
}
|
|
62
|
+
.md .icon {
|
|
63
|
+
height: 2rem;
|
|
64
|
+
width: 2rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.lg {
|
|
68
|
+
font-size: 1.5rem;
|
|
69
|
+
line-height: 2rem;
|
|
70
|
+
}
|
|
71
|
+
.lg .icon {
|
|
72
|
+
height: 3rem;
|
|
73
|
+
width: 3rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.xl {
|
|
77
|
+
font-size: 2rem;
|
|
78
|
+
line-height: 2.5rem;
|
|
79
|
+
}
|
|
80
|
+
.xl .icon {
|
|
81
|
+
height: 4rem;
|
|
82
|
+
width: 4rem;
|
|
83
|
+
}</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
text?: string | undefined;
|
|
5
|
+
size?: "sm" | "md" | "lg" | "xl" | undefined;
|
|
6
|
+
orientation?: "horizontal" | "vertical" | undefined;
|
|
7
|
+
reverse?: boolean | undefined;
|
|
8
|
+
align?: "center" | "end" | "start" | undefined;
|
|
9
|
+
};
|
|
10
|
+
events: {
|
|
11
|
+
[evt: string]: CustomEvent<any>;
|
|
12
|
+
};
|
|
13
|
+
slots: {
|
|
14
|
+
default: {};
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export type EmptyProps = typeof __propDef.props;
|
|
18
|
+
export type EmptyEvents = typeof __propDef.events;
|
|
19
|
+
export type EmptySlots = typeof __propDef.slots;
|
|
20
|
+
export default class Empty extends SvelteComponent<EmptyProps, EmptyEvents, EmptySlots> {
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg
|
|
2
|
+
class="w-6 h-6 text-gray-800 dark:text-white"
|
|
3
|
+
aria-hidden="true"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
fill="currentColor"
|
|
6
|
+
viewBox="0 0 20 18"
|
|
7
|
+
>
|
|
8
|
+
<path
|
|
9
|
+
d="M4.09 7.586A1 1 0 0 1 5 7h13V6a2 2 0 0 0-2-2h-4.557L9.043.8a2.009 2.009 0 0 0-1.6-.8H2a2 2 0 0 0-2 2v14c.001.154.02.308.058.457L4.09 7.586Z"
|
|
10
|
+
/>
|
|
11
|
+
<path d="M6.05 9 2 17.952c.14.031.281.047.424.048h12.95a.992.992 0 0 0 .909-.594L20 9H6.05Z" />
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} FolderOpenIconProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} FolderOpenIconEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} FolderOpenIconSlots */
|
|
4
|
+
export default class FolderOpenIcon extends SvelteComponent<{
|
|
5
|
+
[x: string]: never;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {}> {
|
|
9
|
+
}
|
|
10
|
+
export type FolderOpenIconProps = typeof __propDef.props;
|
|
11
|
+
export type FolderOpenIconEvents = typeof __propDef.events;
|
|
12
|
+
export type FolderOpenIconSlots = typeof __propDef.slots;
|
|
13
|
+
import { SvelteComponent } from "svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {
|
|
16
|
+
[x: string]: never;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
};
|
|
23
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { default as FormFooter } from './forms/form-footer.svelte';
|
|
|
20
20
|
export { default as FormSection } from './forms/form-section.svelte';
|
|
21
21
|
export { default as InfoBox } from './forms/info-box/info-box.svelte';
|
|
22
22
|
export { default as UrlBox } from './forms/url-box/url-box.svelte';
|
|
23
|
+
export { default as NewOrExistingCombo } from './forms/combo/new-or-existing-combo.svelte';
|
|
23
24
|
export { default as Card } from './generic/card/card.svelte';
|
|
24
25
|
export { default as CardContainer } from './generic/card/card-container.svelte';
|
|
25
26
|
export { default as Divider } from './generic/divider/divider.svelte';
|
|
@@ -36,6 +37,7 @@ export { default as Section } from './generic/section/section.svelte';
|
|
|
36
37
|
export { default as Header } from './generic/header/header.svelte';
|
|
37
38
|
export { default as Dot } from './generic/dot/dot.svelte';
|
|
38
39
|
export { default as Notice } from './generic/notice/notice.svelte';
|
|
40
|
+
export { default as Empty } from './generic/empty/empty.svelte';
|
|
39
41
|
export { default as FlexCol } from './layout/flex-col.svelte';
|
|
40
42
|
export { default as FlexRow } from './layout/flex-row.svelte';
|
|
41
43
|
export { default as FlexItem } from './layout/flex-item.svelte';
|
|
@@ -59,6 +61,7 @@ export { default as AppNavItem } from './navigation/app-bar/app-nav-item.svelte'
|
|
|
59
61
|
export { default as AppBranding } from './navigation/app-bar/app-branding.svelte';
|
|
60
62
|
export { default as Wizard } from './navigation/wizard/wizard.svelte';
|
|
61
63
|
export { default as WizardStep } from './navigation/wizard/wizard-step.svelte';
|
|
64
|
+
export { default as Pagination } from './navigation/pagination/pagination.svelte';
|
|
62
65
|
export { default as DataGrid } from './tables/data-grid.svelte';
|
|
63
66
|
export { default as Table } from './tables/table.svelte';
|
|
64
67
|
export { default as TableBody } from './tables/table-body.svelte';
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ export { default as FormFooter } from './forms/form-footer.svelte';
|
|
|
21
21
|
export { default as FormSection } from './forms/form-section.svelte';
|
|
22
22
|
export { default as InfoBox } from './forms/info-box/info-box.svelte';
|
|
23
23
|
export { default as UrlBox } from './forms/url-box/url-box.svelte';
|
|
24
|
+
export { default as NewOrExistingCombo } from './forms/combo/new-or-existing-combo.svelte';
|
|
24
25
|
// Generic
|
|
25
26
|
export { default as Card } from './generic/card/card.svelte';
|
|
26
27
|
export { default as CardContainer } from './generic/card/card-container.svelte';
|
|
@@ -38,6 +39,7 @@ export { default as Section } from './generic/section/section.svelte';
|
|
|
38
39
|
export { default as Header } from './generic/header/header.svelte';
|
|
39
40
|
export { default as Dot } from './generic/dot/dot.svelte';
|
|
40
41
|
export { default as Notice } from './generic/notice/notice.svelte';
|
|
42
|
+
export { default as Empty } from './generic/empty/empty.svelte';
|
|
41
43
|
// Layout
|
|
42
44
|
export { default as FlexCol } from './layout/flex-col.svelte';
|
|
43
45
|
export { default as FlexRow } from './layout/flex-row.svelte';
|
|
@@ -64,6 +66,7 @@ export { default as AppNavItem } from './navigation/app-bar/app-nav-item.svelte'
|
|
|
64
66
|
export { default as AppBranding } from './navigation/app-bar/app-branding.svelte';
|
|
65
67
|
export { default as Wizard } from './navigation/wizard/wizard.svelte';
|
|
66
68
|
export { default as WizardStep } from './navigation/wizard/wizard-step.svelte';
|
|
69
|
+
export { default as Pagination } from './navigation/pagination/pagination.svelte';
|
|
67
70
|
// Tables
|
|
68
71
|
export { default as DataGrid } from './tables/data-grid.svelte';
|
|
69
72
|
export { default as Table } from './tables/table.svelte';
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<script>import { createEventDispatcher } from "svelte";
|
|
2
|
+
export let currentPage = 1;
|
|
3
|
+
export let totalPages = 1;
|
|
4
|
+
export let align = "center";
|
|
5
|
+
const dispatch = createEventDispatcher();
|
|
6
|
+
const changePage = (page) => {
|
|
7
|
+
if (page < 1 || page > totalPages)
|
|
8
|
+
return;
|
|
9
|
+
currentPage = page;
|
|
10
|
+
dispatch("page", page);
|
|
11
|
+
};
|
|
12
|
+
$:
|
|
13
|
+
previousPages = currentPage > 1 ? (() => {
|
|
14
|
+
const pages = [];
|
|
15
|
+
for (let i = currentPage - 1; i > 0 && i >= currentPage - 3; i--) {
|
|
16
|
+
pages.push(i);
|
|
17
|
+
}
|
|
18
|
+
return pages.reverse();
|
|
19
|
+
})() : [];
|
|
20
|
+
$:
|
|
21
|
+
nextPages = currentPage < totalPages ? (() => {
|
|
22
|
+
const pages = [];
|
|
23
|
+
for (let i = currentPage + 1; i <= totalPages && i <= currentPage + 3; i++) {
|
|
24
|
+
pages.push(i);
|
|
25
|
+
}
|
|
26
|
+
return pages;
|
|
27
|
+
})() : [];
|
|
28
|
+
$:
|
|
29
|
+
showFirst = currentPage > 4;
|
|
30
|
+
$:
|
|
31
|
+
showLast = currentPage < totalPages - 3;
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<nav class={align}>
|
|
35
|
+
{#if currentPage > 1}
|
|
36
|
+
<button on:click={() => changePage(currentPage - 1)} class="previous">Previous</button>
|
|
37
|
+
{/if}
|
|
38
|
+
{#if showFirst}
|
|
39
|
+
<button on:click={() => changePage(1)} class="first">1</button>
|
|
40
|
+
<div class="ellipsis">...</div>
|
|
41
|
+
{/if}
|
|
42
|
+
{#each previousPages as page}
|
|
43
|
+
<button on:click={() => changePage(page)}>{page}</button>
|
|
44
|
+
{/each}
|
|
45
|
+
<div class="current">{currentPage}</div>
|
|
46
|
+
{#each nextPages as page}
|
|
47
|
+
<button on:click={() => changePage(page)}>{page}</button>
|
|
48
|
+
{/each}
|
|
49
|
+
{#if showLast}
|
|
50
|
+
<div class="ellipsis">...</div>
|
|
51
|
+
<button on:click={() => changePage(totalPages)} class="last">{totalPages}</button>
|
|
52
|
+
{/if}
|
|
53
|
+
{#if currentPage < totalPages}
|
|
54
|
+
<button on:click={() => changePage(currentPage + 1)} class="next">Next</button>
|
|
55
|
+
{/if}
|
|
56
|
+
</nav>
|
|
57
|
+
|
|
58
|
+
<style>nav {
|
|
59
|
+
display: flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
gap: 0rem;
|
|
63
|
+
}
|
|
64
|
+
nav button {
|
|
65
|
+
appearance: none;
|
|
66
|
+
padding-left: 1rem;
|
|
67
|
+
padding-right: 1rem;
|
|
68
|
+
font-size: 1rem;
|
|
69
|
+
line-height: 1.4rem;
|
|
70
|
+
height: 1.5rem;
|
|
71
|
+
border: none;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
background-color: var(--form-input-background, white);
|
|
74
|
+
color: var(--form-input-text, black);
|
|
75
|
+
}
|
|
76
|
+
nav button:hover {
|
|
77
|
+
background-color: var(--form-input-border, black);
|
|
78
|
+
color: var(--form-input-background, white);
|
|
79
|
+
}
|
|
80
|
+
nav button.previous {
|
|
81
|
+
border-radius: 0.5rem 0 0 0.5rem;
|
|
82
|
+
border-right: solid 1px var(--form-input-border, black);
|
|
83
|
+
}
|
|
84
|
+
nav button.next {
|
|
85
|
+
border-radius: 0 0.5rem 0.5rem 0;
|
|
86
|
+
border-left: solid 1px var(--form-input-border, black);
|
|
87
|
+
}
|
|
88
|
+
nav .ellipsis {
|
|
89
|
+
height: 1.5rem;
|
|
90
|
+
font-size: 1rem;
|
|
91
|
+
line-height: 1rem;
|
|
92
|
+
padding-left: 0.1rem;
|
|
93
|
+
padding-right: 0.1rem;
|
|
94
|
+
background-color: var(--form-input-background, white);
|
|
95
|
+
color: var(--form-input-text, black);
|
|
96
|
+
}
|
|
97
|
+
nav .current {
|
|
98
|
+
padding: 0.5rem 1rem;
|
|
99
|
+
border: 1px solid var(--form-input-border, black);
|
|
100
|
+
border-radius: 0.5rem;
|
|
101
|
+
background-color: var(--form-input-background, white);
|
|
102
|
+
color: var(--form-input-text, black);
|
|
103
|
+
}
|
|
104
|
+
nav.start {
|
|
105
|
+
justify-content: flex-start;
|
|
106
|
+
}
|
|
107
|
+
nav.end {
|
|
108
|
+
justify-content: flex-end;
|
|
109
|
+
}</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
currentPage?: number | undefined;
|
|
5
|
+
totalPages?: number | undefined;
|
|
6
|
+
align?: "center" | "end" | "start" | undefined;
|
|
7
|
+
};
|
|
8
|
+
events: {
|
|
9
|
+
page: CustomEvent<number>;
|
|
10
|
+
} & {
|
|
11
|
+
[evt: string]: CustomEvent<any>;
|
|
12
|
+
};
|
|
13
|
+
slots: {};
|
|
14
|
+
};
|
|
15
|
+
export type PaginationProps = typeof __propDef.props;
|
|
16
|
+
export type PaginationEvents = typeof __propDef.events;
|
|
17
|
+
export type PaginationSlots = typeof __propDef.slots;
|
|
18
|
+
export default class Pagination extends SvelteComponent<PaginationProps, PaginationEvents, PaginationSlots> {
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -88,11 +88,11 @@ setContext(tabContext, ctx);
|
|
|
88
88
|
}
|
|
89
89
|
.traditional .inactive button {
|
|
90
90
|
background: var(--tab-traditional-inactive-bg, transparent);
|
|
91
|
-
color: var(--tab-traditional-inactive-fg, rgb(
|
|
91
|
+
color: var(--tab-traditional-inactive-fg, rgb(150, 150, 150));
|
|
92
92
|
}
|
|
93
93
|
.traditional .inactive button:hover {
|
|
94
94
|
background: var(--tab-traditional-hover-bg, transparent);
|
|
95
|
-
color: var(--tab-traditional-hover-fg, rgb(
|
|
95
|
+
color: var(--tab-traditional-hover-fg, rgb(220, 220, 220));
|
|
96
96
|
}
|
|
97
97
|
.traditional .active button {
|
|
98
98
|
background: var(--tab-traditional-active-bg, rgb(220, 220, 230));
|
|
@@ -110,11 +110,11 @@ setContext(tabContext, ctx);
|
|
|
110
110
|
}
|
|
111
111
|
.underline .inactive button {
|
|
112
112
|
background: var(--tab-underline-inactive-bg, transparent);
|
|
113
|
-
color: var(--tab-underline-inactive-fg, rgb(
|
|
113
|
+
color: var(--tab-underline-inactive-fg, rgb(150, 150, 150));
|
|
114
114
|
}
|
|
115
115
|
.underline .inactive button:hover {
|
|
116
116
|
background: var(--tab-underline-hover-bg, transparent);
|
|
117
|
-
color: var(--tab-underline-hover-fg, rgb(
|
|
117
|
+
color: var(--tab-underline-hover-fg, rgb(220, 220, 220));
|
|
118
118
|
}
|
|
119
119
|
.underline .active button {
|
|
120
120
|
color: var(--tab-underline-active-fg, rgb(255, 134, 78));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script>import { getContext, onDestroy } from "svelte";
|
|
2
|
+
import Notice from "../../generic/notice/notice.svelte";
|
|
2
3
|
const wizard = getContext("wizard");
|
|
3
4
|
const state = wizard.state;
|
|
4
5
|
export let step;
|
|
@@ -6,9 +7,18 @@ export let subtitle;
|
|
|
6
7
|
wizard.register(step, subtitle);
|
|
7
8
|
$:
|
|
8
9
|
isCurrentStep = $state.currentStep === step;
|
|
10
|
+
$:
|
|
11
|
+
errors = $state.errors;
|
|
9
12
|
</script>
|
|
10
13
|
|
|
11
14
|
<div class="step {isCurrentStep ? 'current' : ''}">
|
|
15
|
+
{#if errors.length}
|
|
16
|
+
<div class="errors">
|
|
17
|
+
{#each errors as error}
|
|
18
|
+
<Notice style="error">{error}</Notice>
|
|
19
|
+
{/each}
|
|
20
|
+
</div>
|
|
21
|
+
{/if}
|
|
12
22
|
<slot />
|
|
13
23
|
</div>
|
|
14
24
|
|
|
@@ -17,4 +27,10 @@ $:
|
|
|
17
27
|
}
|
|
18
28
|
.step.current {
|
|
19
29
|
display: block;
|
|
30
|
+
}
|
|
31
|
+
.step .errors {
|
|
32
|
+
margin-bottom: 1rem;
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
gap: 1rem;
|
|
20
36
|
}</style>
|
|
@@ -9,18 +9,21 @@ export let disabled = false;
|
|
|
9
9
|
export let onNext = async () => [];
|
|
10
10
|
export let onSubmit = async () => [];
|
|
11
11
|
let currentStep = 0;
|
|
12
|
+
let errors = [];
|
|
12
13
|
const dispatch = createEventDispatcher();
|
|
13
14
|
const steps = {};
|
|
14
15
|
const wizardStore = writable({
|
|
15
16
|
currentStep,
|
|
16
17
|
totalSteps: 0,
|
|
17
|
-
disabled
|
|
18
|
+
disabled,
|
|
19
|
+
errors
|
|
18
20
|
});
|
|
19
21
|
const publish = () => {
|
|
20
22
|
wizardStore.set({
|
|
21
23
|
currentStep,
|
|
22
24
|
totalSteps: Object.values(steps).length,
|
|
23
|
-
disabled
|
|
25
|
+
disabled,
|
|
26
|
+
errors
|
|
24
27
|
});
|
|
25
28
|
};
|
|
26
29
|
const register = (stepNumber, subtitle2) => {
|
|
@@ -29,7 +32,7 @@ const register = (stepNumber, subtitle2) => {
|
|
|
29
32
|
};
|
|
30
33
|
const validate = async (callback) => {
|
|
31
34
|
disabled = true;
|
|
32
|
-
|
|
35
|
+
errors = await callback() || [];
|
|
33
36
|
disabled = false;
|
|
34
37
|
dispatch("errors", errors);
|
|
35
38
|
return errors;
|
|
@@ -37,9 +40,9 @@ const validate = async (callback) => {
|
|
|
37
40
|
const next = async () => {
|
|
38
41
|
if (currentStep >= Object.values(steps).length || disabled)
|
|
39
42
|
return;
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
42
|
-
return;
|
|
43
|
+
const errors2 = await validate(() => onNext(currentStep));
|
|
44
|
+
if (errors2.length)
|
|
45
|
+
return publish();
|
|
43
46
|
currentStep++;
|
|
44
47
|
dispatch("next", currentStep);
|
|
45
48
|
publish();
|
|
@@ -48,6 +51,7 @@ const previous = () => {
|
|
|
48
51
|
if (currentStep <= 1 || disabled)
|
|
49
52
|
return;
|
|
50
53
|
currentStep--;
|
|
54
|
+
errors = [];
|
|
51
55
|
dispatch("previous", currentStep);
|
|
52
56
|
publish();
|
|
53
57
|
};
|
|
@@ -57,9 +61,9 @@ const reset = () => {
|
|
|
57
61
|
publish();
|
|
58
62
|
};
|
|
59
63
|
const done = async () => {
|
|
60
|
-
const
|
|
61
|
-
if (
|
|
62
|
-
return;
|
|
64
|
+
const errors2 = await validate(onSubmit);
|
|
65
|
+
if (errors2.length)
|
|
66
|
+
return publish();
|
|
63
67
|
dispatch("done");
|
|
64
68
|
reset();
|
|
65
69
|
};
|
|
@@ -111,4 +115,8 @@ footer {
|
|
|
111
115
|
display: flex;
|
|
112
116
|
justify-content: space-between;
|
|
113
117
|
align-items: center;
|
|
118
|
+
flex-wrap: nowrap;
|
|
119
|
+
}
|
|
120
|
+
footer div {
|
|
121
|
+
width: 100%;
|
|
114
122
|
}</style>
|
|
@@ -5,8 +5,8 @@ declare const __propDef: {
|
|
|
5
5
|
title: string;
|
|
6
6
|
level?: SectionLevel | undefined;
|
|
7
7
|
disabled?: boolean | undefined;
|
|
8
|
-
onNext?: ((step: number) => Promise<string[]>) | undefined;
|
|
9
|
-
onSubmit?: (() => Promise<string[]>) | undefined;
|
|
8
|
+
onNext?: ((step: number) => Promise<string[] | void>) | undefined;
|
|
9
|
+
onSubmit?: (() => Promise<string[] | void>) | undefined;
|
|
10
10
|
};
|
|
11
11
|
events: {
|
|
12
12
|
done: CustomEvent<void>;
|
|
@@ -8,6 +8,8 @@ import TableHeaderRow from "./table-header-row.svelte";
|
|
|
8
8
|
import TableHeader from "./table-header.svelte";
|
|
9
9
|
import TableRow from "./table-row.svelte";
|
|
10
10
|
import Table from "./table.svelte";
|
|
11
|
+
import Empty from "../generic/empty/empty.svelte";
|
|
12
|
+
import FolderOpenIcon from "../icons/folder-open-icon.svelte";
|
|
11
13
|
import Loading from "../placeholders/loading.svelte";
|
|
12
14
|
import Text from "../typography/text.svelte";
|
|
13
15
|
import TableCaption from "./table-caption.svelte";
|
|
@@ -72,7 +74,9 @@ $:
|
|
|
72
74
|
{#if rows === undefined}
|
|
73
75
|
<Loading />
|
|
74
76
|
{:else}
|
|
75
|
-
<
|
|
77
|
+
<Empty>
|
|
78
|
+
<FolderOpenIcon />
|
|
79
|
+
</Empty>
|
|
76
80
|
{/if}
|
|
77
81
|
</div>
|
|
78
82
|
</TableCell>
|