@cloudparker/moldex.js 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/dist/actions/badge.d.ts +12 -0
- package/dist/actions/badge.js +22 -0
- package/dist/actions/index.d.ts +2 -0
- package/dist/actions/index.js +2 -0
- package/dist/actions/ripple.d.ts +16 -0
- package/dist/actions/ripple.js +78 -0
- package/dist/button/components/button/button.svelte +59 -0
- package/dist/button/components/button/button.svelte.d.ts +36 -0
- package/dist/button/components/button-list-item/button-list-item.svelte +119 -0
- package/dist/button/components/button-list-item/button-list-item.svelte.d.ts +60 -0
- package/dist/button/components/button-menu/button-menu.svelte +185 -0
- package/dist/button/components/button-menu/button-menu.svelte.d.ts +61 -0
- package/dist/button/index.d.ts +3 -0
- package/dist/button/index.js +3 -0
- package/dist/common/components/drawer/drawer.svelte +61 -0
- package/dist/common/components/drawer/drawer.svelte.d.ts +31 -0
- package/dist/common/components/navbar/navbar.svelte +82 -0
- package/dist/common/components/navbar/navbar.svelte.d.ts +46 -0
- package/dist/common/components/spinner/spinner.svelte +16 -0
- package/dist/common/components/spinner/spinner.svelte.d.ts +20 -0
- package/dist/common/components/vertical-rule/verticcal-rule.svelte +4 -0
- package/dist/common/components/vertical-rule/verticcal-rule.svelte.d.ts +20 -0
- package/dist/common/index.d.ts +4 -0
- package/dist/common/index.js +4 -0
- package/dist/dialog/components/dialog/dialog.svelte +253 -0
- package/dist/dialog/components/dialog/dialog.svelte.d.ts +80 -0
- package/dist/dialog/index.d.ts +2 -0
- package/dist/dialog/index.js +2 -0
- package/dist/dialog/services/dialog-service.d.ts +2 -0
- package/dist/dialog/services/dialog-service.js +25 -0
- package/dist/icon/components/icon/icon.svelte +15 -0
- package/dist/icon/components/icon/icon.svelte.d.ts +24 -0
- package/dist/icon/index.d.ts +2 -0
- package/dist/icon/index.js +2 -0
- package/dist/icon/services/icon-path-service.d.ts +9 -0
- package/dist/icon/services/icon-path-service.js +10 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/package.json +32 -0
- package/readme.md +3 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type BadgeProsType = {
|
|
2
|
+
containerClassName?: string;
|
|
3
|
+
badgePositionClassName?: string;
|
|
4
|
+
badgeContainerClassName?: string;
|
|
5
|
+
badgeClassName?: string;
|
|
6
|
+
badgeBackgroundClassName?: string;
|
|
7
|
+
badgeText?: string;
|
|
8
|
+
hasBadgeBackground?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function badge(node: HTMLElement, { containerClassName, badgePositionClassName, badgeContainerClassName, badgeClassName, badgeBackgroundClassName, badgeText, hasBadgeBackground }?: BadgeProsType): {
|
|
11
|
+
destroy(): void;
|
|
12
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function badge(node, { containerClassName = '', badgePositionClassName = 'top-0 right-0', badgeContainerClassName = '', badgeClassName = '', badgeBackgroundClassName = '', badgeText = '', hasBadgeBackground = true } = {}) {
|
|
2
|
+
let badgeBackElement = hasBadgeBackground ? `<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 opacity-75 ${badgeBackgroundClassName}"></span>` : '';
|
|
3
|
+
const badge = document.createElement('span');
|
|
4
|
+
badge.className = 'absolute transform translate-x-1/2 -translate-y-1/2 ' + badgePositionClassName;
|
|
5
|
+
badge.innerHTML = `
|
|
6
|
+
<span class="relative flex h-3 w-3 ${badgeContainerClassName}">
|
|
7
|
+
${badgeBackElement}
|
|
8
|
+
<span class="relative inline-grid place-items-center rounded-full h-3 w-3 text-3xs text-white bg-sky-500 ${badgeClassName}">${badgeText || ''}</span>
|
|
9
|
+
</span>
|
|
10
|
+
`;
|
|
11
|
+
let list = ['relative'];
|
|
12
|
+
list.push(...containerClassName.split(' ').map(o => o.trim()).filter(o => o));
|
|
13
|
+
const nodeClassList = [...list];
|
|
14
|
+
node.classList.add(...nodeClassList);
|
|
15
|
+
node.appendChild(badge);
|
|
16
|
+
return {
|
|
17
|
+
destroy() {
|
|
18
|
+
node.removeChild(badge);
|
|
19
|
+
node.classList.remove(...nodeClassList);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type RipplePropsType = {
|
|
2
|
+
/**
|
|
3
|
+
* The color of the ripple effect, default is rgba(0, 0, 0, 0.12)
|
|
4
|
+
*/
|
|
5
|
+
color?: string;
|
|
6
|
+
/**
|
|
7
|
+
* If true, the ripple effect will be light color rgba(255, 255, 255, 0.12), default is false.
|
|
8
|
+
*/
|
|
9
|
+
light?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare const DARK_RIPPLE_COLOR = "rgba(0, 0, 0, 0.12)";
|
|
12
|
+
export declare const LIGHT_RIPPLE_COLOR = "rgba(255, 255, 255, 0.12)";
|
|
13
|
+
export declare function ripple(node: HTMLElement, { color, light }?: RipplePropsType): {
|
|
14
|
+
destroy(): void;
|
|
15
|
+
};
|
|
16
|
+
export declare function isTouchDevice(): boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export const DARK_RIPPLE_COLOR = 'rgba(0, 0, 0, 0.12)';
|
|
2
|
+
export const LIGHT_RIPPLE_COLOR = 'rgba(255, 255, 255, 0.12)';
|
|
3
|
+
export function ripple(node, { color, light } = {}) {
|
|
4
|
+
let containerRemoveTimer;
|
|
5
|
+
const isTouchEnabled = isTouchDevice();
|
|
6
|
+
let timeoutInstance;
|
|
7
|
+
function scheduleStartRipple(event) {
|
|
8
|
+
if (node.disabled)
|
|
9
|
+
return;
|
|
10
|
+
if (timeoutInstance) {
|
|
11
|
+
clearTimeout(timeoutInstance);
|
|
12
|
+
}
|
|
13
|
+
timeoutInstance = setTimeout(() => {
|
|
14
|
+
startRipple(event);
|
|
15
|
+
}, 100);
|
|
16
|
+
}
|
|
17
|
+
function mouseMove() {
|
|
18
|
+
if (timeoutInstance) {
|
|
19
|
+
clearTimeout(timeoutInstance);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function startRipple(event) {
|
|
23
|
+
const rippleColor = light ? LIGHT_RIPPLE_COLOR : color || DARK_RIPPLE_COLOR;
|
|
24
|
+
const circle = document.createElement('span');
|
|
25
|
+
const diameter = Math.max(node.clientWidth, node.clientHeight);
|
|
26
|
+
const radius = diameter / 2;
|
|
27
|
+
const touch = event.touches?.[0] || {};
|
|
28
|
+
const rect = node.getBoundingClientRect();
|
|
29
|
+
const circleX = (event instanceof MouseEvent ? event.clientX : touch.clientX) - rect.left - radius;
|
|
30
|
+
const circleY = (event instanceof MouseEvent ? event.clientY : touch.clientY) - rect.top - radius;
|
|
31
|
+
circle.style.width = circle.style.height = `${diameter}px`;
|
|
32
|
+
circle.style.left = `${circleX}px`;
|
|
33
|
+
circle.style.top = `${circleY}px`;
|
|
34
|
+
circle.style.setProperty('--ripple-color', rippleColor);
|
|
35
|
+
circle.classList.add('ripple');
|
|
36
|
+
const newClassList = [];
|
|
37
|
+
if (!node.classList.contains('relative')) {
|
|
38
|
+
newClassList.push('relative');
|
|
39
|
+
}
|
|
40
|
+
if (!node.classList.contains('overflow-hidden')) {
|
|
41
|
+
newClassList.push('overflow-hidden');
|
|
42
|
+
}
|
|
43
|
+
node.classList.add(...newClassList);
|
|
44
|
+
node.appendChild(circle);
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
circle.remove();
|
|
47
|
+
}, 500);
|
|
48
|
+
if (containerRemoveTimer) {
|
|
49
|
+
clearTimeout(containerRemoveTimer);
|
|
50
|
+
}
|
|
51
|
+
containerRemoveTimer = setTimeout(() => {
|
|
52
|
+
node.classList.remove(...newClassList);
|
|
53
|
+
}, 500);
|
|
54
|
+
}
|
|
55
|
+
if (!isTouchEnabled) {
|
|
56
|
+
node.addEventListener('mousedown', scheduleStartRipple);
|
|
57
|
+
node.addEventListener('mousemove', mouseMove);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
node.addEventListener('touchstart', scheduleStartRipple);
|
|
61
|
+
node.addEventListener('touchmove', mouseMove);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
destroy() {
|
|
65
|
+
if (!isTouchEnabled) {
|
|
66
|
+
node.removeEventListener('mousedown', scheduleStartRipple);
|
|
67
|
+
node.removeEventListener('mousemove', mouseMove);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
node.removeEventListener('touchstart', scheduleStartRipple);
|
|
71
|
+
node.removeEventListener('touchmove', mouseMove);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export function isTouchDevice() {
|
|
77
|
+
return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 || window.matchMedia("(pointer: coarse)").matches;
|
|
78
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script lang="ts">import { ripple } from "../../../actions/ripple.js";
|
|
2
|
+
import Spinner from "../../../common/components/spinner/spinner.svelte";
|
|
3
|
+
import Icon from "../../../icon/components/icon/icon.svelte";
|
|
4
|
+
let {
|
|
5
|
+
id = "",
|
|
6
|
+
form = void 0,
|
|
7
|
+
type = "button",
|
|
8
|
+
label = "",
|
|
9
|
+
className = "",
|
|
10
|
+
iconPath = "",
|
|
11
|
+
iconClassName = "",
|
|
12
|
+
rightIconPath = "",
|
|
13
|
+
rightIconClassName = "",
|
|
14
|
+
spinner = false,
|
|
15
|
+
disabled = false,
|
|
16
|
+
spinnerClassName = "",
|
|
17
|
+
onlySpinner = false,
|
|
18
|
+
children,
|
|
19
|
+
useRipple = true,
|
|
20
|
+
onclick = (ev) => {
|
|
21
|
+
}
|
|
22
|
+
} = $props();
|
|
23
|
+
function maybeRipple(node, options) {
|
|
24
|
+
if (useRipple) {
|
|
25
|
+
return ripple(node, options);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
destroy() {
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
{#snippet buttonContent()}
|
|
35
|
+
<div class="flex w-full items-center gap-2">
|
|
36
|
+
{#if spinner}
|
|
37
|
+
<Spinner className="w-4 h-4 {spinnerClassName}" />
|
|
38
|
+
{/if}
|
|
39
|
+
{#if !onlySpinner}
|
|
40
|
+
{#if iconPath}
|
|
41
|
+
<Icon path={iconPath} className={iconClassName} />
|
|
42
|
+
{/if}
|
|
43
|
+
{#if label}
|
|
44
|
+
<span>{label || ''}</span>
|
|
45
|
+
{/if}
|
|
46
|
+
{#if rightIconPath}
|
|
47
|
+
<Icon path={rightIconPath} className={rightIconClassName} />
|
|
48
|
+
{/if}
|
|
49
|
+
{/if}
|
|
50
|
+
</div>
|
|
51
|
+
{/snippet}
|
|
52
|
+
|
|
53
|
+
<button {id} {type} {form} class={className} {onclick} {disabled} use:maybeRipple>
|
|
54
|
+
{#if children}
|
|
55
|
+
{@render children()}
|
|
56
|
+
{:else}
|
|
57
|
+
{@render buttonContent()}
|
|
58
|
+
{/if}
|
|
59
|
+
</button>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
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> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const Button: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
id?: string;
|
|
17
|
+
type?: "button" | "submit" | "reset";
|
|
18
|
+
form?: string | null;
|
|
19
|
+
className?: string;
|
|
20
|
+
iconPath?: string;
|
|
21
|
+
iconClassName?: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
rightIconPath?: string;
|
|
24
|
+
rightIconClassName?: string;
|
|
25
|
+
spinner?: boolean;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
spinnerClassName?: string;
|
|
28
|
+
onlySpinner?: boolean;
|
|
29
|
+
children?: Snippet;
|
|
30
|
+
useRipple?: boolean;
|
|
31
|
+
onclick?: (ev: MouseEvent) => void;
|
|
32
|
+
}, {
|
|
33
|
+
[evt: string]: CustomEvent<any>;
|
|
34
|
+
}, {}, {}, "">;
|
|
35
|
+
type Button = InstanceType<typeof Button>;
|
|
36
|
+
export default Button;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<script context="module" lang="ts"></script>
|
|
2
|
+
|
|
3
|
+
<script lang="ts">import { ripple } from "../../../actions/ripple.js";
|
|
4
|
+
import Icon from "../../../icon/components/icon/icon.svelte";
|
|
5
|
+
import {
|
|
6
|
+
mdiCheckCircle,
|
|
7
|
+
mdiCheckCircleOutline,
|
|
8
|
+
mdiChevronRight
|
|
9
|
+
} from "../../../icon/services/icon-path-service.js";
|
|
10
|
+
let {
|
|
11
|
+
item,
|
|
12
|
+
index,
|
|
13
|
+
listId = "",
|
|
14
|
+
className = "",
|
|
15
|
+
hasCheck = false,
|
|
16
|
+
uncheckIconPath = mdiCheckCircleOutline,
|
|
17
|
+
checkIconPath = mdiCheckCircle,
|
|
18
|
+
checkIconClassName = "",
|
|
19
|
+
uncheckIconClassName = "",
|
|
20
|
+
iconClassName = "",
|
|
21
|
+
imgClassName = "",
|
|
22
|
+
labelClassName = "",
|
|
23
|
+
descClassName = "",
|
|
24
|
+
checkClassName = "",
|
|
25
|
+
checked = false,
|
|
26
|
+
hasArrow = false,
|
|
27
|
+
arrowIconPath = mdiChevronRight,
|
|
28
|
+
arrowClassName = "",
|
|
29
|
+
onclick = (ev, item2, index2) => {
|
|
30
|
+
},
|
|
31
|
+
children
|
|
32
|
+
} = $props();
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#snippet itemInternal()}
|
|
36
|
+
<div class="flex w-full items-center gap-4">
|
|
37
|
+
{#if item?.iconPath}
|
|
38
|
+
<div>
|
|
39
|
+
<Icon path={item?.iconPath} className="{iconClassName} {item?.iconClassName}" />
|
|
40
|
+
</div>
|
|
41
|
+
{/if}
|
|
42
|
+
{#if item?.imgSrc}
|
|
43
|
+
<div>
|
|
44
|
+
<img
|
|
45
|
+
src={item?.imgSrc}
|
|
46
|
+
class="w-6 h-6 {imgClassName} {item?.imgClassName}"
|
|
47
|
+
alt="item-img-{index}"
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
{/if}
|
|
51
|
+
<div class="flex-grow">
|
|
52
|
+
{#if item?.label}
|
|
53
|
+
<div class="text-ellipsis overflow-hidden {labelClassName} {item?.labelClassName || ''}">
|
|
54
|
+
{item?.label || ''}
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
57
|
+
{#if item?.desc}
|
|
58
|
+
<div
|
|
59
|
+
class="text-ellipsis overflow-hidden text-gray-400 text-sm font-light {descClassName} {item?.descClassName ||
|
|
60
|
+
''}"
|
|
61
|
+
>
|
|
62
|
+
{item?.desc || ''}
|
|
63
|
+
</div>
|
|
64
|
+
{/if}
|
|
65
|
+
</div>
|
|
66
|
+
{#if hasCheck}
|
|
67
|
+
<div>
|
|
68
|
+
<Icon
|
|
69
|
+
path={checked ? checkIconPath : uncheckIconPath}
|
|
70
|
+
className="w-5 h-5 {checkClassName} {checked
|
|
71
|
+
? `text-primary ${checkIconClassName}`
|
|
72
|
+
: `text-gray-400 ${uncheckIconClassName}`}"
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
{/if}
|
|
76
|
+
|
|
77
|
+
{#if hasArrow}
|
|
78
|
+
<div>
|
|
79
|
+
<Icon path={arrowIconPath} className="w-5 h-5 text-gray-500 {arrowClassName} " />
|
|
80
|
+
</div>
|
|
81
|
+
{/if}
|
|
82
|
+
</div>
|
|
83
|
+
{/snippet}
|
|
84
|
+
|
|
85
|
+
{#snippet buttonSnippet()}
|
|
86
|
+
<button
|
|
87
|
+
id="{listId}-item-item-{index}"
|
|
88
|
+
type="button"
|
|
89
|
+
class="w-full select-none block px-3 py-2 text-start leading-6 text-gray-900 hover:bg-gray-50 focus:bg-gray-50 focus:outline-none {className} {item.className}"
|
|
90
|
+
role="menuitem"
|
|
91
|
+
onclick={(ev) => onclick(ev, item, index)}
|
|
92
|
+
disabled={item?.disabled}
|
|
93
|
+
use:ripple
|
|
94
|
+
>
|
|
95
|
+
{@render itemInternal()}
|
|
96
|
+
</button>
|
|
97
|
+
{/snippet}
|
|
98
|
+
|
|
99
|
+
{#snippet linkSnippet()}
|
|
100
|
+
<a
|
|
101
|
+
id="{listId}-item-item-{index}"
|
|
102
|
+
href={item?.url}
|
|
103
|
+
class="block select-none px-3 py-1 w-full text-start leading-6 text-gray-900 hover:bg-gray-50 focus:bg-gray-50 focus:outline-none {className} {item.className}"
|
|
104
|
+
role="menuitem"
|
|
105
|
+
target={item?.openInNewWindow ? '_blank' : ''}
|
|
106
|
+
onclick={(ev) => onclick(ev, item, index)}
|
|
107
|
+
use:ripple
|
|
108
|
+
>
|
|
109
|
+
{@render itemInternal()}
|
|
110
|
+
</a>
|
|
111
|
+
{/snippet}
|
|
112
|
+
|
|
113
|
+
{#if children}
|
|
114
|
+
{@render children(item, index)}
|
|
115
|
+
{:else if item?.url && !item?.disabled}
|
|
116
|
+
{@render linkSnippet()}
|
|
117
|
+
{:else}
|
|
118
|
+
{@render buttonSnippet()}
|
|
119
|
+
{/if}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type ListItemType = {
|
|
2
|
+
id?: string;
|
|
3
|
+
label?: string;
|
|
4
|
+
labelClassName?: string;
|
|
5
|
+
desc?: string;
|
|
6
|
+
descClassName?: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
onclick?: (ev: MouseEvent, item: ListItemType) => void;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
iconPath?: string;
|
|
11
|
+
iconClassName?: string;
|
|
12
|
+
imgSrc?: string;
|
|
13
|
+
imgClassName?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
openInNewWindow?: boolean;
|
|
16
|
+
divider?: boolean;
|
|
17
|
+
hasArrow?: boolean;
|
|
18
|
+
arrowIconPath?: string;
|
|
19
|
+
arrowClassName?: string;
|
|
20
|
+
};
|
|
21
|
+
import type { Snippet } from 'svelte';
|
|
22
|
+
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> {
|
|
23
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
24
|
+
$$bindings?: Bindings;
|
|
25
|
+
} & Exports;
|
|
26
|
+
(internal: unknown, props: Props & {
|
|
27
|
+
$$events?: Events;
|
|
28
|
+
$$slots?: Slots;
|
|
29
|
+
}): Exports & {
|
|
30
|
+
$set?: any;
|
|
31
|
+
$on?: any;
|
|
32
|
+
};
|
|
33
|
+
z_$$bindings?: Bindings;
|
|
34
|
+
}
|
|
35
|
+
declare const ButtonListItem: $$__sveltets_2_IsomorphicComponent<{
|
|
36
|
+
item: ListItemType;
|
|
37
|
+
index: number;
|
|
38
|
+
listId?: string;
|
|
39
|
+
className?: string;
|
|
40
|
+
hasCheck?: boolean;
|
|
41
|
+
checkIconPath?: string;
|
|
42
|
+
uncheckIconPath?: string;
|
|
43
|
+
checkIconClassName?: string;
|
|
44
|
+
uncheckIconClassName?: string;
|
|
45
|
+
checkClassName?: string;
|
|
46
|
+
iconClassName?: string;
|
|
47
|
+
imgClassName?: string;
|
|
48
|
+
labelClassName?: string;
|
|
49
|
+
descClassName?: string;
|
|
50
|
+
checked?: boolean;
|
|
51
|
+
hasArrow?: boolean;
|
|
52
|
+
arrowIconPath?: string;
|
|
53
|
+
arrowClassName?: string;
|
|
54
|
+
onclick?: (ev: MouseEvent, item: ListItemType, index: number) => void;
|
|
55
|
+
children?: Snippet<[ListItemType, number]>;
|
|
56
|
+
}, {
|
|
57
|
+
[evt: string]: CustomEvent<any>;
|
|
58
|
+
}, {}, {}, "">;
|
|
59
|
+
type ButtonListItem = InstanceType<typeof ButtonListItem>;
|
|
60
|
+
export default ButtonListItem;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<script lang="ts">import Icon from "../../../icon/components/icon/icon.svelte";
|
|
2
|
+
import {
|
|
3
|
+
mdiCheckCircle,
|
|
4
|
+
mdiCheckCircleOutline,
|
|
5
|
+
mdiChevronDown
|
|
6
|
+
} from "../../../icon/services/icon-path-service.js";
|
|
7
|
+
import ButtonListItem from "../button-list-item/button-list-item.svelte";
|
|
8
|
+
import { ripple } from "../../../actions/ripple.js";
|
|
9
|
+
var MenuStateEnum = /* @__PURE__ */ ((MenuStateEnum2) => {
|
|
10
|
+
MenuStateEnum2[MenuStateEnum2["OPENED"] = 0] = "OPENED";
|
|
11
|
+
MenuStateEnum2[MenuStateEnum2["CLOSED"] = 1] = "CLOSED";
|
|
12
|
+
return MenuStateEnum2;
|
|
13
|
+
})(MenuStateEnum || {});
|
|
14
|
+
let {
|
|
15
|
+
id = "menu",
|
|
16
|
+
className = "",
|
|
17
|
+
screenOnlyDesc = "Menu",
|
|
18
|
+
style = "",
|
|
19
|
+
imgSrc = "",
|
|
20
|
+
imgClassName = "",
|
|
21
|
+
imgAlt = "Menu",
|
|
22
|
+
leftIconPath = "",
|
|
23
|
+
leftIconClassName = "",
|
|
24
|
+
rightIconPath = "",
|
|
25
|
+
rightIconClassName = "",
|
|
26
|
+
dropIconPath = mdiChevronDown,
|
|
27
|
+
dropIconClassName = "",
|
|
28
|
+
labelClassName = "",
|
|
29
|
+
label = "Button",
|
|
30
|
+
dropdownStyle = "",
|
|
31
|
+
dropdownClassName = "",
|
|
32
|
+
hasCheck = false,
|
|
33
|
+
uncheckIconPath = mdiCheckCircleOutline,
|
|
34
|
+
checkIconPath = mdiCheckCircle,
|
|
35
|
+
checkIconClassName = "",
|
|
36
|
+
containerClassName = "",
|
|
37
|
+
backgropClassName = "",
|
|
38
|
+
menus = [],
|
|
39
|
+
menuItemClassName = "",
|
|
40
|
+
uncheckIconClassName = "",
|
|
41
|
+
dropdownOpenClassName = "",
|
|
42
|
+
dropdownCloseClassName = "",
|
|
43
|
+
checkClassName = "",
|
|
44
|
+
listIconClassName = "",
|
|
45
|
+
listImgClassName = "",
|
|
46
|
+
listLabelClassName = "",
|
|
47
|
+
listDescClassName = "",
|
|
48
|
+
dividerClassName = "",
|
|
49
|
+
onmenuclick = (ev, item, index) => {
|
|
50
|
+
},
|
|
51
|
+
children,
|
|
52
|
+
buttonChildren,
|
|
53
|
+
menuItemChildren,
|
|
54
|
+
menuItemInnerChildren
|
|
55
|
+
} = $props();
|
|
56
|
+
let expanded = $state(false);
|
|
57
|
+
let dropdownState = $state(1 /* CLOSED */);
|
|
58
|
+
let options = $state([]);
|
|
59
|
+
let selectedMenu = $state(null);
|
|
60
|
+
function hendleToggleDropdown(ev) {
|
|
61
|
+
ev && ev.stopPropagation();
|
|
62
|
+
if (dropdownState == 1 /* CLOSED */) {
|
|
63
|
+
dropdownState = 0 /* OPENED */;
|
|
64
|
+
} else {
|
|
65
|
+
dropdownState = 1 /* CLOSED */;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function handlemenuItemClick(ev, menu, index) {
|
|
69
|
+
hendleToggleDropdown(ev);
|
|
70
|
+
if (onmenuclick) {
|
|
71
|
+
let item = menus[index];
|
|
72
|
+
if (item) {
|
|
73
|
+
onmenuclick(ev, item, index);
|
|
74
|
+
}
|
|
75
|
+
selectedMenu = menu;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
$effect(() => {
|
|
79
|
+
if (menus?.length) {
|
|
80
|
+
let item = menus[0];
|
|
81
|
+
if (typeof item == "string") {
|
|
82
|
+
options = menus.map((str) => {
|
|
83
|
+
if (str == "-" || str == "") {
|
|
84
|
+
return { divider: true };
|
|
85
|
+
} else {
|
|
86
|
+
return { label: str };
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
options = [];
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<div class="relative min-h-max {containerClassName}">
|
|
98
|
+
<button
|
|
99
|
+
type="button"
|
|
100
|
+
class="flex items-center flex-nowrap text-start {className}"
|
|
101
|
+
{style}
|
|
102
|
+
{id}
|
|
103
|
+
aria-expanded={expanded}
|
|
104
|
+
aria-haspopup="true"
|
|
105
|
+
onclick={hendleToggleDropdown}
|
|
106
|
+
use:ripple
|
|
107
|
+
>
|
|
108
|
+
<span class="sr-only">{screenOnlyDesc}</span>
|
|
109
|
+
<div class="flex items-center flex-nowrap gap-2">
|
|
110
|
+
{#if buttonChildren}
|
|
111
|
+
{@render buttonChildren()}
|
|
112
|
+
{:else}
|
|
113
|
+
{#if imgSrc}
|
|
114
|
+
<img class="h-8 w-8 rounded-full bg-gray-50 {imgClassName}" src={imgSrc} alt={imgAlt} />
|
|
115
|
+
{/if}
|
|
116
|
+
{#if leftIconPath}
|
|
117
|
+
<Icon path={leftIconPath} className={leftIconClassName} />
|
|
118
|
+
{/if}
|
|
119
|
+
{#if label}
|
|
120
|
+
<span class="text-nowrap {labelClassName}">
|
|
121
|
+
{label}
|
|
122
|
+
</span>
|
|
123
|
+
{/if}
|
|
124
|
+
{#if rightIconPath}
|
|
125
|
+
<Icon path={rightIconPath} className=" {rightIconClassName}" />
|
|
126
|
+
{/if}
|
|
127
|
+
{#if dropIconPath}
|
|
128
|
+
<Icon path={dropIconPath} className="text-gray-400 {dropIconClassName}" />
|
|
129
|
+
{/if}
|
|
130
|
+
{/if}
|
|
131
|
+
</div>
|
|
132
|
+
</button>
|
|
133
|
+
{#if dropdownState == MenuStateEnum.OPENED}
|
|
134
|
+
<button
|
|
135
|
+
type="button"
|
|
136
|
+
id="{id}-menu-backdrop"
|
|
137
|
+
class="cursor-auto fixed inset-0 z-10 {backgropClassName}"
|
|
138
|
+
onclick={hendleToggleDropdown}
|
|
139
|
+
tabindex="-1"
|
|
140
|
+
></button>
|
|
141
|
+
{/if}
|
|
142
|
+
<div
|
|
143
|
+
class="absolute mt-1 z-10 w-60 max-h-1/2vh overflow-y-auto origin-top-left rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 focus:outline-none transition ease-out duration-100 {dropdownClassName} {dropdownState ==
|
|
144
|
+
MenuStateEnum.CLOSED
|
|
145
|
+
? `invisible transform opacity-0 scale-95 ${dropdownOpenClassName}`
|
|
146
|
+
: `transform opacity-100 scale-100 ${dropdownCloseClassName}`}"
|
|
147
|
+
style={dropdownStyle}
|
|
148
|
+
role="menu"
|
|
149
|
+
aria-orientation="vertical"
|
|
150
|
+
aria-labelledby={id}
|
|
151
|
+
tabindex="-1"
|
|
152
|
+
>
|
|
153
|
+
{#if children}
|
|
154
|
+
{@render children()}
|
|
155
|
+
{:else}
|
|
156
|
+
{#each options as menu, index (menu.id || index)}
|
|
157
|
+
{#if menu?.divider}
|
|
158
|
+
<div class="border-t border-gray-200 {dividerClassName}"></div>
|
|
159
|
+
{:else if menuItemChildren}
|
|
160
|
+
{@render menuItemChildren(menu, index)}
|
|
161
|
+
{:else}
|
|
162
|
+
<ButtonListItem
|
|
163
|
+
item={menu}
|
|
164
|
+
{index}
|
|
165
|
+
checked={selectedMenu == menu}
|
|
166
|
+
{hasCheck}
|
|
167
|
+
listId={id}
|
|
168
|
+
className={menuItemClassName}
|
|
169
|
+
{uncheckIconPath}
|
|
170
|
+
{checkIconPath}
|
|
171
|
+
{checkIconClassName}
|
|
172
|
+
{uncheckIconClassName}
|
|
173
|
+
{checkClassName}
|
|
174
|
+
iconClassName={listIconClassName}
|
|
175
|
+
imgClassName={listImgClassName}
|
|
176
|
+
labelClassName={listLabelClassName}
|
|
177
|
+
descClassName={listDescClassName}
|
|
178
|
+
children={menuItemInnerChildren}
|
|
179
|
+
onclick={handlemenuItemClick}
|
|
180
|
+
/>
|
|
181
|
+
{/if}
|
|
182
|
+
{/each}
|
|
183
|
+
{/if}
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ListItemType } from '../button-list-item/button-list-item.svelte';
|
|
3
|
+
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> {
|
|
4
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
5
|
+
$$bindings?: Bindings;
|
|
6
|
+
} & Exports;
|
|
7
|
+
(internal: unknown, props: Props & {
|
|
8
|
+
$$events?: Events;
|
|
9
|
+
$$slots?: Slots;
|
|
10
|
+
}): Exports & {
|
|
11
|
+
$set?: any;
|
|
12
|
+
$on?: any;
|
|
13
|
+
};
|
|
14
|
+
z_$$bindings?: Bindings;
|
|
15
|
+
}
|
|
16
|
+
declare const ButtonMenu: $$__sveltets_2_IsomorphicComponent<{
|
|
17
|
+
id?: string;
|
|
18
|
+
className?: string;
|
|
19
|
+
screenOnlyDesc?: string;
|
|
20
|
+
style?: string;
|
|
21
|
+
disabled?: boolean | undefined | null;
|
|
22
|
+
imgSrc?: string;
|
|
23
|
+
imgClassName?: string;
|
|
24
|
+
imgAlt?: string;
|
|
25
|
+
leftIconPath?: string;
|
|
26
|
+
leftIconClassName?: string;
|
|
27
|
+
rightIconPath?: string;
|
|
28
|
+
rightIconClassName?: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
labelClassName?: string;
|
|
31
|
+
dropdownClassName?: string;
|
|
32
|
+
dropdownStyle?: string;
|
|
33
|
+
hasCheck?: boolean;
|
|
34
|
+
checkIconPath?: string;
|
|
35
|
+
checkIconClassName?: string;
|
|
36
|
+
menus?: string[] | ListItemType[];
|
|
37
|
+
containerClassName?: string;
|
|
38
|
+
backgropClassName?: string;
|
|
39
|
+
menuItemClassName?: string;
|
|
40
|
+
uncheckIconPath?: string;
|
|
41
|
+
uncheckIconClassName?: string;
|
|
42
|
+
dropdownOpenClassName?: string;
|
|
43
|
+
dropdownCloseClassName?: string;
|
|
44
|
+
checkClassName?: string;
|
|
45
|
+
listIconClassName?: string;
|
|
46
|
+
listImgClassName?: string;
|
|
47
|
+
listLabelClassName?: string;
|
|
48
|
+
listDescClassName?: string;
|
|
49
|
+
dividerClassName?: string;
|
|
50
|
+
dropIconPath?: string;
|
|
51
|
+
dropIconClassName?: string;
|
|
52
|
+
onmenuclick?: (ev: MouseEvent, item: string | ListItemType, index: number) => void;
|
|
53
|
+
children?: Snippet;
|
|
54
|
+
buttonChildren?: Snippet;
|
|
55
|
+
menuItemChildren?: Snippet<[ListItemType, number]>;
|
|
56
|
+
menuItemInnerChildren?: Snippet<[ListItemType, number]>;
|
|
57
|
+
}, {
|
|
58
|
+
[evt: string]: CustomEvent<any>;
|
|
59
|
+
}, {}, {}, "">;
|
|
60
|
+
type ButtonMenu = InstanceType<typeof ButtonMenu>;
|
|
61
|
+
export default ButtonMenu;
|