svelora 3.0.14 → 3.0.16
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/components/ConfirmDialog/ConfirmDialog.svelte +167 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.svelte.d.ts +10 -0
- package/dist/components/ConfirmDialog/confirm.d.ts +9 -0
- package/dist/components/ConfirmDialog/confirm.js +24 -0
- package/dist/components/ConfirmDialog/confirm.types.d.ts +22 -0
- package/dist/components/ConfirmDialog/confirm.types.js +1 -0
- package/dist/components/ConfirmDialog/index.d.ts +4 -0
- package/dist/components/ConfirmDialog/index.js +2 -0
- package/dist/components/Editor/editor.schemas.js +1 -1
- package/dist/components/SortableList/SortableList.svelte +54 -0
- package/dist/components/SortableList/SortableList.svelte.d.ts +26 -0
- package/dist/components/SortableList/index.d.ts +2 -0
- package/dist/components/SortableList/index.js +1 -0
- package/dist/components/SortableList/sortable-list.types.d.ts +17 -0
- package/dist/components/SortableList/sortable-list.types.js +1 -0
- package/dist/components/Table/Table.svelte +57 -1
- package/dist/components/Table/table.types.d.ts +2 -0
- package/dist/components/Table/table.variants.d.ts +34 -0
- package/dist/components/Table/table.variants.js +13 -0
- package/dist/components/Toast/Toaster.svelte +194 -137
- package/dist/components/Toast/index.d.ts +2 -0
- package/dist/components/Toast/index.js +1 -0
- package/dist/components/Toast/internal/AnimatedIcon.svelte +446 -0
- package/dist/components/Toast/internal/AnimatedIcon.svelte.d.ts +15 -0
- package/dist/components/Toast/internal/animated-icon.types.d.ts +1 -0
- package/dist/components/Toast/internal/animated-icon.types.js +1 -0
- package/dist/components/Toast/internal/french-toast/LICENSE.md +21 -0
- package/dist/components/Toast/internal/french-toast/components/CheckmarkIcon.svelte +64 -0
- package/dist/components/Toast/internal/french-toast/components/CheckmarkIcon.svelte.d.ts +8 -0
- package/dist/components/Toast/internal/french-toast/components/ErrorIcon.svelte +74 -0
- package/dist/components/Toast/internal/french-toast/components/ErrorIcon.svelte.d.ts +8 -0
- package/dist/components/Toast/internal/french-toast/components/LoaderIcon.svelte +28 -0
- package/dist/components/Toast/internal/french-toast/components/LoaderIcon.svelte.d.ts +8 -0
- package/dist/components/Toast/internal/french-toast/components/ToastBar.svelte +169 -0
- package/dist/components/Toast/internal/french-toast/components/ToastBar.svelte.d.ts +20 -0
- package/dist/components/Toast/internal/french-toast/components/ToastIcon.svelte +81 -0
- package/dist/components/Toast/internal/french-toast/components/ToastIcon.svelte.d.ts +7 -0
- package/dist/components/Toast/internal/french-toast/components/ToastMessage.svelte +13 -0
- package/dist/components/Toast/internal/french-toast/components/ToastMessage.svelte.d.ts +8 -0
- package/dist/components/Toast/internal/french-toast/components/ToastWrapper.svelte +57 -0
- package/dist/components/Toast/internal/french-toast/components/ToastWrapper.svelte.d.ts +12 -0
- package/dist/components/Toast/internal/french-toast/components/Toaster.svelte +73 -0
- package/dist/components/Toast/internal/french-toast/components/Toaster.svelte.d.ts +23 -0
- package/dist/components/Toast/internal/french-toast/core/store.svelte.d.ts +15 -0
- package/dist/components/Toast/internal/french-toast/core/store.svelte.js +92 -0
- package/dist/components/Toast/internal/french-toast/core/toast.d.ts +21 -0
- package/dist/components/Toast/internal/french-toast/core/toast.js +67 -0
- package/dist/components/Toast/internal/french-toast/core/types.d.ts +58 -0
- package/dist/components/Toast/internal/french-toast/core/types.js +4 -0
- package/dist/components/Toast/internal/french-toast/core/use-toaster.svelte.d.ts +16 -0
- package/dist/components/Toast/internal/french-toast/core/use-toaster.svelte.js +71 -0
- package/dist/components/Toast/internal/french-toast/core/utils.d.ts +6 -0
- package/dist/components/Toast/internal/french-toast/core/utils.js +25 -0
- package/dist/components/Toast/internal/french-toast/toast-context.d.ts +18 -0
- package/dist/components/Toast/internal/french-toast/toast-context.js +10 -0
- package/dist/components/Toast/internal/notify.d.ts +31 -0
- package/dist/components/Toast/internal/notify.js +100 -0
- package/dist/components/Toast/internal/toast-icons/ToastError.svelte +8 -0
- package/dist/components/Toast/internal/toast-icons/ToastError.svelte.d.ts +4 -0
- package/dist/components/Toast/internal/toast-icons/ToastInfo.svelte +8 -0
- package/dist/components/Toast/internal/toast-icons/ToastInfo.svelte.d.ts +4 -0
- package/dist/components/Toast/internal/toast-icons/ToastLoading.svelte +8 -0
- package/dist/components/Toast/internal/toast-icons/ToastLoading.svelte.d.ts +4 -0
- package/dist/components/Toast/internal/toast-icons/ToastProcessing.svelte +8 -0
- package/dist/components/Toast/internal/toast-icons/ToastProcessing.svelte.d.ts +4 -0
- package/dist/components/Toast/internal/toast-icons/ToastSuccess.svelte +8 -0
- package/dist/components/Toast/internal/toast-icons/ToastSuccess.svelte.d.ts +4 -0
- package/dist/components/Toast/internal/toast-icons/ToastWarning.svelte +8 -0
- package/dist/components/Toast/internal/toast-icons/ToastWarning.svelte.d.ts +4 -0
- package/dist/components/Toast/internal/toast-icons/index.d.ts +6 -0
- package/dist/components/Toast/internal/toast-icons/index.js +6 -0
- package/dist/components/Toast/internal/toast-icons/toast-icon.types.d.ts +4 -0
- package/dist/components/Toast/internal/toast-icons/toast-icon.types.js +1 -0
- package/dist/components/Toast/toast.d.ts +31 -16
- package/dist/components/Toast/toast.js +45 -20
- package/dist/components/Toast/toast.types.d.ts +20 -7
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/internal/DragDropProviderScope.svelte +29 -0
- package/dist/hooks/internal/DragDropProviderScope.svelte.d.ts +7 -0
- package/dist/hooks/internal/SortableProvider.svelte +30 -0
- package/dist/hooks/internal/SortableProvider.svelte.d.ts +7 -0
- package/dist/hooks/internal/drag-drop-context.d.ts +12 -0
- package/dist/hooks/internal/drag-drop-context.js +1 -0
- package/dist/hooks/internal/sortable-context.d.ts +12 -0
- package/dist/hooks/internal/sortable-context.js +1 -0
- package/dist/hooks/useDragDrop/index.d.ts +1 -0
- package/dist/hooks/useDragDrop/index.js +1 -0
- package/dist/hooks/useDragDrop/useDragDrop.svelte.d.ts +40 -0
- package/dist/hooks/useDragDrop/useDragDrop.svelte.js +128 -0
- package/dist/hooks/useSortable/index.d.ts +2 -0
- package/dist/hooks/useSortable/index.js +2 -0
- package/dist/hooks/useSortable/sortable-utils.d.ts +1 -0
- package/dist/hooks/useSortable/sortable-utils.js +13 -0
- package/dist/hooks/useSortable/useSortable.svelte.d.ts +52 -0
- package/dist/hooks/useSortable/useSortable.svelte.js +120 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp/svelora-docs.data.json +14 -6
- package/package.json +5 -3
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<script lang="ts" module>export {};
|
|
2
|
+
</script>
|
|
3
|
+
|
|
4
|
+
<script lang="ts">import { Dialog } from "bits-ui";
|
|
5
|
+
import Button from "../Button/Button.svelte";
|
|
6
|
+
import Input from "../Input/Input.svelte";
|
|
7
|
+
import Textarea from "../Textarea/Textarea.svelte";
|
|
8
|
+
import AnimatedIcon from "../Toast/internal/AnimatedIcon.svelte";
|
|
9
|
+
import { modalVariants } from "../Modal/modal.variants.js";
|
|
10
|
+
let { confirmText: defaultConfirmText = "Confirm", cancelText: defaultCancelText = "Cancel" } = $props();
|
|
11
|
+
let open = $state(false);
|
|
12
|
+
let pending = $state(null);
|
|
13
|
+
let currentInputValue = $state("");
|
|
14
|
+
const classes = $derived(modalVariants({
|
|
15
|
+
transition: "scale",
|
|
16
|
+
size: "sm",
|
|
17
|
+
overlay: true,
|
|
18
|
+
scrollable: false
|
|
19
|
+
}));
|
|
20
|
+
const dismissible = $derived(pending?.options.dismissible !== false);
|
|
21
|
+
const showCancel = $derived(pending?.options.showCancel !== false);
|
|
22
|
+
export function show(options = {}) {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
currentInputValue = options.inputValue ?? "";
|
|
25
|
+
pending = {
|
|
26
|
+
options,
|
|
27
|
+
resolve
|
|
28
|
+
};
|
|
29
|
+
open = true;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function settle(result) {
|
|
33
|
+
const current = pending;
|
|
34
|
+
pending = null;
|
|
35
|
+
open = false;
|
|
36
|
+
current?.resolve(result);
|
|
37
|
+
}
|
|
38
|
+
function handleConfirm() {
|
|
39
|
+
pending?.options.onConfirm?.(currentInputValue);
|
|
40
|
+
settle(true);
|
|
41
|
+
}
|
|
42
|
+
function handleCancel() {
|
|
43
|
+
pending?.options.onCancel?.();
|
|
44
|
+
settle(false);
|
|
45
|
+
}
|
|
46
|
+
function handleOpenChange(value) {
|
|
47
|
+
if (!value && pending) {
|
|
48
|
+
handleCancel();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
open = value;
|
|
52
|
+
}
|
|
53
|
+
const contentProps = $derived.by(() => {
|
|
54
|
+
const behavior = dismissible ? "close" : "ignore";
|
|
55
|
+
return {
|
|
56
|
+
trapFocus: true,
|
|
57
|
+
preventScroll: true,
|
|
58
|
+
escapeKeydownBehavior: behavior,
|
|
59
|
+
interactOutsideBehavior: behavior
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<Dialog.Root bind:open onOpenChange={handleOpenChange}>
|
|
65
|
+
<Dialog.Portal>
|
|
66
|
+
<Dialog.Overlay class={classes.overlay()} />
|
|
67
|
+
{#if pending}
|
|
68
|
+
<Dialog.Content
|
|
69
|
+
{...contentProps}
|
|
70
|
+
class={[classes.content(), 'p-6 text-center']}
|
|
71
|
+
>
|
|
72
|
+
{#if pending.options.title}
|
|
73
|
+
<Dialog.Title class="sr-only">{pending.options.title}</Dialog.Title>
|
|
74
|
+
{/if}
|
|
75
|
+
{#if pending.options.message}
|
|
76
|
+
<Dialog.Description class="sr-only"
|
|
77
|
+
>{pending.options.message}</Dialog.Description
|
|
78
|
+
>
|
|
79
|
+
{/if}
|
|
80
|
+
|
|
81
|
+
{#if pending.options.icon}
|
|
82
|
+
{#key pending.options.icon}
|
|
83
|
+
<div class="mb-4 flex min-h-20 justify-center">
|
|
84
|
+
<AnimatedIcon
|
|
85
|
+
type={pending.options.icon}
|
|
86
|
+
size={80}
|
|
87
|
+
forceMotion
|
|
88
|
+
idle={false}
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
{/key}
|
|
92
|
+
{/if}
|
|
93
|
+
|
|
94
|
+
{#if pending.options.title}
|
|
95
|
+
<h3 class="mb-2 text-lg font-semibold text-on-surface">
|
|
96
|
+
{pending.options.title}
|
|
97
|
+
</h3>
|
|
98
|
+
{/if}
|
|
99
|
+
|
|
100
|
+
{#if pending.options.message}
|
|
101
|
+
<p class="mb-6 text-sm text-on-surface-variant">
|
|
102
|
+
{pending.options.message}
|
|
103
|
+
</p>
|
|
104
|
+
{:else if !pending.options.inputPlaceholder}
|
|
105
|
+
<div class="mb-6"></div>
|
|
106
|
+
{/if}
|
|
107
|
+
|
|
108
|
+
{#if pending.options.inputPlaceholder}
|
|
109
|
+
{#if pending.options.inputChoices && pending.options.inputChoices.length > 0}
|
|
110
|
+
<div class="mb-3 flex flex-wrap justify-center gap-1">
|
|
111
|
+
{#each pending.options.inputChoices as choice (choice)}
|
|
112
|
+
<Button
|
|
113
|
+
label={choice}
|
|
114
|
+
size="xs"
|
|
115
|
+
variant={currentInputValue === choice ? 'solid' : 'outline'}
|
|
116
|
+
color={currentInputValue === choice ? 'primary' : 'surface'}
|
|
117
|
+
onclick={() => (currentInputValue = choice)}
|
|
118
|
+
/>
|
|
119
|
+
{/each}
|
|
120
|
+
</div>
|
|
121
|
+
{/if}
|
|
122
|
+
|
|
123
|
+
<div class="mb-6 text-left">
|
|
124
|
+
{#if pending.options.inputType === 'textarea'}
|
|
125
|
+
<Textarea
|
|
126
|
+
bind:value={currentInputValue}
|
|
127
|
+
placeholder={pending.options.inputPlaceholder}
|
|
128
|
+
class="w-full"
|
|
129
|
+
/>
|
|
130
|
+
{:else}
|
|
131
|
+
<Input
|
|
132
|
+
type={pending.options.inputType ?? 'text'}
|
|
133
|
+
bind:value={currentInputValue}
|
|
134
|
+
placeholder={pending.options.inputPlaceholder}
|
|
135
|
+
class="w-full"
|
|
136
|
+
onkeydown={(e) => {
|
|
137
|
+
if (e.key === 'Enter') {
|
|
138
|
+
e.preventDefault()
|
|
139
|
+
handleConfirm()
|
|
140
|
+
}
|
|
141
|
+
}}
|
|
142
|
+
/>
|
|
143
|
+
{/if}
|
|
144
|
+
</div>
|
|
145
|
+
{/if}
|
|
146
|
+
|
|
147
|
+
<div class="flex justify-center gap-2">
|
|
148
|
+
{#if showCancel}
|
|
149
|
+
<Button
|
|
150
|
+
label={pending.options.cancelText ?? defaultCancelText}
|
|
151
|
+
variant="outline"
|
|
152
|
+
class="flex-1"
|
|
153
|
+
onclick={handleCancel}
|
|
154
|
+
/>
|
|
155
|
+
{/if}
|
|
156
|
+
<Button
|
|
157
|
+
label={pending.options.confirmText ?? defaultConfirmText}
|
|
158
|
+
variant="solid"
|
|
159
|
+
color={pending.options.confirmColor ?? 'primary'}
|
|
160
|
+
class={showCancel ? 'flex-1' : 'w-full'}
|
|
161
|
+
onclick={handleConfirm}
|
|
162
|
+
/>
|
|
163
|
+
</div>
|
|
164
|
+
</Dialog.Content>
|
|
165
|
+
{/if}
|
|
166
|
+
</Dialog.Portal>
|
|
167
|
+
</Dialog.Root>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Props = {
|
|
2
|
+
confirmText?: string;
|
|
3
|
+
cancelText?: string;
|
|
4
|
+
};
|
|
5
|
+
import type { ConfirmOptions } from './confirm.types.js';
|
|
6
|
+
declare const ConfirmDialog: import("svelte").Component<Props, {
|
|
7
|
+
show: (options?: ConfirmOptions) => Promise<boolean>;
|
|
8
|
+
}, "">;
|
|
9
|
+
type ConfirmDialog = ReturnType<typeof ConfirmDialog>;
|
|
10
|
+
export default ConfirmDialog;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConfirmOptions } from './confirm.types.js';
|
|
2
|
+
type ShowFn = (options?: ConfirmOptions) => Promise<boolean>;
|
|
3
|
+
export declare function registerConfirmDialog(fn: ShowFn | null): void;
|
|
4
|
+
export declare const confirmDialog: {
|
|
5
|
+
show(options?: ConfirmOptions): Promise<boolean>;
|
|
6
|
+
delete(options?: ConfirmOptions): Promise<boolean>;
|
|
7
|
+
};
|
|
8
|
+
export type ConfirmDialogUtility = typeof confirmDialog;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
let showFn = null;
|
|
2
|
+
export function registerConfirmDialog(fn) {
|
|
3
|
+
showFn = fn;
|
|
4
|
+
}
|
|
5
|
+
export const confirmDialog = {
|
|
6
|
+
show(options = {}) {
|
|
7
|
+
if (!showFn) {
|
|
8
|
+
console.warn('[confirmDialog] ConfirmDialog is not registered — add <ConfirmDialog /> to your root layout.');
|
|
9
|
+
return Promise.resolve(false);
|
|
10
|
+
}
|
|
11
|
+
return showFn(options);
|
|
12
|
+
},
|
|
13
|
+
delete(options = {}) {
|
|
14
|
+
return this.show({
|
|
15
|
+
title: 'Delete this item?',
|
|
16
|
+
message: 'This action is permanent and cannot be undone.',
|
|
17
|
+
confirmText: 'Delete',
|
|
18
|
+
cancelText: 'Cancel',
|
|
19
|
+
icon: 'warning',
|
|
20
|
+
confirmColor: 'error',
|
|
21
|
+
...options
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ButtonVariantProps } from '../Button/button.variants.js';
|
|
2
|
+
import type { AnimatedIconType } from '../Toast/internal/animated-icon.types.js';
|
|
3
|
+
export type ConfirmIcon = Extract<AnimatedIconType, 'warning' | 'error' | 'question' | 'info' | 'success'>;
|
|
4
|
+
export type ConfirmColor = NonNullable<ButtonVariantProps['color']>;
|
|
5
|
+
export interface ConfirmOptions {
|
|
6
|
+
title?: string;
|
|
7
|
+
message?: string;
|
|
8
|
+
confirmText?: string;
|
|
9
|
+
cancelText?: string;
|
|
10
|
+
icon?: ConfirmIcon;
|
|
11
|
+
confirmColor?: ConfirmColor;
|
|
12
|
+
/** When false, only the confirm button is shown (alert-style). @default true */
|
|
13
|
+
showCancel?: boolean;
|
|
14
|
+
/** When false, backdrop click and Escape do not dismiss. @default true */
|
|
15
|
+
dismissible?: boolean;
|
|
16
|
+
inputPlaceholder?: string;
|
|
17
|
+
inputValue?: string;
|
|
18
|
+
inputType?: 'text' | 'password' | 'email' | 'number' | 'textarea';
|
|
19
|
+
inputChoices?: string[];
|
|
20
|
+
onConfirm?: (value?: string) => void;
|
|
21
|
+
onCancel?: () => void;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as ConfirmDialog } from './ConfirmDialog.svelte';
|
|
2
|
+
export { confirmDialog, registerConfirmDialog } from './confirm.js';
|
|
3
|
+
export type { ConfirmOptions, ConfirmIcon, ConfirmColor } from './confirm.types.js';
|
|
4
|
+
export type { ConfirmDialogUtility } from './confirm.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script lang="ts" module>export {};
|
|
2
|
+
</script>
|
|
3
|
+
|
|
4
|
+
<script lang="ts" generics="T">import { twMerge } from "tailwind-merge";
|
|
5
|
+
import Icon from "../Icon/Icon.svelte";
|
|
6
|
+
import { useSortable } from "../../hooks/useSortable/index.js";
|
|
7
|
+
let { items = $bindable(), getKey, onReorder, axis = "vertical", handle = true, disabled = false, class: className, itemClass, children } = $props();
|
|
8
|
+
const sortable = useSortable({
|
|
9
|
+
getItems: () => items,
|
|
10
|
+
getId: (item) => getKey(item),
|
|
11
|
+
axis: () => axis,
|
|
12
|
+
handle: () => handle ? "[data-sortable-handle]" : undefined,
|
|
13
|
+
disabled: () => disabled,
|
|
14
|
+
onReorder(nextItems) {
|
|
15
|
+
items = nextItems;
|
|
16
|
+
onReorder?.(nextItems);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const listClass = $derived(twMerge(axis === "vertical" ? "flex flex-col gap-2" : axis === "horizontal" ? "flex flex-row flex-wrap gap-2" : "gap-3", className));
|
|
20
|
+
const itemClasses = $derived(twMerge("relative flex items-center gap-3 rounded-lg border border-outline-variant/60 bg-surface-container-low px-3 py-2 transition-shadow select-none", itemClass));
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<sortable.Provider>
|
|
24
|
+
<div use:sortable.container class={listClass} role="list">
|
|
25
|
+
{#each items as item, index (getKey(item))}
|
|
26
|
+
{@const id = getKey(item)}
|
|
27
|
+
{@const dragging = sortable.draggingId === String(id)}
|
|
28
|
+
<div
|
|
29
|
+
use:sortable.item={{ index, item }}
|
|
30
|
+
role="listitem"
|
|
31
|
+
class={twMerge(itemClasses, dragging && 'z-10 opacity-95 shadow-md')}
|
|
32
|
+
aria-grabbed={dragging}
|
|
33
|
+
>
|
|
34
|
+
{#if handle}
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
data-sortable-handle
|
|
38
|
+
class="inline-flex shrink-0 cursor-grab rounded-md p-1 text-on-surface-variant hover:bg-surface-container-high active:cursor-grabbing"
|
|
39
|
+
aria-label="Drag to reorder"
|
|
40
|
+
>
|
|
41
|
+
<Icon name="lucide:grip-vertical" size="16" />
|
|
42
|
+
</button>
|
|
43
|
+
{/if}
|
|
44
|
+
{@render children({ item, index, dragging })}
|
|
45
|
+
</div>
|
|
46
|
+
{/each}
|
|
47
|
+
</div>
|
|
48
|
+
</sortable.Provider>
|
|
49
|
+
|
|
50
|
+
<style>
|
|
51
|
+
:global([data-sortable-active='true']) {
|
|
52
|
+
user-select: none;
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type { SortableListProps } from './sortable-list.types.js';
|
|
2
|
+
import type { SortableListProps } from './sortable-list.types.js';
|
|
3
|
+
declare function $$render<T>(): {
|
|
4
|
+
props: SortableListProps<T>;
|
|
5
|
+
exports: {};
|
|
6
|
+
bindings: "items";
|
|
7
|
+
slots: {};
|
|
8
|
+
events: {};
|
|
9
|
+
};
|
|
10
|
+
declare class __sveltets_Render<T> {
|
|
11
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
12
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
13
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
14
|
+
bindings(): "items";
|
|
15
|
+
exports(): {};
|
|
16
|
+
}
|
|
17
|
+
interface $$IsomorphicComponent {
|
|
18
|
+
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']>> & {
|
|
19
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
20
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
21
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
22
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
23
|
+
}
|
|
24
|
+
declare const SortableList: $$IsomorphicComponent;
|
|
25
|
+
type SortableList<T> = InstanceType<typeof SortableList<T>>;
|
|
26
|
+
export default SortableList;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as SortableList } from './SortableList.svelte';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
3
|
+
export interface SortableListProps<T> {
|
|
4
|
+
items: T[];
|
|
5
|
+
getKey: (item: T) => string | number;
|
|
6
|
+
onReorder?: (items: T[]) => void;
|
|
7
|
+
axis?: 'vertical' | 'horizontal' | 'grid';
|
|
8
|
+
handle?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
class?: ClassNameValue;
|
|
11
|
+
itemClass?: ClassNameValue;
|
|
12
|
+
children: Snippet<[{
|
|
13
|
+
item: T;
|
|
14
|
+
index: number;
|
|
15
|
+
dragging: boolean;
|
|
16
|
+
}]>;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -11,7 +11,7 @@ import { autoGenerateColumns, computePinOffsets, filterByColumns, filterByGlobal
|
|
|
11
11
|
import { tableDefaults, tableVariants } from "./table.variants.js";
|
|
12
12
|
const config = getComponentConfig("table", tableDefaults);
|
|
13
13
|
const icons = getComponentConfig("icons", iconsDefaults);
|
|
14
|
-
let { ref = $bindable(null), as = "div", data = [], columns: columnsProp, rowKey, caption, sorting = $bindable([]), multiSort = false, manualSorting = false, onSortingChange, globalFilter = $bindable(""), globalFilterKeys, manualFiltering = false, onGlobalFilterChange, columnFilters = $bindable({}), onColumnFiltersChange, page = $bindable(0), pageSize = 10, manualPagination = false, onPageChange, selection, selectedRows = $bindable([]), onSelectionChange, columnVisibility = $bindable(), onColumnVisibilityChange, columnPinning = $bindable(), pinnedRows = $bindable([]), onPinnedRowsChange, expandedRows = $bindable([]), onExpandedChange, columnSizing = $bindable({}), onColumnSizingChange, loading = false, loadingColor = config.defaultVariants.loadingColor ?? "primary", loadingAnimation = config.defaultVariants.loadingAnimation ?? "carousel", empty = "No data.", striped = false, hoverable = config.defaultVariants.hoverable ?? true, sticky = false, action, onRowClick, onRowHover, onRowContextmenu, ui, class: className, captionSlot, emptySlot, loadingSlot, expandedSlot, bodyTopSlot, bodyBottomSlot, headerSlot, cellSlot, ...restProps } = $props();
|
|
14
|
+
let { ref = $bindable(null), as = "div", data = [], columns: columnsProp, rowKey, caption, sorting = $bindable([]), multiSort = false, manualSorting = false, onSortingChange, globalFilter = $bindable(""), globalFilterKeys, manualFiltering = false, onGlobalFilterChange, columnFilters = $bindable({}), onColumnFiltersChange, page = $bindable(0), pageSize = 10, manualPagination = false, onPageChange, selection, selectedRows = $bindable([]), onSelectionChange, columnVisibility = $bindable(), onColumnVisibilityChange, columnPinning = $bindable(), pinnedRows = $bindable([]), onPinnedRowsChange, expandedRows = $bindable([]), onExpandedChange, columnSizing = $bindable({}), onColumnSizingChange, loading = false, loadingColor = config.defaultVariants.loadingColor ?? "primary", loadingAnimation = config.defaultVariants.loadingAnimation ?? "carousel", size = config.defaultVariants.size ?? "md", empty = "No data.", striped = false, hoverable = config.defaultVariants.hoverable ?? true, sticky = false, action, onRowClick, onRowHover, onRowContextmenu, ui, class: className, captionSlot, emptySlot, loadingSlot, expandedSlot, bodyTopSlot, bodyBottomSlot, headerSlot, cellSlot, ...restProps } = $props();
|
|
15
15
|
// =========================================================================
|
|
16
16
|
// Apply Svelte action on root element
|
|
17
17
|
// =========================================================================
|
|
@@ -75,6 +75,7 @@ const resolvedColumns = $derived.by(() => {
|
|
|
75
75
|
});
|
|
76
76
|
const visibleColumns = $derived(resolveVisibleColumns(resolvedColumns, columnVisibility, columnPinning));
|
|
77
77
|
const hasFooter = $derived(visibleColumns.some((col) => col.footer));
|
|
78
|
+
const hasColumnFilterRow = $derived(visibleColumns.some((col) => col.filterable === true));
|
|
78
79
|
const totalColspan = $derived(visibleColumns.length + (selection === "multiple" ? 1 : 0));
|
|
79
80
|
// =========================================================================
|
|
80
81
|
// Data Pipeline: filter → sort → paginate
|
|
@@ -304,6 +305,7 @@ function getAlignClass(align) {
|
|
|
304
305
|
// Variant Classes
|
|
305
306
|
// =========================================================================
|
|
306
307
|
const variantSlots = $derived(tableVariants({
|
|
308
|
+
size,
|
|
307
309
|
hoverable: hoverable || undefined,
|
|
308
310
|
striped: striped || undefined,
|
|
309
311
|
sticky: sticky || undefined,
|
|
@@ -523,6 +525,60 @@ function tdClass(key) {
|
|
|
523
525
|
</th>
|
|
524
526
|
{/each}
|
|
525
527
|
</tr>
|
|
528
|
+
|
|
529
|
+
{#if hasColumnFilterRow}
|
|
530
|
+
<tr class="{classes.tr} border-t border-outline-variant/30">
|
|
531
|
+
{#if selection === 'multiple'}
|
|
532
|
+
<th class={classes.th} style="width: 48px"></th>
|
|
533
|
+
{/if}
|
|
534
|
+
{#each visibleColumns as col (col.key)}
|
|
535
|
+
<th
|
|
536
|
+
class="px-2 py-1.5"
|
|
537
|
+
data-pinned={isPinned(col.key) || undefined}
|
|
538
|
+
style={getPinStyle(col.key)}
|
|
539
|
+
>
|
|
540
|
+
{#if col.filterable}
|
|
541
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
542
|
+
<div class="relative">
|
|
543
|
+
<input
|
|
544
|
+
type="text"
|
|
545
|
+
value={columnFilters[col.key] ?? ''}
|
|
546
|
+
placeholder="Filter…"
|
|
547
|
+
aria-label="Filter {col.label ?? col.key}"
|
|
548
|
+
oninput={(e) => {
|
|
549
|
+
const val = (e.currentTarget as HTMLInputElement).value;
|
|
550
|
+
if (val) {
|
|
551
|
+
columnFilters = { ...columnFilters, [col.key]: val };
|
|
552
|
+
} else {
|
|
553
|
+
const { [col.key]: _removed, ...rest } = columnFilters;
|
|
554
|
+
columnFilters = rest;
|
|
555
|
+
}
|
|
556
|
+
onColumnFiltersChange?.(columnFilters);
|
|
557
|
+
page = 0;
|
|
558
|
+
}}
|
|
559
|
+
class="w-full rounded-md border border-outline-variant/40 bg-surface-container-low px-2 py-1 text-xs text-on-surface placeholder:text-on-surface-variant/40 focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30 transition-colors"
|
|
560
|
+
/>
|
|
561
|
+
{#if columnFilters[col.key]}
|
|
562
|
+
<button
|
|
563
|
+
type="button"
|
|
564
|
+
aria-label="Clear filter for {col.label ?? col.key}"
|
|
565
|
+
class="absolute right-1.5 top-1/2 -translate-y-1/2 text-on-surface-variant/50 hover:text-on-surface transition-colors"
|
|
566
|
+
onclick={() => {
|
|
567
|
+
const { [col.key]: _removed, ...rest } = columnFilters;
|
|
568
|
+
columnFilters = rest;
|
|
569
|
+
onColumnFiltersChange?.(columnFilters);
|
|
570
|
+
page = 0;
|
|
571
|
+
}}
|
|
572
|
+
>
|
|
573
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="size-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
|
|
574
|
+
</button>
|
|
575
|
+
{/if}
|
|
576
|
+
</div>
|
|
577
|
+
{/if}
|
|
578
|
+
</th>
|
|
579
|
+
{/each}
|
|
580
|
+
</tr>
|
|
581
|
+
{/if}
|
|
526
582
|
</thead>
|
|
527
583
|
|
|
528
584
|
<!-- TBODY -->
|
|
@@ -160,6 +160,8 @@ export interface TableProps<T extends Record<string, any> = Record<string, any>>
|
|
|
160
160
|
loadingColor?: NonNullable<TableVariantProps['loadingColor']>;
|
|
161
161
|
/** Loading bar animation. @default 'carousel' */
|
|
162
162
|
loadingAnimation?: NonNullable<TableVariantProps['loadingAnimation']>;
|
|
163
|
+
/** Table density preset. @default 'md' */
|
|
164
|
+
size?: NonNullable<TableVariantProps['size']>;
|
|
163
165
|
/** Text shown when data is empty. @default 'No data.' */
|
|
164
166
|
empty?: string;
|
|
165
167
|
/** Alternate row background colors. @default false */
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { type VariantProps } from 'tailwind-variants';
|
|
2
2
|
export declare const tableVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
size: {
|
|
4
|
+
sm: {
|
|
5
|
+
th: string;
|
|
6
|
+
td: string;
|
|
7
|
+
};
|
|
8
|
+
md: {};
|
|
9
|
+
lg: {
|
|
10
|
+
th: string;
|
|
11
|
+
td: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
3
14
|
pinned: {
|
|
4
15
|
true: {
|
|
5
16
|
th: string;
|
|
@@ -63,6 +74,17 @@ export declare const tableVariants: import("tailwind-variants").TVReturnType<{
|
|
|
63
74
|
empty: string;
|
|
64
75
|
loading: string;
|
|
65
76
|
}, undefined, {
|
|
77
|
+
size: {
|
|
78
|
+
sm: {
|
|
79
|
+
th: string;
|
|
80
|
+
td: string;
|
|
81
|
+
};
|
|
82
|
+
md: {};
|
|
83
|
+
lg: {
|
|
84
|
+
th: string;
|
|
85
|
+
td: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
66
88
|
pinned: {
|
|
67
89
|
true: {
|
|
68
90
|
th: string;
|
|
@@ -126,6 +148,17 @@ export declare const tableVariants: import("tailwind-variants").TVReturnType<{
|
|
|
126
148
|
empty: string;
|
|
127
149
|
loading: string;
|
|
128
150
|
}, import("tailwind-variants").TVReturnType<{
|
|
151
|
+
size: {
|
|
152
|
+
sm: {
|
|
153
|
+
th: string;
|
|
154
|
+
td: string;
|
|
155
|
+
};
|
|
156
|
+
md: {};
|
|
157
|
+
lg: {
|
|
158
|
+
th: string;
|
|
159
|
+
td: string;
|
|
160
|
+
};
|
|
161
|
+
};
|
|
129
162
|
pinned: {
|
|
130
163
|
true: {
|
|
131
164
|
th: string;
|
|
@@ -193,6 +226,7 @@ export type TableVariantProps = VariantProps<typeof tableVariants>;
|
|
|
193
226
|
export type TableSlots = keyof ReturnType<typeof tableVariants>;
|
|
194
227
|
export declare const tableDefaults: {
|
|
195
228
|
defaultVariants: {
|
|
229
|
+
size: "md";
|
|
196
230
|
hoverable: true;
|
|
197
231
|
loadingColor: "primary";
|
|
198
232
|
loadingAnimation: "carousel";
|
|
@@ -27,6 +27,17 @@ export const tableVariants = tv({
|
|
|
27
27
|
loading: 'py-10 text-center'
|
|
28
28
|
},
|
|
29
29
|
variants: {
|
|
30
|
+
size: {
|
|
31
|
+
sm: {
|
|
32
|
+
th: 'px-3 py-2 text-[11px]',
|
|
33
|
+
td: 'px-3 py-2 text-xs'
|
|
34
|
+
},
|
|
35
|
+
md: {},
|
|
36
|
+
lg: {
|
|
37
|
+
th: 'px-5 py-3.5 text-sm',
|
|
38
|
+
td: 'px-5 py-4 text-base'
|
|
39
|
+
}
|
|
40
|
+
},
|
|
30
41
|
pinned: {
|
|
31
42
|
true: {
|
|
32
43
|
th: 'sticky bg-surface-container-low/95 backdrop-blur-sm z-1',
|
|
@@ -110,6 +121,7 @@ export const tableVariants = tv({
|
|
|
110
121
|
}
|
|
111
122
|
],
|
|
112
123
|
defaultVariants: {
|
|
124
|
+
size: 'md',
|
|
113
125
|
hoverable: true,
|
|
114
126
|
loadingColor: 'primary',
|
|
115
127
|
loadingAnimation: 'carousel'
|
|
@@ -118,6 +130,7 @@ export const tableVariants = tv({
|
|
|
118
130
|
export const tableDefaults = {
|
|
119
131
|
defaultVariants: {
|
|
120
132
|
...tableVariants.defaultVariants,
|
|
133
|
+
size: 'md',
|
|
121
134
|
hoverable: true,
|
|
122
135
|
loadingColor: 'primary',
|
|
123
136
|
loadingAnimation: 'carousel'
|