kosui 0.0.7
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/LICENSE +7 -0
- package/README.md +3 -0
- package/dist/alert/alert.svelte +28 -0
- package/dist/alert/alert.svelte.d.ts +5 -0
- package/dist/alert/index.d.ts +1 -0
- package/dist/alert/index.js +1 -0
- package/dist/autocomplete/autocomplete-content.svelte +47 -0
- package/dist/autocomplete/autocomplete-content.svelte.d.ts +10 -0
- package/dist/autocomplete/autocomplete-context.svelte.d.ts +12 -0
- package/dist/autocomplete/autocomplete-context.svelte.js +34 -0
- package/dist/autocomplete/autocomplete-input.svelte +43 -0
- package/dist/autocomplete/autocomplete-input.svelte.d.ts +7 -0
- package/dist/autocomplete/autocomplete-item.svelte +68 -0
- package/dist/autocomplete/autocomplete-item.svelte.d.ts +11 -0
- package/dist/autocomplete/autocomplete.svelte +20 -0
- package/dist/autocomplete/autocomplete.svelte.d.ts +8 -0
- package/dist/autocomplete/index.d.ts +4 -0
- package/dist/autocomplete/index.js +4 -0
- package/dist/avatar/avatar.svelte +47 -0
- package/dist/avatar/avatar.svelte.d.ts +8 -0
- package/dist/avatar/index.d.ts +1 -0
- package/dist/avatar/index.js +1 -0
- package/dist/badge/badge.svelte +43 -0
- package/dist/badge/badge.svelte.d.ts +9 -0
- package/dist/badge/index.d.ts +1 -0
- package/dist/badge/index.js +1 -0
- package/dist/base.d.ts +21 -0
- package/dist/base.js +70 -0
- package/dist/bindable.svelte.d.ts +7 -0
- package/dist/bindable.svelte.js +25 -0
- package/dist/box/box.svelte +42 -0
- package/dist/box/box.svelte.d.ts +12 -0
- package/dist/box/index.d.ts +1 -0
- package/dist/box/index.js +1 -0
- package/dist/breadcrumbs/breadcrumbs.svelte +39 -0
- package/dist/breadcrumbs/breadcrumbs.svelte.d.ts +13 -0
- package/dist/breadcrumbs/index.d.ts +1 -0
- package/dist/breadcrumbs/index.js +1 -0
- package/dist/button/button.svelte +70 -0
- package/dist/button/button.svelte.d.ts +13 -0
- package/dist/button/index.d.ts +1 -0
- package/dist/button/index.js +1 -0
- package/dist/chip/chip.svelte +57 -0
- package/dist/chip/chip.svelte.d.ts +11 -0
- package/dist/chip/index.d.ts +1 -0
- package/dist/chip/index.js +1 -0
- package/dist/command/action.svelte.d.ts +35 -0
- package/dist/command/action.svelte.js +76 -0
- package/dist/command/command-content.svelte +15 -0
- package/dist/command/command-content.svelte.d.ts +8 -0
- package/dist/command/command-context.svelte.d.ts +5 -0
- package/dist/command/command-context.svelte.js +13 -0
- package/dist/command/command-input.svelte +44 -0
- package/dist/command/command-input.svelte.d.ts +7 -0
- package/dist/command/command-item.svelte +66 -0
- package/dist/command/command-item.svelte.d.ts +11 -0
- package/dist/command/command-search.svelte +29 -0
- package/dist/command/command-search.svelte.d.ts +5 -0
- package/dist/command/command.svelte +19 -0
- package/dist/command/command.svelte.d.ts +8 -0
- package/dist/command/commander.svelte +107 -0
- package/dist/command/commander.svelte.d.ts +9 -0
- package/dist/command/index.d.ts +8 -0
- package/dist/command/index.js +8 -0
- package/dist/common/divider.svelte +13 -0
- package/dist/common/divider.svelte.d.ts +6 -0
- package/dist/common/header.svelte +35 -0
- package/dist/common/header.svelte.d.ts +10 -0
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.js +3 -0
- package/dist/common/item-context.svelte.d.ts +12 -0
- package/dist/common/item-context.svelte.js +77 -0
- package/dist/dialog/dialog-button.svelte +25 -0
- package/dist/dialog/dialog-button.svelte.d.ts +32 -0
- package/dist/dialog/dialog.svelte +69 -0
- package/dist/dialog/dialog.svelte.d.ts +37 -0
- package/dist/dialog/dialoguer-context.svelte.d.ts +53 -0
- package/dist/dialog/dialoguer-context.svelte.js +85 -0
- package/dist/dialog/dialoguer.svelte +65 -0
- package/dist/dialog/dialoguer.svelte.d.ts +7 -0
- package/dist/dialog/index.d.ts +4 -0
- package/dist/dialog/index.js +4 -0
- package/dist/event-manager.d.ts +15 -0
- package/dist/event-manager.js +47 -0
- package/dist/fab/fab.svelte +28 -0
- package/dist/fab/fab.svelte.d.ts +6 -0
- package/dist/fab/index.d.ts +1 -0
- package/dist/fab/index.js +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +39 -0
- package/dist/input/index.d.ts +1 -0
- package/dist/input/index.js +1 -0
- package/dist/input/input.svelte +41 -0
- package/dist/input/input.svelte.d.ts +7 -0
- package/dist/link/index.d.ts +1 -0
- package/dist/link/index.js +1 -0
- package/dist/link/link.svelte +51 -0
- package/dist/link/link.svelte.d.ts +10 -0
- package/dist/markdown/index.d.ts +25 -0
- package/dist/markdown/index.js +25 -0
- package/dist/markdown/markdown-blockquote.svelte +14 -0
- package/dist/markdown/markdown-blockquote.svelte.d.ts +7 -0
- package/dist/markdown/markdown-br.svelte +12 -0
- package/dist/markdown/markdown-br.svelte.d.ts +7 -0
- package/dist/markdown/markdown-code.svelte +14 -0
- package/dist/markdown/markdown-code.svelte.d.ts +7 -0
- package/dist/markdown/markdown-codespan.svelte +15 -0
- package/dist/markdown/markdown-codespan.svelte.d.ts +7 -0
- package/dist/markdown/markdown-context.svelte.d.ts +26 -0
- package/dist/markdown/markdown-context.svelte.js +30 -0
- package/dist/markdown/markdown-def.svelte +15 -0
- package/dist/markdown/markdown-def.svelte.d.ts +7 -0
- package/dist/markdown/markdown-del.svelte +14 -0
- package/dist/markdown/markdown-del.svelte.d.ts +7 -0
- package/dist/markdown/markdown-em.svelte +14 -0
- package/dist/markdown/markdown-em.svelte.d.ts +7 -0
- package/dist/markdown/markdown-escape.svelte +8 -0
- package/dist/markdown/markdown-escape.svelte.d.ts +5 -0
- package/dist/markdown/markdown-heading.svelte +16 -0
- package/dist/markdown/markdown-heading.svelte.d.ts +7 -0
- package/dist/markdown/markdown-hr.svelte +12 -0
- package/dist/markdown/markdown-hr.svelte.d.ts +7 -0
- package/dist/markdown/markdown-html.svelte +9 -0
- package/dist/markdown/markdown-html.svelte.d.ts +5 -0
- package/dist/markdown/markdown-image.svelte +12 -0
- package/dist/markdown/markdown-image.svelte.d.ts +7 -0
- package/dist/markdown/markdown-link.svelte +15 -0
- package/dist/markdown/markdown-link.svelte.d.ts +7 -0
- package/dist/markdown/markdown-list-item.svelte +14 -0
- package/dist/markdown/markdown-list-item.svelte.d.ts +7 -0
- package/dist/markdown/markdown-list.svelte +19 -0
- package/dist/markdown/markdown-list.svelte.d.ts +7 -0
- package/dist/markdown/markdown-paragraph.svelte +16 -0
- package/dist/markdown/markdown-paragraph.svelte.d.ts +7 -0
- package/dist/markdown/markdown-space.svelte +8 -0
- package/dist/markdown/markdown-space.svelte.d.ts +5 -0
- package/dist/markdown/markdown-strong.svelte +15 -0
- package/dist/markdown/markdown-strong.svelte.d.ts +7 -0
- package/dist/markdown/markdown-table-cell.svelte +16 -0
- package/dist/markdown/markdown-table-cell.svelte.d.ts +7 -0
- package/dist/markdown/markdown-table.svelte +34 -0
- package/dist/markdown/markdown-table.svelte.d.ts +7 -0
- package/dist/markdown/markdown-text.svelte +8 -0
- package/dist/markdown/markdown-text.svelte.d.ts +5 -0
- package/dist/markdown/markdown-token.svelte +25 -0
- package/dist/markdown/markdown-token.svelte.d.ts +7 -0
- package/dist/markdown/markdown-tokens.svelte +13 -0
- package/dist/markdown/markdown-tokens.svelte.d.ts +7 -0
- package/dist/markdown/markdown.svelte +186 -0
- package/dist/markdown/markdown.svelte.d.ts +31 -0
- package/dist/menu/index.d.ts +7 -0
- package/dist/menu/index.js +7 -0
- package/dist/menu/menu-actions.svelte +51 -0
- package/dist/menu/menu-actions.svelte.d.ts +7 -0
- package/dist/menu/menu-content.svelte +47 -0
- package/dist/menu/menu-content.svelte.d.ts +10 -0
- package/dist/menu/menu-context.svelte.d.ts +18 -0
- package/dist/menu/menu-context.svelte.js +118 -0
- package/dist/menu/menu-item.svelte +85 -0
- package/dist/menu/menu-item.svelte.d.ts +11 -0
- package/dist/menu/menu-trigger-button.svelte +31 -0
- package/dist/menu/menu-trigger-button.svelte.d.ts +5 -0
- package/dist/menu/menu-trigger.svelte +42 -0
- package/dist/menu/menu-trigger.svelte.d.ts +10 -0
- package/dist/menu/menu.svelte +29 -0
- package/dist/menu/menu.svelte.d.ts +9 -0
- package/dist/merge-props.d.ts +13 -0
- package/dist/merge-props.js +84 -0
- package/dist/modal/index.d.ts +1 -0
- package/dist/modal/index.js +1 -0
- package/dist/modal/modal.svelte +123 -0
- package/dist/modal/modal.svelte.d.ts +11 -0
- package/dist/ordered-html-elements.d.ts +7 -0
- package/dist/ordered-html-elements.js +29 -0
- package/dist/popover/index.d.ts +1 -0
- package/dist/popover/index.js +1 -0
- package/dist/popover/popover.svelte +184 -0
- package/dist/popover/popover.svelte.d.ts +18 -0
- package/dist/portal/index.d.ts +1 -0
- package/dist/portal/index.js +1 -0
- package/dist/portal/portal.svelte +12 -0
- package/dist/portal/portal.svelte.d.ts +8 -0
- package/dist/portal/proxy.svelte +10 -0
- package/dist/portal/proxy.svelte.d.ts +7 -0
- package/dist/progress/circular-progress.svelte +86 -0
- package/dist/progress/circular-progress.svelte.d.ts +13 -0
- package/dist/progress/index.d.ts +1 -0
- package/dist/progress/index.js +1 -0
- package/dist/shortcut/index.d.ts +2 -0
- package/dist/shortcut/index.js +2 -0
- package/dist/shortcut/shortcut-badge.svelte +41 -0
- package/dist/shortcut/shortcut-badge.svelte.d.ts +11 -0
- package/dist/shortcut/shortcut.d.ts +29 -0
- package/dist/shortcut/shortcut.js +95 -0
- package/dist/toggle/index.d.ts +2 -0
- package/dist/toggle/index.js +2 -0
- package/dist/toggle/toggle-button.svelte +60 -0
- package/dist/toggle/toggle-button.svelte.d.ts +32 -0
- package/dist/toggle/toggle-context.svelte.d.ts +9 -0
- package/dist/toggle/toggle-context.svelte.js +32 -0
- package/dist/toggle/toggle-group.svelte +41 -0
- package/dist/toggle/toggle-group.svelte.d.ts +32 -0
- package/dist/tooltip/index.d.ts +1 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/tooltip/tooltip.svelte +94 -0
- package/dist/tooltip/tooltip.svelte.d.ts +25 -0
- package/dist/utils.d.ts +43 -0
- package/dist/utils.js +72 -0
- package/package.json +76 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { match } from "../utils";
|
|
3
|
+
import { Check, ChevronRight } from "@lucide/svelte";
|
|
4
|
+
import {
|
|
5
|
+
Action,
|
|
6
|
+
Command,
|
|
7
|
+
CommandContent,
|
|
8
|
+
CommandDivider,
|
|
9
|
+
CommandItem,
|
|
10
|
+
CommandSearch,
|
|
11
|
+
Registry,
|
|
12
|
+
} from ".";
|
|
13
|
+
import { events } from "..";
|
|
14
|
+
import { Modal } from "../modal";
|
|
15
|
+
import { Shortcut, ShortcutBadge } from "../shortcut";
|
|
16
|
+
|
|
17
|
+
export type CommanderProps = {
|
|
18
|
+
open?: boolean;
|
|
19
|
+
query?: string;
|
|
20
|
+
command: Registry;
|
|
21
|
+
};
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script lang="ts">
|
|
25
|
+
let {
|
|
26
|
+
open = $bindable(false),
|
|
27
|
+
query = $bindable(""),
|
|
28
|
+
command,
|
|
29
|
+
}: CommanderProps = $props();
|
|
30
|
+
|
|
31
|
+
let actions = $derived(
|
|
32
|
+
command.actions.filter(
|
|
33
|
+
(action) =>
|
|
34
|
+
action.enabled() &&
|
|
35
|
+
(match(action.id, query) ||
|
|
36
|
+
(action.category && match(action.category, query)) ||
|
|
37
|
+
match(action.name, query) ||
|
|
38
|
+
match(action.description, query)),
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
let categoryHasSelected = $derived(
|
|
43
|
+
actions.reduce(
|
|
44
|
+
(acc, { category, selected }) => ({
|
|
45
|
+
...acc,
|
|
46
|
+
[category]: acc[category] || selected !== undefined,
|
|
47
|
+
}),
|
|
48
|
+
{} as Record<string, boolean>,
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
function handleSelect(action: Action) {
|
|
53
|
+
action.callback();
|
|
54
|
+
open = false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
58
|
+
const action = command.getByShortcut(Shortcut.fromEvent(event));
|
|
59
|
+
if (action && action.enabled()) {
|
|
60
|
+
action.callback();
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
event.stopImmediatePropagation();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
$effect(() => {
|
|
67
|
+
return events.on("keydown", handleKeyDown);
|
|
68
|
+
});
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<Modal
|
|
72
|
+
bind:open
|
|
73
|
+
onoutroend={() => (query = "")}
|
|
74
|
+
class="h-[min(60%,48em)] w-[min(calc(100%-1em),36em)] rounded-lg bg-m3-surface-container p-0"
|
|
75
|
+
>
|
|
76
|
+
<Command>
|
|
77
|
+
<CommandSearch bind:value={query} />
|
|
78
|
+
<CommandDivider />
|
|
79
|
+
<CommandContent>
|
|
80
|
+
{#if actions.length > 0}
|
|
81
|
+
{#each actions as action (action.id)}
|
|
82
|
+
<CommandItem
|
|
83
|
+
onSelect={() => handleSelect(action)}
|
|
84
|
+
title={action.description}
|
|
85
|
+
>
|
|
86
|
+
<action.icon size={14} class="mr-2" />
|
|
87
|
+
<div>{action.category}</div>
|
|
88
|
+
<ChevronRight size={14} />
|
|
89
|
+
{#if categoryHasSelected[action.category]}
|
|
90
|
+
{#if action.selected?.()}
|
|
91
|
+
<Check size={16} class="text-m3-primary" />
|
|
92
|
+
{:else}
|
|
93
|
+
<div class="size-4"></div>
|
|
94
|
+
{/if}
|
|
95
|
+
{/if}
|
|
96
|
+
<div>{action.name}</div>
|
|
97
|
+
{#if action.shortcut}
|
|
98
|
+
<ShortcutBadge class="ml-auto" shortcut={action.shortcut} />
|
|
99
|
+
{/if}
|
|
100
|
+
</CommandItem>
|
|
101
|
+
{/each}
|
|
102
|
+
{:else}
|
|
103
|
+
<div class="text-center">No results found.</div>
|
|
104
|
+
{/if}
|
|
105
|
+
</CommandContent>
|
|
106
|
+
</Command>
|
|
107
|
+
</Modal>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Registry } from ".";
|
|
2
|
+
export type CommanderProps = {
|
|
3
|
+
open?: boolean;
|
|
4
|
+
query?: string;
|
|
5
|
+
command: Registry;
|
|
6
|
+
};
|
|
7
|
+
declare const Commander: import("svelte").Component<CommanderProps, {}, "open" | "query">;
|
|
8
|
+
type Commander = ReturnType<typeof Commander>;
|
|
9
|
+
export default Commander;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Divider as CommandDivider, Header as CommandHeader } from "../common";
|
|
2
|
+
export { Action, Registry } from "./action.svelte";
|
|
3
|
+
export { default as CommandContent } from "./command-content.svelte";
|
|
4
|
+
export { default as CommandInput } from "./command-input.svelte";
|
|
5
|
+
export { default as CommandItem } from "./command-item.svelte";
|
|
6
|
+
export { default as CommandSearch } from "./command-search.svelte";
|
|
7
|
+
export { default as Command } from "./command.svelte";
|
|
8
|
+
export { default as Commander } from "./commander.svelte";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Divider as CommandDivider, Header as CommandHeader } from "../common";
|
|
2
|
+
export { Action, Registry } from "./action.svelte";
|
|
3
|
+
export { default as CommandContent } from "./command-content.svelte";
|
|
4
|
+
export { default as CommandInput } from "./command-input.svelte";
|
|
5
|
+
export { default as CommandItem } from "./command-item.svelte";
|
|
6
|
+
export { default as CommandSearch } from "./command-search.svelte";
|
|
7
|
+
export { default as Command } from "./command.svelte";
|
|
8
|
+
export { default as Commander } from "./commander.svelte";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import { twMerge } from "tailwind-merge";
|
|
4
|
+
import type { ClassName } from "../utils";
|
|
5
|
+
|
|
6
|
+
export type DividerProps = {} & ClassName & HTMLAttributes<HTMLHRElement>;
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
let { class: className, ...restProps }: DividerProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<hr class={twMerge("-mx-1 my-1", className)} {...restProps} />
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
|
+
import type { ClassName } from "../utils";
|
|
3
|
+
export type DividerProps = {} & ClassName & HTMLAttributes<HTMLHRElement>;
|
|
4
|
+
declare const Divider: import("svelte").Component<DividerProps, {}, "">;
|
|
5
|
+
type Divider = ReturnType<typeof Divider>;
|
|
6
|
+
export default Divider;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
5
|
+
import { baseClasses, type Variants } from "../base";
|
|
6
|
+
import type { ClassName } from "../utils";
|
|
7
|
+
|
|
8
|
+
export type HeaderProps = {
|
|
9
|
+
children: Snippet;
|
|
10
|
+
} & ClassName &
|
|
11
|
+
Variants &
|
|
12
|
+
HTMLAttributes<HTMLDivElement>;
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<script lang="ts">
|
|
16
|
+
let {
|
|
17
|
+
children,
|
|
18
|
+
class: className,
|
|
19
|
+
variant = "plain",
|
|
20
|
+
color = "primary",
|
|
21
|
+
shape = "rounded",
|
|
22
|
+
...restProps
|
|
23
|
+
}: HeaderProps = $props();
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<div
|
|
27
|
+
class={twMerge(
|
|
28
|
+
baseClasses({ variant, color, shape }),
|
|
29
|
+
"px-2 py-1 text-xs uppercase",
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
{...restProps}
|
|
33
|
+
>
|
|
34
|
+
{@render children()}
|
|
35
|
+
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import { type Variants } from "../base";
|
|
4
|
+
import type { ClassName } from "../utils";
|
|
5
|
+
export type HeaderProps = {
|
|
6
|
+
children: Snippet;
|
|
7
|
+
} & ClassName & Variants & HTMLAttributes<HTMLDivElement>;
|
|
8
|
+
declare const Header: import("svelte").Component<HeaderProps, {}, "">;
|
|
9
|
+
type Header = ReturnType<typeof Header>;
|
|
10
|
+
export default Header;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class ItemContext {
|
|
2
|
+
#private;
|
|
3
|
+
get input(): string;
|
|
4
|
+
set input(value: string);
|
|
5
|
+
bindInput(getInput: () => string, setInput: (val: string) => void): void;
|
|
6
|
+
get items(): HTMLElement[];
|
|
7
|
+
add(item: HTMLElement): () => void;
|
|
8
|
+
delete(item: HTMLElement): void;
|
|
9
|
+
get focused(): HTMLElement | undefined;
|
|
10
|
+
set focused(value: HTMLElement | undefined);
|
|
11
|
+
handleKeyDown(event: KeyboardEvent): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Bindable } from "../bindable.svelte";
|
|
2
|
+
import { OrderedHTMLElements } from "../ordered-html-elements";
|
|
3
|
+
import { Shortcut } from "../shortcut";
|
|
4
|
+
export class ItemContext {
|
|
5
|
+
#input = new Bindable("");
|
|
6
|
+
#items = new OrderedHTMLElements();
|
|
7
|
+
#focused = $state();
|
|
8
|
+
get input() {
|
|
9
|
+
return this.#input.value;
|
|
10
|
+
}
|
|
11
|
+
set input(value) {
|
|
12
|
+
this.#input.value = value;
|
|
13
|
+
}
|
|
14
|
+
bindInput(getInput, setInput) {
|
|
15
|
+
this.#input.bind(getInput, setInput);
|
|
16
|
+
}
|
|
17
|
+
get items() {
|
|
18
|
+
return this.#items.items;
|
|
19
|
+
}
|
|
20
|
+
add(item) {
|
|
21
|
+
this.#items.add(item);
|
|
22
|
+
this.focused = this.#input.value === "" ? undefined : this.items[0];
|
|
23
|
+
return () => this.delete(item);
|
|
24
|
+
}
|
|
25
|
+
delete(item) {
|
|
26
|
+
this.#items.delete(item);
|
|
27
|
+
this.focused = this.#input.value === "" ? undefined : this.items[0];
|
|
28
|
+
}
|
|
29
|
+
get focused() {
|
|
30
|
+
return this.#focused;
|
|
31
|
+
}
|
|
32
|
+
set focused(value) {
|
|
33
|
+
this.#focused = value;
|
|
34
|
+
}
|
|
35
|
+
handleKeyDown(event) {
|
|
36
|
+
if (!this.items)
|
|
37
|
+
return;
|
|
38
|
+
if (Shortcut.ARROW_UP.matches(event)) {
|
|
39
|
+
if (this.items.length !== 0) {
|
|
40
|
+
if (!this.focused) {
|
|
41
|
+
this.focused = this.items[this.items.length - 1];
|
|
42
|
+
this.focused.scrollIntoView(false);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const index = this.items.indexOf(this.focused);
|
|
46
|
+
this.focused =
|
|
47
|
+
this.items[(index - 1 + this.items.length) % this.items.length];
|
|
48
|
+
this.focused.scrollIntoView(false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
event.stopImmediatePropagation();
|
|
53
|
+
}
|
|
54
|
+
else if (Shortcut.ARROW_DOWN.matches(event)) {
|
|
55
|
+
if (this.items.length !== 0) {
|
|
56
|
+
if (!this.focused) {
|
|
57
|
+
this.focused = this.items[0];
|
|
58
|
+
this.focused.scrollIntoView(false);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const index = this.items.indexOf(this.focused);
|
|
62
|
+
this.focused = this.items[(index + 1) % this.items.length];
|
|
63
|
+
this.focused.scrollIntoView(false);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
event.stopImmediatePropagation();
|
|
68
|
+
}
|
|
69
|
+
else if (Shortcut.ENTER.matches(event)) {
|
|
70
|
+
if (this.focused) {
|
|
71
|
+
this.focused.click();
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
event.stopImmediatePropagation();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import { Button, type ButtonProps } from "../button";
|
|
4
|
+
|
|
5
|
+
export type DialogButtonProps<T> = {
|
|
6
|
+
value: T | undefined;
|
|
7
|
+
autofocus?: boolean;
|
|
8
|
+
onSelect: (value: T | undefined) => void;
|
|
9
|
+
children: Snippet;
|
|
10
|
+
} & Omit<ButtonProps, "value">;
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script lang="ts" generics="T">
|
|
14
|
+
let {
|
|
15
|
+
value,
|
|
16
|
+
onSelect,
|
|
17
|
+
autofocus = false,
|
|
18
|
+
children,
|
|
19
|
+
...restProps
|
|
20
|
+
}: DialogButtonProps<T> = $props();
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<Button onclick={() => onSelect(value)} {autofocus} {...restProps}>
|
|
24
|
+
{@render children()}
|
|
25
|
+
</Button>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import { type ButtonProps } from "../button";
|
|
3
|
+
export type DialogButtonProps<T> = {
|
|
4
|
+
value: T | undefined;
|
|
5
|
+
autofocus?: boolean;
|
|
6
|
+
onSelect: (value: T | undefined) => void;
|
|
7
|
+
children: Snippet;
|
|
8
|
+
} & Omit<ButtonProps, "value">;
|
|
9
|
+
declare function $$render<T>(): {
|
|
10
|
+
props: DialogButtonProps<T>;
|
|
11
|
+
exports: {};
|
|
12
|
+
bindings: "";
|
|
13
|
+
slots: {};
|
|
14
|
+
events: {};
|
|
15
|
+
};
|
|
16
|
+
declare class __sveltets_Render<T> {
|
|
17
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
18
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
19
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
20
|
+
bindings(): "";
|
|
21
|
+
exports(): {};
|
|
22
|
+
}
|
|
23
|
+
interface $$IsomorphicComponent {
|
|
24
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
25
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
26
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
27
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
28
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
29
|
+
}
|
|
30
|
+
declare const DialogButton: $$IsomorphicComponent;
|
|
31
|
+
type DialogButton<T> = InstanceType<typeof DialogButton<T>>;
|
|
32
|
+
export default DialogButton;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { Icon } from "@lucide/svelte";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
5
|
+
import { mergeComponentProps } from "../merge-props";
|
|
6
|
+
import { Modal, type ModalProps } from "../modal";
|
|
7
|
+
|
|
8
|
+
export type DialogProps<T> = {
|
|
9
|
+
ref?: HTMLDialogElement;
|
|
10
|
+
onSelect?: (value: T | undefined) => void;
|
|
11
|
+
icon?: typeof Icon;
|
|
12
|
+
title?: string;
|
|
13
|
+
children: Snippet;
|
|
14
|
+
actions?: Snippet<[{ onSelect: (value: T | undefined) => void }]>;
|
|
15
|
+
} & ModalProps;
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<script lang="ts" generics="T">
|
|
19
|
+
let {
|
|
20
|
+
ref = $bindable(),
|
|
21
|
+
open = $bindable(),
|
|
22
|
+
onSelect,
|
|
23
|
+
class: className,
|
|
24
|
+
icon: IconComponent,
|
|
25
|
+
title,
|
|
26
|
+
children,
|
|
27
|
+
actions,
|
|
28
|
+
...restProps
|
|
29
|
+
}: DialogProps<T> = $props();
|
|
30
|
+
|
|
31
|
+
function handleSelect(value: T | undefined) {
|
|
32
|
+
onSelect?.(value);
|
|
33
|
+
open = false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function handleCancel() {
|
|
37
|
+
onSelect?.(undefined);
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<Modal
|
|
42
|
+
bind:ref
|
|
43
|
+
bind:open
|
|
44
|
+
class={twMerge("w-[min(calc(100%-1em),36em)]", className)}
|
|
45
|
+
{...mergeComponentProps(
|
|
46
|
+
Modal,
|
|
47
|
+
{ role: "dialog", "aria-modal": "true", onCancel: handleCancel },
|
|
48
|
+
restProps,
|
|
49
|
+
)}
|
|
50
|
+
>
|
|
51
|
+
<div class={twMerge("flex flex-col gap-4")}>
|
|
52
|
+
{#if IconComponent}
|
|
53
|
+
<IconComponent class="mx-auto" />
|
|
54
|
+
{/if}
|
|
55
|
+
{#if title}
|
|
56
|
+
<div class={twMerge("text-xl", IconComponent ? "text-center" : "")}>
|
|
57
|
+
{title}
|
|
58
|
+
</div>
|
|
59
|
+
{/if}
|
|
60
|
+
<div>
|
|
61
|
+
{@render children()}
|
|
62
|
+
</div>
|
|
63
|
+
{#if actions}
|
|
64
|
+
<div class="mt-2 flex place-content-end gap-2">
|
|
65
|
+
{@render actions({ onSelect: handleSelect })}
|
|
66
|
+
</div>
|
|
67
|
+
{/if}
|
|
68
|
+
</div>
|
|
69
|
+
</Modal>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Icon } from "@lucide/svelte";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import { type ModalProps } from "../modal";
|
|
4
|
+
export type DialogProps<T> = {
|
|
5
|
+
ref?: HTMLDialogElement;
|
|
6
|
+
onSelect?: (value: T | undefined) => void;
|
|
7
|
+
icon?: typeof Icon;
|
|
8
|
+
title?: string;
|
|
9
|
+
children: Snippet;
|
|
10
|
+
actions?: Snippet<[{
|
|
11
|
+
onSelect: (value: T | undefined) => void;
|
|
12
|
+
}]>;
|
|
13
|
+
} & ModalProps;
|
|
14
|
+
declare function $$render<T>(): {
|
|
15
|
+
props: DialogProps<T>;
|
|
16
|
+
exports: {};
|
|
17
|
+
bindings: "open" | "ref";
|
|
18
|
+
slots: {};
|
|
19
|
+
events: {};
|
|
20
|
+
};
|
|
21
|
+
declare class __sveltets_Render<T> {
|
|
22
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
23
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
24
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
25
|
+
bindings(): "open" | "ref";
|
|
26
|
+
exports(): {};
|
|
27
|
+
}
|
|
28
|
+
interface $$IsomorphicComponent {
|
|
29
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
30
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
31
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
32
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
33
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
34
|
+
}
|
|
35
|
+
declare const Dialog: $$IsomorphicComponent;
|
|
36
|
+
type Dialog<T> = InstanceType<typeof Dialog<T>>;
|
|
37
|
+
export default Dialog;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Icon } from "@lucide/svelte";
|
|
2
|
+
import { type Snippet } from "svelte";
|
|
3
|
+
import type { Variants } from "../base";
|
|
4
|
+
import type { InputProps } from "../input";
|
|
5
|
+
export type ButtonProps<T> = {
|
|
6
|
+
text: string;
|
|
7
|
+
value: T;
|
|
8
|
+
default?: boolean;
|
|
9
|
+
} & Variants;
|
|
10
|
+
type ShowDialogProps<T> = {
|
|
11
|
+
icon?: typeof Icon;
|
|
12
|
+
title?: string;
|
|
13
|
+
inputProps?: InputProps;
|
|
14
|
+
message: Snippet<[]> | string;
|
|
15
|
+
buttons: ButtonProps<T>[];
|
|
16
|
+
};
|
|
17
|
+
type NoticeDialogProps = {
|
|
18
|
+
icon?: typeof Icon;
|
|
19
|
+
title?: string;
|
|
20
|
+
message: Snippet<[]> | string;
|
|
21
|
+
acceptText?: string;
|
|
22
|
+
};
|
|
23
|
+
type ConfirmDialogProps = {
|
|
24
|
+
icon?: typeof Icon;
|
|
25
|
+
title?: string;
|
|
26
|
+
message: Snippet<[]> | string;
|
|
27
|
+
cancelText?: string;
|
|
28
|
+
acceptText?: string;
|
|
29
|
+
};
|
|
30
|
+
type InputDialogProps = {
|
|
31
|
+
icon?: typeof Icon;
|
|
32
|
+
title?: string;
|
|
33
|
+
props: InputProps;
|
|
34
|
+
message: Snippet<[]> | string;
|
|
35
|
+
cancelText?: string;
|
|
36
|
+
acceptText?: string;
|
|
37
|
+
};
|
|
38
|
+
export declare class DialoguerContext {
|
|
39
|
+
message: Snippet<[]> | string;
|
|
40
|
+
icon: typeof Icon | undefined;
|
|
41
|
+
title: string | undefined;
|
|
42
|
+
inputProps: InputProps | undefined;
|
|
43
|
+
buttons: ButtonProps<unknown>[];
|
|
44
|
+
resolve: (value: unknown) => void;
|
|
45
|
+
open: boolean;
|
|
46
|
+
show<T>(dialog: ShowDialogProps<T>): Promise<T>;
|
|
47
|
+
notice(dialog: NoticeDialogProps): Promise<void>;
|
|
48
|
+
confirm(dialog: ConfirmDialogProps): Promise<boolean>;
|
|
49
|
+
input(dialog: InputDialogProps): Promise<string | undefined>;
|
|
50
|
+
}
|
|
51
|
+
export declare function setDialoguerContext(state: DialoguerContext): DialoguerContext;
|
|
52
|
+
export declare function getDialoguerContext(): DialoguerContext;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { getContext, setContext } from "svelte";
|
|
2
|
+
export class DialoguerContext {
|
|
3
|
+
message = $state("");
|
|
4
|
+
icon = $state();
|
|
5
|
+
title = $state();
|
|
6
|
+
inputProps = $state();
|
|
7
|
+
buttons = $state.raw([]);
|
|
8
|
+
resolve = $state(() => { });
|
|
9
|
+
open = $state(false);
|
|
10
|
+
show(dialog) {
|
|
11
|
+
({
|
|
12
|
+
icon: this.icon,
|
|
13
|
+
title: this.title,
|
|
14
|
+
inputProps: this.inputProps,
|
|
15
|
+
message: this.message,
|
|
16
|
+
buttons: this.buttons,
|
|
17
|
+
} = dialog);
|
|
18
|
+
this.open = true;
|
|
19
|
+
return new Promise((newResolve) => (this.resolve = newResolve));
|
|
20
|
+
}
|
|
21
|
+
async notice(dialog) {
|
|
22
|
+
await this.show({
|
|
23
|
+
icon: dialog.icon,
|
|
24
|
+
title: dialog.title,
|
|
25
|
+
inputProps: undefined,
|
|
26
|
+
message: dialog.message,
|
|
27
|
+
buttons: [
|
|
28
|
+
{
|
|
29
|
+
text: dialog.acceptText ?? "OK",
|
|
30
|
+
value: null,
|
|
31
|
+
default: true,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async confirm(dialog) {
|
|
37
|
+
return await this.show({
|
|
38
|
+
icon: dialog.icon,
|
|
39
|
+
title: dialog.title,
|
|
40
|
+
inputProps: undefined,
|
|
41
|
+
message: dialog.message,
|
|
42
|
+
buttons: [
|
|
43
|
+
{
|
|
44
|
+
text: dialog.cancelText ?? "Cancel",
|
|
45
|
+
value: false,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
text: dialog.acceptText ?? "Accept",
|
|
50
|
+
value: true,
|
|
51
|
+
variant: "filled",
|
|
52
|
+
default: true,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async input(dialog) {
|
|
58
|
+
return await this.show({
|
|
59
|
+
icon: dialog.icon,
|
|
60
|
+
title: dialog.title,
|
|
61
|
+
inputProps: dialog.props,
|
|
62
|
+
message: dialog.message,
|
|
63
|
+
buttons: [
|
|
64
|
+
{
|
|
65
|
+
text: dialog.cancelText ?? "Cancel",
|
|
66
|
+
value: "cancel",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
text: dialog.acceptText ?? "Accept",
|
|
70
|
+
value: "accept",
|
|
71
|
+
variant: "filled",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function setDialoguerContext(state) {
|
|
78
|
+
return setContext(DialoguerContext, state);
|
|
79
|
+
}
|
|
80
|
+
export function getDialoguerContext() {
|
|
81
|
+
const ctx = getContext(DialoguerContext);
|
|
82
|
+
if (!ctx)
|
|
83
|
+
throw new Error("DialoguerContext is undefined");
|
|
84
|
+
return ctx;
|
|
85
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import { Input } from "../input";
|
|
4
|
+
import DialogButton from "./dialog-button.svelte";
|
|
5
|
+
import Dialog from "./dialog.svelte";
|
|
6
|
+
import {
|
|
7
|
+
DialoguerContext,
|
|
8
|
+
setDialoguerContext,
|
|
9
|
+
type ButtonProps,
|
|
10
|
+
} from "./dialoguer-context.svelte";
|
|
11
|
+
|
|
12
|
+
const dialog = setDialoguerContext(new DialoguerContext());
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
children: Snippet;
|
|
16
|
+
};
|
|
17
|
+
let { children }: Props = $props();
|
|
18
|
+
|
|
19
|
+
let value: string = $derived(dialog.inputProps?.value ?? "");
|
|
20
|
+
|
|
21
|
+
function getValue(button: ButtonProps<unknown>) {
|
|
22
|
+
if (dialog.inputProps === undefined) {
|
|
23
|
+
return button.value;
|
|
24
|
+
}
|
|
25
|
+
if (button.value === "cancel") {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
if (button.value === "accept") {
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
throw new Error("Invalid state");
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<Dialog
|
|
36
|
+
bind:open={dialog.open}
|
|
37
|
+
icon={dialog.icon}
|
|
38
|
+
title={dialog.title}
|
|
39
|
+
onSelect={dialog.resolve}
|
|
40
|
+
>
|
|
41
|
+
{#if typeof dialog.message === "function"}
|
|
42
|
+
{@render dialog.message()}
|
|
43
|
+
{:else}
|
|
44
|
+
{dialog.message}
|
|
45
|
+
{/if}
|
|
46
|
+
|
|
47
|
+
{#if dialog.inputProps !== undefined}
|
|
48
|
+
<Input class="mt-2 w-full" bind:value autofocus {...dialog.inputProps} />
|
|
49
|
+
{/if}
|
|
50
|
+
|
|
51
|
+
{#snippet actions(props)}
|
|
52
|
+
{#each dialog.buttons as button (button)}
|
|
53
|
+
<DialogButton
|
|
54
|
+
variant={button.variant}
|
|
55
|
+
value={getValue(button)}
|
|
56
|
+
autofocus={button.default}
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
59
|
+
{button.text}
|
|
60
|
+
</DialogButton>
|
|
61
|
+
{/each}
|
|
62
|
+
{/snippet}
|
|
63
|
+
</Dialog>
|
|
64
|
+
|
|
65
|
+
{@render children()}
|