svelte-multiselect 11.2.4 → 11.3.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/dist/CircleSpinner.svelte.d.ts +3 -3
- package/dist/CmdPalette.svelte +8 -5
- package/dist/CmdPalette.svelte.d.ts +61 -16
- package/dist/CodeExample.svelte +10 -3
- package/dist/CodeExample.svelte.d.ts +6 -3
- package/dist/CopyButton.svelte +1 -1
- package/dist/CopyButton.svelte.d.ts +3 -3
- package/dist/FileDetails.svelte +3 -3
- package/dist/FileDetails.svelte.d.ts +6 -3
- package/dist/GitHubCorner.svelte.d.ts +3 -3
- package/dist/Icon.svelte.d.ts +3 -3
- package/dist/MultiSelect.svelte +6 -4
- package/dist/MultiSelect.svelte.d.ts +7 -7
- package/dist/Nav.svelte +447 -0
- package/dist/Nav.svelte.d.ts +42 -0
- package/dist/PrevNext.svelte +3 -3
- package/dist/PrevNext.svelte.d.ts +51 -31
- package/dist/Toggle.svelte +2 -7
- package/dist/Toggle.svelte.d.ts +4 -9
- package/dist/Wiggle.svelte.d.ts +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +15 -15
- package/readme.md +0 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
type $$ComponentProps = {
|
|
2
2
|
color?: string;
|
|
3
3
|
duration?: string;
|
|
4
4
|
size?: string;
|
|
5
|
-
}
|
|
6
|
-
declare const CircleSpinner: import("svelte").Component
|
|
5
|
+
};
|
|
6
|
+
declare const CircleSpinner: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
7
|
type CircleSpinner = ReturnType<typeof CircleSpinner>;
|
|
8
8
|
export default CircleSpinner;
|
package/dist/CmdPalette.svelte
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
generics="Action extends { label: string; action: (label: string) => void } & Record<string, unknown> = { label: string; action: (label: string) => void }"
|
|
4
|
+
>import { fade } from 'svelte/transition';
|
|
2
5
|
import MultiSelect from './MultiSelect.svelte';
|
|
3
|
-
let { actions, triggers = [`k`], close_keys = [`Escape`], fade_duration = 200, dialog_style = ``, open = $bindable(false), dialog = $bindable(null), input = $bindable(null), placeholder = `Filter actions...`, ...rest } = $props();
|
|
6
|
+
let { actions, triggers = [`k`], close_keys = [`Escape`], fade_duration = 200, dialog_style = ``, open = $bindable(false), dialog = $bindable(null), input = $bindable(null), placeholder = `Filter actions...`, dialog_props, ...rest } = $props();
|
|
4
7
|
$effect(() => {
|
|
5
8
|
if (open && input && document.activeElement !== input)
|
|
6
9
|
input.focus();
|
|
@@ -22,10 +25,9 @@ function close_if_outside(event) {
|
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
function trigger_action_and_close({ option }) {
|
|
25
|
-
|
|
26
|
-
if (!action)
|
|
28
|
+
if (!option?.action)
|
|
27
29
|
return;
|
|
28
|
-
action(label);
|
|
30
|
+
option.action(option.label);
|
|
29
31
|
open = false;
|
|
30
32
|
}
|
|
31
33
|
</script>
|
|
@@ -38,6 +40,7 @@ function trigger_action_and_close({ option }) {
|
|
|
38
40
|
bind:this={dialog}
|
|
39
41
|
transition:fade={{ duration: fade_duration }}
|
|
40
42
|
style={dialog_style}
|
|
43
|
+
{...dialog_props}
|
|
41
44
|
>
|
|
42
45
|
<MultiSelect
|
|
43
46
|
options={actions}
|
|
@@ -1,21 +1,66 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
import type { ObjectOption } from './types';
|
|
4
|
-
interface Action extends ObjectOption {
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
declare function $$render<Action extends {
|
|
5
3
|
label: string;
|
|
6
4
|
action: (label: string) => void;
|
|
5
|
+
} & Record<string, unknown> = {
|
|
6
|
+
label: string;
|
|
7
|
+
action: (label: string) => void;
|
|
8
|
+
}>(): {
|
|
9
|
+
props: Omit<import("./types").MultiSelectProps<Action>, "options"> & {
|
|
10
|
+
actions: Action[];
|
|
11
|
+
triggers?: string[];
|
|
12
|
+
close_keys?: string[];
|
|
13
|
+
fade_duration?: number;
|
|
14
|
+
dialog_style?: string;
|
|
15
|
+
open?: boolean;
|
|
16
|
+
dialog?: HTMLDialogElement | null;
|
|
17
|
+
input?: HTMLInputElement | null;
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
dialog_props?: HTMLAttributes<HTMLDialogElement>;
|
|
20
|
+
};
|
|
21
|
+
exports: {};
|
|
22
|
+
bindings: "dialog" | "input" | "open";
|
|
23
|
+
slots: {};
|
|
24
|
+
events: {};
|
|
25
|
+
};
|
|
26
|
+
declare class __sveltets_Render<Action extends {
|
|
27
|
+
label: string;
|
|
28
|
+
action: (label: string) => void;
|
|
29
|
+
} & Record<string, unknown> = {
|
|
30
|
+
label: string;
|
|
31
|
+
action: (label: string) => void;
|
|
32
|
+
}> {
|
|
33
|
+
props(): ReturnType<typeof $$render<Action>>['props'];
|
|
34
|
+
events(): ReturnType<typeof $$render<Action>>['events'];
|
|
35
|
+
slots(): ReturnType<typeof $$render<Action>>['slots'];
|
|
36
|
+
bindings(): "dialog" | "input" | "open";
|
|
37
|
+
exports(): {};
|
|
7
38
|
}
|
|
8
|
-
interface
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
39
|
+
interface $$IsomorphicComponent {
|
|
40
|
+
new <Action extends {
|
|
41
|
+
label: string;
|
|
42
|
+
action: (label: string) => void;
|
|
43
|
+
} & Record<string, unknown> = {
|
|
44
|
+
label: string;
|
|
45
|
+
action: (label: string) => void;
|
|
46
|
+
}>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Action>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Action>['props']>, ReturnType<__sveltets_Render<Action>['events']>, ReturnType<__sveltets_Render<Action>['slots']>> & {
|
|
47
|
+
$$bindings?: ReturnType<__sveltets_Render<Action>['bindings']>;
|
|
48
|
+
} & ReturnType<__sveltets_Render<Action>['exports']>;
|
|
49
|
+
<Action extends {
|
|
50
|
+
label: string;
|
|
51
|
+
action: (label: string) => void;
|
|
52
|
+
} & Record<string, unknown> = {
|
|
53
|
+
label: string;
|
|
54
|
+
action: (label: string) => void;
|
|
55
|
+
}>(internal: unknown, props: ReturnType<__sveltets_Render<Action>['props']> & {}): ReturnType<__sveltets_Render<Action>['exports']>;
|
|
56
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
18
57
|
}
|
|
19
|
-
declare const CmdPalette:
|
|
20
|
-
type CmdPalette
|
|
58
|
+
declare const CmdPalette: $$IsomorphicComponent;
|
|
59
|
+
type CmdPalette<Action extends {
|
|
60
|
+
label: string;
|
|
61
|
+
action: (label: string) => void;
|
|
62
|
+
} & Record<string, unknown> = {
|
|
63
|
+
label: string;
|
|
64
|
+
action: (label: string) => void;
|
|
65
|
+
}> = InstanceType<typeof CmdPalette<Action>>;
|
|
21
66
|
export default CmdPalette;
|
package/dist/CodeExample.svelte
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">// see svelte.config.js where this component is passed to mdsvexamples
|
|
2
2
|
import { Icon } from './';
|
|
3
|
-
let { src = ``, meta = {}, open = $bindable(!meta.collapsible), title, example, code,
|
|
3
|
+
let { src = ``, meta = {}, open = $bindable(!meta.collapsible), title, example, code, link_props, // Applied after computed attributes (href, title, etc.), allowing override
|
|
4
|
+
button_props, } = $props();
|
|
4
5
|
let { id, collapsible, code_above, repl, github, repo, file } = $derived(meta);
|
|
5
6
|
const links = { target: `_blank`, rel: `noreferrer` };
|
|
6
7
|
</script>
|
|
@@ -17,13 +18,19 @@ const links = { target: `_blank`, rel: `noreferrer` };
|
|
|
17
18
|
{ cond, href, icon }
|
|
18
19
|
(icon)
|
|
19
20
|
}
|
|
20
|
-
<a
|
|
21
|
+
<a
|
|
22
|
+
{href}
|
|
23
|
+
{...links}
|
|
24
|
+
title={icon}
|
|
25
|
+
style:display={cond ? `inline-block` : `none`}
|
|
26
|
+
{...link_props}
|
|
27
|
+
>
|
|
21
28
|
<Icon {icon} />
|
|
22
29
|
</a>
|
|
23
30
|
{/each}
|
|
24
31
|
{#if collapsible}
|
|
25
32
|
{@render title?.()}
|
|
26
|
-
<button onclick={() => (open = !open)}>
|
|
33
|
+
<button onclick={() => (open = !open)} {...button_props}>
|
|
27
34
|
<Icon icon={open ? `Collapse` : `Expand`} />
|
|
28
35
|
{open ? `Close` : `View code`}
|
|
29
36
|
</button>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
type $$ComponentProps = {
|
|
3
4
|
src?: string;
|
|
4
5
|
meta?: {
|
|
5
6
|
collapsible?: boolean;
|
|
@@ -16,7 +17,9 @@ interface Props {
|
|
|
16
17
|
title?: Snippet<[]>;
|
|
17
18
|
example?: Snippet<[]>;
|
|
18
19
|
code?: Snippet<[]>;
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
link_props?: HTMLAttributes<HTMLAnchorElement>;
|
|
21
|
+
button_props?: HTMLAttributes<HTMLButtonElement>;
|
|
22
|
+
};
|
|
23
|
+
declare const CodeExample: import("svelte").Component<$$ComponentProps, {}, "open">;
|
|
21
24
|
type CodeExample = ReturnType<typeof CodeExample>;
|
|
22
25
|
export default CodeExample;
|
package/dist/CopyButton.svelte
CHANGED
|
@@ -9,7 +9,7 @@ $effect(() => {
|
|
|
9
9
|
if (!global && !global_selector)
|
|
10
10
|
return;
|
|
11
11
|
const apply_copy_buttons = () => {
|
|
12
|
-
const btn_style = `position: absolute; top:
|
|
12
|
+
const btn_style = `position: absolute; top: 6pt; right: 6pt; ${rest.style ?? ``}`;
|
|
13
13
|
const skip_sel = skip_selector ?? as;
|
|
14
14
|
for (const code of document.querySelectorAll(global_selector ?? `pre > code`)) {
|
|
15
15
|
const pre = code.parentElement;
|
|
@@ -3,7 +3,7 @@ import type { Snippet } from 'svelte';
|
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
import type { IconName } from './icons';
|
|
5
5
|
type State = `ready` | `success` | `error`;
|
|
6
|
-
|
|
6
|
+
type $$ComponentProps = Omit<HTMLAttributes<HTMLButtonElement>, `children`> & {
|
|
7
7
|
content?: string;
|
|
8
8
|
state?: State;
|
|
9
9
|
global_selector?: string | null;
|
|
@@ -19,7 +19,7 @@ interface Props extends Omit<HTMLAttributes<HTMLButtonElement>, `children`> {
|
|
|
19
19
|
icon: IconName;
|
|
20
20
|
text: string;
|
|
21
21
|
}]>;
|
|
22
|
-
}
|
|
23
|
-
declare const CopyButton: import("svelte").Component
|
|
22
|
+
};
|
|
23
|
+
declare const CopyButton: import("svelte").Component<$$ComponentProps, {}, "state">;
|
|
24
24
|
type CopyButton = ReturnType<typeof CopyButton>;
|
|
25
25
|
export default CopyButton;
|
package/dist/FileDetails.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script lang="ts">let { files = $bindable([]), toggle_all_btn_title = `Toggle all`, default_lang = `typescript`, as = `ol`, style = null, title_snippet, } = $props();
|
|
1
|
+
<script lang="ts">let { files = $bindable([]), toggle_all_btn_title = `Toggle all`, default_lang = `typescript`, as = `ol`, style = null, title_snippet, button_props, details_props, } = $props();
|
|
2
2
|
function toggle_all() {
|
|
3
3
|
const any_open = files.some((file) => file.node?.open);
|
|
4
4
|
for (const file of files) {
|
|
@@ -11,7 +11,7 @@ export {};
|
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
{#if files?.length > 1}
|
|
14
|
-
<button onclick={toggle_all} title={toggle_all_btn_title}>
|
|
14
|
+
<button onclick={toggle_all} title={toggle_all_btn_title} {...button_props}>
|
|
15
15
|
{files.some((file) => file.node?.open) ? `Close` : `Open`} all
|
|
16
16
|
</button>
|
|
17
17
|
{/if}
|
|
@@ -21,7 +21,7 @@ export {};
|
|
|
21
21
|
{@const { title, content, language = default_lang } = file ?? {}}
|
|
22
22
|
<li>
|
|
23
23
|
<!-- https://github.com/sveltejs/svelte/issues/12721#issuecomment-2269544690 -->
|
|
24
|
-
<details bind:this={file.node}>
|
|
24
|
+
<details bind:this={file.node} {...details_props}>
|
|
25
25
|
{#if title || title_snippet}
|
|
26
26
|
<summary>
|
|
27
27
|
{#if title_snippet}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes, HTMLDetailsAttributes } from 'svelte/elements';
|
|
2
3
|
type File = {
|
|
3
4
|
title: string;
|
|
4
5
|
content: string;
|
|
5
6
|
language?: string;
|
|
6
7
|
node?: HTMLDetailsElement | null;
|
|
7
8
|
};
|
|
8
|
-
|
|
9
|
+
type $$ComponentProps = {
|
|
9
10
|
files?: File[];
|
|
10
11
|
toggle_all_btn_title?: string;
|
|
11
12
|
default_lang?: string;
|
|
@@ -14,7 +15,9 @@ interface Props {
|
|
|
14
15
|
title_snippet?: Snippet<[{
|
|
15
16
|
idx: number;
|
|
16
17
|
} & File]>;
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
button_props?: HTMLAttributes<HTMLButtonElement>;
|
|
19
|
+
details_props?: HTMLDetailsAttributes;
|
|
20
|
+
};
|
|
21
|
+
declare const FileDetails: import("svelte").Component<$$ComponentProps, {}, "files">;
|
|
19
22
|
type FileDetails = ReturnType<typeof FileDetails>;
|
|
20
23
|
export default FileDetails;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
type $$ComponentProps = {
|
|
2
2
|
href: string;
|
|
3
3
|
title?: string;
|
|
4
4
|
aria_label?: string;
|
|
@@ -7,7 +7,7 @@ interface Props {
|
|
|
7
7
|
fill?: string | null;
|
|
8
8
|
corner?: `top-left` | `top-right` | `bottom-left` | `bottom-right`;
|
|
9
9
|
style?: string;
|
|
10
|
-
}
|
|
11
|
-
declare const GitHubCorner: import("svelte").Component
|
|
10
|
+
};
|
|
11
|
+
declare const GitHubCorner: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
12
|
type GitHubCorner = ReturnType<typeof GitHubCorner>;
|
|
13
13
|
export default GitHubCorner;
|
package/dist/Icon.svelte.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
2
|
import { type IconName } from './icons';
|
|
3
|
-
|
|
3
|
+
type $$ComponentProps = HTMLAttributes<SVGSVGElement> & {
|
|
4
4
|
icon: IconName;
|
|
5
|
-
}
|
|
6
|
-
declare const Icon: import("svelte").Component
|
|
5
|
+
};
|
|
6
|
+
declare const Icon: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
7
|
type Icon = ReturnType<typeof Icon>;
|
|
8
8
|
export default Icon;
|
package/dist/MultiSelect.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script lang="ts">import { tick } from 'svelte';
|
|
1
|
+
<script lang="ts" generics="Option extends import('./types').Option">import { tick } from 'svelte';
|
|
2
2
|
import { flip } from 'svelte/animate';
|
|
3
3
|
import { highlight_matches } from './attachments';
|
|
4
4
|
import CircleSpinner from './CircleSpinner.svelte';
|
|
@@ -12,9 +12,11 @@ let { activeIndex = $bindable(null), activeOption = $bindable(null), createOptio
|
|
|
12
12
|
return fuzzy
|
|
13
13
|
? fuzzy_match(searchText, label)
|
|
14
14
|
: label.toLowerCase().includes(searchText.toLowerCase());
|
|
15
|
-
}, fuzzy = true, closeDropdownOnSelect = `if-mobile`, form_input = $bindable(null), highlightMatches = true, id = null, input = $bindable(null), inputClass = ``, inputStyle = null, inputmode = null, invalid = $bindable(false), liActiveOptionClass = ``, liActiveUserMsgClass = ``, liOptionClass = ``, liOptionStyle = null, liSelectedClass = ``, liSelectedStyle = null, liUserMsgClass = ``, loading = false, matchingOptions = $bindable([]), maxOptions = undefined, maxSelect = null, maxSelectMsg = (current, max) => (max > 1 ? `${current}/${max}` : ``), maxSelectMsgClass = ``, name = null, noMatchingOptionsMsg = `No matching options`, open = $bindable(false), options = $bindable(), outerDiv = $bindable(null), outerDivClass = ``, parseLabelsAsHtml = false, pattern = null, placeholder = null, removeAllTitle = `Remove all`, removeBtnTitle = `Remove`, minSelect = null, required = false, resetFilterOnAdd = true, searchText = $bindable(``), selected = $bindable(
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
}, fuzzy = true, closeDropdownOnSelect = `if-mobile`, form_input = $bindable(null), highlightMatches = true, id = null, input = $bindable(null), inputClass = ``, inputStyle = null, inputmode = null, invalid = $bindable(false), liActiveOptionClass = ``, liActiveUserMsgClass = ``, liOptionClass = ``, liOptionStyle = null, liSelectedClass = ``, liSelectedStyle = null, liUserMsgClass = ``, loading = false, matchingOptions = $bindable([]), maxOptions = undefined, maxSelect = null, maxSelectMsg = (current, max) => (max > 1 ? `${current}/${max}` : ``), maxSelectMsgClass = ``, name = null, noMatchingOptionsMsg = `No matching options`, open = $bindable(false), options = $bindable(), outerDiv = $bindable(null), outerDivClass = ``, parseLabelsAsHtml = false, pattern = null, placeholder = null, removeAllTitle = `Remove all`, removeBtnTitle = `Remove`, minSelect = null, required = false, resetFilterOnAdd = true, searchText = $bindable(``), value = $bindable(null), selected = $bindable(value !== null && value !== undefined
|
|
16
|
+
? (Array.isArray(value) ? value : [value])
|
|
17
|
+
: (options
|
|
18
|
+
?.filter((opt) => opt instanceof Object && opt?.preselected)
|
|
19
|
+
.slice(0, maxSelect ?? undefined) ?? [])), sortSelected = false, selectedOptionsDraggable = !sortSelected, style = null, ulOptionsClass = ``, ulSelectedClass = ``, ulSelectedStyle = null, ulOptionsStyle = null, expandIcon, selectedItem, children, removeIcon, afterInput, spinner, disabledIcon, option, userMsg, onblur, onclick, onfocus, onkeydown, onkeyup, onmousedown, onmouseenter, onmouseleave, ontouchcancel, ontouchend, ontouchmove, ontouchstart, onadd, oncreate, onremove, onremoveAll, onchange, onopen, onclose, portal: portal_params = {}, ...rest } = $props();
|
|
18
20
|
$effect.pre(() => {
|
|
19
21
|
// if maxSelect=1, value is the single item in selected (or null if selected is empty)
|
|
20
22
|
// this solves both https://github.com/janosh/svelte-multiselect/issues/86 and
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { MultiSelectProps
|
|
2
|
-
declare function $$render<Option extends
|
|
3
|
-
props: MultiSelectProps
|
|
1
|
+
import type { MultiSelectProps } from './types';
|
|
2
|
+
declare function $$render<Option extends import('./types').Option>(): {
|
|
3
|
+
props: MultiSelectProps<Option>;
|
|
4
4
|
exports: {};
|
|
5
5
|
bindings: "input" | "invalid" | "value" | "selected" | "open" | "activeIndex" | "activeOption" | "form_input" | "matchingOptions" | "options" | "outerDiv" | "searchText";
|
|
6
6
|
slots: {};
|
|
7
7
|
events: {};
|
|
8
8
|
};
|
|
9
|
-
declare class __sveltets_Render<Option extends
|
|
9
|
+
declare class __sveltets_Render<Option extends import('./types').Option> {
|
|
10
10
|
props(): ReturnType<typeof $$render<Option>>['props'];
|
|
11
11
|
events(): ReturnType<typeof $$render<Option>>['events'];
|
|
12
12
|
slots(): ReturnType<typeof $$render<Option>>['slots'];
|
|
@@ -14,12 +14,12 @@ declare class __sveltets_Render<Option extends T> {
|
|
|
14
14
|
exports(): {};
|
|
15
15
|
}
|
|
16
16
|
interface $$IsomorphicComponent {
|
|
17
|
-
new <Option extends
|
|
17
|
+
new <Option extends import('./types').Option>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Option>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Option>['props']>, ReturnType<__sveltets_Render<Option>['events']>, ReturnType<__sveltets_Render<Option>['slots']>> & {
|
|
18
18
|
$$bindings?: ReturnType<__sveltets_Render<Option>['bindings']>;
|
|
19
19
|
} & ReturnType<__sveltets_Render<Option>['exports']>;
|
|
20
|
-
<Option extends
|
|
20
|
+
<Option extends import('./types').Option>(internal: unknown, props: ReturnType<__sveltets_Render<Option>['props']> & {}): ReturnType<__sveltets_Render<Option>['exports']>;
|
|
21
21
|
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
22
22
|
}
|
|
23
23
|
declare const MultiSelect: $$IsomorphicComponent;
|
|
24
|
-
type MultiSelect<Option extends
|
|
24
|
+
type MultiSelect<Option extends import('./types').Option> = InstanceType<typeof MultiSelect<Option>>;
|
|
25
25
|
export default MultiSelect;
|
package/dist/Nav.svelte
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
generics="Route extends string | [string, string] | [string, string[]] = string | [string, string] | [string, string[]]"
|
|
4
|
+
>import { Icon } from './';
|
|
5
|
+
import { click_outside } from './';
|
|
6
|
+
let { routes = [], children, link, menu_props, link_props, page, labels, ...rest } = $props();
|
|
7
|
+
let is_open = $state(false);
|
|
8
|
+
let hovered_dropdown = $state(null);
|
|
9
|
+
let focused_item_index = $state(-1);
|
|
10
|
+
let is_touch_device = $state(false);
|
|
11
|
+
const panel_id = `nav-menu-${crypto.randomUUID()}`;
|
|
12
|
+
// Detect touch device
|
|
13
|
+
$effect(() => {
|
|
14
|
+
if (typeof globalThis !== `undefined`) {
|
|
15
|
+
is_touch_device = `ontouchstart` in globalThis || navigator.maxTouchPoints > 0;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
function close_menus() {
|
|
19
|
+
is_open = false;
|
|
20
|
+
hovered_dropdown = null;
|
|
21
|
+
focused_item_index = -1;
|
|
22
|
+
}
|
|
23
|
+
function toggle_dropdown(href, focus_first = false) {
|
|
24
|
+
const is_opening = hovered_dropdown !== href;
|
|
25
|
+
hovered_dropdown = hovered_dropdown === href ? null : href;
|
|
26
|
+
focused_item_index = is_opening && focus_first ? 0 : -1;
|
|
27
|
+
// Focus management for keyboard users
|
|
28
|
+
if (is_opening && focus_first) {
|
|
29
|
+
setTimeout(() => {
|
|
30
|
+
const dropdown = document.querySelector(`.dropdown-wrapper[data-href="${href}"]`);
|
|
31
|
+
const first_link = dropdown?.querySelector(`.dropdown a`);
|
|
32
|
+
if (first_link instanceof HTMLElement) {
|
|
33
|
+
first_link.focus();
|
|
34
|
+
}
|
|
35
|
+
}, 0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function onkeydown(event) {
|
|
39
|
+
if (event.key === `Escape`)
|
|
40
|
+
close_menus();
|
|
41
|
+
}
|
|
42
|
+
function handle_dropdown_keydown(event, href, sub_routes) {
|
|
43
|
+
const { key } = event;
|
|
44
|
+
if (key === `Enter` || key === ` `) {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
toggle_dropdown(href, true);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Arrow key navigation within open dropdown
|
|
50
|
+
if (hovered_dropdown === href && (key === `ArrowDown` || key === `ArrowUp`)) {
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
const direction = key === `ArrowDown` ? 1 : -1;
|
|
53
|
+
const new_index = Math.max(0, Math.min(sub_routes.length - 1, focused_item_index + direction));
|
|
54
|
+
focused_item_index = new_index;
|
|
55
|
+
const dropdown = document.querySelector(`.dropdown-wrapper[data-href="${href}"]`);
|
|
56
|
+
const links = dropdown?.querySelectorAll(`.dropdown a`);
|
|
57
|
+
if (links?.[new_index] instanceof HTMLElement) {
|
|
58
|
+
links[new_index].focus();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Open dropdown with ArrowDown when closed
|
|
62
|
+
if (hovered_dropdown !== href && key === `ArrowDown`) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
toggle_dropdown(href, true);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function handle_dropdown_item_keydown(event, href) {
|
|
68
|
+
if (event.key === `Escape`) {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
close_menus();
|
|
71
|
+
// Return focus to dropdown toggle button
|
|
72
|
+
document
|
|
73
|
+
.querySelector(`.dropdown-wrapper[data-href="${href}"]`)
|
|
74
|
+
?.querySelector(`.dropdown-toggle`)
|
|
75
|
+
?.focus();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function is_current(path) {
|
|
79
|
+
if (path === `/`)
|
|
80
|
+
return page?.url.pathname === `/` ? `page` : undefined;
|
|
81
|
+
// Match exact path or path followed by / to avoid partial matches
|
|
82
|
+
// e.g. /tc-periodic-v2 should not match /tc-periodic
|
|
83
|
+
const pathname = page?.url.pathname;
|
|
84
|
+
const exact_match = pathname === path;
|
|
85
|
+
const prefix_match = pathname?.startsWith(path + `/`);
|
|
86
|
+
return exact_match || prefix_match ? `page` : undefined;
|
|
87
|
+
}
|
|
88
|
+
const is_child_current = (sub_routes) => sub_routes.some((child_path) => is_current(child_path) === `page`);
|
|
89
|
+
function format_label(text, remove_parent = false) {
|
|
90
|
+
const custom_label = labels?.[text];
|
|
91
|
+
if (custom_label)
|
|
92
|
+
return { label: custom_label, style: `` };
|
|
93
|
+
if (remove_parent)
|
|
94
|
+
text = text.split(`/`).filter(Boolean).pop() ?? text;
|
|
95
|
+
const label = text.replace(/^\//, ``).replaceAll(`-`, ` `);
|
|
96
|
+
return { label, style: `text-transform: capitalize` };
|
|
97
|
+
}
|
|
98
|
+
function parse_route(route) {
|
|
99
|
+
if (typeof route === `string`)
|
|
100
|
+
return { href: route, label: route };
|
|
101
|
+
const [first, second] = route;
|
|
102
|
+
return Array.isArray(second)
|
|
103
|
+
? { href: first, label: first, children: second }
|
|
104
|
+
: { href: first, label: second };
|
|
105
|
+
}
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<svelte:window {onkeydown} />
|
|
109
|
+
|
|
110
|
+
<nav
|
|
111
|
+
{...rest}
|
|
112
|
+
{@attach click_outside({ callback: close_menus })}
|
|
113
|
+
class="bleed-1400 {rest.class ?? ``}"
|
|
114
|
+
>
|
|
115
|
+
<button
|
|
116
|
+
class="burger-button"
|
|
117
|
+
onclick={() => is_open = !is_open}
|
|
118
|
+
aria-label="Toggle navigation menu"
|
|
119
|
+
aria-expanded={is_open}
|
|
120
|
+
aria-controls={panel_id}
|
|
121
|
+
>
|
|
122
|
+
<span class="burger-line"></span>
|
|
123
|
+
<span class="burger-line"></span>
|
|
124
|
+
<span class="burger-line"></span>
|
|
125
|
+
</button>
|
|
126
|
+
|
|
127
|
+
<div
|
|
128
|
+
id={panel_id}
|
|
129
|
+
class="menu"
|
|
130
|
+
class:open={is_open}
|
|
131
|
+
tabindex="0"
|
|
132
|
+
role="menu"
|
|
133
|
+
{onkeydown}
|
|
134
|
+
{...menu_props}
|
|
135
|
+
>
|
|
136
|
+
{#each routes as route (JSON.stringify(route))}
|
|
137
|
+
{@const { href, label, children: sub_routes } = parse_route(route)}
|
|
138
|
+
|
|
139
|
+
{#if sub_routes}
|
|
140
|
+
<!-- Dropdown menu item -->
|
|
141
|
+
{@const parent = format_label(label)}
|
|
142
|
+
{@const child_is_active = is_child_current(sub_routes)}
|
|
143
|
+
{@const parent_page_exists = sub_routes.includes(href)}
|
|
144
|
+
{@const filtered_sub_routes = sub_routes.filter((route) => route !== href)}
|
|
145
|
+
<div
|
|
146
|
+
class="dropdown-wrapper"
|
|
147
|
+
class:active={child_is_active}
|
|
148
|
+
data-href={href}
|
|
149
|
+
role="group"
|
|
150
|
+
aria-current={child_is_active ? `true` : undefined}
|
|
151
|
+
onmouseenter={() => !is_touch_device && (hovered_dropdown = href)}
|
|
152
|
+
onmouseleave={() => !is_touch_device && (hovered_dropdown = null)}
|
|
153
|
+
onfocusin={() => (hovered_dropdown = href)}
|
|
154
|
+
onfocusout={(event) => {
|
|
155
|
+
const next = event.relatedTarget as Node | null
|
|
156
|
+
if (!next || !(event.currentTarget as HTMLElement).contains(next)) {
|
|
157
|
+
hovered_dropdown = null
|
|
158
|
+
}
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<div class="dropdown-trigger-wrapper">
|
|
162
|
+
<svelte:element
|
|
163
|
+
this={parent_page_exists ? `a` : `span`}
|
|
164
|
+
href={parent_page_exists ? href : undefined}
|
|
165
|
+
class="dropdown-trigger"
|
|
166
|
+
aria-current={is_current(href)}
|
|
167
|
+
onclick={close_menus}
|
|
168
|
+
role={parent_page_exists ? undefined : `button`}
|
|
169
|
+
style={parent.style}
|
|
170
|
+
>
|
|
171
|
+
{@html parent.label}
|
|
172
|
+
</svelte:element>
|
|
173
|
+
<button
|
|
174
|
+
class="dropdown-toggle"
|
|
175
|
+
aria-label="Toggle {parent.label} submenu"
|
|
176
|
+
aria-expanded={hovered_dropdown === href}
|
|
177
|
+
aria-haspopup="true"
|
|
178
|
+
onclick={() => toggle_dropdown(href, false)}
|
|
179
|
+
onkeydown={(event) => handle_dropdown_keydown(event, href, filtered_sub_routes)}
|
|
180
|
+
>
|
|
181
|
+
<Icon
|
|
182
|
+
icon="ChevronExpand"
|
|
183
|
+
style="width: 0.8em; height: 0.8em"
|
|
184
|
+
/>
|
|
185
|
+
</button>
|
|
186
|
+
</div>
|
|
187
|
+
<div
|
|
188
|
+
class="dropdown"
|
|
189
|
+
class:visible={hovered_dropdown === href}
|
|
190
|
+
role="menu"
|
|
191
|
+
tabindex="-1"
|
|
192
|
+
onmouseenter={() => !is_touch_device && (hovered_dropdown = href)}
|
|
193
|
+
onmouseleave={() => !is_touch_device && (hovered_dropdown = null)}
|
|
194
|
+
onfocusin={() => (hovered_dropdown = href)}
|
|
195
|
+
onfocusout={(event) => {
|
|
196
|
+
const next = event.relatedTarget as Node | null
|
|
197
|
+
if (!next || !(event.currentTarget as HTMLElement).contains(next)) {
|
|
198
|
+
hovered_dropdown = null
|
|
199
|
+
}
|
|
200
|
+
}}
|
|
201
|
+
>
|
|
202
|
+
{#each filtered_sub_routes as child_href (child_href)}
|
|
203
|
+
{@const child = format_label(child_href, true)}
|
|
204
|
+
{#if link}
|
|
205
|
+
{@render link({ href: child_href, label: child.label })}
|
|
206
|
+
{:else}
|
|
207
|
+
<a
|
|
208
|
+
href={child_href}
|
|
209
|
+
role="menuitem"
|
|
210
|
+
aria-current={is_current(child_href)}
|
|
211
|
+
onclick={close_menus}
|
|
212
|
+
onkeydown={(event) => handle_dropdown_item_keydown(event, href)}
|
|
213
|
+
{...link_props}
|
|
214
|
+
style={`${child.style}; ${link_props?.style ?? ``}`}
|
|
215
|
+
>
|
|
216
|
+
{@html child.label}
|
|
217
|
+
</a>
|
|
218
|
+
{/if}
|
|
219
|
+
{/each}
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
{:else}
|
|
223
|
+
<!-- Regular link item -->
|
|
224
|
+
{@const regular = format_label(label)}
|
|
225
|
+
{#if link}
|
|
226
|
+
{@render link({ href, label })}
|
|
227
|
+
{:else}
|
|
228
|
+
<a
|
|
229
|
+
{href}
|
|
230
|
+
aria-current={is_current(href)}
|
|
231
|
+
onclick={close_menus}
|
|
232
|
+
{...link_props}
|
|
233
|
+
style={`${regular.style}; ${link_props?.style ?? ``}`}
|
|
234
|
+
>
|
|
235
|
+
{@html regular.label}
|
|
236
|
+
</a>
|
|
237
|
+
{/if}
|
|
238
|
+
{/if}
|
|
239
|
+
{/each}
|
|
240
|
+
|
|
241
|
+
{@render children?.({ is_open, panel_id, routes })}
|
|
242
|
+
</div>
|
|
243
|
+
</nav>
|
|
244
|
+
|
|
245
|
+
<style>
|
|
246
|
+
nav {
|
|
247
|
+
position: relative;
|
|
248
|
+
margin: -0.75em auto 1.25em;
|
|
249
|
+
--nav-border-radius: 6pt;
|
|
250
|
+
--nav-surface-bg: light-dark(#fff, #1a1a1a);
|
|
251
|
+
--nav-surface-border: light-dark(rgba(128, 128, 128, 0.25), rgba(200, 200, 200, 0.2));
|
|
252
|
+
--nav-surface-shadow: light-dark(
|
|
253
|
+
0 2px 8px rgba(0, 0, 0, 0.15),
|
|
254
|
+
0 4px 12px rgba(0, 0, 0, 0.5)
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
.menu {
|
|
258
|
+
display: flex;
|
|
259
|
+
gap: 1em;
|
|
260
|
+
place-content: center;
|
|
261
|
+
flex-wrap: wrap;
|
|
262
|
+
padding: 0.5em;
|
|
263
|
+
}
|
|
264
|
+
.menu > a {
|
|
265
|
+
line-height: 1.3;
|
|
266
|
+
padding: 1pt 5pt;
|
|
267
|
+
border-radius: var(--nav-border-radius);
|
|
268
|
+
text-decoration: none;
|
|
269
|
+
color: inherit;
|
|
270
|
+
transition: background-color 0.2s;
|
|
271
|
+
}
|
|
272
|
+
.menu > a:hover {
|
|
273
|
+
background-color: var(--nav-link-bg-hover);
|
|
274
|
+
}
|
|
275
|
+
.menu > a[aria-current='page'] {
|
|
276
|
+
color: var(--nav-link-active-color);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Dropdown styles */
|
|
280
|
+
.dropdown-wrapper {
|
|
281
|
+
position: relative;
|
|
282
|
+
}
|
|
283
|
+
.dropdown-wrapper.active .dropdown-trigger {
|
|
284
|
+
color: var(--nav-link-active-color);
|
|
285
|
+
}
|
|
286
|
+
.dropdown-wrapper::after {
|
|
287
|
+
content: '';
|
|
288
|
+
position: absolute;
|
|
289
|
+
top: 100%;
|
|
290
|
+
left: 0;
|
|
291
|
+
right: 0;
|
|
292
|
+
height: var(--nav-dropdown-margin, 3pt);
|
|
293
|
+
}
|
|
294
|
+
.dropdown-trigger-wrapper {
|
|
295
|
+
display: flex;
|
|
296
|
+
align-items: center;
|
|
297
|
+
gap: 0;
|
|
298
|
+
border-radius: var(--nav-border-radius);
|
|
299
|
+
transition: background-color 0.2s;
|
|
300
|
+
}
|
|
301
|
+
.dropdown-trigger-wrapper:hover {
|
|
302
|
+
background-color: var(--nav-link-bg-hover);
|
|
303
|
+
}
|
|
304
|
+
.dropdown-trigger {
|
|
305
|
+
line-height: 1.3;
|
|
306
|
+
padding: 1pt 5pt;
|
|
307
|
+
text-decoration: none;
|
|
308
|
+
color: inherit;
|
|
309
|
+
border-radius: var(--nav-border-radius) 0 0 var(--nav-border-radius);
|
|
310
|
+
}
|
|
311
|
+
.dropdown-trigger[aria-current='page'] {
|
|
312
|
+
color: var(--nav-link-active-color);
|
|
313
|
+
}
|
|
314
|
+
.dropdown-toggle {
|
|
315
|
+
padding: 1pt 3pt;
|
|
316
|
+
border: none;
|
|
317
|
+
background: transparent;
|
|
318
|
+
color: inherit;
|
|
319
|
+
cursor: pointer;
|
|
320
|
+
display: flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
justify-content: center;
|
|
323
|
+
border-radius: 0 var(--nav-border-radius) var(--nav-border-radius) 0;
|
|
324
|
+
}
|
|
325
|
+
.dropdown {
|
|
326
|
+
position: absolute;
|
|
327
|
+
top: 100%;
|
|
328
|
+
left: 0;
|
|
329
|
+
margin: var(--nav-dropdown-margin, 3pt 0 0 0);
|
|
330
|
+
min-width: max-content;
|
|
331
|
+
background-color: var(--nav-dropdown-bg, var(--nav-surface-bg));
|
|
332
|
+
border: 1px solid var(--nav-dropdown-border-color, var(--nav-surface-border));
|
|
333
|
+
border-radius: var(--nav-border-radius, 6pt);
|
|
334
|
+
box-shadow: var(--nav-dropdown-shadow, var(--nav-surface-shadow));
|
|
335
|
+
padding: var(--nav-dropdown-padding, 2pt 3pt);
|
|
336
|
+
display: none;
|
|
337
|
+
flex-direction: column;
|
|
338
|
+
gap: var(--nav-dropdown-gap, 5pt);
|
|
339
|
+
z-index: var(--nav-dropdown-z-index, 100);
|
|
340
|
+
}
|
|
341
|
+
.dropdown.visible {
|
|
342
|
+
display: flex;
|
|
343
|
+
}
|
|
344
|
+
.dropdown a {
|
|
345
|
+
padding: var(--nav-dropdown-link-padding, 1pt 4pt);
|
|
346
|
+
border-radius: var(--nav-border-radius);
|
|
347
|
+
text-decoration: none;
|
|
348
|
+
color: inherit;
|
|
349
|
+
white-space: nowrap;
|
|
350
|
+
transition: background-color 0.2s;
|
|
351
|
+
}
|
|
352
|
+
.dropdown a:hover {
|
|
353
|
+
background-color: var(--nav-link-bg-hover);
|
|
354
|
+
}
|
|
355
|
+
.dropdown a[aria-current='page'] {
|
|
356
|
+
color: var(--nav-link-active-color);
|
|
357
|
+
}
|
|
358
|
+
/* Mobile burger button */
|
|
359
|
+
.burger-button {
|
|
360
|
+
display: none;
|
|
361
|
+
position: fixed;
|
|
362
|
+
top: 1rem;
|
|
363
|
+
left: 1rem;
|
|
364
|
+
flex-direction: column;
|
|
365
|
+
justify-content: space-around;
|
|
366
|
+
width: 1.4rem;
|
|
367
|
+
height: 1.4rem;
|
|
368
|
+
background: transparent;
|
|
369
|
+
padding: 0;
|
|
370
|
+
z-index: var(--nav-toggle-btn-z-index, 10);
|
|
371
|
+
}
|
|
372
|
+
.burger-line {
|
|
373
|
+
height: 0.18rem;
|
|
374
|
+
background-color: var(--text-color);
|
|
375
|
+
border-radius: 8px;
|
|
376
|
+
transition: all 0.2s linear;
|
|
377
|
+
transform-origin: 1px;
|
|
378
|
+
}
|
|
379
|
+
.burger-button[aria-expanded='true'] .burger-line:first-child {
|
|
380
|
+
transform: rotate(45deg);
|
|
381
|
+
}
|
|
382
|
+
.burger-button[aria-expanded='true'] .burger-line:nth-child(2) {
|
|
383
|
+
opacity: 0;
|
|
384
|
+
}
|
|
385
|
+
.burger-button[aria-expanded='true'] .burger-line:nth-child(3) {
|
|
386
|
+
transform: rotate(-45deg);
|
|
387
|
+
}
|
|
388
|
+
/* Mobile styles */
|
|
389
|
+
@media (max-width: 767px) {
|
|
390
|
+
.burger-button {
|
|
391
|
+
display: flex;
|
|
392
|
+
}
|
|
393
|
+
.menu {
|
|
394
|
+
position: fixed;
|
|
395
|
+
top: 3rem;
|
|
396
|
+
left: 1rem;
|
|
397
|
+
background-color: var(--nav-surface-bg);
|
|
398
|
+
border: 1px solid var(--nav-surface-border);
|
|
399
|
+
box-shadow: var(--nav-surface-shadow);
|
|
400
|
+
opacity: 0;
|
|
401
|
+
visibility: hidden;
|
|
402
|
+
transition: all 0.3s ease;
|
|
403
|
+
z-index: var(--nav-mobile-z-index, 2);
|
|
404
|
+
flex-direction: column;
|
|
405
|
+
align-items: stretch;
|
|
406
|
+
justify-content: flex-start;
|
|
407
|
+
gap: 0.2em;
|
|
408
|
+
max-width: 90vw;
|
|
409
|
+
border-radius: 6px;
|
|
410
|
+
}
|
|
411
|
+
.menu.open {
|
|
412
|
+
opacity: 1;
|
|
413
|
+
visibility: visible;
|
|
414
|
+
}
|
|
415
|
+
.menu > a,
|
|
416
|
+
.dropdown-wrapper {
|
|
417
|
+
padding: 2pt 8pt;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* Mobile dropdown styles - show as expandable section */
|
|
421
|
+
.dropdown-wrapper {
|
|
422
|
+
flex-direction: column;
|
|
423
|
+
align-items: stretch;
|
|
424
|
+
}
|
|
425
|
+
.dropdown-trigger-wrapper {
|
|
426
|
+
display: flex;
|
|
427
|
+
align-items: center;
|
|
428
|
+
justify-content: space-between;
|
|
429
|
+
}
|
|
430
|
+
.dropdown-trigger {
|
|
431
|
+
flex: 1;
|
|
432
|
+
border-radius: var(--nav-border-radius);
|
|
433
|
+
}
|
|
434
|
+
.dropdown-toggle {
|
|
435
|
+
padding: 4pt 8pt;
|
|
436
|
+
border-radius: var(--nav-border-radius);
|
|
437
|
+
}
|
|
438
|
+
.dropdown {
|
|
439
|
+
position: static;
|
|
440
|
+
border: none;
|
|
441
|
+
box-shadow: none;
|
|
442
|
+
margin-top: 0.25em;
|
|
443
|
+
padding: 0 0 0 1em;
|
|
444
|
+
background-color: transparent;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Page } from '@sveltejs/kit';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
declare function $$render<Route extends string | [string, string] | [string, string[]] = string | [string, string] | [string, string[]]>(): {
|
|
5
|
+
props: {
|
|
6
|
+
routes: Route[];
|
|
7
|
+
children?: Snippet<[{
|
|
8
|
+
is_open: boolean;
|
|
9
|
+
panel_id: string;
|
|
10
|
+
routes: Route[];
|
|
11
|
+
}]>;
|
|
12
|
+
link?: Snippet<[{
|
|
13
|
+
href: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}]>;
|
|
16
|
+
menu_props?: HTMLAttributes<HTMLDivElement>;
|
|
17
|
+
link_props?: HTMLAttributes<HTMLAnchorElement>;
|
|
18
|
+
page?: Page;
|
|
19
|
+
labels?: Record<string, string>;
|
|
20
|
+
} & Omit<HTMLAttributes<HTMLElement>, "children">;
|
|
21
|
+
exports: {};
|
|
22
|
+
bindings: "";
|
|
23
|
+
slots: {};
|
|
24
|
+
events: {};
|
|
25
|
+
};
|
|
26
|
+
declare class __sveltets_Render<Route extends string | [string, string] | [string, string[]] = string | [string, string] | [string, string[]]> {
|
|
27
|
+
props(): ReturnType<typeof $$render<Route>>['props'];
|
|
28
|
+
events(): ReturnType<typeof $$render<Route>>['events'];
|
|
29
|
+
slots(): ReturnType<typeof $$render<Route>>['slots'];
|
|
30
|
+
bindings(): "";
|
|
31
|
+
exports(): {};
|
|
32
|
+
}
|
|
33
|
+
interface $$IsomorphicComponent {
|
|
34
|
+
new <Route extends string | [string, string] | [string, string[]] = string | [string, string] | [string, string[]]>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Route>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Route>['props']>, ReturnType<__sveltets_Render<Route>['events']>, ReturnType<__sveltets_Render<Route>['slots']>> & {
|
|
35
|
+
$$bindings?: ReturnType<__sveltets_Render<Route>['bindings']>;
|
|
36
|
+
} & ReturnType<__sveltets_Render<Route>['exports']>;
|
|
37
|
+
<Route extends string | [string, string] | [string, string[]] = string | [string, string] | [string, string[]]>(internal: unknown, props: ReturnType<__sveltets_Render<Route>['props']> & {}): ReturnType<__sveltets_Render<Route>['exports']>;
|
|
38
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
39
|
+
}
|
|
40
|
+
declare const Nav: $$IsomorphicComponent;
|
|
41
|
+
type Nav<Route extends string | [string, string] | [string, string[]] = string | [string, string] | [string, string[]]> = InstanceType<typeof Nav<Route>>;
|
|
42
|
+
export default Nav;
|
package/dist/PrevNext.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script lang="ts">let { items = [], node = `nav`, current = ``, log = `errors`, nav_options = { replace_state: true, no_scroll: true }, titles = { prev: `← Previous`, next: `Next →` }, onkeyup = ({ prev, next }) => ({ ArrowLeft: prev[0], ArrowRight: next[0] }), prev_snippet, children, between, next_snippet, min_items = 3, ...rest } = $props();
|
|
1
|
+
<script lang="ts" generics="Item extends [string, unknown] = [string, unknown]">let { items = [], node = `nav`, current = ``, log = `errors`, nav_options = { replace_state: true, no_scroll: true }, titles = { prev: `← Previous`, next: `Next →` }, onkeyup = ({ prev, next }) => ({ ArrowLeft: prev[0], ArrowRight: next[0] }), prev_snippet, children, between, next_snippet, min_items = 3, link_props, ...rest } = $props();
|
|
2
2
|
// Convert items to consistent [key, value] format
|
|
3
3
|
let items_arr = $derived((items ?? []).map((itm) => (typeof itm === `string` ? [itm, itm] : itm)));
|
|
4
4
|
// Calculate prev/next items with wraparound
|
|
@@ -56,7 +56,7 @@ export {};
|
|
|
56
56
|
{:else}
|
|
57
57
|
<div>
|
|
58
58
|
{#if titles.prev}<span>{@html titles.prev}</span>{/if}
|
|
59
|
-
<a href={prev[0]}>{prev[0]}</a>
|
|
59
|
+
<a {...link_props} href={prev[0]}>{prev[0]}</a>
|
|
60
60
|
</div>
|
|
61
61
|
{/if}
|
|
62
62
|
{/if}
|
|
@@ -69,7 +69,7 @@ export {};
|
|
|
69
69
|
{:else}
|
|
70
70
|
<div>
|
|
71
71
|
{#if titles.next}<span>{@html titles.next}</span>{/if}
|
|
72
|
-
<a href={next[0]}>{next[0]}</a>
|
|
72
|
+
<a {...link_props} href={next[0]}>{next[0]}</a>
|
|
73
73
|
</div>
|
|
74
74
|
{/if}
|
|
75
75
|
{/if}
|
|
@@ -1,36 +1,56 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
declare function $$render<Item extends [string, unknown] = [string, unknown]>(): {
|
|
4
|
+
props: Omit<HTMLAttributes<HTMLElement>, "children" | "onkeyup"> & {
|
|
5
|
+
items?: (string | Item)[];
|
|
6
|
+
node?: string;
|
|
7
|
+
current?: string;
|
|
8
|
+
log?: `verbose` | `errors` | `silent`;
|
|
9
|
+
nav_options?: {
|
|
10
|
+
replace_state: boolean;
|
|
11
|
+
no_scroll: boolean;
|
|
12
|
+
};
|
|
13
|
+
titles?: {
|
|
14
|
+
prev: string;
|
|
15
|
+
next: string;
|
|
16
|
+
};
|
|
17
|
+
onkeyup?: ((obj: {
|
|
18
|
+
prev: Item;
|
|
19
|
+
next: Item;
|
|
20
|
+
}) => Record<string, string | undefined>) | null;
|
|
21
|
+
prev_snippet?: Snippet<[{
|
|
22
|
+
item: Item;
|
|
23
|
+
}]>;
|
|
24
|
+
children?: Snippet<[{
|
|
25
|
+
kind: `prev` | `next`;
|
|
26
|
+
item: Item;
|
|
27
|
+
}]>;
|
|
28
|
+
between?: Snippet<[]>;
|
|
29
|
+
next_snippet?: Snippet<[{
|
|
30
|
+
item: Item;
|
|
31
|
+
}]>;
|
|
32
|
+
min_items?: number;
|
|
33
|
+
link_props?: HTMLAttributes<HTMLAnchorElement>;
|
|
12
34
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}]>;
|
|
32
|
-
min_items?: number;
|
|
35
|
+
exports: {};
|
|
36
|
+
bindings: "";
|
|
37
|
+
slots: {};
|
|
38
|
+
events: {};
|
|
39
|
+
};
|
|
40
|
+
declare class __sveltets_Render<Item extends [string, unknown] = [string, unknown]> {
|
|
41
|
+
props(): ReturnType<typeof $$render<Item>>['props'];
|
|
42
|
+
events(): ReturnType<typeof $$render<Item>>['events'];
|
|
43
|
+
slots(): ReturnType<typeof $$render<Item>>['slots'];
|
|
44
|
+
bindings(): "";
|
|
45
|
+
exports(): {};
|
|
46
|
+
}
|
|
47
|
+
interface $$IsomorphicComponent {
|
|
48
|
+
new <Item extends [string, unknown] = [string, unknown]>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Item>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Item>['props']>, ReturnType<__sveltets_Render<Item>['events']>, ReturnType<__sveltets_Render<Item>['slots']>> & {
|
|
49
|
+
$$bindings?: ReturnType<__sveltets_Render<Item>['bindings']>;
|
|
50
|
+
} & ReturnType<__sveltets_Render<Item>['exports']>;
|
|
51
|
+
<Item extends [string, unknown] = [string, unknown]>(internal: unknown, props: ReturnType<__sveltets_Render<Item>['props']> & {}): ReturnType<__sveltets_Render<Item>['exports']>;
|
|
52
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
33
53
|
}
|
|
34
|
-
declare const PrevNext:
|
|
35
|
-
type PrevNext =
|
|
54
|
+
declare const PrevNext: $$IsomorphicComponent;
|
|
55
|
+
type PrevNext<Item extends [string, unknown] = [string, unknown]> = InstanceType<typeof PrevNext<Item>>;
|
|
36
56
|
export default PrevNext;
|
package/dist/Toggle.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script lang="ts">let { checked = $bindable(false),
|
|
1
|
+
<script lang="ts">let { checked = $bindable(false), onkeydown, children, input_props, ...rest } = $props();
|
|
2
2
|
// normally input type=checkbox toggles on space bar, this handler also responds to enter
|
|
3
3
|
function handle_keydown(event) {
|
|
4
4
|
onkeydown?.(event);
|
|
@@ -16,13 +16,8 @@ export {};
|
|
|
16
16
|
<input
|
|
17
17
|
type="checkbox"
|
|
18
18
|
bind:checked
|
|
19
|
-
{
|
|
20
|
-
{required}
|
|
19
|
+
{...input_props}
|
|
21
20
|
onkeydown={handle_keydown}
|
|
22
|
-
{onchange}
|
|
23
|
-
{onblur}
|
|
24
|
-
{onclick}
|
|
25
|
-
style={input_style}
|
|
26
21
|
/>
|
|
27
22
|
<span></span>
|
|
28
23
|
</label>
|
package/dist/Toggle.svelte.d.ts
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
|
|
3
|
+
type $$ComponentProps = HTMLAttributes<HTMLLabelElement> & {
|
|
4
4
|
checked?: boolean;
|
|
5
|
-
required?: boolean;
|
|
6
|
-
input_style?: string;
|
|
7
|
-
id?: string | null;
|
|
8
|
-
onclick?: (event: MouseEvent) => void;
|
|
9
|
-
onchange?: (event: Event) => void;
|
|
10
|
-
onblur?: (event: FocusEvent) => void;
|
|
11
5
|
onkeydown?: (event: KeyboardEvent) => void;
|
|
12
6
|
children?: Snippet<[]>;
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
input_props?: HTMLAttributes<HTMLInputElement>;
|
|
8
|
+
};
|
|
9
|
+
declare const Toggle: import("svelte").Component<$$ComponentProps, {}, "checked">;
|
|
15
10
|
type Toggle = ReturnType<typeof Toggle>;
|
|
16
11
|
export default Toggle;
|
package/dist/Wiggle.svelte.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
type $$ComponentProps = {
|
|
3
3
|
wiggle?: boolean;
|
|
4
4
|
angle?: number;
|
|
5
5
|
scale?: number;
|
|
@@ -9,7 +9,7 @@ interface Props {
|
|
|
9
9
|
stiffness?: number;
|
|
10
10
|
damping?: number;
|
|
11
11
|
children?: Snippet;
|
|
12
|
-
}
|
|
13
|
-
declare const Wiggle: import("svelte").Component
|
|
12
|
+
};
|
|
13
|
+
declare const Wiggle: import("svelte").Component<$$ComponentProps, {}, "wiggle">;
|
|
14
14
|
type Wiggle = ReturnType<typeof Wiggle>;
|
|
15
15
|
export default Wiggle;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { default as FileDetails } from './FileDetails.svelte';
|
|
|
7
7
|
export { default as GitHubCorner } from './GitHubCorner.svelte';
|
|
8
8
|
export { default as Icon } from './Icon.svelte';
|
|
9
9
|
export { default, default as MultiSelect } from './MultiSelect.svelte';
|
|
10
|
+
export { default as Nav } from './Nav.svelte';
|
|
10
11
|
export { default as PrevNext } from './PrevNext.svelte';
|
|
11
12
|
export { default as Toggle } from './Toggle.svelte';
|
|
12
13
|
export * from './types';
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { default as FileDetails } from './FileDetails.svelte';
|
|
|
7
7
|
export { default as GitHubCorner } from './GitHubCorner.svelte';
|
|
8
8
|
export { default as Icon } from './Icon.svelte';
|
|
9
9
|
export { default, default as MultiSelect } from './MultiSelect.svelte';
|
|
10
|
+
export { default as Nav } from './Nav.svelte';
|
|
10
11
|
export { default as PrevNext } from './PrevNext.svelte';
|
|
11
12
|
export { default as Toggle } from './Toggle.svelte';
|
|
12
13
|
export * from './types';
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"homepage": "https://janosh.github.io/svelte-multiselect",
|
|
6
6
|
"repository": "https://github.com/janosh/svelte-multiselect",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"version": "11.
|
|
8
|
+
"version": "11.3.0",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"svelte": "./dist/index.js",
|
|
11
11
|
"bugs": "https://github.com/janosh/svelte-multiselect/issues",
|
|
@@ -13,31 +13,31 @@
|
|
|
13
13
|
"svelte": "^5.35.6"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@playwright/test": "^1.
|
|
17
|
-
"@stylistic/eslint-plugin": "^5.
|
|
16
|
+
"@playwright/test": "^1.56.1",
|
|
17
|
+
"@stylistic/eslint-plugin": "^5.5.0",
|
|
18
18
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
19
|
-
"@sveltejs/kit": "^2.
|
|
19
|
+
"@sveltejs/kit": "^2.48.4",
|
|
20
20
|
"@sveltejs/package": "2.5.4",
|
|
21
21
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
22
|
-
"@types/node": "^24.
|
|
23
|
-
"@vitest/coverage-v8": "^
|
|
24
|
-
"eslint": "^9.
|
|
25
|
-
"eslint-plugin-svelte": "^3.
|
|
26
|
-
"happy-dom": "^
|
|
22
|
+
"@types/node": "^24.10.0",
|
|
23
|
+
"@vitest/coverage-v8": "^4.0.8",
|
|
24
|
+
"eslint": "^9.39.1",
|
|
25
|
+
"eslint-plugin-svelte": "^3.13.0",
|
|
26
|
+
"happy-dom": "^20.0.10",
|
|
27
27
|
"hastscript": "^9.0.1",
|
|
28
28
|
"mdsvex": "^0.12.6",
|
|
29
29
|
"mdsvexamples": "^0.5.0",
|
|
30
30
|
"rehype-autolink-headings": "^7.1.0",
|
|
31
31
|
"rehype-slug": "^6.0.0",
|
|
32
|
-
"svelte": "^5.
|
|
33
|
-
"svelte-check": "^4.3.
|
|
32
|
+
"svelte": "^5.43.5",
|
|
33
|
+
"svelte-check": "^4.3.3",
|
|
34
34
|
"svelte-preprocess": "^6.0.3",
|
|
35
35
|
"svelte-toc": "^0.6.2",
|
|
36
|
-
"svelte2tsx": "^0.7.
|
|
36
|
+
"svelte2tsx": "^0.7.45",
|
|
37
37
|
"typescript": "5.9.3",
|
|
38
|
-
"typescript-eslint": "^8.
|
|
39
|
-
"vite": "^7.
|
|
40
|
-
"vitest": "^
|
|
38
|
+
"typescript-eslint": "^8.46.3",
|
|
39
|
+
"vite": "^7.2.2",
|
|
40
|
+
"vitest": "^4.0.8"
|
|
41
41
|
},
|
|
42
42
|
"keywords": [
|
|
43
43
|
"svelte",
|
package/readme.md
CHANGED