@adriansyah/heroui-svelte 0.0.1 → 0.0.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/README.md +3 -3
- package/dist/components/autocomplete/autocomplete-popover.svelte +1 -1
- package/dist/components/autocomplete/autocomplete-trigger.svelte +45 -21
- package/dist/components/autocomplete/autocomplete-trigger.svelte.d.ts +8 -2
- package/dist/components/autocomplete/autocomplete.svelte +12 -6
- package/dist/components/autocomplete/index.svelte.d.ts +3 -3
- package/dist/components/autocomplete/index.svelte.js +10 -11
- package/dist/components/checkbox/checkbox-content.svelte +7 -6
- package/dist/components/checkbox/checkbox-control.svelte +7 -6
- package/dist/components/checkbox/checkbox.svelte +6 -1
- package/dist/components/filter/index.svelte.js +2 -17
- package/dist/components/list-box/index.svelte.d.ts +20 -0
- package/dist/components/list-box/index.svelte.js +55 -1
- package/dist/components/list-box/list-box-item-indicator.svelte +3 -9
- package/dist/components/list-box/list-box-item.svelte +23 -48
- package/dist/components/list-box/list-box-item.svelte.d.ts +4 -1
- package/dist/components/list-box/list-box.svelte +1 -2
- package/dist/components/modal/modal-trigger.svelte +18 -9
- package/dist/components/modal/modal-trigger.svelte.d.ts +5 -1
- package/dist/components/pagination/pagination-content.svelte +17 -1
- package/dist/components/pagination/pagination-link.svelte +5 -1
- package/dist/components/pagination/pagination-next.svelte +7 -1
- package/dist/components/pagination/pagination-previous.svelte +7 -1
- package/dist/components/pagination/pagination-summary.svelte +7 -1
- package/dist/components/pagination/pagination.svelte +8 -1
- package/dist/components/popover/index.svelte.d.ts +1 -1
- package/dist/components/popover/index.svelte.js +1 -1
- package/dist/components/popover/popover-trigger.svelte +26 -9
- package/dist/components/popover/popover-trigger.svelte.d.ts +12 -7
- package/dist/components/popover/popover.svelte +2 -2
- package/dist/components/popover/popover.svelte.d.ts +2 -4
- package/dist/components/search-input/search-input.svelte +4 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A Svelte 5 wrapper for [HeroUI](https://heroui.com), bringing HeroUI's styling a
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
bun add
|
|
8
|
+
bun add @adriansyah/heroui-svelte @heroui/styles
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
@@ -16,7 +16,7 @@ Import Tailwind CSS and HeroUI styles in your main CSS file:
|
|
|
16
16
|
@import "tailwindcss";
|
|
17
17
|
@import "@heroui/styles";
|
|
18
18
|
|
|
19
|
-
@source "../../node_modules/heroui-svelte/dist";
|
|
19
|
+
@source "../../node_modules/@adriansyah/heroui-svelte/dist";
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
Adjust the `@source` path to match your project structure.
|
|
@@ -27,7 +27,7 @@ Import components from `heroui-svelte` and use them in your Svelte 5 components.
|
|
|
27
27
|
|
|
28
28
|
```svelte
|
|
29
29
|
<script lang="ts">
|
|
30
|
-
import { Button } from "heroui-svelte";
|
|
30
|
+
import { Button } from "@adriansyah/heroui-svelte";
|
|
31
31
|
</script>
|
|
32
32
|
|
|
33
33
|
<Button>Get started</Button>
|
|
@@ -1,28 +1,52 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
-
import {
|
|
3
|
+
import { AutocompleteContext } from "../../index.js";
|
|
4
4
|
import { autocompleteVariants } from "@heroui/styles";
|
|
5
|
+
import AutocompleteClearButton from "./autocomplete-clear-button.svelte";
|
|
6
|
+
import AutocompleteIndicator from "./autocomplete-indicator.svelte";
|
|
7
|
+
import AutocompleteValue from "./autocomplete-value.svelte";
|
|
8
|
+
import type { Snippet } from "svelte";
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
type Props = HTMLAttributes<HTMLDivElement> & {
|
|
11
|
+
child?: Snippet<[{ props: HTMLAttributes<any>; ctx: AutocompleteContext }]>;
|
|
12
|
+
};
|
|
7
13
|
|
|
8
|
-
const { children, ...props }: Props = $props();
|
|
9
|
-
const
|
|
14
|
+
const { children, child, ...props }: Props = $props();
|
|
15
|
+
const ctx = AutocompleteContext.get();
|
|
16
|
+
const popover = ctx.popover;
|
|
17
|
+
const merged: HTMLAttributes<any> = $derived({
|
|
18
|
+
...props,
|
|
19
|
+
tabindex: 0,
|
|
20
|
+
role: "button",
|
|
21
|
+
"data-open": popover.open,
|
|
22
|
+
"data-popover": popover.node?.popover,
|
|
23
|
+
onclick: (ev) => {
|
|
24
|
+
props.onclick?.(ev);
|
|
25
|
+
popover.toggle(undefined, ev.currentTarget);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
10
28
|
</script>
|
|
11
29
|
|
|
12
|
-
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
{#if child}
|
|
31
|
+
{@render child({ props: merged, ctx })}
|
|
32
|
+
{:else}
|
|
33
|
+
<div
|
|
34
|
+
{...merged}
|
|
35
|
+
data-slot="autocomplete-trigger"
|
|
36
|
+
class={autocompleteVariants().trigger({
|
|
37
|
+
...ctx.heroui,
|
|
38
|
+
class: [
|
|
39
|
+
props?.class?.toString(),
|
|
40
|
+
"data-[open=true]:[[data-popover=''],[data-popover='auto']]:pointer-events-none",
|
|
41
|
+
],
|
|
42
|
+
})}
|
|
43
|
+
>
|
|
44
|
+
{#if children}
|
|
45
|
+
{@render children()}
|
|
46
|
+
{:else}
|
|
47
|
+
<AutocompleteValue placeholder={props.placeholder ?? undefined} />
|
|
48
|
+
<AutocompleteIndicator />
|
|
49
|
+
<AutocompleteClearButton />
|
|
50
|
+
{/if}
|
|
51
|
+
</div>
|
|
52
|
+
{/if}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { HTMLAttributes } from "svelte/elements";
|
|
2
|
-
|
|
3
|
-
}
|
|
2
|
+
import { AutocompleteContext } from "../../index.js";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
type Props = HTMLAttributes<HTMLDivElement> & {
|
|
5
|
+
child?: Snippet<[{
|
|
6
|
+
props: HTMLAttributes<any>;
|
|
7
|
+
ctx: AutocompleteContext;
|
|
8
|
+
}]>;
|
|
9
|
+
};
|
|
4
10
|
declare const AutocompleteTrigger: import("svelte").Component<Props, {}, "">;
|
|
5
11
|
type AutocompleteTrigger = ReturnType<typeof AutocompleteTrigger>;
|
|
6
12
|
export default AutocompleteTrigger;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
-
import {
|
|
4
|
-
Popover,
|
|
5
|
-
AutocompleteContext,
|
|
6
|
-
type AutocompleteOpts,
|
|
7
|
-
} from "../../index.js";
|
|
3
|
+
import { Popover, AutocompleteContext, type AutocompleteOpts } from "../../index.js";
|
|
8
4
|
import { box } from "svelte-utils";
|
|
5
|
+
import { autocompleteVariants } from "@heroui/styles";
|
|
9
6
|
|
|
10
7
|
type Props = HTMLAttributes<HTMLElement> &
|
|
11
8
|
Partial<AutocompleteOpts> & {
|
|
@@ -48,5 +45,14 @@
|
|
|
48
45
|
</script>
|
|
49
46
|
|
|
50
47
|
<Popover {offset} {placement}>
|
|
51
|
-
|
|
48
|
+
<div
|
|
49
|
+
{...props}
|
|
50
|
+
class={autocompleteVariants().base({
|
|
51
|
+
fullWidth,
|
|
52
|
+
variant,
|
|
53
|
+
class: props.class?.toString(),
|
|
54
|
+
})}
|
|
55
|
+
>
|
|
56
|
+
{@render props.children?.()}
|
|
57
|
+
</div>
|
|
52
58
|
</Popover>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { AutocompleteVariants } from "@heroui/styles";
|
|
2
|
-
import { Context, type Box, type Getter } from "svelte-utils";
|
|
3
|
-
import { ListBoxContext,
|
|
2
|
+
import { Context, type Box, type Getter, PopoverState } from "svelte-utils";
|
|
3
|
+
import { ListBoxContext, type ListBoxOpts, type PopoverContextOpts } from "../../index.js";
|
|
4
4
|
export type AutocompleteOpts = ListBoxOpts & AutocompleteVariants & PopoverContextOpts & {
|
|
5
5
|
invalid?: boolean;
|
|
6
6
|
};
|
|
7
7
|
export declare class AutocompleteContext extends Context {
|
|
8
8
|
opts: AutocompleteOpts;
|
|
9
|
-
|
|
9
|
+
popover: PopoverState;
|
|
10
10
|
listboxCtx: ListBoxContext;
|
|
11
11
|
constructor(opts: Getter<AutocompleteOpts>, selected: Box<string[]>);
|
|
12
12
|
autoCloseOnFocusLost(): () => void;
|
|
@@ -1,34 +1,33 @@
|
|
|
1
|
-
import { Context, isEventTargetInAny, watch } from "svelte-utils";
|
|
2
|
-
import { ListBoxContext
|
|
1
|
+
import { Context, isEventTargetInAny, watch, PopoverState } from "svelte-utils";
|
|
2
|
+
import { ListBoxContext } from "../../index.js";
|
|
3
3
|
export class AutocompleteContext extends Context {
|
|
4
4
|
opts;
|
|
5
|
-
|
|
5
|
+
popover = new PopoverState();
|
|
6
6
|
listboxCtx;
|
|
7
7
|
constructor(opts, selected) {
|
|
8
8
|
super();
|
|
9
9
|
this.opts = $derived.by(opts);
|
|
10
|
-
this.popoverCtx = new PopoverContext(opts);
|
|
11
10
|
this.listboxCtx = new ListBoxContext(opts, selected);
|
|
12
11
|
this.autoCloseOnFocusLost();
|
|
13
12
|
this.autoCloseOnSingleSelect();
|
|
14
13
|
}
|
|
15
14
|
autoCloseOnFocusLost() {
|
|
16
15
|
const handleWindowClick = (ev) => {
|
|
17
|
-
if (!this.
|
|
16
|
+
if (!this.popover.node?.matches(":popover-open"))
|
|
18
17
|
return;
|
|
19
|
-
if (isEventTargetInAny(ev, this.
|
|
18
|
+
if (isEventTargetInAny(ev, this.popover.anchor, this.popover.node)) {
|
|
20
19
|
return;
|
|
21
20
|
}
|
|
22
21
|
this.close();
|
|
23
22
|
};
|
|
24
23
|
const handleEscapeKey = (ev) => {
|
|
25
|
-
const focused = this.
|
|
24
|
+
const focused = this.popover.node?.matches(":focus-within") || this.popover.anchor?.matches(":focus-within");
|
|
26
25
|
if (ev.code !== "Escape" || !focused)
|
|
27
26
|
return;
|
|
28
27
|
ev.preventDefault();
|
|
29
28
|
ev.stopImmediatePropagation();
|
|
30
29
|
this.close();
|
|
31
|
-
this.
|
|
30
|
+
this.popover.anchor?.focus();
|
|
32
31
|
};
|
|
33
32
|
window.addEventListener("click", handleWindowClick);
|
|
34
33
|
window.addEventListener("keydown", handleEscapeKey);
|
|
@@ -45,13 +44,13 @@ export class AutocompleteContext extends Context {
|
|
|
45
44
|
});
|
|
46
45
|
}
|
|
47
46
|
close() {
|
|
48
|
-
this.
|
|
47
|
+
this.popover.hide();
|
|
49
48
|
}
|
|
50
49
|
open(source) {
|
|
51
|
-
this.
|
|
50
|
+
this.popover.node?.showPopover({ source });
|
|
52
51
|
}
|
|
53
52
|
toggle(source) {
|
|
54
|
-
this.
|
|
53
|
+
this.popover.node?.togglePopover({ source });
|
|
55
54
|
}
|
|
56
55
|
get props() {
|
|
57
56
|
return {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { checkboxVariants } from "@heroui/styles";
|
|
3
3
|
import type { HTMLLabelAttributes } from "svelte/elements";
|
|
4
4
|
import { InputContext, Input } from "../../index.js";
|
|
5
|
+
import CheckboxControl from "./checkbox-control.svelte";
|
|
5
6
|
|
|
6
7
|
type Props = HTMLLabelAttributes;
|
|
7
8
|
|
|
@@ -16,11 +17,11 @@
|
|
|
16
17
|
);
|
|
17
18
|
</script>
|
|
18
19
|
|
|
19
|
-
<label
|
|
20
|
-
{...props}
|
|
21
|
-
data-slot="checkbox-content"
|
|
22
|
-
class={contentClass}
|
|
23
|
-
>
|
|
20
|
+
<label {...props} data-slot="checkbox-content" class={contentClass}>
|
|
24
21
|
<Input headless hidden type="checkbox" />
|
|
25
|
-
{
|
|
22
|
+
{#if props.children}
|
|
23
|
+
{@render props.children()}
|
|
24
|
+
{:else}
|
|
25
|
+
<CheckboxControl />
|
|
26
|
+
{/if}
|
|
26
27
|
</label>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { checkboxVariants } from "@heroui/styles";
|
|
3
3
|
import type { HTMLAttributes } from "svelte/elements";
|
|
4
4
|
import { InputContext } from "../../index.js";
|
|
5
|
+
import CheckboxIndicator from "./checkbox-indicator.svelte";
|
|
5
6
|
|
|
6
7
|
type Props = HTMLAttributes<HTMLSpanElement>;
|
|
7
8
|
|
|
@@ -16,10 +17,10 @@
|
|
|
16
17
|
);
|
|
17
18
|
</script>
|
|
18
19
|
|
|
19
|
-
<span
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{
|
|
20
|
+
<span {...props} data-slot="checkbox-control" class={controlClass}>
|
|
21
|
+
{#if props.children}
|
|
22
|
+
{@render props.children()}
|
|
23
|
+
{:else}
|
|
24
|
+
<CheckboxIndicator />
|
|
25
|
+
{/if}
|
|
25
26
|
</span>
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import type { HTMLAttributes } from "svelte/elements";
|
|
4
4
|
import { type InputOpts, InputContext } from "../../index.js";
|
|
5
5
|
import { box } from "svelte-utils";
|
|
6
|
+
import CheckboxContent from "./checkbox-content.svelte";
|
|
6
7
|
|
|
7
8
|
type Props = InputOpts &
|
|
8
9
|
HTMLAttributes<HTMLDivElement> & {
|
|
@@ -56,5 +57,9 @@
|
|
|
56
57
|
data-indeterminate={indeterminate}
|
|
57
58
|
class={checkboxClass}
|
|
58
59
|
>
|
|
59
|
-
{
|
|
60
|
+
{#if props.children}
|
|
61
|
+
{@render props.children()}
|
|
62
|
+
{:else}
|
|
63
|
+
<CheckboxContent />
|
|
64
|
+
{/if}
|
|
60
65
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { untrack } from "svelte";
|
|
2
|
-
import { box, Context } from "svelte-utils";
|
|
2
|
+
import { box, boxLink, Context } from "svelte-utils";
|
|
3
3
|
export class FilterContext extends Context {
|
|
4
4
|
#opts;
|
|
5
5
|
#query;
|
|
@@ -32,21 +32,6 @@ export class FilterContext extends Context {
|
|
|
32
32
|
this.#query = query;
|
|
33
33
|
}
|
|
34
34
|
sync(box) {
|
|
35
|
-
|
|
36
|
-
box.current;
|
|
37
|
-
untrack(() => {
|
|
38
|
-
if (box.current === this.query)
|
|
39
|
-
return;
|
|
40
|
-
this.query = box.current;
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
$effect(() => {
|
|
44
|
-
this.query;
|
|
45
|
-
untrack(() => {
|
|
46
|
-
if (box.current === this.query)
|
|
47
|
-
return;
|
|
48
|
-
box.current = this.query;
|
|
49
|
-
});
|
|
50
|
-
});
|
|
35
|
+
boxLink(box, this.#query);
|
|
51
36
|
}
|
|
52
37
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Context, type Box, type Getter } from "svelte-utils";
|
|
2
|
+
import { FilterContext } from "../filter";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
4
|
export type ListBoxOpts = {
|
|
3
5
|
disabled?: boolean;
|
|
4
6
|
multiple?: boolean;
|
|
@@ -15,3 +17,21 @@ export declare class ListBoxContext extends Context {
|
|
|
15
17
|
setSelected(value: string, checked: boolean): void;
|
|
16
18
|
constructor(opts: Getter<ListBoxOpts>, selected?: Box<string[]>);
|
|
17
19
|
}
|
|
20
|
+
export type ListBoxItemOpts = {
|
|
21
|
+
value: string;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export declare class ListBoxItemContext extends Context {
|
|
25
|
+
#private;
|
|
26
|
+
readonly listbox: ListBoxContext;
|
|
27
|
+
readonly opts: ListBoxItemOpts;
|
|
28
|
+
readonly filter?: FilterContext;
|
|
29
|
+
get selected(): boolean;
|
|
30
|
+
set selected(value: boolean);
|
|
31
|
+
get value(): string;
|
|
32
|
+
constructor(opts: Getter<ListBoxItemOpts>, selected?: Box<boolean>);
|
|
33
|
+
toggle: () => void;
|
|
34
|
+
get visible(): boolean;
|
|
35
|
+
get disabled(): boolean | undefined;
|
|
36
|
+
props: (props?: HTMLAttributes<HTMLDivElement>) => HTMLAttributes<HTMLDivElement>;
|
|
37
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { box, boxArray, Context } from "svelte-utils";
|
|
1
|
+
import { box, boxArray, boxLink, Context } from "svelte-utils";
|
|
2
|
+
import { FilterContext } from "../filter";
|
|
3
|
+
import { onDestroy } from "svelte";
|
|
2
4
|
export class ListBoxContext extends Context {
|
|
3
5
|
#opts;
|
|
4
6
|
get opts() { return this.#opts; }
|
|
@@ -23,3 +25,55 @@ export class ListBoxContext extends Context {
|
|
|
23
25
|
this.#selected = selected;
|
|
24
26
|
}
|
|
25
27
|
}
|
|
28
|
+
export class ListBoxItemContext extends Context {
|
|
29
|
+
listbox;
|
|
30
|
+
opts;
|
|
31
|
+
filter;
|
|
32
|
+
#selected;
|
|
33
|
+
get selected() { return this.#selected.current; }
|
|
34
|
+
set selected(value) { this.#selected.current = value; }
|
|
35
|
+
get value() { return this.opts.value; }
|
|
36
|
+
constructor(opts, selected = box(false)) {
|
|
37
|
+
super();
|
|
38
|
+
this.listbox = ListBoxContext.get();
|
|
39
|
+
this.filter = FilterContext.getOr();
|
|
40
|
+
this.opts = $derived.by(opts);
|
|
41
|
+
this.#selected = selected;
|
|
42
|
+
$effect(() => this.filter?.register(this.value));
|
|
43
|
+
onDestroy(() => {
|
|
44
|
+
this.listbox.setSelected(this.value, false);
|
|
45
|
+
});
|
|
46
|
+
boxLink(box(() => this.listbox.isSelected(this.value), v => this.listbox.setSelected(this.value, v)), selected);
|
|
47
|
+
}
|
|
48
|
+
toggle = () => {
|
|
49
|
+
this.selected = !this.selected;
|
|
50
|
+
};
|
|
51
|
+
get visible() {
|
|
52
|
+
return this.filter === undefined || this.filter.matches(this.value);
|
|
53
|
+
}
|
|
54
|
+
get disabled() {
|
|
55
|
+
return this.opts.disabled || this.listbox.opts.disabled;
|
|
56
|
+
}
|
|
57
|
+
props = (props) => {
|
|
58
|
+
return {
|
|
59
|
+
onkeydown: ev => {
|
|
60
|
+
this.#onKeyDown(ev);
|
|
61
|
+
props?.onkeydown?.(ev);
|
|
62
|
+
},
|
|
63
|
+
onclick: ev => {
|
|
64
|
+
this.toggle();
|
|
65
|
+
props?.onclick?.(ev);
|
|
66
|
+
},
|
|
67
|
+
"data-disabled": this.disabled,
|
|
68
|
+
"aria-disabled": this.disabled,
|
|
69
|
+
tabindex: 0,
|
|
70
|
+
role: "checkbox"
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
#onKeyDown(ev) {
|
|
74
|
+
if (ev.code === "Space" ||
|
|
75
|
+
(ev.code === "Enter" && ev.target === ev.currentTarget)) {
|
|
76
|
+
this.toggle();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
3
|
import { listboxItemVariants } from "@heroui/styles";
|
|
4
|
-
import {
|
|
4
|
+
import { ListBoxItemContext } from "./index.svelte";
|
|
5
5
|
|
|
6
6
|
let { ...props }: HTMLAttributes<HTMLDivElement> = $props();
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
const ctx = ListBoxContext.get();
|
|
10
|
-
const value = $derived(
|
|
11
|
-
node?.closest(".list-box-item")?.getAttribute("data-value"),
|
|
12
|
-
);
|
|
13
|
-
const selected = $derived(value && ctx.isSelected(value));
|
|
8
|
+
const ctx = ListBoxItemContext.get();
|
|
14
9
|
</script>
|
|
15
10
|
|
|
16
11
|
<div
|
|
17
12
|
{...props}
|
|
18
|
-
bind:this={node}
|
|
19
13
|
data-slot="list-box-item-indicator"
|
|
20
14
|
class={listboxItemVariants().indicator({ class: props.class?.toString() })}
|
|
21
15
|
>
|
|
@@ -26,7 +20,7 @@
|
|
|
26
20
|
role="presentation"
|
|
27
21
|
stroke="currentColor"
|
|
28
22
|
stroke-dasharray={22}
|
|
29
|
-
stroke-dashoffset={selected ? 44 : 66}
|
|
23
|
+
stroke-dashoffset={ctx.selected ? 44 : 66}
|
|
30
24
|
stroke-linecap="round"
|
|
31
25
|
stroke-linejoin="round"
|
|
32
26
|
stroke-width={2}
|
|
@@ -1,78 +1,53 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
3
|
import { listboxItemVariants } from "@heroui/styles";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { ListBoxItemContext } from "../../index.js";
|
|
5
|
+
import { box } from "svelte-utils";
|
|
6
|
+
import type { Snippet } from "svelte";
|
|
7
7
|
|
|
8
8
|
let {
|
|
9
|
-
value,
|
|
9
|
+
value = crypto.randomUUID(),
|
|
10
10
|
disabled,
|
|
11
11
|
selected = $bindable(),
|
|
12
|
+
child,
|
|
12
13
|
...props
|
|
13
14
|
}: HTMLAttributes<HTMLDivElement> & {
|
|
14
|
-
value
|
|
15
|
+
value?: string;
|
|
15
16
|
selected?: boolean;
|
|
16
17
|
disabled?: boolean;
|
|
18
|
+
child?: Snippet<[ListBoxItemContext]>;
|
|
17
19
|
} = $props();
|
|
18
20
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(curr) => {
|
|
26
|
-
if (curr === ctx.isSelected(value)) return;
|
|
27
|
-
ctx.setSelected(value, curr ?? ctx.isSelected(value));
|
|
28
|
-
},
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
watch(
|
|
32
|
-
() => ctx.isSelected(value),
|
|
33
|
-
(curr) => {
|
|
34
|
-
if (curr === selected) return;
|
|
35
|
-
selected = curr;
|
|
36
|
-
},
|
|
21
|
+
const ctx = new ListBoxItemContext(
|
|
22
|
+
() => ({ value, disabled }),
|
|
23
|
+
box(
|
|
24
|
+
() => !!selected,
|
|
25
|
+
(v) => (selected = v),
|
|
26
|
+
),
|
|
37
27
|
);
|
|
38
|
-
|
|
39
|
-
$effect(() => () => ctx.setSelected(value, false));
|
|
40
|
-
$effect(() => filter?.register(value));
|
|
41
28
|
</script>
|
|
42
29
|
|
|
43
|
-
{#if
|
|
30
|
+
{#if child}
|
|
31
|
+
{@render child(ctx)}
|
|
32
|
+
{:else if ctx.visible}
|
|
44
33
|
<div
|
|
45
|
-
{...props}
|
|
46
|
-
onkeydown={(ev) => {
|
|
47
|
-
if (
|
|
48
|
-
ev.code === "Space" ||
|
|
49
|
-
(ev.code === "Enter" && ev.target === ev.currentTarget)
|
|
50
|
-
) {
|
|
51
|
-
ev.preventDefault();
|
|
52
|
-
ctx.setSelected(value, !selected);
|
|
53
|
-
}
|
|
54
|
-
}}
|
|
55
|
-
onclick={() => ctx.setSelected(value, !selected)}
|
|
56
|
-
role="checkbox"
|
|
57
|
-
tabindex="0"
|
|
58
|
-
data-value={value}
|
|
59
|
-
data-disabled={ctx.opts.disabled ?? disabled}
|
|
34
|
+
{...ctx.props(props)}
|
|
60
35
|
data-slot="list-box-item"
|
|
61
36
|
class={listboxItemVariants().item({ class: props.class?.toString() })}
|
|
62
37
|
>
|
|
63
|
-
{#if ctx.opts.name}
|
|
38
|
+
{#if ctx.listbox.opts.name}
|
|
64
39
|
<input
|
|
65
40
|
{@attach (node) => {
|
|
66
41
|
const form = node.form;
|
|
67
42
|
if (!form) return;
|
|
68
|
-
const reset = () => ctx.
|
|
43
|
+
const reset = () => (ctx.selected = false);
|
|
69
44
|
form.addEventListener("reset", reset);
|
|
70
45
|
return () => form.removeEventListener("reset", reset);
|
|
71
46
|
}}
|
|
72
|
-
checked={ctx.
|
|
73
|
-
disabled={ctx.
|
|
74
|
-
required={ctx.opts.required}
|
|
75
|
-
name={ctx.opts.name}
|
|
47
|
+
checked={ctx.selected}
|
|
48
|
+
disabled={ctx.disabled}
|
|
49
|
+
required={ctx.listbox.opts.required}
|
|
50
|
+
name={ctx.listbox.opts.name}
|
|
76
51
|
type={"checkbox"}
|
|
77
52
|
{value}
|
|
78
53
|
hidden
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { HTMLAttributes } from "svelte/elements";
|
|
2
|
+
import { ListBoxItemContext } from "../../index.js";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
2
4
|
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
3
|
-
value
|
|
5
|
+
value?: string;
|
|
4
6
|
selected?: boolean;
|
|
5
7
|
disabled?: boolean;
|
|
8
|
+
child?: Snippet<[ListBoxItemContext]>;
|
|
6
9
|
};
|
|
7
10
|
declare const ListBoxItem: import("svelte").Component<$$ComponentProps, {}, "selected">;
|
|
8
11
|
type ListBoxItem = ReturnType<typeof ListBoxItem>;
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
3
|
import Button from "../button/button.svelte";
|
|
3
4
|
import { ModalContext } from "./index.svelte";
|
|
4
|
-
import type { ComponentProps } from "svelte";
|
|
5
|
+
import type { ComponentProps, Snippet } from "svelte";
|
|
5
6
|
|
|
6
7
|
const {
|
|
7
8
|
action = "show",
|
|
9
|
+
child,
|
|
8
10
|
...props
|
|
9
11
|
}: ComponentProps<typeof Button> & {
|
|
10
12
|
action?: "show" | "close";
|
|
13
|
+
child?: Snippet<[{ props: HTMLAttributes<any> }]>;
|
|
11
14
|
} = $props();
|
|
12
15
|
|
|
13
16
|
const ctx = ModalContext.get();
|
|
17
|
+
const merged: HTMLAttributes<any> = $derived({
|
|
18
|
+
...props,
|
|
19
|
+
onclick: (ev) => {
|
|
20
|
+
ctx.dialog.toggle?.();
|
|
21
|
+
props.onclick?.(ev);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
14
24
|
</script>
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
>
|
|
22
|
-
|
|
23
|
-
</Button>
|
|
26
|
+
{#if child}
|
|
27
|
+
{@render child({ props: merged })}
|
|
28
|
+
{:else}
|
|
29
|
+
<Button {...merged} type="button">
|
|
30
|
+
{@render props.children?.()}
|
|
31
|
+
</Button>
|
|
32
|
+
{/if}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
1
2
|
import Button from "../button/button.svelte";
|
|
2
|
-
import type { ComponentProps } from "svelte";
|
|
3
|
+
import type { ComponentProps, Snippet } from "svelte";
|
|
3
4
|
type $$ComponentProps = ComponentProps<typeof Button> & {
|
|
4
5
|
action?: "show" | "close";
|
|
6
|
+
child?: Snippet<[{
|
|
7
|
+
props: HTMLAttributes<any>;
|
|
8
|
+
}]>;
|
|
5
9
|
};
|
|
6
10
|
declare const ModalTrigger: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
11
|
type ModalTrigger = ReturnType<typeof ModalTrigger>;
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
3
|
import PaginationState from "./index.svelte";
|
|
4
4
|
import { paginationVariants } from "@heroui/styles";
|
|
5
|
+
import PaginationItem from "./pagination-item.svelte";
|
|
6
|
+
import PaginationPrevious from "./pagination-previous.svelte";
|
|
7
|
+
import PaginationNext from "./pagination-next.svelte";
|
|
8
|
+
import PaginationLink from "./pagination-link.svelte";
|
|
5
9
|
|
|
6
10
|
const props: HTMLAttributes<HTMLUListElement> = $props();
|
|
7
11
|
const pagination = PaginationState.get();
|
|
@@ -13,5 +17,17 @@
|
|
|
13
17
|
class: props.class?.toString(),
|
|
14
18
|
})}
|
|
15
19
|
>
|
|
16
|
-
{
|
|
20
|
+
{#if props.children}
|
|
21
|
+
{@render props.children()}
|
|
22
|
+
{:else}
|
|
23
|
+
<PaginationItem>
|
|
24
|
+
<PaginationPrevious />
|
|
25
|
+
</PaginationItem>
|
|
26
|
+
<PaginationItem>
|
|
27
|
+
<PaginationLink disabled={pagination.total === 0} page={pagination.page} />
|
|
28
|
+
</PaginationItem>
|
|
29
|
+
<PaginationItem>
|
|
30
|
+
<PaginationNext />
|
|
31
|
+
</PaginationItem>
|
|
32
|
+
{/if}
|
|
17
33
|
</ul>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
3
3
|
import PaginationState from "./index.svelte";
|
|
4
4
|
import { paginationVariants } from "@heroui/styles";
|
|
5
|
+
import { PaginationNextIcon } from ".";
|
|
5
6
|
|
|
6
7
|
const props: HTMLButtonAttributes = $props();
|
|
7
8
|
const pagination = PaginationState.get();
|
|
@@ -19,5 +20,10 @@
|
|
|
19
20
|
class: ["pagination__link--nav"],
|
|
20
21
|
})}
|
|
21
22
|
>
|
|
22
|
-
{
|
|
23
|
+
{#if props.children}
|
|
24
|
+
{@render props.children()}
|
|
25
|
+
{:else}
|
|
26
|
+
Next
|
|
27
|
+
<PaginationNextIcon />
|
|
28
|
+
{/if}
|
|
23
29
|
</button>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
3
3
|
import PaginationState from "./index.svelte";
|
|
4
4
|
import { paginationVariants } from "@heroui/styles";
|
|
5
|
+
import PaginationPreviousIcon from "./pagination-previous-icon.svelte";
|
|
5
6
|
|
|
6
7
|
const props: HTMLButtonAttributes = $props();
|
|
7
8
|
const pagination = PaginationState.get();
|
|
@@ -19,5 +20,10 @@
|
|
|
19
20
|
class: ["pagination__link--nav"],
|
|
20
21
|
})}
|
|
21
22
|
>
|
|
22
|
-
{
|
|
23
|
+
{#if props.children}
|
|
24
|
+
{@render props.children()}
|
|
25
|
+
{:else}
|
|
26
|
+
<PaginationPreviousIcon />
|
|
27
|
+
Prev
|
|
28
|
+
{/if}
|
|
23
29
|
</button>
|
|
@@ -19,5 +19,11 @@
|
|
|
19
19
|
class: props.class?.toString(),
|
|
20
20
|
})}
|
|
21
21
|
>
|
|
22
|
-
{
|
|
22
|
+
{#if children}
|
|
23
|
+
{@render children(pagination)}
|
|
24
|
+
{:else if pagination.total === 0}
|
|
25
|
+
Showing empty
|
|
26
|
+
{:else}
|
|
27
|
+
Showing {pagination.start} ~ {pagination.end} of {pagination.total}
|
|
28
|
+
{/if}
|
|
23
29
|
</div>
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import type { HTMLAttributes } from "svelte/elements";
|
|
5
5
|
import PaginationState from "./index.svelte";
|
|
6
6
|
import { box } from "svelte-utils";
|
|
7
|
+
import PaginationSummary from "./pagination-summary.svelte";
|
|
8
|
+
import PaginationContent from "./pagination-content.svelte";
|
|
7
9
|
|
|
8
10
|
let {
|
|
9
11
|
page = $bindable(1),
|
|
@@ -36,5 +38,10 @@
|
|
|
36
38
|
class: props.class?.toString(),
|
|
37
39
|
})}
|
|
38
40
|
>
|
|
39
|
-
{
|
|
41
|
+
{#if props.children}
|
|
42
|
+
{@render props.children()}
|
|
43
|
+
{:else}
|
|
44
|
+
<PaginationSummary />
|
|
45
|
+
<PaginationContent />
|
|
46
|
+
{/if}
|
|
40
47
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, PopoverState, type Box, type Getter } from "svelte-utils";
|
|
1
|
+
import { Context, PopoverState, type Box, type Getter } from "@adriansyah/svelte-utils";
|
|
2
2
|
export type PopoverContextOpts = {
|
|
3
3
|
placement?: "bottom" | "top" | "left" | "right";
|
|
4
4
|
offset?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, getPopoverArea, PopoverState } from "svelte-utils";
|
|
1
|
+
import { Context, getPopoverArea, PopoverState } from "@adriansyah/svelte-utils";
|
|
2
2
|
export class PopoverContext extends Context {
|
|
3
3
|
get open() { return this.popover.open; }
|
|
4
4
|
set open(open) { this.popover.open = open; }
|
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { ComponentProps } from "svelte";
|
|
2
|
+
import type { ComponentProps, Snippet } from "svelte";
|
|
3
3
|
import Button from "../button/button.svelte";
|
|
4
4
|
import { PopoverContext } from "./index.svelte";
|
|
5
|
+
import type { PopoverState } from "@adriansyah/svelte-utils";
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
type Props = ComponentProps<typeof Button> & {
|
|
8
|
+
child?: Snippet<
|
|
9
|
+
[{ props: ComponentProps<typeof Button>; popover: PopoverState }]
|
|
10
|
+
>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const { child, ...props }: Props = $props();
|
|
7
14
|
|
|
8
15
|
const ctx = PopoverContext.get();
|
|
16
|
+
const merged: ComponentProps<typeof Button> = $derived({
|
|
17
|
+
...props,
|
|
18
|
+
...{
|
|
19
|
+
type: "button",
|
|
20
|
+
command: "toggle-popover",
|
|
21
|
+
commandfor: ctx.popover.nodeId,
|
|
22
|
+
pressed: ctx.popover.open,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
9
25
|
</script>
|
|
10
26
|
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/>
|
|
27
|
+
{#if child}
|
|
28
|
+
{@render child({
|
|
29
|
+
props: merged,
|
|
30
|
+
popover: ctx.popover,
|
|
31
|
+
})}
|
|
32
|
+
{:else}
|
|
33
|
+
<Button {...merged} />
|
|
34
|
+
{/if}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import type { ComponentProps, Snippet } from "svelte";
|
|
2
|
+
import Button from "../button/button.svelte";
|
|
3
|
+
import type { PopoverState } from "@adriansyah/svelte-utils";
|
|
4
|
+
type Props = ComponentProps<typeof Button> & {
|
|
5
|
+
child?: Snippet<[
|
|
6
|
+
{
|
|
7
|
+
props: ComponentProps<typeof Button>;
|
|
8
|
+
popover: PopoverState;
|
|
9
|
+
}
|
|
10
|
+
]>;
|
|
11
|
+
};
|
|
12
|
+
declare const PopoverTrigger: import("svelte").Component<Props, {}, "">;
|
|
8
13
|
type PopoverTrigger = ReturnType<typeof PopoverTrigger>;
|
|
9
14
|
export default PopoverTrigger;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
children,
|
|
18
18
|
}: Partial<Props> = $props();
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
new PopoverContext(
|
|
21
21
|
() => ({
|
|
22
22
|
fallbackAnchor,
|
|
23
23
|
offset,
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
() => open,
|
|
28
28
|
(v) => (open = v),
|
|
29
29
|
),
|
|
30
|
-
|
|
30
|
+
);
|
|
31
31
|
</script>
|
|
32
32
|
|
|
33
33
|
{@render children?.()}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type PopoverContextOpts } from "./index.svelte";
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
declare const Popover: import("svelte").Component<Partial<Omit<PopoverContextOpts, "open" | "fallbackAnchor"> & {
|
|
4
4
|
open?: boolean;
|
|
5
5
|
fallbackAnchor?: HTMLElement;
|
|
6
6
|
children?: Snippet;
|
|
7
|
-
}>, {
|
|
8
|
-
context: PopoverContext;
|
|
9
|
-
}, "open">;
|
|
7
|
+
}>, {}, "open">;
|
|
10
8
|
type Popover = ReturnType<typeof Popover>;
|
|
11
9
|
export default Popover;
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
const filter = FilterContext.getOr();
|
|
36
36
|
const empty = $derived(value === undefined || value === "");
|
|
37
|
-
InputContext
|
|
37
|
+
new InputContext(
|
|
38
38
|
() => ({
|
|
39
39
|
disabled,
|
|
40
40
|
fullWidth,
|
|
@@ -48,13 +48,14 @@
|
|
|
48
48
|
() => value,
|
|
49
49
|
(v) => (value = v),
|
|
50
50
|
),
|
|
51
|
-
|
|
51
|
+
);
|
|
52
52
|
|
|
53
53
|
watch(
|
|
54
54
|
() => value ?? "",
|
|
55
55
|
(currentValue) => {
|
|
56
|
+
if (currentValue === value) return;
|
|
56
57
|
const timeout = setTimeout(
|
|
57
|
-
() => (debounced = currentValue),
|
|
58
|
+
() => (debounced = String(currentValue)),
|
|
58
59
|
Math.max(0, debounce),
|
|
59
60
|
);
|
|
60
61
|
return () => clearTimeout(timeout);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adriansyah/heroui-svelte",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@chromatic-com/storybook": "latest",
|
|
6
6
|
"@heroui/styles": "^3.2.6",
|
|
@@ -66,6 +66,6 @@
|
|
|
66
66
|
"type": "module",
|
|
67
67
|
"types": "./dist/index.d.ts",
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"svelte-utils": "
|
|
69
|
+
"@adriansyah/svelte-utils": "^0.0.1"
|
|
70
70
|
}
|
|
71
71
|
}
|