runeforge 0.0.1
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 +21 -0
- package/README.md +551 -0
- package/dist/components/Avatar.svelte +31 -0
- package/dist/components/Avatar.svelte.d.ts +10 -0
- package/dist/components/IconRenderer.svelte +22 -0
- package/dist/components/IconRenderer.svelte.d.ts +8 -0
- package/dist/components/Modal.svelte +47 -0
- package/dist/components/Modal.svelte.d.ts +9 -0
- package/dist/components/common/Header.svelte +30 -0
- package/dist/components/common/Header.svelte.d.ts +11 -0
- package/dist/components/crud/Field.svelte +159 -0
- package/dist/components/crud/Field.svelte.d.ts +30 -0
- package/dist/components/crud/GenericCRUD.svelte +236 -0
- package/dist/components/crud/GenericCRUD.svelte.d.ts +44 -0
- package/dist/components/crud/columns/Avatar.svelte +15 -0
- package/dist/components/crud/columns/Avatar.svelte.d.ts +8 -0
- package/dist/components/crud/columns/Icon.svelte +8 -0
- package/dist/components/crud/columns/Icon.svelte.d.ts +4 -0
- package/dist/components/crud/utils/constants.d.ts +1 -0
- package/dist/components/crud/utils/constants.js +6 -0
- package/dist/components/crud/utils/formatters.d.ts +6 -0
- package/dist/components/crud/utils/formatters.js +42 -0
- package/dist/components/crud/utils/misc.d.ts +5 -0
- package/dist/components/crud/utils/misc.js +8 -0
- package/dist/components/crud/utils/resolution.d.ts +4 -0
- package/dist/components/crud/utils/resolution.js +22 -0
- package/dist/components/crud/views/Create.svelte +147 -0
- package/dist/components/crud/views/Create.svelte.d.ts +34 -0
- package/dist/components/crud/views/List.svelte +170 -0
- package/dist/components/crud/views/List.svelte.d.ts +41 -0
- package/dist/components/crud/views/Read.svelte +85 -0
- package/dist/components/crud/views/Read.svelte.d.ts +33 -0
- package/dist/components/crud/views/Update.svelte +148 -0
- package/dist/components/crud/views/Update.svelte.d.ts +35 -0
- package/dist/components/form/Button.svelte +27 -0
- package/dist/components/form/Button.svelte.d.ts +10 -0
- package/dist/components/form/Label.svelte +37 -0
- package/dist/components/form/Label.svelte.d.ts +14 -0
- package/dist/components/form/PasswordInput.svelte +61 -0
- package/dist/components/form/PasswordInput.svelte.d.ts +13 -0
- package/dist/components/form/Required.svelte +1 -0
- package/dist/components/form/Required.svelte.d.ts +26 -0
- package/dist/components/form/Select.svelte +114 -0
- package/dist/components/form/Select.svelte.d.ts +14 -0
- package/dist/components/navigation/Breadcrumbs.svelte +51 -0
- package/dist/components/navigation/Breadcrumbs.svelte.d.ts +9 -0
- package/dist/components/table/ColumnFilter.svelte +140 -0
- package/dist/components/table/ColumnFilter.svelte.d.ts +33 -0
- package/dist/components/table/PaginatedTable.svelte +106 -0
- package/dist/components/table/PaginatedTable.svelte.d.ts +35 -0
- package/dist/components/table/Paginator.svelte +62 -0
- package/dist/components/table/Paginator.svelte.d.ts +10 -0
- package/dist/components/table/SortHeader.svelte +43 -0
- package/dist/components/table/SortHeader.svelte.d.ts +10 -0
- package/dist/components/table/TableBody.svelte +70 -0
- package/dist/components/table/TableBody.svelte.d.ts +36 -0
- package/dist/components/table/TableHeader.svelte +83 -0
- package/dist/components/table/TableHeader.svelte.d.ts +39 -0
- package/dist/components/table/state.svelte.d.ts +30 -0
- package/dist/components/table/state.svelte.js +109 -0
- package/dist/components/table/utils.d.ts +7 -0
- package/dist/components/table/utils.js +44 -0
- package/dist/i18n/context.d.ts +3 -0
- package/dist/i18n/context.js +10 -0
- package/dist/i18n/en.d.ts +2 -0
- package/dist/i18n/en.js +24 -0
- package/dist/i18n/es.d.ts +2 -0
- package/dist/i18n/es.js +24 -0
- package/dist/i18n/types.d.ts +24 -0
- package/dist/i18n/types.js +1 -0
- package/dist/icons/bootstrapIconSet.d.ts +1 -0
- package/dist/icons/bootstrapIconSet.js +1 -0
- package/dist/icons/context.d.ts +3 -0
- package/dist/icons/context.js +9 -0
- package/dist/icons/defaultIconSet.d.ts +1 -0
- package/dist/icons/defaultIconSet.js +1 -0
- package/dist/icons/defaults/Create.svelte +6 -0
- package/dist/icons/defaults/Create.svelte.d.ts +7 -0
- package/dist/icons/defaults/Delete.svelte +6 -0
- package/dist/icons/defaults/Delete.svelte.d.ts +7 -0
- package/dist/icons/defaults/Edit.svelte +7 -0
- package/dist/icons/defaults/Edit.svelte.d.ts +7 -0
- package/dist/icons/defaults/Filter.svelte +6 -0
- package/dist/icons/defaults/Filter.svelte.d.ts +7 -0
- package/dist/icons/defaults/FilterActive.svelte +6 -0
- package/dist/icons/defaults/FilterActive.svelte.d.ts +7 -0
- package/dist/icons/defaults/Folder.svelte +6 -0
- package/dist/icons/defaults/Folder.svelte.d.ts +7 -0
- package/dist/icons/defaults/Home.svelte +6 -0
- package/dist/icons/defaults/Home.svelte.d.ts +7 -0
- package/dist/icons/defaults/PasswordHide.svelte +9 -0
- package/dist/icons/defaults/PasswordHide.svelte.d.ts +7 -0
- package/dist/icons/defaults/PasswordShow.svelte +7 -0
- package/dist/icons/defaults/PasswordShow.svelte.d.ts +7 -0
- package/dist/icons/defaults/SortAsc.svelte +6 -0
- package/dist/icons/defaults/SortAsc.svelte.d.ts +7 -0
- package/dist/icons/defaults/SortDesc.svelte +6 -0
- package/dist/icons/defaults/SortDesc.svelte.d.ts +7 -0
- package/dist/icons/defaults/SortNone.svelte +6 -0
- package/dist/icons/defaults/SortNone.svelte.d.ts +7 -0
- package/dist/icons/defaults/View.svelte +7 -0
- package/dist/icons/defaults/View.svelte.d.ts +7 -0
- package/dist/icons/sets/bootstrap.d.ts +2 -0
- package/dist/icons/sets/bootstrap.js +29 -0
- package/dist/icons/sets/default.d.ts +2 -0
- package/dist/icons/sets/default.js +28 -0
- package/dist/icons/types.d.ts +26 -0
- package/dist/icons/types.js +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +41 -0
- package/dist/types/attribute.d.ts +38 -0
- package/dist/types/attribute.js +11 -0
- package/dist/types/breadcrumb.d.ts +7 -0
- package/dist/types/breadcrumb.js +1 -0
- package/dist/types/crud.d.ts +48 -0
- package/dist/types/crud.js +1 -0
- package/dist/types/table.d.ts +16 -0
- package/dist/types/table.js +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ActionConfiguration, FieldDefinition } from '../../../types/crud.js';
|
|
2
|
+
declare function $$render<T extends object = Record<string, unknown>>(): {
|
|
3
|
+
props: {
|
|
4
|
+
labelOne?: string;
|
|
5
|
+
labelMany?: string;
|
|
6
|
+
icon?: any;
|
|
7
|
+
fields?: FieldDefinition<T>[];
|
|
8
|
+
instance?: T;
|
|
9
|
+
update?: ActionConfiguration<T>;
|
|
10
|
+
serverError?: string;
|
|
11
|
+
onCancel?: () => void;
|
|
12
|
+
onSuccess?: () => void;
|
|
13
|
+
};
|
|
14
|
+
exports: {};
|
|
15
|
+
bindings: "";
|
|
16
|
+
slots: {};
|
|
17
|
+
events: {};
|
|
18
|
+
};
|
|
19
|
+
declare class __sveltets_Render<T extends object = Record<string, unknown>> {
|
|
20
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
21
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
22
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
23
|
+
bindings(): "";
|
|
24
|
+
exports(): {};
|
|
25
|
+
}
|
|
26
|
+
interface $$IsomorphicComponent {
|
|
27
|
+
new <T extends object = Record<string, unknown>>(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']>> & {
|
|
28
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
29
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
30
|
+
<T extends object = Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
31
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
32
|
+
}
|
|
33
|
+
declare const Update: $$IsomorphicComponent;
|
|
34
|
+
type Update<T extends object = Record<string, unknown>> = InstanceType<typeof Update<T>>;
|
|
35
|
+
export default Update;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
type = 'button',
|
|
7
|
+
disabled = false,
|
|
8
|
+
btn = true,
|
|
9
|
+
variant,
|
|
10
|
+
class: additionalClass,
|
|
11
|
+
children,
|
|
12
|
+
...rest
|
|
13
|
+
}: {
|
|
14
|
+
btn?: boolean;
|
|
15
|
+
variant?: string;
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
} & HTMLButtonAttributes = $props();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<button
|
|
21
|
+
{type}
|
|
22
|
+
class={[btn && 'btn', variant && `btn-${variant}`, additionalClass]}
|
|
23
|
+
{disabled}
|
|
24
|
+
{...rest}
|
|
25
|
+
>
|
|
26
|
+
{#if children}{@render children()}{/if}
|
|
27
|
+
</button>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
btn?: boolean;
|
|
5
|
+
variant?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
} & HTMLButtonAttributes;
|
|
8
|
+
declare const Button: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type Button = ReturnType<typeof Button>;
|
|
10
|
+
export default Button;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { ClassValue } from 'svelte/elements';
|
|
4
|
+
import Required from './Required.svelte';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
text,
|
|
8
|
+
for: labelFor,
|
|
9
|
+
capitalize = false,
|
|
10
|
+
required = false,
|
|
11
|
+
ariaLabel,
|
|
12
|
+
class: additionalClass,
|
|
13
|
+
children,
|
|
14
|
+
}: {
|
|
15
|
+
text?: string;
|
|
16
|
+
for?: string;
|
|
17
|
+
capitalize?: boolean;
|
|
18
|
+
required?: boolean;
|
|
19
|
+
ariaLabel?: string;
|
|
20
|
+
class?: ClassValue;
|
|
21
|
+
children?: Snippet;
|
|
22
|
+
} = $props();
|
|
23
|
+
|
|
24
|
+
const derivedAriaLabel = $derived(ariaLabel ?? text);
|
|
25
|
+
const labelClasses = 'text-sm font-medium text-base-content/60';
|
|
26
|
+
const derivedClasses = $derived(additionalClass ?? labelClasses);
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<label
|
|
30
|
+
class={[derivedClasses, capitalize && 'capitalize']}
|
|
31
|
+
for={labelFor}
|
|
32
|
+
aria-label={derivedAriaLabel}
|
|
33
|
+
>
|
|
34
|
+
{#if text}{text}{/if}
|
|
35
|
+
{#if required}<Required />{/if}
|
|
36
|
+
{#if children}{@render children()}{/if}
|
|
37
|
+
</label>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ClassValue } from 'svelte/elements';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
text?: string;
|
|
5
|
+
for?: string;
|
|
6
|
+
capitalize?: boolean;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
ariaLabel?: string;
|
|
9
|
+
class?: ClassValue;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
};
|
|
12
|
+
declare const Label: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
|
+
type Label = ReturnType<typeof Label>;
|
|
14
|
+
export default Label;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { FullAutoFill } from 'svelte/elements';
|
|
3
|
+
import Label from './Label.svelte';
|
|
4
|
+
import Button from './Button.svelte';
|
|
5
|
+
import { getIconSet } from '../../icons/context.js';
|
|
6
|
+
import { defaultIconSet } from '../../icons/sets/default.js';
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
name,
|
|
10
|
+
id,
|
|
11
|
+
value = '',
|
|
12
|
+
autocomplete,
|
|
13
|
+
required = true,
|
|
14
|
+
placeholder = '',
|
|
15
|
+
invalid = false,
|
|
16
|
+
}: {
|
|
17
|
+
name?: string;
|
|
18
|
+
id?: string;
|
|
19
|
+
value?: string;
|
|
20
|
+
autocomplete?: FullAutoFill;
|
|
21
|
+
required?: boolean;
|
|
22
|
+
placeholder?: string;
|
|
23
|
+
invalid?: boolean;
|
|
24
|
+
} = $props();
|
|
25
|
+
|
|
26
|
+
const icons = $derived(getIconSet() ?? defaultIconSet);
|
|
27
|
+
let visible = $state(false);
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<Label
|
|
31
|
+
class={[
|
|
32
|
+
'input input-bordered w-full',
|
|
33
|
+
{ 'input-error': invalid }
|
|
34
|
+
]}
|
|
35
|
+
>
|
|
36
|
+
<input
|
|
37
|
+
{name}
|
|
38
|
+
{id}
|
|
39
|
+
{required}
|
|
40
|
+
{placeholder}
|
|
41
|
+
{value}
|
|
42
|
+
{autocomplete}
|
|
43
|
+
type={visible ? 'text' : 'password'}
|
|
44
|
+
class="grow"
|
|
45
|
+
/>
|
|
46
|
+
<Button
|
|
47
|
+
btn={false}
|
|
48
|
+
class="cursor-pointer opacity-60 hover:opacity-100"
|
|
49
|
+
aria-label={visible ? 'Ocultar contraseña' : 'Mostrar contraseña'}
|
|
50
|
+
aria-pressed={visible}
|
|
51
|
+
onclick={() => (visible = !visible)}
|
|
52
|
+
>
|
|
53
|
+
{#if visible}
|
|
54
|
+
{@const HideIcon = icons.passwordHide}
|
|
55
|
+
<HideIcon class="size-4" />
|
|
56
|
+
{:else}
|
|
57
|
+
{@const ShowIcon = icons.passwordShow}
|
|
58
|
+
<ShowIcon class="size-4" />
|
|
59
|
+
{/if}
|
|
60
|
+
</Button>
|
|
61
|
+
</Label>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FullAutoFill } from 'svelte/elements';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
name?: string;
|
|
4
|
+
id?: string;
|
|
5
|
+
value?: string;
|
|
6
|
+
autocomplete?: FullAutoFill;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
invalid?: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const PasswordInput: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type PasswordInput = ReturnType<typeof PasswordInput>;
|
|
13
|
+
export default PasswordInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<span class="text-error ml-0.5">*</span>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default Required;
|
|
2
|
+
type Required = SvelteComponent<{
|
|
3
|
+
[x: string]: never;
|
|
4
|
+
}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const Required: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
+
$$bindings?: Bindings;
|
|
17
|
+
} & Exports;
|
|
18
|
+
(internal: unknown, props: {
|
|
19
|
+
$$events?: Events;
|
|
20
|
+
$$slots?: Slots;
|
|
21
|
+
}): Exports & {
|
|
22
|
+
$set?: any;
|
|
23
|
+
$on?: any;
|
|
24
|
+
};
|
|
25
|
+
z_$$bindings?: Bindings;
|
|
26
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getStrings } from '../../i18n/context.js';
|
|
3
|
+
|
|
4
|
+
const strings = getStrings();
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
name,
|
|
8
|
+
value = $bindable(''),
|
|
9
|
+
options = [],
|
|
10
|
+
placeholder = strings.selectPlaceholder,
|
|
11
|
+
error = '',
|
|
12
|
+
disabled = false,
|
|
13
|
+
}: {
|
|
14
|
+
name?: string;
|
|
15
|
+
value?: string;
|
|
16
|
+
options?: { value: string; label: string }[];
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
error?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
} = $props();
|
|
21
|
+
|
|
22
|
+
let open = $state(false);
|
|
23
|
+
let search = $state('');
|
|
24
|
+
let container: HTMLDivElement;
|
|
25
|
+
|
|
26
|
+
const filtered = $derived(
|
|
27
|
+
search.trim()
|
|
28
|
+
? options.filter((o) => o.label.toLowerCase().includes(search.toLowerCase()))
|
|
29
|
+
: options
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const selectedLabel = $derived(
|
|
33
|
+
options.find((o) => o.value === value)?.label ?? placeholder
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
function toggle() {
|
|
37
|
+
if (disabled) return;
|
|
38
|
+
open = !open;
|
|
39
|
+
if (!open) search = '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function pick(val: string) {
|
|
43
|
+
value = val;
|
|
44
|
+
open = false;
|
|
45
|
+
search = '';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function onWindowClick(e: MouseEvent) {
|
|
49
|
+
if (open && !container.contains(e.target as Node)) {
|
|
50
|
+
open = false;
|
|
51
|
+
search = '';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<svelte:window onclick={onWindowClick} />
|
|
57
|
+
|
|
58
|
+
<div class="relative w-full" bind:this={container}>
|
|
59
|
+
{#if name}
|
|
60
|
+
<input type="hidden" {name} {value} />
|
|
61
|
+
{/if}
|
|
62
|
+
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
class="select select-bordered w-full text-left font-normal"
|
|
66
|
+
class:select-error={!!error}
|
|
67
|
+
class:opacity-40={!value}
|
|
68
|
+
{disabled}
|
|
69
|
+
onclick={toggle}
|
|
70
|
+
>
|
|
71
|
+
{selectedLabel}
|
|
72
|
+
</button>
|
|
73
|
+
|
|
74
|
+
{#if open}
|
|
75
|
+
<div class="absolute z-50 mt-1 w-full rounded-box border border-base-content/10 bg-base-100 shadow-lg">
|
|
76
|
+
<div class="p-2">
|
|
77
|
+
<input
|
|
78
|
+
type="text"
|
|
79
|
+
class="input input-bordered input-sm w-full"
|
|
80
|
+
placeholder={strings.selectSearch}
|
|
81
|
+
bind:value={search}
|
|
82
|
+
autocomplete="off"
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
<ul class="max-h-48 overflow-y-auto p-1">
|
|
86
|
+
<li>
|
|
87
|
+
<button
|
|
88
|
+
type="button"
|
|
89
|
+
class="w-full rounded-btn px-3 py-2 text-left text-sm text-base-content/40 hover:bg-base-200"
|
|
90
|
+
onclick={() => pick('')}
|
|
91
|
+
>
|
|
92
|
+
{placeholder}
|
|
93
|
+
</button>
|
|
94
|
+
</li>
|
|
95
|
+
{#each filtered as option (option.value)}
|
|
96
|
+
<li>
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
class="w-full rounded-btn px-3 py-2 text-left text-sm hover:bg-base-200"
|
|
100
|
+
class:bg-primary={value === option.value}
|
|
101
|
+
class:text-primary-content={value === option.value}
|
|
102
|
+
onclick={() => pick(option.value)}
|
|
103
|
+
>
|
|
104
|
+
{option.label}
|
|
105
|
+
</button>
|
|
106
|
+
</li>
|
|
107
|
+
{/each}
|
|
108
|
+
{#if filtered.length === 0}
|
|
109
|
+
<li class="px-3 py-2 text-sm text-base-content/40">{strings.selectNoResults}</li>
|
|
110
|
+
{/if}
|
|
111
|
+
</ul>
|
|
112
|
+
</div>
|
|
113
|
+
{/if}
|
|
114
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
name?: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
options?: {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}[];
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
};
|
|
12
|
+
declare const Select: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
13
|
+
type Select = ReturnType<typeof Select>;
|
|
14
|
+
export default Select;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getIconSet } from '../../icons/context.js';
|
|
3
|
+
import { defaultIconSet } from '../../icons/sets/default.js';
|
|
4
|
+
import type { BreadcrumbItem } from '../../types/breadcrumb.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
items = [],
|
|
8
|
+
admin = false,
|
|
9
|
+
homeHref,
|
|
10
|
+
}: {
|
|
11
|
+
items?: BreadcrumbItem[];
|
|
12
|
+
admin?: boolean;
|
|
13
|
+
homeHref?: string;
|
|
14
|
+
} = $props();
|
|
15
|
+
|
|
16
|
+
const icons = $derived(getIconSet() ?? defaultIconSet);
|
|
17
|
+
|
|
18
|
+
const home: BreadcrumbItem = $derived({
|
|
19
|
+
label: 'Inicio',
|
|
20
|
+
icon: icons.home,
|
|
21
|
+
link: { href: homeHref ?? (admin ? '/admin' : '/') },
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const allItems = $derived([home, ...items]);
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<div class="breadcrumbs text-sm">
|
|
28
|
+
<ul>
|
|
29
|
+
{#each allItems as item, i (i)}
|
|
30
|
+
<li>
|
|
31
|
+
{#if item.link !== undefined}
|
|
32
|
+
<a class="inline-flex items-center gap-2" {...item.link}>
|
|
33
|
+
{#if item.icon}
|
|
34
|
+
{@const ItemIcon = item.icon}
|
|
35
|
+
<ItemIcon class="size-4" />
|
|
36
|
+
{/if}
|
|
37
|
+
<span class={item.prominent ? '' : 'hidden sm:inline'}>{item.label}</span>
|
|
38
|
+
</a>
|
|
39
|
+
{:else}
|
|
40
|
+
<span class="inline-flex items-center gap-2">
|
|
41
|
+
{#if item.icon}
|
|
42
|
+
{@const ItemIcon = item.icon}
|
|
43
|
+
<ItemIcon class="size-4" />
|
|
44
|
+
{/if}
|
|
45
|
+
<span class={item.prominent ? '' : 'hidden sm:inline'}>{item.label}</span>
|
|
46
|
+
</span>
|
|
47
|
+
{/if}
|
|
48
|
+
</li>
|
|
49
|
+
{/each}
|
|
50
|
+
</ul>
|
|
51
|
+
</div>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BreadcrumbItem } from '../../types/breadcrumb.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
items?: BreadcrumbItem[];
|
|
4
|
+
admin?: boolean;
|
|
5
|
+
homeHref?: string;
|
|
6
|
+
};
|
|
7
|
+
declare const Breadcrumbs: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type Breadcrumbs = ReturnType<typeof Breadcrumbs>;
|
|
9
|
+
export default Breadcrumbs;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends object">
|
|
2
|
+
import Label from '../form/Label.svelte';
|
|
3
|
+
import Button from '../form/Button.svelte';
|
|
4
|
+
import { getIconSet } from '../../icons/context.js';
|
|
5
|
+
import { defaultIconSet } from '../../icons/sets/default.js';
|
|
6
|
+
import { getStrings } from '../../i18n/context.js';
|
|
7
|
+
|
|
8
|
+
const strings = getStrings();
|
|
9
|
+
import type { DistinctEntry } from '../../types/table.js';
|
|
10
|
+
import type { FilterState } from './state.svelte.js';
|
|
11
|
+
import type { ColumnDefinition } from '../../types/crud.js';
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
column,
|
|
15
|
+
entries = [],
|
|
16
|
+
filter,
|
|
17
|
+
maxCheckboxValues = 20,
|
|
18
|
+
onchange,
|
|
19
|
+
}: {
|
|
20
|
+
column: ColumnDefinition<T>;
|
|
21
|
+
entries?: DistinctEntry<T>[];
|
|
22
|
+
filter: FilterState;
|
|
23
|
+
maxCheckboxValues?: number;
|
|
24
|
+
onchange?: () => void;
|
|
25
|
+
} = $props();
|
|
26
|
+
|
|
27
|
+
const icons = $derived(getIconSet() ?? defaultIconSet);
|
|
28
|
+
const popId = $derived(`filter-pop-${column.attribute}`);
|
|
29
|
+
const anchor = $derived(`--filter-anchor-${column.attribute}`);
|
|
30
|
+
const isDatetime = $derived(column.type === 'datetime');
|
|
31
|
+
|
|
32
|
+
const dateRange = $derived(filter.dateRangeFor(column.attribute));
|
|
33
|
+
const calendarValue = $derived(
|
|
34
|
+
dateRange.from || dateRange.to ? `${dateRange.from}/${dateRange.to}` : ''
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
let calendarEl: HTMLElement | undefined = $state();
|
|
38
|
+
|
|
39
|
+
$effect(() => {
|
|
40
|
+
if (!calendarEl) return;
|
|
41
|
+
function handler(e: Event) {
|
|
42
|
+
const value = (e as CustomEvent<{ value: string }>).detail?.value ?? '';
|
|
43
|
+
const [from = '', to = ''] = value.split('/');
|
|
44
|
+
filter.setDateRange(column.attribute, from, to);
|
|
45
|
+
onchange?.();
|
|
46
|
+
}
|
|
47
|
+
calendarEl.addEventListener('change', handler);
|
|
48
|
+
return () => calendarEl?.removeEventListener('change', handler);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
function setText(value: string) {
|
|
52
|
+
filter.setText(column.attribute, value);
|
|
53
|
+
onchange?.();
|
|
54
|
+
}
|
|
55
|
+
function toggle(value: string) {
|
|
56
|
+
filter.toggleValue(column.attribute, value);
|
|
57
|
+
onchange?.();
|
|
58
|
+
}
|
|
59
|
+
function clear() {
|
|
60
|
+
filter.clear(column.attribute);
|
|
61
|
+
onchange?.();
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<Button
|
|
66
|
+
variant="ghost"
|
|
67
|
+
class={[
|
|
68
|
+
'btn-xs btn-square',
|
|
69
|
+
filter.hasActive(column.attribute) && 'text-primary'
|
|
70
|
+
]}
|
|
71
|
+
popovertarget={popId}
|
|
72
|
+
style="anchor-name:{anchor}"
|
|
73
|
+
aria-label={strings.filterColumn(column.title ?? column.attribute)}
|
|
74
|
+
title={strings.filter}
|
|
75
|
+
>
|
|
76
|
+
{#if filter.hasActive(column.attribute)}
|
|
77
|
+
{@const Icon = icons.filterActive}
|
|
78
|
+
<Icon class="size-3.5" />
|
|
79
|
+
{:else}
|
|
80
|
+
{@const Icon = icons.filter}
|
|
81
|
+
<Icon class="size-3.5" />
|
|
82
|
+
{/if}
|
|
83
|
+
</Button>
|
|
84
|
+
|
|
85
|
+
<div
|
|
86
|
+
popover="auto"
|
|
87
|
+
id={popId}
|
|
88
|
+
style="position-anchor:{anchor}"
|
|
89
|
+
class="dropdown dropdown-end rounded-box border border-base-content/10 bg-base-100 p-3 shadow-lg"
|
|
90
|
+
class:w-56={!isDatetime}
|
|
91
|
+
>
|
|
92
|
+
{#if isDatetime}
|
|
93
|
+
<calendar-range
|
|
94
|
+
class="cally bg-base-100"
|
|
95
|
+
value={calendarValue}
|
|
96
|
+
bind:this={calendarEl}
|
|
97
|
+
>
|
|
98
|
+
<svg aria-label={strings.previous} class="fill-current size-4" {...{"slot": "previous"}} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M15.75 19.5 8.25 12l7.5-7.5"/></svg>
|
|
99
|
+
<svg aria-label={strings.next} class="fill-current size-4" {...{"slot": "next"}} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="m8.25 4.5 7.5 7.5-7.5 7.5"/></svg>
|
|
100
|
+
<calendar-month></calendar-month>
|
|
101
|
+
</calendar-range>
|
|
102
|
+
{#if dateRange.from || dateRange.to}
|
|
103
|
+
<p class="mt-2 text-xs text-base-content/60">
|
|
104
|
+
{dateRange.from || '…'} → {dateRange.to || '…'}
|
|
105
|
+
</p>
|
|
106
|
+
{/if}
|
|
107
|
+
{:else}
|
|
108
|
+
<input
|
|
109
|
+
type="text"
|
|
110
|
+
class="input input-bordered input-sm w-full"
|
|
111
|
+
placeholder={strings.filterPlaceholder}
|
|
112
|
+
value={filter.textFor(column.attribute)}
|
|
113
|
+
oninput={(e) => setText(e.currentTarget.value)}
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
{#if entries.length > 0 && entries.length < maxCheckboxValues}
|
|
117
|
+
<div class="mt-2 flex max-h-60 flex-col gap-1 overflow-y-auto">
|
|
118
|
+
{#each entries as entry (entry.key)}
|
|
119
|
+
<Label class="flex cursor-pointer items-center gap-2 text-sm font-normal normal-case">
|
|
120
|
+
<input
|
|
121
|
+
type="checkbox"
|
|
122
|
+
class="checkbox checkbox-xs shrink-0"
|
|
123
|
+
checked={filter.isChecked(column.attribute, entry.key)}
|
|
124
|
+
onchange={() => toggle(entry.key)}
|
|
125
|
+
/>
|
|
126
|
+
<span class="truncate">
|
|
127
|
+
{entry.key === '' ? strings.emptyValue : entry.key}
|
|
128
|
+
</span>
|
|
129
|
+
</Label>
|
|
130
|
+
{/each}
|
|
131
|
+
</div>
|
|
132
|
+
{/if}
|
|
133
|
+
{/if}
|
|
134
|
+
|
|
135
|
+
{#if filter.hasActive(column.attribute)}
|
|
136
|
+
<Button variant="ghost" class="btn-sm mt-2 w-full" onclick={clear}>
|
|
137
|
+
{strings.clearFilter}
|
|
138
|
+
</Button>
|
|
139
|
+
{/if}
|
|
140
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { DistinctEntry } from '../../types/table.js';
|
|
2
|
+
import type { FilterState } from './state.svelte.js';
|
|
3
|
+
import type { ColumnDefinition } from '../../types/crud.js';
|
|
4
|
+
declare function $$render<T extends object>(): {
|
|
5
|
+
props: {
|
|
6
|
+
column: ColumnDefinition<T>;
|
|
7
|
+
entries?: DistinctEntry<T>[];
|
|
8
|
+
filter: FilterState;
|
|
9
|
+
maxCheckboxValues?: number;
|
|
10
|
+
onchange?: () => void;
|
|
11
|
+
};
|
|
12
|
+
exports: {};
|
|
13
|
+
bindings: "";
|
|
14
|
+
slots: {};
|
|
15
|
+
events: {};
|
|
16
|
+
};
|
|
17
|
+
declare class __sveltets_Render<T extends object> {
|
|
18
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
19
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
20
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
21
|
+
bindings(): "";
|
|
22
|
+
exports(): {};
|
|
23
|
+
}
|
|
24
|
+
interface $$IsomorphicComponent {
|
|
25
|
+
new <T extends object>(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']>> & {
|
|
26
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
27
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
28
|
+
<T extends object>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
29
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
30
|
+
}
|
|
31
|
+
declare const ColumnFilter: $$IsomorphicComponent;
|
|
32
|
+
type ColumnFilter<T extends object> = InstanceType<typeof ColumnFilter<T>>;
|
|
33
|
+
export default ColumnFilter;
|