svseeds 0.5.2 → 0.6.0
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/README.md +7 -1
- package/_svseeds/_ColorPicker.svelte +11 -4
- package/_svseeds/_ColorPicker.svelte.d.ts +1 -35
- package/_svseeds/_Disclosure.svelte +10 -6
- package/_svseeds/_Disclosure.svelte.d.ts +1 -1
- package/_svseeds/_Drawer.svelte +10 -4
- package/_svseeds/_Modal.svelte +2 -2
- package/_svseeds/_Toast.svelte +258 -0
- package/_svseeds/_Toast.svelte.d.ts +14 -0
- package/_svseeds/_Tooltip.svelte +16 -0
- package/_svseeds/_Tooltip.svelte.d.ts +0 -32
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,4 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
SvSeeds is a collection of essential functional components for Svelte development. These components are intentionally designed with minimal styling, giving you complete freedom to apply your own styles based on your project requirements. For specialized needs, you can download the components as .svelte files through our CLI tool and customize their functionality directly.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Documentation
|
|
10
|
+
|
|
11
|
+
Visit https://svseeds.dev to view the documentation.
|
|
12
|
+
|
|
13
|
+
## License
|
|
14
|
+
|
|
15
|
+
Licensed under the [MIT license](https://github.com/scirexs/svseeds-ui/blob/main/LICENSE).
|
|
@@ -25,10 +25,17 @@
|
|
|
25
25
|
```
|
|
26
26
|
### Exports
|
|
27
27
|
```ts
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Converts RGB color values to hexadecimal color code.
|
|
30
|
+
*
|
|
31
|
+
* @param rgb - Array of RGB values [red, green, blue] where each value is 0-255
|
|
32
|
+
* @returns Hexadecimal color code string starting with '#'
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* getHex([255, 123, 34]) // "#ff7b22"
|
|
36
|
+
* getHex([255, 255, 255]) // "#ffffff"
|
|
37
|
+
*/
|
|
38
|
+
function getHex(rgb: [number, number, number]): string
|
|
32
39
|
```
|
|
33
40
|
-->
|
|
34
41
|
<script module lang="ts">
|
|
@@ -14,38 +14,4 @@ type RgbColor = [number, number, number];
|
|
|
14
14
|
import { type Action } from "svelte/action";
|
|
15
15
|
import { type HTMLInputAttributes } from "svelte/elements";
|
|
16
16
|
import { type SVSClass } from "./core";
|
|
17
|
-
|
|
18
|
-
* ### Types
|
|
19
|
-
* default value: *`(value)`*
|
|
20
|
-
* ```ts
|
|
21
|
-
* interface ColorPickerProps {
|
|
22
|
-
* value?: string; // bindable ("#000000")
|
|
23
|
-
* alpha?: number; // bindable (1)
|
|
24
|
-
* attributes?: HTMLInputAttributes;
|
|
25
|
-
* action?: Action;
|
|
26
|
-
* element?: HTMLInputElement; // bindable
|
|
27
|
-
* styling?: SVSClass;
|
|
28
|
-
* variant?: string; // bindable (VARIANT.NEUTRAL)
|
|
29
|
-
* }
|
|
30
|
-
* ```
|
|
31
|
-
* ### Anatomy
|
|
32
|
-
* ```svelte
|
|
33
|
-
* <label class="whole">
|
|
34
|
-
* <div class="middle"> // this middle element is background for transparency color
|
|
35
|
-
* <div class="main"> // this main element is color sample
|
|
36
|
-
* <input type="color" {...attributes} bind:value bind:this={element} use:action />
|
|
37
|
-
* </div>
|
|
38
|
-
* </div>
|
|
39
|
-
* </label>
|
|
40
|
-
* ```
|
|
41
|
-
* ### Exports
|
|
42
|
-
* ```ts
|
|
43
|
-
* type RgbColor = [number, number, number];
|
|
44
|
-
* function getHex(rgb: RgbColor): string
|
|
45
|
-
* // getHex([255, 123, 34]) => "#ff7b22"
|
|
46
|
-
* // getHex([255, 255, 255]) => "#ffffff"
|
|
47
|
-
* ```
|
|
48
|
-
*/
|
|
49
|
-
declare const ColorPicker: import("svelte").Component<ColorPickerProps, {}, "variant" | "alpha" | "value" | "element">;
|
|
50
|
-
type ColorPicker = ReturnType<typeof ColorPicker>;
|
|
51
|
-
export default ColorPicker;
|
|
17
|
+
export {};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
label: string | Snippet<[boolean, string]>; // Snippet<[open,variant]>
|
|
8
8
|
children: Snippet<[string]>; // Snippet<[variant]>
|
|
9
9
|
open?: boolean; // bindable (false)
|
|
10
|
-
duration?: number; // (
|
|
10
|
+
duration?: number; // (200)
|
|
11
11
|
attributes?: HTMLDetailsAttributes;
|
|
12
12
|
action?: Action;
|
|
13
13
|
element?: HTMLDetailsElement; // bindable
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
label: string | Snippet<[boolean, string]>; // Snippet<[open,variant]>
|
|
33
33
|
children: Snippet<[string]>; // Snippet<[variant]>
|
|
34
34
|
open?: boolean; // bindable (false)
|
|
35
|
-
duration?: number; // (
|
|
35
|
+
duration?: number; // (200)
|
|
36
36
|
attributes?: HTMLDetailsAttributes;
|
|
37
37
|
action?: Action;
|
|
38
38
|
element?: HTMLDetailsElement; // bindable
|
|
@@ -43,10 +43,13 @@
|
|
|
43
43
|
export type DisclosureBindProps = "open" | "variant" | "element";
|
|
44
44
|
|
|
45
45
|
type DisclosureTarget = { currentTarget: EventTarget & HTMLDetailsElement };
|
|
46
|
-
const DEFAULT_DURATION =
|
|
46
|
+
const DEFAULT_DURATION = 200;
|
|
47
47
|
const preset = "svs-disclosure";
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
function isPrefersReducedMotion(): boolean {
|
|
50
|
+
if (typeof window === "undefined") return false;
|
|
51
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
52
|
+
}
|
|
50
53
|
class ToggleGurad {
|
|
51
54
|
#active = false;
|
|
52
55
|
get active(): boolean {
|
|
@@ -54,7 +57,7 @@
|
|
|
54
57
|
}
|
|
55
58
|
activate(duration: number) {
|
|
56
59
|
this.#active = true;
|
|
57
|
-
|
|
60
|
+
setTimeout(() => this.#active = false, duration);
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -70,6 +73,7 @@
|
|
|
70
73
|
|
|
71
74
|
// *** Initialize *** //
|
|
72
75
|
if (!variant) variant = VARIANT.NEUTRAL;
|
|
76
|
+
if (isPrefersReducedMotion()) duration = 0;
|
|
73
77
|
if (!isUnsignedInteger(duration)) duration = DEFAULT_DURATION;
|
|
74
78
|
const cls = fnClass(preset, styling);
|
|
75
79
|
const attrs = omit(attributes, "class", "open", "ontoggle");
|
|
@@ -88,7 +92,7 @@
|
|
|
88
92
|
if (open) {
|
|
89
93
|
toggle(true);
|
|
90
94
|
} else {
|
|
91
|
-
|
|
95
|
+
setTimeout(() => toggle(false), duration);
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
function toggle(bool: boolean) {
|
|
@@ -23,7 +23,7 @@ import { type SVSClass } from "./core";
|
|
|
23
23
|
* label: string | Snippet<[boolean, string]>; // Snippet<[open,variant]>
|
|
24
24
|
* children: Snippet<[string]>; // Snippet<[variant]>
|
|
25
25
|
* open?: boolean; // bindable (false)
|
|
26
|
-
* duration?: number; // (
|
|
26
|
+
* duration?: number; // (200)
|
|
27
27
|
* attributes?: HTMLDetailsAttributes;
|
|
28
28
|
* action?: Action;
|
|
29
29
|
* element?: HTMLDetailsElement; // bindable
|
package/_svseeds/_Drawer.svelte
CHANGED
|
@@ -43,9 +43,13 @@
|
|
|
43
43
|
export type DrawerReqdProps = "children";
|
|
44
44
|
export type DrawerBindProps = "open" | "variant" | "element";
|
|
45
45
|
|
|
46
|
+
const DEFAULT_DURATION = 200;
|
|
46
47
|
const preset = "svs-drawer";
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
function isPrefersReducedMotion(): boolean {
|
|
50
|
+
if (typeof window === "undefined") return false;
|
|
51
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
52
|
+
}
|
|
49
53
|
function getPositionProp(position: Position): string {
|
|
50
54
|
switch (position) {
|
|
51
55
|
case "top":
|
|
@@ -63,14 +67,16 @@
|
|
|
63
67
|
|
|
64
68
|
import { type Snippet, untrack } from "svelte";
|
|
65
69
|
import { type HTMLAttributes } from "svelte/elements";
|
|
66
|
-
import { type SVSClass, VARIANT, PARTS, fnClass, omit } from "./core";
|
|
70
|
+
import { type SVSClass, VARIANT, PARTS, fnClass, isUnsignedInteger, omit } from "./core";
|
|
67
71
|
</script>
|
|
68
72
|
|
|
69
73
|
<script lang="ts">
|
|
70
|
-
let { children, open = $bindable(false), position = "left", size = "auto", duration =
|
|
74
|
+
let { children, open = $bindable(false), position = "left", size = "auto", duration = -1, closable = true, id, attributes, element = $bindable(), styling, variant = $bindable("") }: DrawerProps = $props();
|
|
71
75
|
|
|
72
76
|
// *** Initialize *** //
|
|
73
77
|
if (!variant) variant = VARIANT.NEUTRAL;
|
|
78
|
+
if (isPrefersReducedMotion()) duration = 0;
|
|
79
|
+
if (!isUnsignedInteger(duration)) duration = DEFAULT_DURATION;
|
|
74
80
|
const cls = fnClass(preset, styling);
|
|
75
81
|
const attrs = omit(attributes, "class", "id", "style", "popover", "ontoggle");
|
|
76
82
|
const popover = closable ? "auto" : "manual";
|
|
@@ -95,7 +101,7 @@
|
|
|
95
101
|
attributes?.["ontoggle"]?.(ev as any);
|
|
96
102
|
open = ev.newState === "open";
|
|
97
103
|
style = baseStyle + "overflow:hidden;";
|
|
98
|
-
|
|
104
|
+
setTimeout(() => style = baseStyle, duration);
|
|
99
105
|
}
|
|
100
106
|
$effect(() => untrack(() => { if (open) element?.showPopover(); }));
|
|
101
107
|
</script>
|
package/_svseeds/_Modal.svelte
CHANGED
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
// *** Initialize *** //
|
|
56
56
|
if (!variant) variant = VARIANT.NEUTRAL;
|
|
57
57
|
const cls = fnClass(preset, styling);
|
|
58
|
-
const attrs = omit(attributes, "class", "id", "
|
|
58
|
+
const attrs = omit(attributes, "class", "id", "aria-label", "onclick", "onkeydown", "ontoggle");
|
|
59
59
|
|
|
60
60
|
// *** Bind Handlers *** //
|
|
61
61
|
$effect.pre(() => {
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
|
|
91
91
|
<!---------------------------------------->
|
|
92
92
|
|
|
93
|
-
<dialog bind:this={element} class={cls(PARTS.WHOLE, variant)} aria-label={ariaLabel} {id} {onclick} {onkeydown} {ontoggle}
|
|
93
|
+
<dialog bind:this={element} class={cls(PARTS.WHOLE, variant)} aria-label={ariaLabel} {id} {onclick} {onkeydown} {ontoggle} {...attrs} style="margin:auto;background-color:transparent;">
|
|
94
94
|
{#if open}
|
|
95
95
|
<div class={cls(PARTS.MAIN, variant)} transition:fade={{ duration, easing: cubicOut }}>
|
|
96
96
|
{@render children(variant)}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
### Types
|
|
4
|
+
default value: *`(value)`*
|
|
5
|
+
```ts
|
|
6
|
+
interface ToastProps {
|
|
7
|
+
children: Snippet<[string, string, string, string]>; // Snippet<[message,type,id,variant]>
|
|
8
|
+
name?: string;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
duration?: number; // (200)
|
|
11
|
+
styling?: SVSClass;
|
|
12
|
+
variant?: string; // bindable (VARIANT.NEUTRAL)
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
### Anatomy
|
|
16
|
+
```svelte
|
|
17
|
+
<div class="whole">
|
|
18
|
+
{#each}
|
|
19
|
+
<div class="middle" animate:flip={{ duration }}>
|
|
20
|
+
<div class="main">
|
|
21
|
+
{children}
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
{/each}
|
|
25
|
+
</div>
|
|
26
|
+
```
|
|
27
|
+
### Exports
|
|
28
|
+
```ts
|
|
29
|
+
/**
|
|
30
|
+
* Displays a toast notification.
|
|
31
|
+
*
|
|
32
|
+
* @param message - Text message to display in the toast
|
|
33
|
+
* @param type - Optional toast type/category (also used for part of aria-label)
|
|
34
|
+
* @param name - Unique identifier for the toast component
|
|
35
|
+
* @param timeout - Custom auto-dismiss timeout in milliseconds
|
|
36
|
+
* @returns ID of the displayed toast
|
|
37
|
+
*/
|
|
38
|
+
function toast(message: string, type?: string, name?: string, timeout?: number): string
|
|
39
|
+
/**
|
|
40
|
+
* Removes a specific toast notification.
|
|
41
|
+
*
|
|
42
|
+
* @param id - ID of the toast to remove
|
|
43
|
+
* @param name - Unique identifier for the toast component
|
|
44
|
+
*/
|
|
45
|
+
function removeToast(id: string, name?: string)
|
|
46
|
+
```
|
|
47
|
+
-->
|
|
48
|
+
<script module lang="ts">
|
|
49
|
+
export interface ToastProps {
|
|
50
|
+
children: Snippet<[string, string, string, string]>; // Snippet<[message,type,id,variant]>
|
|
51
|
+
name?: string;
|
|
52
|
+
timeout?: number;
|
|
53
|
+
duration?: number; // (200)
|
|
54
|
+
styling?: SVSClass;
|
|
55
|
+
variant?: string; // bindable (VARIANT.NEUTRAL)
|
|
56
|
+
}
|
|
57
|
+
export type ToastReqdProps = "children";
|
|
58
|
+
export type ToastBindProps = "variant";
|
|
59
|
+
|
|
60
|
+
export function toast(message: string, type?: string, name?: string, timeout?: number): string {
|
|
61
|
+
return core.add(message, type, name, timeout);
|
|
62
|
+
}
|
|
63
|
+
export function removeToast(id: string, name?: string) {
|
|
64
|
+
core.remove(id, name);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const preset = "svs-toast";
|
|
68
|
+
const DEFALT_DURATION = 200;
|
|
69
|
+
|
|
70
|
+
function isPrefersReducedMotion(): boolean {
|
|
71
|
+
if (typeof window === "undefined") return false;
|
|
72
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
73
|
+
}
|
|
74
|
+
function isValidTimeout(timeout?: number): timeout is number {
|
|
75
|
+
return !!timeout && isUnsignedInteger(timeout);
|
|
76
|
+
}
|
|
77
|
+
class ToastCore {
|
|
78
|
+
#containers: Map<string, ToastContainer> = new Map();
|
|
79
|
+
#uniqueId;
|
|
80
|
+
|
|
81
|
+
constructor() {
|
|
82
|
+
this.#uniqueId = new UniqueId();
|
|
83
|
+
}
|
|
84
|
+
register(container: ToastContainer, name?: string) {
|
|
85
|
+
this.#containers.set(this.#uniqueId.register(name), container);
|
|
86
|
+
}
|
|
87
|
+
add(message: string, type?: string, name?: string, timeout?: number): string {
|
|
88
|
+
return this.#containers.get(name ?? this.#uniqueId.default)?.addToast(type ?? "", message, timeout) ?? "";
|
|
89
|
+
}
|
|
90
|
+
remove(id: string, name?: string) {
|
|
91
|
+
this.#containers.get(name ?? this.#uniqueId.default)?.hideToast(id);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
class UniqueId {
|
|
95
|
+
#default = "";
|
|
96
|
+
#ids: Set<string> = new Set();
|
|
97
|
+
get default(): string {
|
|
98
|
+
return this.#default;
|
|
99
|
+
}
|
|
100
|
+
register(name?: string): string {
|
|
101
|
+
const id = name ? name : elemId.id;
|
|
102
|
+
if (this.#ids.has(id)) return "";
|
|
103
|
+
if (!this.#default) this.#default = id;
|
|
104
|
+
this.#ids.add(id);
|
|
105
|
+
return id;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
class ToastContainer {
|
|
109
|
+
#open: boolean = $state(false);
|
|
110
|
+
#style: string;
|
|
111
|
+
#keydownFn = (ev: KeyboardEvent) => {};
|
|
112
|
+
element = $state<HTMLDivElement>();
|
|
113
|
+
toasts: Toast[] = $state([]);
|
|
114
|
+
onkeydown = $derived(this.#open ? this.#keydownFn : undefined);
|
|
115
|
+
|
|
116
|
+
constructor(duration: number, onkeydown: (ev: KeyboardEvent) => void, timeout?: number) {
|
|
117
|
+
this.#style = `position:fixed;background-color:transparent;pointer-events:none;`;
|
|
118
|
+
this.#keydownFn = onkeydown;
|
|
119
|
+
Toast.init(duration, timeout);
|
|
120
|
+
}
|
|
121
|
+
addToast(type: string, message: string, timeout?: number): string {
|
|
122
|
+
if (!this.toasts.length) this.#show();
|
|
123
|
+
const toast = new Toast(type, message, (id) => this.remove(id), timeout);
|
|
124
|
+
this.toasts.push(toast);
|
|
125
|
+
return toast.id;
|
|
126
|
+
}
|
|
127
|
+
hideToast(id: string) {
|
|
128
|
+
this.toasts.find((x) => x.id === id)?.hide();
|
|
129
|
+
}
|
|
130
|
+
remove(id: string) {
|
|
131
|
+
this.toasts = this.toasts.filter((x) => x.id !== id);
|
|
132
|
+
if (!this.toasts.length) this.hide();
|
|
133
|
+
}
|
|
134
|
+
#show() {
|
|
135
|
+
this.element?.showPopover();
|
|
136
|
+
this.#open = true;
|
|
137
|
+
}
|
|
138
|
+
hide() {
|
|
139
|
+
this.element?.hidePopover();
|
|
140
|
+
this.#open = false;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get open(): boolean {
|
|
144
|
+
return this.#open;
|
|
145
|
+
}
|
|
146
|
+
get style(): string {
|
|
147
|
+
return this.#style;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
class Toast {
|
|
151
|
+
static #DEFALT_TIMEOUT = Infinity;
|
|
152
|
+
static #DURATION = 0;
|
|
153
|
+
#isVisible = $state(false);
|
|
154
|
+
#id: string;
|
|
155
|
+
#type: string;
|
|
156
|
+
#message: string;
|
|
157
|
+
#remove: (id: string) => void;
|
|
158
|
+
#timeout: number;
|
|
159
|
+
#timeoutId: number = 0;
|
|
160
|
+
constructor(type: string, message: string, remove: (id: string) => void, timeout?: number) {
|
|
161
|
+
this.#id = elemId.id;
|
|
162
|
+
this.#type = type;
|
|
163
|
+
this.#message = message;
|
|
164
|
+
this.#remove = remove;
|
|
165
|
+
this.#timeout = isValidTimeout(timeout) ? timeout : Toast.#DEFALT_TIMEOUT;
|
|
166
|
+
this.#setAutoDismiss();
|
|
167
|
+
}
|
|
168
|
+
show() {
|
|
169
|
+
this.#isVisible = true;
|
|
170
|
+
}
|
|
171
|
+
hide() {
|
|
172
|
+
this.#isVisible = false;
|
|
173
|
+
this.reset();
|
|
174
|
+
setTimeout(() => {
|
|
175
|
+
this.#remove(this.#id);
|
|
176
|
+
}, Toast.#DURATION);
|
|
177
|
+
}
|
|
178
|
+
reset() {
|
|
179
|
+
clearTimeout(this.#timeoutId);
|
|
180
|
+
}
|
|
181
|
+
restart(ev: PointerEvent) {
|
|
182
|
+
this.#setAutoDismiss(ev.pointerType === "touch");
|
|
183
|
+
}
|
|
184
|
+
#setAutoDismiss(extend?: boolean) {
|
|
185
|
+
if (!Number.isFinite(this.#timeout)) return;
|
|
186
|
+
if (typeof window === "undefined") return;
|
|
187
|
+
const timer = extend ? this.#timeout * 1.5 : this.#timeout;
|
|
188
|
+
this.#timeoutId = window.setTimeout(() => this.hide(), timer);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static init(duration: number, timeout?: number) {
|
|
192
|
+
Toast.#DEFALT_TIMEOUT = isValidTimeout(timeout) ? timeout : Infinity;
|
|
193
|
+
Toast.#DURATION = duration;
|
|
194
|
+
}
|
|
195
|
+
get label(): string {
|
|
196
|
+
return this.#type ? `${this.#type} message` : "message";
|
|
197
|
+
}
|
|
198
|
+
get isVisible(): boolean {
|
|
199
|
+
return this.#isVisible;
|
|
200
|
+
}
|
|
201
|
+
get id(): string {
|
|
202
|
+
return this.#id;
|
|
203
|
+
}
|
|
204
|
+
get type(): string {
|
|
205
|
+
return this.#type;
|
|
206
|
+
}
|
|
207
|
+
get message(): string {
|
|
208
|
+
return this.#message;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const core = new ToastCore();
|
|
212
|
+
|
|
213
|
+
import { type Snippet } from "svelte";
|
|
214
|
+
import { flip } from "svelte/animate";
|
|
215
|
+
import { type SVSClass, VARIANT, PARTS, elemId, fnClass, isUnsignedInteger } from "./core";
|
|
216
|
+
</script>
|
|
217
|
+
|
|
218
|
+
<script lang="ts">
|
|
219
|
+
let { children, name, timeout, duration = -1, styling, variant = $bindable("") }: ToastProps = $props();
|
|
220
|
+
|
|
221
|
+
// *** Initialize *** //
|
|
222
|
+
if (!variant) variant = VARIANT.NEUTRAL;
|
|
223
|
+
const cls = fnClass(preset, styling);
|
|
224
|
+
if (isPrefersReducedMotion()) duration = 0;
|
|
225
|
+
if (!isUnsignedInteger(duration)) duration = DEFALT_DURATION;
|
|
226
|
+
const container = new ToastContainer(duration, onkeydown, timeout);
|
|
227
|
+
core.register(container, name);
|
|
228
|
+
|
|
229
|
+
// *** Event Handlers *** //
|
|
230
|
+
function mount(_node: HTMLDivElement, index: number) {
|
|
231
|
+
setTimeout(() => container.toasts[index].show(), 0);
|
|
232
|
+
}
|
|
233
|
+
function enter(index: number): () => void {
|
|
234
|
+
return () => container.toasts[index].reset();
|
|
235
|
+
}
|
|
236
|
+
function leave(index: number): (ev: PointerEvent) => void {
|
|
237
|
+
return (ev) => container.toasts[index].restart(ev);
|
|
238
|
+
}
|
|
239
|
+
function onkeydown(ev: KeyboardEvent) {
|
|
240
|
+
if (ev.key !== "F6") return;
|
|
241
|
+
if (ev.composed) return;
|
|
242
|
+
container.element?.focus();
|
|
243
|
+
}
|
|
244
|
+
</script>
|
|
245
|
+
|
|
246
|
+
<!---------------------------------------->
|
|
247
|
+
<svelte:body onkeydown={container.onkeydown} />
|
|
248
|
+
|
|
249
|
+
<div bind:this={container.element} class={cls(PARTS.WHOLE, variant)} role="region" tabindex="-1" popover="manual" aria-label={`${container.toasts.length} notifications`} style={container.style}>
|
|
250
|
+
{#each container.toasts as toast, i (toast.id)}
|
|
251
|
+
{@const v = toast.isVisible ? variant : VARIANT.INACTIVE}
|
|
252
|
+
<div class={cls(PARTS.MIDDLE, v)} style="width:fit-content;height:fit-content;overflow:hidden;" tabindex="-1" animate:flip={{ duration }}>
|
|
253
|
+
<div class={cls(PARTS.MAIN, v)} role="dialog" aria-modal="false" aria-label={toast.label} tabindex="0" style="pointer-events:auto;" onpointerenter={enter(i)} onpointerleave={leave(i)} onpointercancel={leave(i)} use:mount={i}>
|
|
254
|
+
{@render children(toast.message, toast.type, toast.id, variant)}
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
{/each}
|
|
258
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ToastProps {
|
|
2
|
+
children: Snippet<[string, string, string, string]>;
|
|
3
|
+
name?: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
duration?: number;
|
|
6
|
+
styling?: SVSClass;
|
|
7
|
+
variant?: string;
|
|
8
|
+
}
|
|
9
|
+
export type ToastReqdProps = "children";
|
|
10
|
+
export type ToastBindProps = "variant";
|
|
11
|
+
export declare function toast(message: string, type?: string, name?: string, timeout?: number): string;
|
|
12
|
+
export declare function removeToast(id: string, name?: string): void;
|
|
13
|
+
import { type Snippet } from "svelte";
|
|
14
|
+
import { type SVSClass } from "./core";
|
package/_svseeds/_Tooltip.svelte
CHANGED
|
@@ -27,6 +27,22 @@
|
|
|
27
27
|
{/if}
|
|
28
28
|
</div>
|
|
29
29
|
```
|
|
30
|
+
### Exports
|
|
31
|
+
```ts
|
|
32
|
+
/**
|
|
33
|
+
* Action function for use with SvSeeds components.
|
|
34
|
+
*
|
|
35
|
+
* @param text - Text content for the tooltip's aria-label
|
|
36
|
+
* @param delay - Delay in milliseconds before the tooltip appears (default: 1000)
|
|
37
|
+
* @param cursor - Whether the tooltip should follow cursor movement
|
|
38
|
+
* @param name - Unique identifier for the tooltip component
|
|
39
|
+
*/
|
|
40
|
+
function tooltipAction(text: string, delay?: number, cursor?: boolean, name?: string): Action
|
|
41
|
+
/**
|
|
42
|
+
* Action function for use with standard HTML elements.
|
|
43
|
+
*/
|
|
44
|
+
function tooltip(node: HTMLElement, params: { text: string, delay?: number, cursor?: boolean, name?: string }): ActionReturn
|
|
45
|
+
```
|
|
30
46
|
-->
|
|
31
47
|
<script module lang="ts">
|
|
32
48
|
export interface TooltipProps {
|
|
@@ -26,35 +26,3 @@ export type Align = "start" | "center" | "end";
|
|
|
26
26
|
import { type Snippet } from "svelte";
|
|
27
27
|
import { type Action, type ActionReturn } from "svelte/action";
|
|
28
28
|
import { type SVSClass } from "./core";
|
|
29
|
-
/**
|
|
30
|
-
* ### Types
|
|
31
|
-
* default value: *`(value)`*
|
|
32
|
-
* ```ts
|
|
33
|
-
* interface TooltipProps {
|
|
34
|
-
* children?: Snippet<[string, string, boolean]>; // Snippet<[text,variant,isFlipped]>
|
|
35
|
-
* name?: string;
|
|
36
|
-
* position?: Position; // ("top")
|
|
37
|
-
* align?: Align; // ("center")
|
|
38
|
-
* offset?: Vector; // ({ x: 0, y: 0 })
|
|
39
|
-
* element?: HTMLDivElement; // bindable
|
|
40
|
-
* styling?: SVSClass;
|
|
41
|
-
* variant?: string; // bindable (VARIANT.NEUTRAL)
|
|
42
|
-
* }
|
|
43
|
-
* type Vector = { x: number, y: number };
|
|
44
|
-
* type Position = "top" | "right" | "bottom" | "left";
|
|
45
|
-
* type Align = "start" | "center" | "end";
|
|
46
|
-
* ```
|
|
47
|
-
* ### Anatomy
|
|
48
|
-
* ```svelte
|
|
49
|
-
* <div class="whole" bind:this={element} conditional>
|
|
50
|
-
* {#if children}
|
|
51
|
-
* {children}
|
|
52
|
-
* {:else}
|
|
53
|
-
* {text} // `text` is an argument of the tooltip/tooltipAction function
|
|
54
|
-
* {/if}
|
|
55
|
-
* </div>
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
declare const Tooltip: import("svelte").Component<TooltipProps, {}, "variant" | "element">;
|
|
59
|
-
type Tooltip = ReturnType<typeof Tooltip>;
|
|
60
|
-
export default Tooltip;
|
package/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export { default as Sortable, type SortableProps, type SortableReqdProps, type S
|
|
|
15
15
|
export { default as Tabs, type TabsProps, type TabsReqdProps, type TabsBindProps } from "./_svseeds/_Tabs.svelte";
|
|
16
16
|
export { default as TagsInput, type TagsInputProps, type TagsInputReqdProps, type TagsInputBindProps, type TagsInputEvents } from "./_svseeds/_TagsInput.svelte";
|
|
17
17
|
export { default as TextField, type TextFieldProps, type TextFieldReqdProps, type TextFieldBindProps, type TextFieldValidation } from "./_svseeds/_TextField.svelte";
|
|
18
|
+
export { default as Toast, type ToastProps, type ToastReqdProps, type ToastBindProps, toast, removeToast } from "./_svseeds/_Toast.svelte";
|
|
18
19
|
export { default as Toggle, type ToggleProps, type ToggleReqdProps, type ToggleBindProps } from "./_svseeds/_Toggle.svelte";
|
|
19
20
|
export { default as ToggleGroup, type ToggleGroupProps, type ToggleGroupReqdProps, type ToggleGroupBindProps } from "./_svseeds/_ToggleGroup.svelte";
|
|
20
21
|
export { default as Tooltip, type TooltipProps, type TooltipReqdProps, type TooltipBindProps, type Vector, type Position, type Align, tooltip, tooltipAction } from "./_svseeds/_Tooltip.svelte";
|
package/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export { default as Sortable, SortableItems } from "./_svseeds/_Sortable.svelte"
|
|
|
15
15
|
export { default as Tabs } from "./_svseeds/_Tabs.svelte";
|
|
16
16
|
export { default as TagsInput } from "./_svseeds/_TagsInput.svelte";
|
|
17
17
|
export { default as TextField } from "./_svseeds/_TextField.svelte";
|
|
18
|
+
export { default as Toast, toast, removeToast } from "./_svseeds/_Toast.svelte";
|
|
18
19
|
export { default as Toggle } from "./_svseeds/_Toggle.svelte";
|
|
19
20
|
export { default as ToggleGroup } from "./_svseeds/_ToggleGroup.svelte";
|
|
20
21
|
export { default as Tooltip, tooltip, tooltipAction } from "./_svseeds/_Tooltip.svelte";
|