@makolabs/ripple 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 +575 -8
- package/dist/adapters/storage/BaseAdapter.d.ts +20 -0
- package/dist/adapters/storage/BaseAdapter.js +171 -0
- package/dist/adapters/storage/S3Adapter.d.ts +21 -0
- package/dist/adapters/storage/S3Adapter.js +194 -0
- package/dist/adapters/storage/index.d.ts +3 -0
- package/dist/adapters/storage/index.js +3 -0
- package/dist/adapters/storage/types.d.ts +102 -0
- package/dist/adapters/storage/types.js +4 -0
- package/dist/button/Button.svelte +48 -0
- package/dist/button/Button.svelte.d.ts +4 -0
- package/dist/button/button.d.ts +113 -0
- package/dist/button/button.js +168 -0
- package/dist/charts/Chart.svelte +545 -0
- package/dist/charts/Chart.svelte.d.ts +4 -0
- package/dist/drawer/Drawer.svelte +224 -0
- package/dist/drawer/Drawer.svelte.d.ts +4 -0
- package/dist/drawer/drawer.d.ts +160 -0
- package/dist/drawer/drawer.js +80 -0
- package/dist/elements/accordion/Accordion.svelte +98 -0
- package/dist/elements/accordion/Accordion.svelte.d.ts +4 -0
- package/dist/elements/accordion/accordion.d.ts +227 -0
- package/dist/elements/accordion/accordion.js +138 -0
- package/dist/elements/alert/Alert.svelte +57 -0
- package/dist/elements/alert/Alert.svelte.d.ts +4 -0
- package/dist/elements/badge/Badge.svelte +43 -0
- package/dist/elements/badge/Badge.svelte.d.ts +4 -0
- package/dist/elements/badge/badge.d.ts +181 -0
- package/dist/elements/badge/badge.js +65 -0
- package/dist/elements/dropdown/Dropdown.svelte +234 -0
- package/dist/elements/dropdown/Dropdown.svelte.d.ts +4 -0
- package/dist/elements/dropdown/Select.svelte +333 -0
- package/dist/elements/dropdown/Select.svelte.d.ts +4 -0
- package/dist/elements/dropdown/dropdown.d.ts +251 -0
- package/dist/elements/dropdown/dropdown.js +95 -0
- package/dist/elements/dropdown/select.d.ts +200 -0
- package/dist/elements/dropdown/select.js +82 -0
- package/dist/elements/file-upload/FileUpload.svelte +135 -0
- package/dist/elements/file-upload/FileUpload.svelte.d.ts +4 -0
- package/dist/elements/file-upload/FilesPreview.svelte +93 -0
- package/dist/elements/file-upload/FilesPreview.svelte.d.ts +4 -0
- package/dist/elements/progress/Progress.svelte +145 -0
- package/dist/elements/progress/Progress.svelte.d.ts +4 -0
- package/dist/elements/timeline/Timeline.svelte +92 -0
- package/dist/elements/timeline/Timeline.svelte.d.ts +7 -0
- package/dist/file-browser/FileBrowser.svelte +877 -0
- package/dist/file-browser/FileBrowser.svelte.d.ts +14 -0
- package/dist/file-browser/index.d.ts +1 -0
- package/dist/file-browser/index.js +1 -0
- package/dist/filters/CompactFilters.svelte +147 -0
- package/dist/filters/CompactFilters.svelte.d.ts +4 -0
- package/dist/filters/index.d.ts +1 -0
- package/dist/filters/index.js +1 -0
- package/dist/forms/Checkbox.svelte +54 -0
- package/dist/forms/Checkbox.svelte.d.ts +4 -0
- package/dist/forms/DateRange.svelte +493 -0
- package/dist/forms/DateRange.svelte.d.ts +4 -0
- package/dist/forms/Form.svelte +39 -0
- package/dist/forms/Form.svelte.d.ts +4 -0
- package/dist/forms/Input.svelte +86 -0
- package/dist/forms/Input.svelte.d.ts +4 -0
- package/dist/forms/NumberInput.svelte +159 -0
- package/dist/forms/NumberInput.svelte.d.ts +4 -0
- package/dist/forms/RadioInputs.svelte +64 -0
- package/dist/forms/RadioInputs.svelte.d.ts +4 -0
- package/dist/forms/RadioPill.svelte +66 -0
- package/dist/forms/RadioPill.svelte.d.ts +4 -0
- package/dist/forms/Slider.svelte +342 -0
- package/dist/forms/Slider.svelte.d.ts +4 -0
- package/dist/forms/Tags.svelte +181 -0
- package/dist/forms/Tags.svelte.d.ts +4 -0
- package/dist/forms/Toggle.svelte +132 -0
- package/dist/forms/Toggle.svelte.d.ts +4 -0
- package/dist/forms/slider.d.ts +143 -0
- package/dist/forms/slider.js +62 -0
- package/dist/header/Breadcrumbs.svelte +73 -0
- package/dist/header/Breadcrumbs.svelte.d.ts +4 -0
- package/dist/header/PageHeader.svelte +68 -0
- package/dist/header/PageHeader.svelte.d.ts +4 -0
- package/dist/header/breadcrumbs.d.ts +226 -0
- package/dist/header/breadcrumbs.js +87 -0
- package/dist/helper/cls.d.ts +1 -0
- package/dist/helper/cls.js +4 -0
- package/dist/helper/date.d.ts +7 -0
- package/dist/helper/date.js +15 -0
- package/dist/helper/nav.svelte.d.ts +6 -0
- package/dist/helper/nav.svelte.js +23 -0
- package/dist/index.d.ts +856 -1
- package/dist/index.js +78 -1
- package/dist/layout/card/Card.svelte +41 -0
- package/dist/layout/card/Card.svelte.d.ts +4 -0
- package/dist/layout/card/MetricCard.svelte +64 -0
- package/dist/layout/card/MetricCard.svelte.d.ts +4 -0
- package/dist/layout/card/StatsCard.svelte +266 -0
- package/dist/layout/card/StatsCard.svelte.d.ts +4 -0
- package/dist/layout/card/card.d.ts +128 -0
- package/dist/layout/card/card.js +51 -0
- package/dist/layout/card/metric-card.d.ts +49 -0
- package/dist/layout/card/metric-card.js +10 -0
- package/dist/layout/card/stats-card.d.ts +191 -0
- package/dist/layout/card/stats-card.js +73 -0
- package/dist/layout/navbar/Navbar.svelte +206 -0
- package/dist/layout/navbar/Navbar.svelte.d.ts +4 -0
- package/dist/layout/navbar/navbar.d.ts +205 -0
- package/dist/layout/navbar/navbar.js +98 -0
- package/dist/layout/sidebar/NavGroup.svelte +91 -0
- package/dist/layout/sidebar/NavGroup.svelte.d.ts +4 -0
- package/dist/layout/sidebar/NavItem.svelte +29 -0
- package/dist/layout/sidebar/NavItem.svelte.d.ts +4 -0
- package/dist/layout/sidebar/Sidebar.svelte +193 -0
- package/dist/layout/sidebar/Sidebar.svelte.d.ts +4 -0
- package/dist/layout/table/Cells.svelte +111 -0
- package/dist/layout/table/Cells.svelte.d.ts +27 -0
- package/dist/layout/table/Table.svelte +790 -0
- package/dist/layout/table/Table.svelte.d.ts +4 -0
- package/dist/layout/table/table.d.ts +256 -0
- package/dist/layout/table/table.js +141 -0
- package/dist/layout/tabs/Tab.svelte +60 -0
- package/dist/layout/tabs/Tab.svelte.d.ts +4 -0
- package/dist/layout/tabs/TabContent.svelte +30 -0
- package/dist/layout/tabs/TabContent.svelte.d.ts +4 -0
- package/dist/layout/tabs/TabGroup.svelte +62 -0
- package/dist/layout/tabs/TabGroup.svelte.d.ts +4 -0
- package/dist/layout/tabs/tabs.d.ts +140 -0
- package/dist/layout/tabs/tabs.js +298 -0
- package/dist/modal/Modal.svelte +207 -0
- package/dist/modal/Modal.svelte.d.ts +4 -0
- package/dist/modal/modal.d.ts +211 -0
- package/dist/modal/modal.js +81 -0
- package/dist/sonner/sonner.svelte +13 -0
- package/dist/sonner/sonner.svelte.d.ts +4 -0
- package/dist/types/variants.d.ts +1 -0
- package/dist/types/variants.js +1 -0
- package/dist/utils/Portal.svelte +108 -0
- package/dist/utils/Portal.svelte.d.ts +8 -0
- package/dist/utils/dateUtils.d.ts +7 -0
- package/dist/utils/dateUtils.js +26 -0
- package/dist/variants.d.ts +30 -0
- package/dist/variants.js +36 -0
- package/package.json +39 -6
- package/dist/layout/Card.svelte +0 -179
- package/dist/layout/Card.svelte.d.ts +0 -208
- package/dist/layout/index.d.ts +0 -1
- package/dist/layout/index.js +0 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const navbar = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
base: 'sticky top-0 z-40 w-full backdrop-blur',
|
|
5
|
+
wrapper: 'mx-auto px-4 sm:px-6 lg:px-8',
|
|
6
|
+
container: 'flex h-16 justify-between',
|
|
7
|
+
brand: 'flex flex-shrink-0 items-center',
|
|
8
|
+
menu: 'hidden sm:ml-6 sm:flex sm:space-x-8',
|
|
9
|
+
mobileMenu: 'sm:hidden',
|
|
10
|
+
mobileMenuButton: 'inline-flex items-center justify-center rounded-md p-2',
|
|
11
|
+
mobileMenuContainer: 'space-y-1 pb-3 pt-2',
|
|
12
|
+
links: 'flex items-center space-x-4',
|
|
13
|
+
link: 'inline-flex h-full items-center gap-2 border-b-2 px-1 pt-1 text-sm font-medium',
|
|
14
|
+
mobileLink: 'block border-l-4 py-2 pl-3 pr-4 text-base font-medium',
|
|
15
|
+
actions: 'hidden sm:ml-6 sm:flex sm:items-center',
|
|
16
|
+
avatar: 'h-8 w-8 rounded-full',
|
|
17
|
+
selectButton: 'flex rounded-full focus:outline-none',
|
|
18
|
+
selectMenu: 'absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5',
|
|
19
|
+
selectItem: 'block px-4 py-2 text-sm',
|
|
20
|
+
divider: 'border-t border-default-200 my-2'
|
|
21
|
+
},
|
|
22
|
+
variants: {
|
|
23
|
+
color: {
|
|
24
|
+
default: {
|
|
25
|
+
base: 'bg-white/80 border-b border-default-200',
|
|
26
|
+
mobileMenuButton: 'text-default-500 hover:bg-default-100 focus:outline-none',
|
|
27
|
+
link: 'text-default-500 hover:text-default-900 border-transparent hover:border-default-300',
|
|
28
|
+
mobileLink: 'text-default-600 hover:bg-default-50 border-transparent',
|
|
29
|
+
selectItem: 'text-default-700 hover:bg-default-100'
|
|
30
|
+
},
|
|
31
|
+
primary: {
|
|
32
|
+
base: 'bg-primary-50/80 border-b border-primary-200',
|
|
33
|
+
mobileMenuButton: 'text-primary-500 hover:bg-primary-100 focus:outline-none',
|
|
34
|
+
link: 'text-primary-500 hover:text-primary-900 border-transparent hover:border-primary-300',
|
|
35
|
+
mobileLink: 'text-primary-600 hover:bg-primary-50 border-transparent',
|
|
36
|
+
selectItem: 'text-primary-700 hover:bg-primary-100'
|
|
37
|
+
},
|
|
38
|
+
secondary: {
|
|
39
|
+
base: 'bg-secondary-50/80 border-b border-secondary-200',
|
|
40
|
+
mobileMenuButton: 'text-secondary-500 hover:bg-secondary-100 focus:outline-none',
|
|
41
|
+
link: 'text-secondary-500 hover:text-secondary-900 border-transparent hover:border-secondary-300',
|
|
42
|
+
mobileLink: 'text-secondary-600 hover:bg-secondary-50 border-transparent',
|
|
43
|
+
selectItem: 'text-secondary-700 hover:bg-secondary-100'
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
size: {
|
|
47
|
+
sm: {
|
|
48
|
+
container: 'h-12',
|
|
49
|
+
link: 'text-xs',
|
|
50
|
+
mobileLink: 'text-xs'
|
|
51
|
+
},
|
|
52
|
+
base: {
|
|
53
|
+
container: 'h-16',
|
|
54
|
+
link: 'text-sm',
|
|
55
|
+
mobileLink: 'text-sm'
|
|
56
|
+
},
|
|
57
|
+
lg: {
|
|
58
|
+
container: 'h-20',
|
|
59
|
+
link: 'text-base',
|
|
60
|
+
mobileLink: 'text-base'
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
active: {
|
|
64
|
+
true: {}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
compoundVariants: [
|
|
68
|
+
{
|
|
69
|
+
active: true,
|
|
70
|
+
color: 'default',
|
|
71
|
+
class: {
|
|
72
|
+
link: 'border-default-500 text-default-900',
|
|
73
|
+
mobileLink: 'border-default-500 bg-default-50 text-default-700'
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
active: true,
|
|
78
|
+
color: 'primary',
|
|
79
|
+
class: {
|
|
80
|
+
link: 'border-primary-500 text-primary-900',
|
|
81
|
+
mobileLink: 'border-primary-500 bg-primary-50 text-primary-700'
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
active: true,
|
|
86
|
+
color: 'secondary',
|
|
87
|
+
class: {
|
|
88
|
+
link: 'border-secondary-500 text-secondary-900',
|
|
89
|
+
mobileLink: 'border-secondary-500 bg-secondary-50 text-secondary-700'
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
defaultVariants: {
|
|
94
|
+
color: 'default',
|
|
95
|
+
size: 'base',
|
|
96
|
+
active: false
|
|
97
|
+
}
|
|
98
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
import type { MenuBar, NavGroupProps } from '../../index.js';
|
|
4
|
+
import { cn } from '../../helper/cls.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
labelArea,
|
|
8
|
+
children,
|
|
9
|
+
class: className = '',
|
|
10
|
+
active: isActive = false
|
|
11
|
+
}: NavGroupProps = $props();
|
|
12
|
+
|
|
13
|
+
function toggle() {
|
|
14
|
+
isActive = !isActive;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resetIsActive() {
|
|
18
|
+
isActive = false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const menubar: MenuBar = getContext('menubar');
|
|
22
|
+
|
|
23
|
+
const navGroupClasses = $derived(
|
|
24
|
+
cn(
|
|
25
|
+
`items-center gap-x-3 p-1.5 rounded-md w-full cursor-pointer text-default-400 text-sm/6 text-left font-medium`,
|
|
26
|
+
{
|
|
27
|
+
'font-semibold ': isActive,
|
|
28
|
+
hidden: menubar.collapsed,
|
|
29
|
+
'hidden xl:flex': !menubar.collapsed
|
|
30
|
+
},
|
|
31
|
+
className
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const chevronIconClasses = $derived(
|
|
36
|
+
cn('size-4 text-default-600 shrink-0', {
|
|
37
|
+
'rotate-90': isActive,
|
|
38
|
+
'-ml-2 xl:ml-auto': !menubar.collapsed,
|
|
39
|
+
'-ml-2': menubar.collapsed
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const labelClasses = $derived(
|
|
44
|
+
cn('items-center gap-x-3', {
|
|
45
|
+
hidden: menubar.collapsed,
|
|
46
|
+
'hidden xl:flex': !menubar.collapsed
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const iconClasses = $derived(
|
|
51
|
+
cn('size-6 shrink-0 text-default-600', {
|
|
52
|
+
'flex xl:hidden': !menubar.collapsed
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const topDivClasses = $derived(
|
|
57
|
+
cn('overflow-hidden transition-all duration-200', {
|
|
58
|
+
'bg-transparent mt-0 mt-1 w-auto': !menubar.collapsed,
|
|
59
|
+
'xl:hidden': !isActive,
|
|
60
|
+
'hidden xl:block': menubar.collapsed
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<div>
|
|
66
|
+
<button type="button" class={navGroupClasses} onclick={toggle}>
|
|
67
|
+
{@render labelArea(labelClasses, iconClasses)}
|
|
68
|
+
{@render ChevronIcon(chevronIconClasses, 0.7)}
|
|
69
|
+
</button>
|
|
70
|
+
|
|
71
|
+
<div class={topDivClasses}>
|
|
72
|
+
<ul>
|
|
73
|
+
{@render children?.()}
|
|
74
|
+
</ul>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
{#snippet ChevronIcon(className: string, size: number)}
|
|
79
|
+
<svg
|
|
80
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
81
|
+
width="{size}em"
|
|
82
|
+
height="{size}em"
|
|
83
|
+
viewBox="0 0 16 16"
|
|
84
|
+
class={className}
|
|
85
|
+
>
|
|
86
|
+
<path
|
|
87
|
+
fill="currentColor"
|
|
88
|
+
d="M5.74 3.2a.75.75 0 0 0-.04 1.06L9.227 8L5.7 11.74a.75.75 0 1 0 1.1 1.02l4-4.25a.75.75 0 0 0 0-1.02l-4-4.25a.75.75 0 0 0-1.06-.04"
|
|
89
|
+
/>
|
|
90
|
+
</svg>
|
|
91
|
+
{/snippet}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { getContext } from 'svelte';
|
|
4
|
+
import type { MenuBar, NavItemProps } from '../../index.js';
|
|
5
|
+
import { cn } from '../../helper/cls.js';
|
|
6
|
+
|
|
7
|
+
let { href, children, active, class: className = '' }: NavItemProps = $props();
|
|
8
|
+
|
|
9
|
+
const menubar: MenuBar = getContext('menubar');
|
|
10
|
+
|
|
11
|
+
const navItemClasses = $derived(
|
|
12
|
+
cn([
|
|
13
|
+
'group flex gap-x-3 p-2 rounded-md text-default-400 text-sm/6',
|
|
14
|
+
{ 'bg-default-950 font-semibold': active, 'hover:bg-default-950': !active },
|
|
15
|
+
className
|
|
16
|
+
])
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const navChildrenClasses = $derived(
|
|
20
|
+
clsx('flex-1 truncate', {
|
|
21
|
+
hidden: menubar.collapsed,
|
|
22
|
+
'hidden xl:flex': !menubar.collapsed
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<a {href} class={navItemClasses}>
|
|
28
|
+
{@render children?.(navChildrenClasses)}
|
|
29
|
+
</a>
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { setContext, onMount } from 'svelte';
|
|
3
|
+
import type { MenuBar, NavigationItem, SidebarProps, ParentItem, LinkItem } from '../../index.js';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { isRouteActive } from '../../helper/nav.svelte.js';
|
|
6
|
+
import { goto } from '$app/navigation';
|
|
7
|
+
|
|
8
|
+
let { items = [], logo }: SidebarProps = $props();
|
|
9
|
+
let menubar: MenuBar = $state({
|
|
10
|
+
collapsed: false
|
|
11
|
+
});
|
|
12
|
+
setContext('menubar', menubar);
|
|
13
|
+
|
|
14
|
+
// Track screen size for responsive behavior
|
|
15
|
+
let isSmallScreen = $state(false);
|
|
16
|
+
|
|
17
|
+
function updateCollapseState() {
|
|
18
|
+
if (typeof window !== 'undefined') {
|
|
19
|
+
isSmallScreen = window.innerWidth < 1280; // xl breakpoint
|
|
20
|
+
if (isSmallScreen && !menubar.collapsed) {
|
|
21
|
+
menubar.collapsed = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
onMount(() => {
|
|
27
|
+
updateCollapseState();
|
|
28
|
+
window.addEventListener('resize', updateCollapseState);
|
|
29
|
+
return () => window.removeEventListener('resize', updateCollapseState);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
function toggle() {
|
|
33
|
+
menubar.collapsed = !menubar.collapsed;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Process a navigation item to determine if it should be active
|
|
38
|
+
*/
|
|
39
|
+
function processNavigationItem(item: NavigationItem): NavigationItem {
|
|
40
|
+
if ('type' in item && item.type === 'horizontal-divider') {
|
|
41
|
+
return item;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if ('children' in item) {
|
|
45
|
+
const parentItem = item as ParentItem;
|
|
46
|
+
let anyChildActive = parentItem.active;
|
|
47
|
+
|
|
48
|
+
const updatedChildren = parentItem.children.map((child) => {
|
|
49
|
+
const childActive = isRouteActive(child.href, true);
|
|
50
|
+
if (childActive) {
|
|
51
|
+
anyChildActive = true;
|
|
52
|
+
}
|
|
53
|
+
return { ...child, active: childActive };
|
|
54
|
+
});
|
|
55
|
+
return { ...parentItem, active: anyChildActive, children: updatedChildren };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if ('href' in item) {
|
|
59
|
+
const linkItem = item as LinkItem;
|
|
60
|
+
return { ...linkItem, active: isRouteActive(linkItem.href) };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return item;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Reactively compute the active states based on the current route
|
|
67
|
+
const navigationItems = $derived(items.map((item) => processNavigationItem(item)));
|
|
68
|
+
$inspect(navigationItems);
|
|
69
|
+
|
|
70
|
+
const sidebarClasses = $derived(
|
|
71
|
+
clsx(
|
|
72
|
+
`min-h-screen flex flex-col bg-gradient-to-b from-gray-900 to-default-900 h-full shrink-0`,
|
|
73
|
+
{
|
|
74
|
+
'w-16': menubar.collapsed,
|
|
75
|
+
'w-64': !menubar.collapsed
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const logoWrapperClasses = $derived(
|
|
81
|
+
clsx(
|
|
82
|
+
'flex items-center h-16 flex-shrink-0 px-4 bg-gradient-to-r from-gray-900 to-default-900/50 border-b border-white/10',
|
|
83
|
+
{
|
|
84
|
+
'justify-between': !menubar.collapsed,
|
|
85
|
+
'justify-center': menubar.collapsed
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<div class={sidebarClasses}>
|
|
92
|
+
<div class={logoWrapperClasses}>
|
|
93
|
+
<div class="flex items-center gap-x-1">
|
|
94
|
+
{#if logo.src && !menubar.collapsed}
|
|
95
|
+
<img src={logo.src} alt={logo.title} class="size-8 shrink-0" />
|
|
96
|
+
{/if}
|
|
97
|
+
{#if logo.title && !menubar.collapsed}
|
|
98
|
+
<h1 class="text-xl font-bold text-white">{logo.title}</h1>
|
|
99
|
+
{/if}
|
|
100
|
+
</div>
|
|
101
|
+
<button
|
|
102
|
+
onclick={toggle}
|
|
103
|
+
class="cursor-pointer text-white {isSmallScreen
|
|
104
|
+
? 'block'
|
|
105
|
+
: menubar.collapsed
|
|
106
|
+
? 'block'
|
|
107
|
+
: 'hidden xl:block'}"
|
|
108
|
+
aria-label="Toggle Sidebar"
|
|
109
|
+
>
|
|
110
|
+
{@render ToggleIcon()}
|
|
111
|
+
</button>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<div class="flex flex-1 flex-col overflow-y-auto bg-gradient-to-b from-transparent to-black/20">
|
|
115
|
+
<nav class="flex-1 space-y-6 px-2 py-4">
|
|
116
|
+
{#each navigationItems as item, index (index)}
|
|
117
|
+
{#if 'type' in item && item.type === 'horizontal-divider'}
|
|
118
|
+
<li class="my-2 border-t border-white/10"></li>
|
|
119
|
+
{:else if 'children' in item}
|
|
120
|
+
<div>
|
|
121
|
+
{#if !menubar.collapsed}
|
|
122
|
+
<h3 class="text-default-200 px-3 text-xs font-semibold tracking-wider uppercase">
|
|
123
|
+
{item.label}
|
|
124
|
+
</h3>
|
|
125
|
+
{/if}
|
|
126
|
+
<div class={menubar.collapsed ? '' : 'mt-2 space-y-1'}>
|
|
127
|
+
{#each item.children as child (child.label)}
|
|
128
|
+
<button
|
|
129
|
+
class="group hover:bg-default-500/10 flex w-full cursor-pointer items-center rounded-md px-3 py-2 text-sm font-medium transition-all duration-150 ease-in-out hover:text-white {child.active
|
|
130
|
+
? 'bg-default-500/20'
|
|
131
|
+
: ''} {menubar.collapsed ? 'justify-center' : ''}"
|
|
132
|
+
class:text-white={child.active}
|
|
133
|
+
class:text-gray-300={!child.active}
|
|
134
|
+
onclick={() => goto(child.href)}
|
|
135
|
+
title={menubar.collapsed ? child.label : ''}
|
|
136
|
+
>
|
|
137
|
+
{#if child.Icon}
|
|
138
|
+
{@const Icon = child.Icon}
|
|
139
|
+
<Icon
|
|
140
|
+
class="h-5 w-5 flex-shrink-0 {child.active
|
|
141
|
+
? 'text-default-200'
|
|
142
|
+
: 'text-gray-400'} {menubar.collapsed ? '' : 'mr-3'}"
|
|
143
|
+
/>
|
|
144
|
+
{/if}
|
|
145
|
+
{#if !menubar.collapsed}
|
|
146
|
+
<span class="truncate">{child.label}</span>
|
|
147
|
+
{/if}
|
|
148
|
+
</button>
|
|
149
|
+
{/each}
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
{:else if 'href' in item}
|
|
153
|
+
<button
|
|
154
|
+
class="group hover:bg-default-500/10 flex w-full cursor-pointer items-center rounded-md px-3 py-2 text-sm font-medium transition-all duration-150 ease-in-out hover:text-white {item.active
|
|
155
|
+
? 'bg-default-500/20'
|
|
156
|
+
: ''} {menubar.collapsed ? 'justify-center' : ''}"
|
|
157
|
+
class:text-white={item.active}
|
|
158
|
+
class:text-gray-300={!item.active}
|
|
159
|
+
onclick={() => (window.location.href = item.href)}
|
|
160
|
+
title={menubar.collapsed ? item.label : ''}
|
|
161
|
+
>
|
|
162
|
+
{#if item.Icon}
|
|
163
|
+
{@const Icon = item.Icon}
|
|
164
|
+
<Icon
|
|
165
|
+
class="h-5 w-5 flex-shrink-0 {item.active
|
|
166
|
+
? 'text-default-200'
|
|
167
|
+
: 'text-gray-400'} {menubar.collapsed ? '' : 'mr-3'}"
|
|
168
|
+
/>
|
|
169
|
+
{/if}
|
|
170
|
+
{#if !menubar.collapsed}
|
|
171
|
+
<span class="truncate">{item.label}</span>
|
|
172
|
+
{/if}
|
|
173
|
+
</button>
|
|
174
|
+
{/if}
|
|
175
|
+
{/each}
|
|
176
|
+
</nav>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
{#snippet ToggleIcon(classes = 'size-6 shrink-0 text-default-200')}
|
|
181
|
+
<svg
|
|
182
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
183
|
+
width="0.8em"
|
|
184
|
+
height="0.8em"
|
|
185
|
+
viewBox="0 0 24 24"
|
|
186
|
+
class={classes}
|
|
187
|
+
>
|
|
188
|
+
<path
|
|
189
|
+
fill="currentColor"
|
|
190
|
+
d="M3 17h18a1 1 0 0 1 .117 1.993L21 19H3a1 1 0 0 1-.117-1.993zh18zm0-6l18-.002a1 1 0 0 1 .117 1.993l-.117.007L3 13a1 1 0 0 1-.117-1.993zl18-.002zm0-6h18a1 1 0 0 1 .117 1.993L21 7H3a1 1 0 0 1-.117-1.993zh18z"
|
|
191
|
+
/>
|
|
192
|
+
</svg>
|
|
193
|
+
{/snippet}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { StatusType, KeyType, DataRow } from './table.js';
|
|
3
|
+
|
|
4
|
+
export { DateCell, Currency, Percentage, PhoneNumber, Email, Status, Time };
|
|
5
|
+
|
|
6
|
+
function getStatusClass(status: string): KeyType {
|
|
7
|
+
const base = 'inline-flex px-2 py-1 text-xs font-medium rounded-full';
|
|
8
|
+
const classes: Record<StatusType, string> = {
|
|
9
|
+
active: `${base} bg-success-100 text-success-700`,
|
|
10
|
+
inactive: `${base} bg-default-100 text-default-700`,
|
|
11
|
+
pending: `${base} bg-warning-100 text-warning-700`,
|
|
12
|
+
error: `${base} bg-danger-100 text-danger-700`,
|
|
13
|
+
default: `${base} bg-default-100 text-default-700`
|
|
14
|
+
};
|
|
15
|
+
return classes[status as StatusType] || classes.default;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function formatPhoneNumber(phoneNumber: string | number | null | undefined): KeyType | null {
|
|
19
|
+
if (phoneNumber === undefined || phoneNumber === null) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const clean = String(phoneNumber).replace(/\D/g, '');
|
|
23
|
+
const match = clean.match(/^(\d{3})(\d{3})(\d{4})$/);
|
|
24
|
+
return match ? `(${match[1]}) ${match[2]}-${match[3]}` : String(phoneNumber);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function formatTime(time: string | number | Date): KeyType {
|
|
28
|
+
return new Date(time).toLocaleTimeString('en-US', {
|
|
29
|
+
hour: '2-digit',
|
|
30
|
+
minute: '2-digit'
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function formatCurrency(value: number): KeyType {
|
|
35
|
+
return new Intl.NumberFormat('en-US', {
|
|
36
|
+
style: 'currency',
|
|
37
|
+
currency: 'USD',
|
|
38
|
+
minimumFractionDigits: 2,
|
|
39
|
+
maximumFractionDigits: 2
|
|
40
|
+
}).format(value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function formatPercentage(value: number): KeyType {
|
|
44
|
+
return new Intl.NumberFormat('en-US', {
|
|
45
|
+
style: 'percent',
|
|
46
|
+
minimumFractionDigits: 2,
|
|
47
|
+
maximumFractionDigits: 2
|
|
48
|
+
}).format(value / 100);
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
{#snippet DateCell(row: DataRow, key: KeyType)}
|
|
53
|
+
{#if row[key] !== undefined && row[key] !== null}
|
|
54
|
+
{new Date(row[key]).toLocaleDateString('en-US')}
|
|
55
|
+
{:else}
|
|
56
|
+
<span class="text-default-300">—</span>
|
|
57
|
+
{/if}
|
|
58
|
+
{/snippet}
|
|
59
|
+
|
|
60
|
+
{#snippet Currency(row: DataRow, key: KeyType)}
|
|
61
|
+
{#if row[key] !== undefined && row[key] !== null}
|
|
62
|
+
{formatCurrency(row[key])}
|
|
63
|
+
{:else}
|
|
64
|
+
<span class="text-default-300">—</span>
|
|
65
|
+
{/if}
|
|
66
|
+
{/snippet}
|
|
67
|
+
|
|
68
|
+
{#snippet Percentage(row: DataRow, key: KeyType)}
|
|
69
|
+
{#if row[key] !== undefined && row[key] !== null}
|
|
70
|
+
{formatPercentage(row[key])}
|
|
71
|
+
{:else}
|
|
72
|
+
<span class="text-default-300">—</span>
|
|
73
|
+
{/if}
|
|
74
|
+
{/snippet}
|
|
75
|
+
|
|
76
|
+
{#snippet PhoneNumber(row: DataRow, key: KeyType)}
|
|
77
|
+
{#if row[key] !== undefined && row[key] !== null}
|
|
78
|
+
{formatPhoneNumber(row[key])}
|
|
79
|
+
{:else}
|
|
80
|
+
<span class="text-default-300">—</span>
|
|
81
|
+
{/if}
|
|
82
|
+
{/snippet}
|
|
83
|
+
|
|
84
|
+
{#snippet Email(row: DataRow, key: KeyType)}
|
|
85
|
+
{#if row[key] !== undefined && row[key] !== null}
|
|
86
|
+
<a href="mailto:{row[key]}" class="text-primary-600 hover:underline">
|
|
87
|
+
{row[key]}
|
|
88
|
+
</a>
|
|
89
|
+
{:else}
|
|
90
|
+
<span class="text-default-300">—</span>
|
|
91
|
+
{/if}
|
|
92
|
+
{/snippet}
|
|
93
|
+
|
|
94
|
+
{#snippet Status(row: DataRow, key: KeyType)}
|
|
95
|
+
{#if row[key] !== undefined && row[key] !== null}
|
|
96
|
+
{@const status = String(row[key]).toLowerCase()}
|
|
97
|
+
<span class={getStatusClass(status)}>
|
|
98
|
+
{row[key]}
|
|
99
|
+
</span>
|
|
100
|
+
{:else}
|
|
101
|
+
<span class="text-default-300">—</span>
|
|
102
|
+
{/if}
|
|
103
|
+
{/snippet}
|
|
104
|
+
|
|
105
|
+
{#snippet Time(row: DataRow, key: KeyType)}
|
|
106
|
+
{#if row[key] !== undefined && row[key] !== null}
|
|
107
|
+
{formatTime(row[key])}
|
|
108
|
+
{:else}
|
|
109
|
+
<span class="text-default-300">—</span>
|
|
110
|
+
{/if}
|
|
111
|
+
{/snippet}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { KeyType, DataRow } from './table.js';
|
|
2
|
+
export { DateCell, Currency, Percentage, PhoneNumber, Email, Status, Time };
|
|
3
|
+
declare const DateCell: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
|
|
4
|
+
declare const Currency: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
|
|
5
|
+
declare const Percentage: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
|
|
6
|
+
declare const PhoneNumber: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
|
|
7
|
+
declare const Email: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
|
|
8
|
+
declare const Status: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
|
|
9
|
+
declare const Time: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
|
|
10
|
+
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> {
|
|
11
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
12
|
+
$$bindings?: Bindings;
|
|
13
|
+
} & Exports;
|
|
14
|
+
(internal: unknown, props: {
|
|
15
|
+
$$events?: Events;
|
|
16
|
+
$$slots?: Slots;
|
|
17
|
+
}): Exports & {
|
|
18
|
+
$set?: any;
|
|
19
|
+
$on?: any;
|
|
20
|
+
};
|
|
21
|
+
z_$$bindings?: Bindings;
|
|
22
|
+
}
|
|
23
|
+
declare const Cells: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
24
|
+
[evt: string]: CustomEvent<any>;
|
|
25
|
+
}, {}, {}, string>;
|
|
26
|
+
type Cells = InstanceType<typeof Cells>;
|
|
27
|
+
export default Cells;
|