svseeds 0.4.1 → 0.4.3
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/_svseeds/Accordion.svelte +31 -14
- package/_svseeds/Accordion.svelte.d.ts +20 -4
- package/_svseeds/DarkToggle.svelte +76 -40
- package/_svseeds/DarkToggle.svelte.d.ts +23 -4
- package/_svseeds/TagsInput.svelte +58 -28
- package/_svseeds/TagsInput.svelte.d.ts +34 -6
- package/_svseeds/TagsInputField.svelte +66 -33
- package/_svseeds/TagsInputField.svelte.d.ts +36 -4
- package/_svseeds/ToggleGroupField.svelte +59 -32
- package/_svseeds/ToggleGroupField.svelte.d.ts +30 -4
- package/_svseeds/_Badge.svelte +33 -17
- package/_svseeds/_Badge.svelte.d.ts +17 -2
- package/_svseeds/_Button.svelte +39 -20
- package/_svseeds/_Button.svelte.d.ts +20 -2
- package/_svseeds/_CheckField.svelte +54 -30
- package/_svseeds/_CheckField.svelte.d.ts +24 -2
- package/_svseeds/_ColorPicker.svelte +38 -17
- package/_svseeds/_ColorPicker.svelte.d.ts +21 -2
- package/_svseeds/_ComboBox.svelte +38 -20
- package/_svseeds/_ComboBox.svelte.d.ts +17 -2
- package/_svseeds/_ContextMenu.svelte +26 -12
- package/_svseeds/_ContextMenu.svelte.d.ts +15 -2
- package/_svseeds/_Disclosure.svelte +37 -21
- package/_svseeds/_Disclosure.svelte.d.ts +19 -3
- package/_svseeds/_HotkeyCapture.svelte +28 -13
- package/_svseeds/_HotkeyCapture.svelte.d.ts +16 -2
- package/_svseeds/_Modal.svelte +32 -15
- package/_svseeds/_Modal.svelte.d.ts +18 -3
- package/_svseeds/_ProgressTracker.svelte +31 -16
- package/_svseeds/_ProgressTracker.svelte.d.ts +16 -2
- package/_svseeds/_SelectField.svelte +53 -29
- package/_svseeds/_SelectField.svelte.d.ts +25 -2
- package/_svseeds/_Slider.svelte +43 -22
- package/_svseeds/_Slider.svelte.d.ts +22 -2
- package/_svseeds/_Sortable.svelte +57 -19
- package/_svseeds/_Sortable.svelte.d.ts +39 -2
- package/_svseeds/_Tabs.svelte +31 -17
- package/_svseeds/_Tabs.svelte.d.ts +16 -3
- package/_svseeds/_TextField.svelte +56 -31
- package/_svseeds/_TextField.svelte.d.ts +26 -2
- package/_svseeds/_Toggle.svelte +45 -25
- package/_svseeds/_Toggle.svelte.d.ts +21 -2
- package/_svseeds/_ToggleGroup.svelte +32 -15
- package/_svseeds/_ToggleGroup.svelte.d.ts +18 -2
- package/_svseeds/_Tooltip.svelte +32 -13
- package/_svseeds/_Tooltip.svelte.d.ts +20 -2
- package/_svseeds/core.d.ts +186 -8
- package/_svseeds/core.js +1 -1
- package/index.d.ts +24 -24
- package/index.js +3 -3
- package/package.json +1 -1
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
default value: `<value>`
|
|
4
|
+
```ts
|
|
5
|
+
interface SortableProps {
|
|
6
|
+
items: SortableItems; // wrapper of string array as items to handle DnD
|
|
7
|
+
item: Snippet<[string, string, PointerEventHandler]>; // Snippet<[status, value, onpointerdown]>
|
|
8
|
+
ghost?: Snippet<[string]>; // custom shadow while dragging <the translucent item>; Snippet<[value]>
|
|
9
|
+
name?: string; // name of this group <random string>
|
|
10
|
+
mode?: SortableMode; // sort mode <"std">;
|
|
11
|
+
accept?: string[]; // list of accept group names <undefined>; undefined=any,[]=none
|
|
12
|
+
sort?: boolean; // enable sort within same group <true>
|
|
13
|
+
multiple?: boolean; // enable multiple select & drag with them <false>
|
|
14
|
+
draggable?: boolean; // enable default pointerdown handler <true>
|
|
15
|
+
appendable?: boolean; // enable append when enter group area <false>
|
|
16
|
+
confirm?: boolean // enable confirm interval time to move items <false>
|
|
17
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
18
|
+
style?: SVSStyle;
|
|
19
|
+
}
|
|
20
|
+
type SortableMode = "std" | "clone" | "swap";
|
|
21
|
+
class SortableItems { // methods are same with array's
|
|
22
|
+
constructor(values: string[])
|
|
23
|
+
at(index: number): string | undefined
|
|
24
|
+
replace(index: number, value: string): boolean
|
|
25
|
+
push(value: string)
|
|
26
|
+
pop(): string | undefined
|
|
27
|
+
unshift(value: string)
|
|
28
|
+
shift(): string | undefined
|
|
29
|
+
insert(index: number, value: string) // instead of splice
|
|
30
|
+
extract(index: number): string | undefined // instead of splice
|
|
31
|
+
isEmpty(): boolean
|
|
32
|
+
clear(): void
|
|
33
|
+
get length(): number
|
|
34
|
+
get values(): string[]
|
|
35
|
+
set values(values: string[])
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
-->
|
|
1
39
|
<script module lang="ts">
|
|
2
40
|
import { cubicOut } from "svelte/easing";
|
|
3
41
|
const tp: TransitionParams = { duration: 300, easing: cubicOut }; // config of transition
|
|
@@ -11,21 +49,21 @@
|
|
|
11
49
|
/***************************************************************/
|
|
12
50
|
|
|
13
51
|
type SortableMode = "std" | "clone" | "swap";
|
|
14
|
-
export
|
|
15
|
-
items: SortableItems
|
|
16
|
-
item: Snippet<[string, string, PointerEventHandler]
|
|
17
|
-
ghost?: Snippet<[string]
|
|
18
|
-
name?: string
|
|
19
|
-
mode?: SortableMode
|
|
20
|
-
accept?: string[]
|
|
21
|
-
sort?: boolean
|
|
22
|
-
multiple?: boolean
|
|
23
|
-
draggable?: boolean
|
|
24
|
-
appendable?: boolean
|
|
52
|
+
export interface SortableProps {
|
|
53
|
+
items: SortableItems; // wrapper of string array as items to handle DnD
|
|
54
|
+
item: Snippet<[string, string, PointerEventHandler]>; // Snippet<[status, value, onpointerdown]>
|
|
55
|
+
ghost?: Snippet<[string]>; // custom shadow while dragging <the translucent item>; Snippet<[value]>
|
|
56
|
+
name?: string; // name of this group <random string>
|
|
57
|
+
mode?: SortableMode; // sort mode <"std">; "std","clone","swap"
|
|
58
|
+
accept?: string[]; // list of accept group names <undefined>; undefined=any,[]=none
|
|
59
|
+
sort?: boolean; // enable sort within same group <true>
|
|
60
|
+
multiple?: boolean; // enable multiple select & drag with them <false>
|
|
61
|
+
draggable?: boolean; // enable default pointerdown handler <true>
|
|
62
|
+
appendable?: boolean; // enable append when enter group area <false>
|
|
25
63
|
confirm?: boolean // enable confirm interval time to move items <false>
|
|
26
|
-
status?: string
|
|
27
|
-
style?: SVSStyle
|
|
28
|
-
}
|
|
64
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
65
|
+
style?: SVSStyle;
|
|
66
|
+
}
|
|
29
67
|
export type SortableReqdProps = "items" | "item";
|
|
30
68
|
export type SortableBindProps = "status";
|
|
31
69
|
|
|
@@ -603,14 +641,14 @@
|
|
|
603
641
|
import { on } from "svelte/events";
|
|
604
642
|
import { type EasingFunction, crossfade } from "svelte/transition";
|
|
605
643
|
import { flip } from "svelte/animate";
|
|
606
|
-
import { type SVSStyle, STATE,
|
|
644
|
+
import { type SVSStyle, STATE, PARTS, fnClass, throttle } from "./core";
|
|
607
645
|
</script>
|
|
608
646
|
|
|
609
647
|
<script lang="ts">
|
|
610
648
|
let { items, item, ghost, name, mode = "std", accept, sort = true, multiple = false, draggable = true, appendable = false, confirm = false, status = $bindable(""), style }: SortableProps = $props();
|
|
611
649
|
|
|
612
650
|
// *** Initialize *** //
|
|
613
|
-
if (!status) status = STATE.
|
|
651
|
+
if (!status) status = STATE.NEUTRAL;
|
|
614
652
|
const cls = fnClass(preset, style);
|
|
615
653
|
const group: KeyValue = SortableItems._newItem(name);
|
|
616
654
|
const elems: HTMLElement[] = [];
|
|
@@ -719,14 +757,14 @@
|
|
|
719
757
|
|
|
720
758
|
<!---------------------------------------->
|
|
721
759
|
|
|
722
|
-
<ul class={cls(
|
|
760
|
+
<ul class={cls(PARTS.WHOLE, status)} onpointerenter={drag.active ? groupenter : undefined} onpointerleave={drag.active ? groupleave : undefined}>
|
|
723
761
|
{#each items._inner as {key, value}, i (key)}
|
|
724
762
|
{@const style = "touch-action:none;"}
|
|
725
763
|
{@const itemStatus = isSelected(key) ? STATE.ACTIVE : status}
|
|
726
764
|
{@const onpointerdown = draggable ? downF(key, elems[i]) : undefined}
|
|
727
765
|
{@const onpointerenter = drag.active ? enterF(key) : undefined}
|
|
728
766
|
{@const onpointerleave = drag.active ? leave : undefined}
|
|
729
|
-
<li bind:this={elems[i]} class={cls(
|
|
767
|
+
<li bind:this={elems[i]} class={cls(PARTS.MAIN, itemStatus)} in:s={{key}} out:r={{key}} animate:flip={tp} {style} {onpointerdown} {onpointerenter} {onpointerleave} {ondragstart}>
|
|
730
768
|
{@render item(itemStatus, value, downF(key, elems[i]))}
|
|
731
769
|
</li>
|
|
732
770
|
{/each}
|
|
@@ -734,7 +772,7 @@
|
|
|
734
772
|
{#if shadow.rendering}
|
|
735
773
|
{@const style = `opacity: 0.5; pointer-events: none; position: fixed; left: ${shadow.pt.x}px; top: ${shadow.pt.y}px; ${shadow.cssVisibility} ${shadow.cssSize}`}
|
|
736
774
|
<ul style="display: contents;">
|
|
737
|
-
<li bind:this={shadow.elem} class={shadow.isGhost ? undefined : cls(
|
|
775
|
+
<li bind:this={shadow.elem} class={shadow.isGhost ? undefined : cls(PARTS.MAIN, status)} {style}>
|
|
738
776
|
{#if shadow.isGhost}
|
|
739
777
|
{@render ghost!(items._value(drag.key))}
|
|
740
778
|
{:else}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/***************************************************************/
|
|
2
2
|
type SortableMode = "std" | "clone" | "swap";
|
|
3
|
-
export
|
|
3
|
+
export interface SortableProps {
|
|
4
4
|
items: SortableItems;
|
|
5
5
|
item: Snippet<[string, string, PointerEventHandler]>;
|
|
6
6
|
ghost?: Snippet<[string]>;
|
|
@@ -14,7 +14,7 @@ export type SortableProps = {
|
|
|
14
14
|
confirm?: boolean;
|
|
15
15
|
status?: string;
|
|
16
16
|
style?: SVSStyle;
|
|
17
|
-
}
|
|
17
|
+
}
|
|
18
18
|
export type SortableReqdProps = "items" | "item";
|
|
19
19
|
export type SortableBindProps = "status";
|
|
20
20
|
export declare class SortableItems {
|
|
@@ -57,6 +57,43 @@ type KeyValue = {
|
|
|
57
57
|
type DragState = "ready" | "dragging" | "idle";
|
|
58
58
|
import { type Snippet } from "svelte";
|
|
59
59
|
import { type SVSStyle } from "./core";
|
|
60
|
+
/**
|
|
61
|
+
* default value: `<value>`
|
|
62
|
+
* ```ts
|
|
63
|
+
* interface SortableProps {
|
|
64
|
+
* items: SortableItems; // wrapper of string array as items to handle DnD
|
|
65
|
+
* item: Snippet<[string, string, PointerEventHandler]>; // Snippet<[status, value, onpointerdown]>
|
|
66
|
+
* ghost?: Snippet<[string]>; // custom shadow while dragging <the translucent item>; Snippet<[value]>
|
|
67
|
+
* name?: string; // name of this group <random string>
|
|
68
|
+
* mode?: SortableMode; // sort mode <"std">;
|
|
69
|
+
* accept?: string[]; // list of accept group names <undefined>; undefined=any,[]=none
|
|
70
|
+
* sort?: boolean; // enable sort within same group <true>
|
|
71
|
+
* multiple?: boolean; // enable multiple select & drag with them <false>
|
|
72
|
+
* draggable?: boolean; // enable default pointerdown handler <true>
|
|
73
|
+
* appendable?: boolean; // enable append when enter group area <false>
|
|
74
|
+
* confirm?: boolean // enable confirm interval time to move items <false>
|
|
75
|
+
* status?: string; // bindable <STATE.NEUTRAL>
|
|
76
|
+
* style?: SVSStyle;
|
|
77
|
+
* }
|
|
78
|
+
* type SortableMode = "std" | "clone" | "swap";
|
|
79
|
+
* class SortableItems { // methods are same with array's
|
|
80
|
+
* constructor(values: string[])
|
|
81
|
+
* at(index: number): string | undefined
|
|
82
|
+
* replace(index: number, value: string): boolean
|
|
83
|
+
* push(value: string)
|
|
84
|
+
* pop(): string | undefined
|
|
85
|
+
* unshift(value: string)
|
|
86
|
+
* shift(): string | undefined
|
|
87
|
+
* insert(index: number, value: string) // instead of splice
|
|
88
|
+
* extract(index: number): string | undefined // instead of splice
|
|
89
|
+
* isEmpty(): boolean
|
|
90
|
+
* clear(): void
|
|
91
|
+
* get length(): number
|
|
92
|
+
* get values(): string[]
|
|
93
|
+
* set values(values: string[])
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
60
97
|
declare const Sortable: import("svelte").Component<SortableProps, {}, "status">;
|
|
61
98
|
type Sortable = ReturnType<typeof Sortable>;
|
|
62
99
|
export default Sortable;
|
package/_svseeds/_Tabs.svelte
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
default value: `<value>`
|
|
4
|
+
```ts
|
|
5
|
+
interface TabsProps {
|
|
6
|
+
labels?: string[];
|
|
7
|
+
current?: number; // bindable <0>
|
|
8
|
+
ariaOrientation?: "horizontal" | "vertical";
|
|
9
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
10
|
+
style?: SVSStyle;
|
|
11
|
+
[key: string]: unknown | Snippet;
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
-->
|
|
1
15
|
<script module lang="ts">
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
status?: string
|
|
7
|
-
style?: SVSStyle
|
|
8
|
-
[key: string]: unknown | Snippet
|
|
9
|
-
}
|
|
16
|
+
export interface TabsProps {
|
|
17
|
+
labels?: string[];
|
|
18
|
+
current?: number; // bindable <0>
|
|
19
|
+
ariaOrientation?: "horizontal" | "vertical";
|
|
20
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
21
|
+
style?: SVSStyle;
|
|
22
|
+
[key: string]: unknown | Snippet;
|
|
23
|
+
}
|
|
10
24
|
export type TabsReqdProps = never;
|
|
11
25
|
export type TabsBindProps = "current" | "status";
|
|
12
26
|
|
|
@@ -30,14 +44,14 @@
|
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
import { type Snippet } from "svelte";
|
|
33
|
-
import { type SVSStyle, STATE,
|
|
47
|
+
import { type SVSStyle, STATE, PARTS, elemId, fnClass } from "./core";
|
|
34
48
|
</script>
|
|
35
49
|
|
|
36
50
|
<script lang="ts">
|
|
37
|
-
let {
|
|
51
|
+
let { labels = [], current = $bindable(0), ariaOrientation, status = $bindable(""), style, ...rest }: TabsProps = $props();
|
|
38
52
|
|
|
39
53
|
// *** Initialize *** //
|
|
40
|
-
if (!status) status = STATE.
|
|
54
|
+
if (!status) status = STATE.NEUTRAL;
|
|
41
55
|
const cls = fnClass(preset, style);
|
|
42
56
|
const isStrLabel = labels.length > 0;
|
|
43
57
|
const tabs = toNamedId(isStrLabel ? labels : getSnippetNames(roleLabel, rest));
|
|
@@ -52,8 +66,8 @@
|
|
|
52
66
|
}
|
|
53
67
|
const isNextKey = (key: string) => key === "ArrowRight" || key === "ArrowDown";
|
|
54
68
|
const isPrevKey = (key: string) => key === "ArrowLeft" || key === "ArrowUp";
|
|
55
|
-
const nextTabElem = (i: number) => i
|
|
56
|
-
const prevTabElem = (i: number) => i
|
|
69
|
+
const nextTabElem = (i: number) => i + 1 >= tabs.length ? elems[0] : elems[i + 1];
|
|
70
|
+
const prevTabElem = (i: number) => i - 1 < 0 ? elems[tabs.length - 1] : elems[i - 1];
|
|
57
71
|
function moveFocus(index: number): (ev: KeyboardEvent) => void {
|
|
58
72
|
return (ev: KeyboardEvent) => {
|
|
59
73
|
if (isNextKey(ev.key)) nextTabElem(index)?.focus();
|
|
@@ -65,12 +79,12 @@
|
|
|
65
79
|
<!---------------------------------------->
|
|
66
80
|
|
|
67
81
|
{#if isValidTabs}
|
|
68
|
-
<div class={cls(
|
|
69
|
-
<div class={cls(
|
|
82
|
+
<div class={cls(PARTS.WHOLE, status)}>
|
|
83
|
+
<div class={cls(PARTS.TOP, status)} role="tablist" aria-orientation={ariaOrientation}>
|
|
70
84
|
{#each tabs as { id, name }, i (id)}
|
|
71
85
|
{@const selected = i === current}
|
|
72
86
|
{@const tabStatus = selected ? STATE.ACTIVE : status}
|
|
73
|
-
<button bind:this={elems[i]} class={cls(
|
|
87
|
+
<button bind:this={elems[i]} class={cls(PARTS.LABEL, tabStatus)} onclick={activate(i)} onkeydown={moveFocus(i)} tabindex={selected ? 0 : -1} aria-selected={selected} aria-controls={panels[i].id} type="button" role="tab" {id}>
|
|
74
88
|
{#if isStrLabel}
|
|
75
89
|
{name}
|
|
76
90
|
{:else}
|
|
@@ -82,7 +96,7 @@
|
|
|
82
96
|
{#each panels as { id, name }, i (id)}
|
|
83
97
|
{@const selected = i === current}
|
|
84
98
|
{@const style = selected ? undefined : "display: none;"}
|
|
85
|
-
<div class={cls(
|
|
99
|
+
<div class={cls(PARTS.MAIN, status)} aria-labelledby={tabs[i].id} role="tabpanel" tabindex={0} hidden={!selected} {id} {style}>
|
|
86
100
|
{@render (rest[name] as Snippet)()}
|
|
87
101
|
</div>
|
|
88
102
|
{/each}
|
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
export
|
|
2
|
-
orientation?: "horizontal" | "vertical";
|
|
1
|
+
export interface TabsProps {
|
|
3
2
|
labels?: string[];
|
|
4
3
|
current?: number;
|
|
4
|
+
ariaOrientation?: "horizontal" | "vertical";
|
|
5
5
|
status?: string;
|
|
6
6
|
style?: SVSStyle;
|
|
7
7
|
[key: string]: unknown | Snippet;
|
|
8
|
-
}
|
|
8
|
+
}
|
|
9
9
|
export type TabsReqdProps = never;
|
|
10
10
|
export type TabsBindProps = "current" | "status";
|
|
11
11
|
import { type Snippet } from "svelte";
|
|
12
12
|
import { type SVSStyle } from "./core";
|
|
13
|
+
/**
|
|
14
|
+
* default value: `<value>`
|
|
15
|
+
* ```ts
|
|
16
|
+
* interface TabsProps {
|
|
17
|
+
* labels?: string[];
|
|
18
|
+
* current?: number; // bindable <0>
|
|
19
|
+
* ariaOrientation?: "horizontal" | "vertical";
|
|
20
|
+
* status?: string; // bindable <STATE.NEUTRAL>
|
|
21
|
+
* style?: SVSStyle;
|
|
22
|
+
* [key: string]: unknown | Snippet;
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
13
26
|
declare const Tabs: import("svelte").Component<TabsProps, {}, "status" | "current">;
|
|
14
27
|
type Tabs = ReturnType<typeof Tabs>;
|
|
15
28
|
export default Tabs;
|
|
@@ -1,22 +1,47 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
default value: `<value>`
|
|
4
|
+
```ts
|
|
5
|
+
interface TextFieldProps {
|
|
6
|
+
label?: string;
|
|
7
|
+
extra?: string;
|
|
8
|
+
aux?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
9
|
+
left?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
10
|
+
right?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
11
|
+
bottom?: string;
|
|
12
|
+
descFirst?: boolean; // <false>
|
|
13
|
+
value?: string; // bindable
|
|
14
|
+
type?: "text" | "area" | "email" | "password" | "search" | "tel" | "url" | "number"; // bindable <"text">
|
|
15
|
+
options?: SvelteSet<string> | Set<string>;
|
|
16
|
+
validations?: TextFieldValidation[];
|
|
17
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
18
|
+
style?: SVSStyle;
|
|
19
|
+
attributes?: HTMLInputAttributes | HTMLTextareaAttributes;
|
|
20
|
+
action?: Action;
|
|
21
|
+
element?: HTMLInputElement | HTMLTextAreaElement; // bindable
|
|
22
|
+
}
|
|
23
|
+
type TextFieldValidation = (value: string, validity: ValidityState) => string;
|
|
24
|
+
```
|
|
25
|
+
-->
|
|
1
26
|
<script module lang="ts">
|
|
2
|
-
export
|
|
3
|
-
label?: string
|
|
4
|
-
extra?: string
|
|
5
|
-
aux?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]
|
|
6
|
-
left?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]
|
|
7
|
-
right?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]
|
|
8
|
-
bottom?: string
|
|
9
|
-
descFirst?: boolean
|
|
10
|
-
value?: string
|
|
11
|
-
type?: "text" | "area" | "email" | "password" | "search" | "tel" | "url" | "number"
|
|
12
|
-
options?: SvelteSet<string> | Set<string
|
|
13
|
-
validations?: TextFieldValidation[]
|
|
14
|
-
status?: string
|
|
15
|
-
style?: SVSStyle
|
|
16
|
-
attributes?: HTMLInputAttributes | HTMLTextareaAttributes
|
|
17
|
-
action?: Action
|
|
18
|
-
element?: HTMLInputElement | HTMLTextAreaElement
|
|
19
|
-
}
|
|
27
|
+
export interface TextFieldProps {
|
|
28
|
+
label?: string;
|
|
29
|
+
extra?: string;
|
|
30
|
+
aux?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
31
|
+
left?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
32
|
+
right?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
33
|
+
bottom?: string;
|
|
34
|
+
descFirst?: boolean; // <false>
|
|
35
|
+
value?: string; // bindable
|
|
36
|
+
type?: "text" | "area" | "email" | "password" | "search" | "tel" | "url" | "number"; // bindable <"text">
|
|
37
|
+
options?: SvelteSet<string> | Set<string>;
|
|
38
|
+
validations?: TextFieldValidation[];
|
|
39
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
40
|
+
style?: SVSStyle;
|
|
41
|
+
attributes?: HTMLInputAttributes | HTMLTextareaAttributes;
|
|
42
|
+
action?: Action;
|
|
43
|
+
element?: HTMLInputElement | HTMLTextAreaElement; // bindable
|
|
44
|
+
}
|
|
20
45
|
export type TextFieldReqdProps = never;
|
|
21
46
|
export type TextFieldBindProps = "value" | "type" | "status" | "element";
|
|
22
47
|
export type TextFieldValidation = (value: string, validity: ValidityState) => string;
|
|
@@ -27,14 +52,14 @@
|
|
|
27
52
|
import { type Action } from "svelte/action";
|
|
28
53
|
import { type SvelteSet } from "svelte/reactivity";
|
|
29
54
|
import { type HTMLInputAttributes, type HTMLTextareaAttributes } from "svelte/elements";
|
|
30
|
-
import { type SVSStyle, STATE,
|
|
55
|
+
import { type SVSStyle, STATE, PARTS, elemId, fnClass, isNeutral, omit } from "./core";
|
|
31
56
|
</script>
|
|
32
57
|
|
|
33
58
|
<script lang="ts">
|
|
34
59
|
let { label, extra, aux, left, right, bottom, descFirst = false, value = $bindable(""), type = $bindable("text"), options, validations = [], status = $bindable(""), style, attributes, action, element = $bindable() }: TextFieldProps = $props();
|
|
35
60
|
|
|
36
61
|
// *** Initialize *** //
|
|
37
|
-
if (!status) status = STATE.
|
|
62
|
+
if (!status) status = STATE.NEUTRAL;
|
|
38
63
|
const cls = fnClass(preset, style);
|
|
39
64
|
const id = attributes?.id ? attributes.id : elemId.get(label?.trim());
|
|
40
65
|
const idLabel = elemId.get(label?.trim());
|
|
@@ -45,7 +70,7 @@
|
|
|
45
70
|
let message = $state(bottom);
|
|
46
71
|
|
|
47
72
|
// *** Status *** //
|
|
48
|
-
let neutral = isNeutral(status) ? status : STATE.
|
|
73
|
+
let neutral = isNeutral(status) ? status : STATE.NEUTRAL;
|
|
49
74
|
$effect(() => { neutral = isNeutral(status) ? status : neutral });
|
|
50
75
|
let live = $derived(status === STATE.INACTIVE ? "alert" : "status");
|
|
51
76
|
let invalid = $derived(status === STATE.INACTIVE ? true : undefined);
|
|
@@ -90,30 +115,30 @@
|
|
|
90
115
|
|
|
91
116
|
<!---------------------------------------->
|
|
92
117
|
|
|
93
|
-
<div class={cls(
|
|
118
|
+
<div class={cls(PARTS.WHOLE, status)} role="group" aria-labelledby={idLabel}>
|
|
94
119
|
{#if aux}
|
|
95
|
-
<div class={cls(
|
|
120
|
+
<div class={cls(PARTS.TOP, status)}>
|
|
96
121
|
{@render lbl()}
|
|
97
|
-
<span class={cls(
|
|
122
|
+
<span class={cls(PARTS.AUX, status)}>{@render aux(status, value, element)}</span>
|
|
98
123
|
</div>
|
|
99
124
|
{:else}
|
|
100
125
|
{@render lbl()}
|
|
101
126
|
{/if}
|
|
102
127
|
{@render desc(descFirst)}
|
|
103
|
-
<div class={cls(
|
|
104
|
-
{@render side(
|
|
128
|
+
<div class={cls(PARTS.MIDDLE, status)}>
|
|
129
|
+
{@render side(PARTS.LEFT, left)}
|
|
105
130
|
{@render main()}
|
|
106
|
-
{@render side(
|
|
131
|
+
{@render side(PARTS.RIGHT, right)}
|
|
107
132
|
</div>
|
|
108
133
|
{@render desc(!descFirst)}
|
|
109
134
|
</div>
|
|
110
135
|
|
|
111
136
|
{#snippet lbl()}
|
|
112
137
|
{#if label?.trim()}
|
|
113
|
-
<label class={cls(
|
|
138
|
+
<label class={cls(PARTS.LABEL, status)} for={id} id={idLabel}>
|
|
114
139
|
{label}
|
|
115
140
|
{#if extra?.trim()}
|
|
116
|
-
<span class={cls(
|
|
141
|
+
<span class={cls(PARTS.EXTRA, status)}>{extra}</span>
|
|
117
142
|
{/if}
|
|
118
143
|
</label>
|
|
119
144
|
{/if}
|
|
@@ -124,7 +149,7 @@
|
|
|
124
149
|
{/if}
|
|
125
150
|
{/snippet}
|
|
126
151
|
{#snippet main()}
|
|
127
|
-
{@const c = cls(
|
|
152
|
+
{@const c = cls(PARTS.MAIN, status)}
|
|
128
153
|
{#if type === "area"}
|
|
129
154
|
{#if action}
|
|
130
155
|
<textarea bind:value bind:this={element} class={c} {id} {onchange} {oninvalid} {...attrs} aria-describedby={idDesc} aria-invalid={invalid} aria-errormessage={idMsg} use:action></textarea>
|
|
@@ -148,6 +173,6 @@
|
|
|
148
173
|
{/snippet}
|
|
149
174
|
{#snippet desc(show: boolean)}
|
|
150
175
|
{#if show && message?.trim()}
|
|
151
|
-
<div class={cls(
|
|
176
|
+
<div class={cls(PARTS.BOTTOM, status)} id={idDesc ?? idErr} role={live}>{message}</div>
|
|
152
177
|
{/if}
|
|
153
178
|
{/snippet}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface TextFieldProps {
|
|
2
2
|
label?: string;
|
|
3
3
|
extra?: string;
|
|
4
4
|
aux?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>;
|
|
@@ -15,7 +15,7 @@ export type TextFieldProps = {
|
|
|
15
15
|
attributes?: HTMLInputAttributes | HTMLTextareaAttributes;
|
|
16
16
|
action?: Action;
|
|
17
17
|
element?: HTMLInputElement | HTMLTextAreaElement;
|
|
18
|
-
}
|
|
18
|
+
}
|
|
19
19
|
export type TextFieldReqdProps = never;
|
|
20
20
|
export type TextFieldBindProps = "value" | "type" | "status" | "element";
|
|
21
21
|
export type TextFieldValidation = (value: string, validity: ValidityState) => string;
|
|
@@ -24,6 +24,30 @@ import { type Action } from "svelte/action";
|
|
|
24
24
|
import { type SvelteSet } from "svelte/reactivity";
|
|
25
25
|
import { type HTMLInputAttributes, type HTMLTextareaAttributes } from "svelte/elements";
|
|
26
26
|
import { type SVSStyle } from "./core";
|
|
27
|
+
/**
|
|
28
|
+
* default value: `<value>`
|
|
29
|
+
* ```ts
|
|
30
|
+
* interface TextFieldProps {
|
|
31
|
+
* label?: string;
|
|
32
|
+
* extra?: string;
|
|
33
|
+
* aux?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
34
|
+
* left?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
35
|
+
* right?: Snippet<[string, string, HTMLInputElement | HTMLTextAreaElement | undefined]>; // Snippet<[status,value,element]>
|
|
36
|
+
* bottom?: string;
|
|
37
|
+
* descFirst?: boolean; // <false>
|
|
38
|
+
* value?: string; // bindable
|
|
39
|
+
* type?: "text" | "area" | "email" | "password" | "search" | "tel" | "url" | "number"; // bindable <"text">
|
|
40
|
+
* options?: SvelteSet<string> | Set<string>;
|
|
41
|
+
* validations?: TextFieldValidation[];
|
|
42
|
+
* status?: string; // bindable <STATE.NEUTRAL>
|
|
43
|
+
* style?: SVSStyle;
|
|
44
|
+
* attributes?: HTMLInputAttributes | HTMLTextareaAttributes;
|
|
45
|
+
* action?: Action;
|
|
46
|
+
* element?: HTMLInputElement | HTMLTextAreaElement; // bindable
|
|
47
|
+
* }
|
|
48
|
+
* type TextFieldValidation = (value: string, validity: ValidityState) => string;
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
27
51
|
declare const TextField: import("svelte").Component<TextFieldProps, {}, "type" | "value" | "status" | "element">;
|
|
28
52
|
type TextField = ReturnType<typeof TextField>;
|
|
29
53
|
export default TextField;
|
package/_svseeds/_Toggle.svelte
CHANGED
|
@@ -1,16 +1,36 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
default value: `<value>`
|
|
4
|
+
```ts
|
|
5
|
+
interface ToggleProps {
|
|
6
|
+
main?: Snippet<[string, boolean, HTMLButtonElement | undefined]>; // Snippet<[status,value,element]>
|
|
7
|
+
left?: Snippet<[string, boolean, HTMLButtonElement | undefined]>; // Snippet<[status,value,element]>
|
|
8
|
+
right?: Snippet<[string, boolean, HTMLButtonElement | undefined]>; // Snippet<[status,value,element]>
|
|
9
|
+
value?: boolean; // bindable <false>
|
|
10
|
+
type?: "button" | "switch"; // <"button">
|
|
11
|
+
ariaLabel?: string;
|
|
12
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
13
|
+
style?: SVSStyle;
|
|
14
|
+
attributes?: HTMLButtonAttributes;
|
|
15
|
+
action?: Action;
|
|
16
|
+
element?: HTMLButtonElement; // bindable
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
-->
|
|
1
20
|
<script module lang="ts">
|
|
2
|
-
export
|
|
3
|
-
main?: Snippet<[string, boolean, HTMLButtonElement | undefined]
|
|
4
|
-
left?: Snippet<[string, boolean, HTMLButtonElement | undefined]
|
|
5
|
-
right?: Snippet<[string, boolean, HTMLButtonElement | undefined]
|
|
6
|
-
value?: boolean
|
|
7
|
-
type?: "button" | "switch"
|
|
8
|
-
|
|
9
|
-
|
|
21
|
+
export interface ToggleProps {
|
|
22
|
+
main?: Snippet<[string, boolean, HTMLButtonElement | undefined]>; // Snippet<[status,value,element]>
|
|
23
|
+
left?: Snippet<[string, boolean, HTMLButtonElement | undefined]>; // Snippet<[status,value,element]>
|
|
24
|
+
right?: Snippet<[string, boolean, HTMLButtonElement | undefined]>; // Snippet<[status,value,element]>
|
|
25
|
+
value?: boolean; // bindable <false>
|
|
26
|
+
type?: "button" | "switch"; // <"button">
|
|
27
|
+
ariaLabel?: string;
|
|
28
|
+
status?: string; // bindable <STATE.NEUTRAL>
|
|
29
|
+
style?: SVSStyle;
|
|
10
30
|
attributes?: HTMLButtonAttributes;
|
|
11
|
-
action?: Action
|
|
12
|
-
element?: HTMLButtonElement
|
|
13
|
-
}
|
|
31
|
+
action?: Action;
|
|
32
|
+
element?: HTMLButtonElement; // bindable
|
|
33
|
+
}
|
|
14
34
|
export type ToggleReqdProps = never;
|
|
15
35
|
export type ToggleBindProps = "value" | "status" | "element";
|
|
16
36
|
|
|
@@ -20,17 +40,17 @@
|
|
|
20
40
|
import { type Snippet, untrack } from "svelte";
|
|
21
41
|
import { type Action } from "svelte/action";
|
|
22
42
|
import { type HTMLButtonAttributes } from "svelte/elements";
|
|
23
|
-
import { type SVSStyle, STATE,
|
|
43
|
+
import { type SVSStyle, STATE, PARTS, fnClass, isNeutral, omit } from "./core";
|
|
24
44
|
</script>
|
|
25
45
|
|
|
26
46
|
<script lang="ts">
|
|
27
|
-
let { main, left, right, value = $bindable(false), type = "button", status = $bindable(""), style, attributes, action, element = $bindable() }: ToggleProps = $props();
|
|
47
|
+
let { main, left, right, value = $bindable(false), type = "button", ariaLabel, status = $bindable(""), style, attributes, action, element = $bindable() }: ToggleProps = $props();
|
|
28
48
|
|
|
29
49
|
// *** Initialize *** //
|
|
30
|
-
if (!status) status = STATE.
|
|
50
|
+
if (!status) status = STATE.NEUTRAL;
|
|
31
51
|
const cls = fnClass(preset, style);
|
|
32
|
-
const attrs = omit(attributes, "class", "
|
|
33
|
-
let neutral = isNeutral(status) ? status : STATE.
|
|
52
|
+
const attrs = omit(attributes, "class", "type", "role", "aria-checked", "aria-pressed", "onclick");
|
|
53
|
+
let neutral = isNeutral(status) ? status : STATE.NEUTRAL;
|
|
34
54
|
|
|
35
55
|
// *** Bind Handlers *** //
|
|
36
56
|
$effect(() => { neutral = isNeutral(status) ? status : neutral });
|
|
@@ -51,10 +71,10 @@
|
|
|
51
71
|
<!---------------------------------------->
|
|
52
72
|
|
|
53
73
|
{#if left || right}
|
|
54
|
-
<span class={cls(
|
|
55
|
-
{@render side(
|
|
74
|
+
<span class={cls(PARTS.WHOLE, status)} role="group">
|
|
75
|
+
{@render side(PARTS.LEFT, left)}
|
|
56
76
|
{@render button(type)}
|
|
57
|
-
{@render side(
|
|
77
|
+
{@render side(PARTS.RIGHT, right)}
|
|
58
78
|
</span>
|
|
59
79
|
{:else}
|
|
60
80
|
{@render button(type)}
|
|
@@ -71,32 +91,32 @@
|
|
|
71
91
|
{/if}
|
|
72
92
|
{/snippet}
|
|
73
93
|
{#snippet button(role: string)}
|
|
74
|
-
{@const c = cls(
|
|
94
|
+
{@const c = cls(PARTS.MAIN, status)}
|
|
75
95
|
{#if role === "button"}
|
|
76
96
|
{#if action}
|
|
77
|
-
<button bind:this={element} class={c} type="button" aria-pressed={value} {onclick} {...attrs} use:action>
|
|
97
|
+
<button bind:this={element} class={c} type="button" aria-pressed={value} aria-label={ariaLabel} {onclick} {...attrs} use:action>
|
|
78
98
|
{@render contents()}
|
|
79
99
|
</button>
|
|
80
100
|
{:else}
|
|
81
|
-
<button bind:this={element} class={c} type="button" aria-pressed={value} {onclick} {...attrs}>
|
|
101
|
+
<button bind:this={element} class={c} type="button" aria-pressed={value} aria-label={ariaLabel} {onclick} {...attrs}>
|
|
82
102
|
{@render contents()}
|
|
83
103
|
</button>
|
|
84
104
|
{/if}
|
|
85
105
|
{:else}
|
|
86
106
|
{@const style = "position: relative;"}
|
|
87
107
|
{#if action}
|
|
88
|
-
<button bind:this={element} class={c} {style} type="button" {role} aria-checked={value} {onclick} {...attrs} use:action>
|
|
108
|
+
<button bind:this={element} class={c} {style} type="button" {role} aria-checked={value} aria-label={ariaLabel} {onclick} {...attrs} use:action>
|
|
89
109
|
{@render thumb()}
|
|
90
110
|
</button>
|
|
91
111
|
{:else}
|
|
92
|
-
<button bind:this={element} class={c} {style} type="button" {role} aria-checked={value} {onclick} {...attrs}>
|
|
112
|
+
<button bind:this={element} class={c} {style} type="button" {role} aria-checked={value} aria-label={ariaLabel} {onclick} {...attrs}>
|
|
93
113
|
{@render thumb()}
|
|
94
114
|
</button>
|
|
95
115
|
{/if}
|
|
96
116
|
{/if}
|
|
97
117
|
{/snippet}
|
|
98
118
|
{#snippet thumb()}
|
|
99
|
-
<span class={cls(
|
|
119
|
+
<span class={cls(PARTS.AUX, status)} style="position: absolute;">
|
|
100
120
|
{@render contents()}
|
|
101
121
|
</span>
|
|
102
122
|
{/snippet}
|