@liwe3/webcomponents-svelte 1.0.14 → 1.1.11
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 +46 -0
- package/dist/AIMarkdownEditor.svelte +179 -0
- package/dist/AIMarkdownEditor.svelte.d.ts +30 -0
- package/dist/AIMarkdownEditor.svelte.d.ts.map +1 -0
- package/dist/AITextEditor.svelte +28 -27
- package/dist/AITextEditor.svelte.d.ts +1 -0
- package/dist/AITextEditor.svelte.d.ts.map +1 -1
- package/dist/ButtonToolbar.svelte +55 -0
- package/dist/ButtonToolbar.svelte.d.ts +15 -0
- package/dist/ButtonToolbar.svelte.d.ts.map +1 -0
- package/dist/CheckList.svelte +87 -0
- package/dist/CheckList.svelte.d.ts +11 -0
- package/dist/CheckList.svelte.d.ts.map +1 -0
- package/dist/ChunkUploader.svelte +211 -0
- package/dist/ChunkUploader.svelte.d.ts +29 -0
- package/dist/ChunkUploader.svelte.d.ts.map +1 -0
- package/dist/ContainerBox.svelte +58 -0
- package/dist/ContainerBox.svelte.d.ts +11 -0
- package/dist/ContainerBox.svelte.d.ts.map +1 -0
- package/dist/Dialogs.svelte +82 -0
- package/dist/Dialogs.svelte.d.ts +65 -0
- package/dist/Dialogs.svelte.d.ts.map +1 -0
- package/dist/Drawer.svelte +201 -0
- package/dist/Drawer.svelte.d.ts +33 -0
- package/dist/Drawer.svelte.d.ts.map +1 -0
- package/dist/MarkdownPreview.svelte +50 -0
- package/dist/MarkdownPreview.svelte.d.ts +9 -0
- package/dist/MarkdownPreview.svelte.d.ts.map +1 -0
- package/dist/ResizableCropper.svelte +168 -0
- package/dist/ResizableCropper.svelte.d.ts +24 -0
- package/dist/ResizableCropper.svelte.d.ts.map +1 -0
- package/dist/Toasts.svelte +6 -2
- package/dist/Toasts.svelte.d.ts +4 -2
- package/dist/Toasts.svelte.d.ts.map +1 -1
- package/dist/TreeView.svelte +103 -0
- package/dist/TreeView.svelte.d.ts +28 -0
- package/dist/TreeView.svelte.d.ts.map +1 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
export type ChunkFileEvent = {
|
|
3
|
+
id : string;
|
|
4
|
+
status : string;
|
|
5
|
+
progress : number;
|
|
6
|
+
uploadId : string;
|
|
7
|
+
key : string;
|
|
8
|
+
originalFileName : string;
|
|
9
|
+
size : number;
|
|
10
|
+
};
|
|
11
|
+
</script>
|
|
12
|
+
<script lang="ts">
|
|
13
|
+
import { onMount } from 'svelte';
|
|
14
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
15
|
+
import type {
|
|
16
|
+
ChunkUploaderElement as ChunkUploaderElementType,
|
|
17
|
+
UploadedFile,
|
|
18
|
+
} from '@liwe3/webcomponents';
|
|
19
|
+
|
|
20
|
+
interface Props extends HTMLAttributes<ChunkUploaderElementType> {
|
|
21
|
+
serverURL? : string;
|
|
22
|
+
chunkSize? : number;
|
|
23
|
+
authToken? : string;
|
|
24
|
+
validFiletypes? : string[];
|
|
25
|
+
maxFileSize? : number;
|
|
26
|
+
labelDropFiles? : string;
|
|
27
|
+
labelBrowse? : string;
|
|
28
|
+
folder? : string;
|
|
29
|
+
onfilecomplete? : ( event : ChunkFileEvent ) => void;
|
|
30
|
+
onuploadcomplete? : ( events : ChunkFileEvent[] ) => void;
|
|
31
|
+
onuploadaborted? : ( events : ChunkFileEvent[] ) => void;
|
|
32
|
+
parseResponse? : ( response : any, endpoint : 'initiate' | 'part' | 'complete' ) => any;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
serverURL = '',
|
|
37
|
+
chunkSize = 5,
|
|
38
|
+
authToken,
|
|
39
|
+
validFiletypes,
|
|
40
|
+
maxFileSize = 5120,
|
|
41
|
+
labelDropFiles,
|
|
42
|
+
labelBrowse,
|
|
43
|
+
folder,
|
|
44
|
+
onfilecomplete,
|
|
45
|
+
onuploadcomplete,
|
|
46
|
+
onuploadaborted,
|
|
47
|
+
parseResponse,
|
|
48
|
+
...restProps
|
|
49
|
+
} : Props = $props();
|
|
50
|
+
|
|
51
|
+
let uploaderElement : ChunkUploaderElementType;
|
|
52
|
+
let isReady = $state( false );
|
|
53
|
+
let removeListeners : (() => void) | null = null;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Syncs the latest prop values down to the underlying web component.
|
|
57
|
+
*/
|
|
58
|
+
const syncProps = () => {
|
|
59
|
+
if ( !isReady || !uploaderElement ) return;
|
|
60
|
+
|
|
61
|
+
uploaderElement.serverURL = serverURL ?? '';
|
|
62
|
+
uploaderElement.chunkSize = chunkSize;
|
|
63
|
+
uploaderElement.authToken = authToken;
|
|
64
|
+
uploaderElement.validFiletypes = validFiletypes?.length
|
|
65
|
+
? [ ...validFiletypes ]
|
|
66
|
+
: undefined;
|
|
67
|
+
uploaderElement.maxFileSize = maxFileSize;
|
|
68
|
+
uploaderElement.labelDropFiles = labelDropFiles;
|
|
69
|
+
uploaderElement.labelBrowse = labelBrowse;
|
|
70
|
+
uploaderElement.folder = folder;
|
|
71
|
+
uploaderElement.parseResponse = parseResponse;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const _mapEvent = ( dets : any ) : ChunkFileEvent => {
|
|
75
|
+
return {
|
|
76
|
+
id: dets.id,
|
|
77
|
+
originalFileName: dets.file.name,
|
|
78
|
+
status: dets.status,
|
|
79
|
+
progress: dets.progress,
|
|
80
|
+
size: dets.uploadedBytes,
|
|
81
|
+
uploadId: dets.uploadId,
|
|
82
|
+
key: dets.key,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Forwards custom events emitted by the web component to Svelte callbacks.
|
|
88
|
+
*/
|
|
89
|
+
const bindEvents = () => {
|
|
90
|
+
if ( !uploaderElement ) return;
|
|
91
|
+
|
|
92
|
+
const handleFileComplete = ( event : Event ) => {
|
|
93
|
+
const data : ChunkFileEvent = _mapEvent( event.detail );
|
|
94
|
+
onfilecomplete?.( data );
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const handleUploadComplete = ( event : Event ) => {
|
|
98
|
+
const res : ChunkFileEvent[] = ( event as any ).detail.map( ( det ) => _mapEvent( det ) );
|
|
99
|
+
onuploadcomplete?.( res );
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const handleUploadAborted = ( event : Event ) => {
|
|
103
|
+
const res : ChunkFileEvent[] = ( event as any ).detail.map( ( det ) => _mapEvent( det ) );
|
|
104
|
+
onuploadaborted?.( res );
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
uploaderElement.addEventListener(
|
|
108
|
+
'filecomplete',
|
|
109
|
+
handleFileComplete as EventListener,
|
|
110
|
+
);
|
|
111
|
+
uploaderElement.addEventListener(
|
|
112
|
+
'uploadcomplete',
|
|
113
|
+
handleUploadComplete as EventListener,
|
|
114
|
+
);
|
|
115
|
+
uploaderElement.addEventListener(
|
|
116
|
+
'uploadaborted',
|
|
117
|
+
handleUploadAborted as EventListener,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
removeListeners = () => {
|
|
121
|
+
uploaderElement.removeEventListener(
|
|
122
|
+
'filecomplete',
|
|
123
|
+
handleFileComplete as EventListener,
|
|
124
|
+
);
|
|
125
|
+
uploaderElement.removeEventListener(
|
|
126
|
+
'uploadcomplete',
|
|
127
|
+
handleUploadComplete as EventListener,
|
|
128
|
+
);
|
|
129
|
+
uploaderElement.removeEventListener(
|
|
130
|
+
'uploadaborted',
|
|
131
|
+
handleUploadAborted as EventListener,
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
onMount( () => {
|
|
137
|
+
let isMounted = true;
|
|
138
|
+
|
|
139
|
+
const setup = async () => {
|
|
140
|
+
await import( '@liwe3/webcomponents/chunk-uploader' );
|
|
141
|
+
await customElements.whenDefined( 'liwe3-chunk-uploader' );
|
|
142
|
+
|
|
143
|
+
if ( !isMounted ) return;
|
|
144
|
+
isReady = true;
|
|
145
|
+
syncProps();
|
|
146
|
+
bindEvents();
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
void setup();
|
|
150
|
+
|
|
151
|
+
return () => {
|
|
152
|
+
isMounted = false;
|
|
153
|
+
removeListeners?.();
|
|
154
|
+
removeListeners = null;
|
|
155
|
+
};
|
|
156
|
+
} );
|
|
157
|
+
|
|
158
|
+
$effect( () => {
|
|
159
|
+
if ( !isReady || !uploaderElement ) return;
|
|
160
|
+
uploaderElement.serverURL = serverURL ?? '';
|
|
161
|
+
} );
|
|
162
|
+
|
|
163
|
+
$effect( () => {
|
|
164
|
+
if ( !isReady || !uploaderElement ) return;
|
|
165
|
+
uploaderElement.chunkSize = chunkSize;
|
|
166
|
+
} );
|
|
167
|
+
|
|
168
|
+
$effect( () => {
|
|
169
|
+
if ( !isReady || !uploaderElement ) return;
|
|
170
|
+
uploaderElement.authToken = authToken;
|
|
171
|
+
} );
|
|
172
|
+
|
|
173
|
+
$effect( () => {
|
|
174
|
+
if ( !isReady || !uploaderElement ) return;
|
|
175
|
+
uploaderElement.validFiletypes = validFiletypes?.length
|
|
176
|
+
? [ ...validFiletypes ]
|
|
177
|
+
: undefined;
|
|
178
|
+
} );
|
|
179
|
+
|
|
180
|
+
$effect( () => {
|
|
181
|
+
if ( !isReady || !uploaderElement ) return;
|
|
182
|
+
uploaderElement.maxFileSize = maxFileSize;
|
|
183
|
+
} );
|
|
184
|
+
|
|
185
|
+
$effect( () => {
|
|
186
|
+
if ( !isReady || !uploaderElement ) return;
|
|
187
|
+
uploaderElement.labelDropFiles = labelDropFiles;
|
|
188
|
+
} );
|
|
189
|
+
|
|
190
|
+
$effect( () => {
|
|
191
|
+
if ( !isReady || !uploaderElement ) return;
|
|
192
|
+
uploaderElement.labelBrowse = labelBrowse;
|
|
193
|
+
} );
|
|
194
|
+
|
|
195
|
+
$effect( () => {
|
|
196
|
+
if ( !isReady || !uploaderElement ) return;
|
|
197
|
+
uploaderElement.folder = folder;
|
|
198
|
+
} );
|
|
199
|
+
|
|
200
|
+
$effect( () => {
|
|
201
|
+
if ( !isReady || !uploaderElement ) return;
|
|
202
|
+
uploaderElement.parseResponse = parseResponse;
|
|
203
|
+
} );
|
|
204
|
+
|
|
205
|
+
$effect( () => {
|
|
206
|
+
if ( !uploaderElement ) return;
|
|
207
|
+
uploaderElement.setAttribute( 'folder', folder! );
|
|
208
|
+
} );
|
|
209
|
+
</script>
|
|
210
|
+
|
|
211
|
+
<liwe3-chunk-uploader bind:this={uploaderElement} {...restProps}></liwe3-chunk-uploader>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type ChunkFileEvent = {
|
|
2
|
+
id: string;
|
|
3
|
+
status: string;
|
|
4
|
+
progress: number;
|
|
5
|
+
uploadId: string;
|
|
6
|
+
key: string;
|
|
7
|
+
originalFileName: string;
|
|
8
|
+
size: number;
|
|
9
|
+
};
|
|
10
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
11
|
+
import type { ChunkUploaderElement as ChunkUploaderElementType } from '@liwe3/webcomponents';
|
|
12
|
+
interface Props extends HTMLAttributes<ChunkUploaderElementType> {
|
|
13
|
+
serverURL?: string;
|
|
14
|
+
chunkSize?: number;
|
|
15
|
+
authToken?: string;
|
|
16
|
+
validFiletypes?: string[];
|
|
17
|
+
maxFileSize?: number;
|
|
18
|
+
labelDropFiles?: string;
|
|
19
|
+
labelBrowse?: string;
|
|
20
|
+
folder?: string;
|
|
21
|
+
onfilecomplete?: (event: ChunkFileEvent) => void;
|
|
22
|
+
onuploadcomplete?: (events: ChunkFileEvent[]) => void;
|
|
23
|
+
onuploadaborted?: (events: ChunkFileEvent[]) => void;
|
|
24
|
+
parseResponse?: (response: any, endpoint: 'initiate' | 'part' | 'complete') => any;
|
|
25
|
+
}
|
|
26
|
+
declare const ChunkUploader: import("svelte").Component<Props, {}, "">;
|
|
27
|
+
type ChunkUploader = ReturnType<typeof ChunkUploader>;
|
|
28
|
+
export default ChunkUploader;
|
|
29
|
+
//# sourceMappingURL=ChunkUploader.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChunkUploader.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ChunkUploader.svelte.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG;IAC5B,EAAE,EAAG,MAAM,CAAC;IACZ,MAAM,EAAG,MAAM,CAAC;IAChB,QAAQ,EAAG,MAAM,CAAC;IAClB,QAAQ,EAAG,MAAM,CAAC;IAClB,GAAG,EAAG,MAAM,CAAC;IACb,gBAAgB,EAAG,MAAM,CAAC;IAC1B,IAAI,EAAG,MAAM,CAAC;CACd,CAAC;AAIF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EACX,oBAAoB,IAAI,wBAAwB,EAEhD,MAAM,sBAAsB,CAAC;AAG9B,UAAU,KAAM,SAAQ,cAAc,CAAC,wBAAwB,CAAC;IAC/D,SAAS,CAAC,EAAG,MAAM,CAAC;IACpB,SAAS,CAAC,EAAG,MAAM,CAAC;IACpB,SAAS,CAAC,EAAG,MAAM,CAAC;IACpB,cAAc,CAAC,EAAG,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAG,MAAM,CAAC;IACtB,cAAc,CAAC,EAAG,MAAM,CAAC;IACzB,WAAW,CAAC,EAAG,MAAM,CAAC;IACtB,MAAM,CAAC,EAAG,MAAM,CAAC;IACjB,cAAc,CAAC,EAAG,CAAE,KAAK,EAAG,cAAc,KAAM,IAAI,CAAC;IACrD,gBAAgB,CAAC,EAAG,CAAE,MAAM,EAAG,cAAc,EAAE,KAAM,IAAI,CAAC;IAC1D,eAAe,CAAC,EAAG,CAAE,MAAM,EAAG,cAAc,EAAE,KAAM,IAAI,CAAC;IACzD,aAAa,CAAC,EAAG,CAAE,QAAQ,EAAG,GAAG,EAAE,QAAQ,EAAG,UAAU,GAAG,MAAM,GAAG,UAAU,KAAM,GAAG,CAAC;CACxF;AA4LD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
import type { PopoverMenuItem, MenuPosition } from "@liwe3/webcomponents";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
menuPosition?: MenuPosition;
|
|
7
|
+
menuItems?: PopoverMenuItem[];
|
|
8
|
+
alwaysShowMenu?: boolean;
|
|
9
|
+
children?: import("svelte").Snippet;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
menuPosition = "bottom-left",
|
|
14
|
+
menuItems = [],
|
|
15
|
+
alwaysShowMenu = false,
|
|
16
|
+
children,
|
|
17
|
+
...restProps
|
|
18
|
+
}: Props = $props();
|
|
19
|
+
|
|
20
|
+
let containerBoxElement: HTMLElement;
|
|
21
|
+
let isReady = $state(false);
|
|
22
|
+
|
|
23
|
+
const updateProps = () => {
|
|
24
|
+
if (!containerBoxElement || !isReady) return;
|
|
25
|
+
|
|
26
|
+
const el = containerBoxElement as any;
|
|
27
|
+
|
|
28
|
+
if (typeof el.setMenuPosition === "function") {
|
|
29
|
+
el.setMenuPosition(menuPosition);
|
|
30
|
+
}
|
|
31
|
+
if (typeof el.setMenuItems === "function") {
|
|
32
|
+
el.setMenuItems(menuItems);
|
|
33
|
+
}
|
|
34
|
+
if (typeof el.setAlwaysShowMenu === "function") {
|
|
35
|
+
el.setAlwaysShowMenu(alwaysShowMenu);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
onMount(async () => {
|
|
40
|
+
// Dynamically import the web component
|
|
41
|
+
await import("@liwe3/webcomponents/container-box");
|
|
42
|
+
await customElements.whenDefined("liwe3-container-box");
|
|
43
|
+
|
|
44
|
+
isReady = true;
|
|
45
|
+
updateProps();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
$effect(() => {
|
|
49
|
+
if (isReady) {
|
|
50
|
+
updateProps();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<!-- svelte-ignore a11y_unknown_aria_attribute -->
|
|
56
|
+
<liwe3-container-box bind:this={containerBoxElement} {...restProps}>
|
|
57
|
+
{@render children?.()}
|
|
58
|
+
</liwe3-container-box>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PopoverMenuItem, MenuPosition } from "@liwe3/webcomponents";
|
|
2
|
+
interface Props {
|
|
3
|
+
menuPosition?: MenuPosition;
|
|
4
|
+
menuItems?: PopoverMenuItem[];
|
|
5
|
+
alwaysShowMenu?: boolean;
|
|
6
|
+
children?: import("svelte").Snippet;
|
|
7
|
+
}
|
|
8
|
+
declare const ContainerBox: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type ContainerBox = ReturnType<typeof ContainerBox>;
|
|
10
|
+
export default ContainerBox;
|
|
11
|
+
//# sourceMappingURL=ContainerBox.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContainerBox.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ContainerBox.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGxE,UAAU,KAAK;IACb,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;CACrC;AAwDH,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { DialogConfig, DialogElement } from '@liwe3/webcomponents';
|
|
3
|
+
|
|
4
|
+
// Re-export types for convenience
|
|
5
|
+
export type { DialogConfig, DialogElement };
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Shows a dialog with the given configuration.
|
|
9
|
+
*
|
|
10
|
+
* IMPORTANT: Make sure to add the <Dialogs /> component to your layout first!
|
|
11
|
+
* The <Dialogs /> component initializes the dialog web component system.
|
|
12
|
+
*
|
|
13
|
+
* @param config - The dialog configuration
|
|
14
|
+
* @returns The dialog element instance (or undefined if called during SSR)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // In your +layout.svelte
|
|
19
|
+
* import { Dialogs } from '@liwe3/webcomponents-svelte';
|
|
20
|
+
* <Dialogs />
|
|
21
|
+
*
|
|
22
|
+
* // In any component
|
|
23
|
+
* import { dialogAdd } from '@liwe3/webcomponents-svelte';
|
|
24
|
+
*
|
|
25
|
+
* const dialog = dialogAdd({
|
|
26
|
+
* title: 'Delete File',
|
|
27
|
+
* body: '<p>Are you sure you want to delete this file?</p>',
|
|
28
|
+
* buttons: [
|
|
29
|
+
* {
|
|
30
|
+
* label: 'Delete',
|
|
31
|
+
* backgroundColor: '#dc3545',
|
|
32
|
+
* onclick: () => {
|
|
33
|
+
* console.log('File deleted');
|
|
34
|
+
* dialog?.close();
|
|
35
|
+
* }
|
|
36
|
+
* },
|
|
37
|
+
* {
|
|
38
|
+
* label: 'Cancel',
|
|
39
|
+
* onclick: () => {
|
|
40
|
+
* dialog?.close();
|
|
41
|
+
* }
|
|
42
|
+
* }
|
|
43
|
+
* ],
|
|
44
|
+
* modal: true,
|
|
45
|
+
* escToClose: true,
|
|
46
|
+
* clickToClose: true
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export const dialogAdd = ( config : DialogConfig ) : DialogElement | undefined => {
|
|
51
|
+
// Only run on client side
|
|
52
|
+
if ( typeof window === 'undefined' ) return undefined;
|
|
53
|
+
|
|
54
|
+
// Get the dialogAdd function from window (set by the web component)
|
|
55
|
+
// The <Dialogs /> component should have already loaded the web component
|
|
56
|
+
const globalDialogAdd = ( window as any ).__liwe3_dialogAdd;
|
|
57
|
+
|
|
58
|
+
if ( !globalDialogAdd ) {
|
|
59
|
+
console.error(
|
|
60
|
+
'dialogAdd: Dialog web component not initialized. Did you forget to add <Dialogs /> to your layout?',
|
|
61
|
+
);
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return globalDialogAdd( config );
|
|
66
|
+
};
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<script lang="ts">
|
|
70
|
+
import { onMount } from 'svelte';
|
|
71
|
+
|
|
72
|
+
onMount( async () => {
|
|
73
|
+
// Only run on the client side (onMount only runs in browser)
|
|
74
|
+
// Import and initialize the Dialog web component
|
|
75
|
+
const { dialogAdd: coreDialogAdd } = await import( '@liwe3/webcomponents/dialog' );
|
|
76
|
+
|
|
77
|
+
// Expose dialogAdd on window so the wrapper can access it
|
|
78
|
+
( window as any ).__liwe3_dialogAdd = coreDialogAdd;
|
|
79
|
+
} );
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<!-- This component doesn't render anything, it just loads the web component -->
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { DialogConfig, DialogElement } from '@liwe3/webcomponents';
|
|
2
|
+
export type { DialogConfig, DialogElement };
|
|
3
|
+
/**
|
|
4
|
+
* Shows a dialog with the given configuration.
|
|
5
|
+
*
|
|
6
|
+
* IMPORTANT: Make sure to add the <Dialogs /> component to your layout first!
|
|
7
|
+
* The <Dialogs /> component initializes the dialog web component system.
|
|
8
|
+
*
|
|
9
|
+
* @param config - The dialog configuration
|
|
10
|
+
* @returns The dialog element instance (or undefined if called during SSR)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // In your +layout.svelte
|
|
15
|
+
* import { Dialogs } from '@liwe3/webcomponents-svelte';
|
|
16
|
+
* <Dialogs />
|
|
17
|
+
*
|
|
18
|
+
* // In any component
|
|
19
|
+
* import { dialogAdd } from '@liwe3/webcomponents-svelte';
|
|
20
|
+
*
|
|
21
|
+
* const dialog = dialogAdd({
|
|
22
|
+
* title: 'Delete File',
|
|
23
|
+
* body: '<p>Are you sure you want to delete this file?</p>',
|
|
24
|
+
* buttons: [
|
|
25
|
+
* {
|
|
26
|
+
* label: 'Delete',
|
|
27
|
+
* backgroundColor: '#dc3545',
|
|
28
|
+
* onclick: () => {
|
|
29
|
+
* console.log('File deleted');
|
|
30
|
+
* dialog?.close();
|
|
31
|
+
* }
|
|
32
|
+
* },
|
|
33
|
+
* {
|
|
34
|
+
* label: 'Cancel',
|
|
35
|
+
* onclick: () => {
|
|
36
|
+
* dialog?.close();
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* ],
|
|
40
|
+
* modal: true,
|
|
41
|
+
* escToClose: true,
|
|
42
|
+
* clickToClose: true
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const dialogAdd: (config: DialogConfig) => DialogElement | undefined;
|
|
47
|
+
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> {
|
|
48
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
49
|
+
$$bindings?: Bindings;
|
|
50
|
+
} & Exports;
|
|
51
|
+
(internal: unknown, props: {
|
|
52
|
+
$$events?: Events;
|
|
53
|
+
$$slots?: Slots;
|
|
54
|
+
}): Exports & {
|
|
55
|
+
$set?: any;
|
|
56
|
+
$on?: any;
|
|
57
|
+
};
|
|
58
|
+
z_$$bindings?: Bindings;
|
|
59
|
+
}
|
|
60
|
+
declare const Dialogs: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
61
|
+
[evt: string]: CustomEvent<any>;
|
|
62
|
+
}, {}, {}, string>;
|
|
63
|
+
type Dialogs = InstanceType<typeof Dialogs>;
|
|
64
|
+
export default Dialogs;
|
|
65
|
+
//# sourceMappingURL=Dialogs.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dialogs.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Dialogs.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGxE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,SAAS,GAAK,QAAS,YAAY,KAAK,aAAa,GAAG,SAgBpE,CAAC;AAwBF,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,OAAO;;kBAA+E,CAAC;AAC3E,KAAK,OAAO,GAAG,YAAY,CAAC,OAAO,OAAO,CAAC,CAAC;AAC9C,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy, onMount } from "svelte";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
|
|
5
|
+
type DrawerDirection = "horizontal" | "vertical";
|
|
6
|
+
type DrawerState = "expanded" | "shrunk" | "closed";
|
|
7
|
+
|
|
8
|
+
interface DrawerElement extends HTMLElement {
|
|
9
|
+
direction: DrawerDirection;
|
|
10
|
+
duration: number;
|
|
11
|
+
showTitleWhenShrunk: boolean;
|
|
12
|
+
closable: boolean;
|
|
13
|
+
title: string;
|
|
14
|
+
icon: string;
|
|
15
|
+
showToggleButton: boolean;
|
|
16
|
+
contentPadding: string;
|
|
17
|
+
state: DrawerState;
|
|
18
|
+
expand: () => void;
|
|
19
|
+
shrink: () => void;
|
|
20
|
+
close: () => void;
|
|
21
|
+
toggle: () => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Props {
|
|
25
|
+
direction?: DrawerDirection;
|
|
26
|
+
duration?: number;
|
|
27
|
+
showTitleWhenShrunk?: boolean;
|
|
28
|
+
closable?: boolean;
|
|
29
|
+
title?: string;
|
|
30
|
+
icon?: string;
|
|
31
|
+
state?: DrawerState;
|
|
32
|
+
showToggleButton?: boolean;
|
|
33
|
+
contentPadding?: string;
|
|
34
|
+
onstatechange?: (
|
|
35
|
+
event: CustomEvent<{ oldState: DrawerState; newState: DrawerState }>
|
|
36
|
+
) => void;
|
|
37
|
+
onexpanded?: (event: CustomEvent) => void;
|
|
38
|
+
onshrunk?: (event: CustomEvent) => void;
|
|
39
|
+
onclosed?: (event: CustomEvent) => void;
|
|
40
|
+
children?: Snippet;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let {
|
|
44
|
+
direction = "horizontal",
|
|
45
|
+
duration = 300,
|
|
46
|
+
showTitleWhenShrunk = false,
|
|
47
|
+
closable = true,
|
|
48
|
+
title = "",
|
|
49
|
+
icon = "☰",
|
|
50
|
+
state = $bindable<DrawerState>("expanded"),
|
|
51
|
+
showToggleButton = true,
|
|
52
|
+
contentPadding = "16px",
|
|
53
|
+
onstatechange,
|
|
54
|
+
onexpanded,
|
|
55
|
+
onshrunk,
|
|
56
|
+
onclosed,
|
|
57
|
+
children,
|
|
58
|
+
...restProps
|
|
59
|
+
}: Props = $props();
|
|
60
|
+
|
|
61
|
+
let drawerElement: DrawerElement;
|
|
62
|
+
let isReady = false;
|
|
63
|
+
let eventsBound = false;
|
|
64
|
+
let removeListeners: (() => void) | null = null;
|
|
65
|
+
|
|
66
|
+
const updateAttributes = () => {
|
|
67
|
+
if (!drawerElement || !isReady) return;
|
|
68
|
+
|
|
69
|
+
drawerElement.direction = direction;
|
|
70
|
+
drawerElement.duration = duration;
|
|
71
|
+
drawerElement.showTitleWhenShrunk = showTitleWhenShrunk;
|
|
72
|
+
drawerElement.closable = closable;
|
|
73
|
+
drawerElement.title = title;
|
|
74
|
+
drawerElement.icon = icon;
|
|
75
|
+
drawerElement.showToggleButton = showToggleButton;
|
|
76
|
+
drawerElement.contentPadding = contentPadding ?? "16px";
|
|
77
|
+
drawerElement.state = state;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const bindEvents = () => {
|
|
81
|
+
if (!drawerElement || eventsBound) return;
|
|
82
|
+
|
|
83
|
+
const handleStateChange = (event: Event) => {
|
|
84
|
+
const customEvent = event as CustomEvent<{
|
|
85
|
+
oldState: DrawerState;
|
|
86
|
+
newState: DrawerState;
|
|
87
|
+
}>;
|
|
88
|
+
|
|
89
|
+
state = customEvent.detail.newState;
|
|
90
|
+
onstatechange?.(customEvent);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const handleExpanded = (event: Event) => {
|
|
94
|
+
onexpanded?.(event as CustomEvent);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const handleShrunk = (event: Event) => {
|
|
98
|
+
onshrunk?.(event as CustomEvent);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const handleClosed = (event: Event) => {
|
|
102
|
+
onclosed?.(event as CustomEvent);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
drawerElement.addEventListener(
|
|
106
|
+
"drawer-state-change",
|
|
107
|
+
handleStateChange as EventListener
|
|
108
|
+
);
|
|
109
|
+
drawerElement.addEventListener(
|
|
110
|
+
"drawer-expanded",
|
|
111
|
+
handleExpanded as EventListener
|
|
112
|
+
);
|
|
113
|
+
drawerElement.addEventListener(
|
|
114
|
+
"drawer-shrunk",
|
|
115
|
+
handleShrunk as EventListener
|
|
116
|
+
);
|
|
117
|
+
drawerElement.addEventListener(
|
|
118
|
+
"drawer-closed",
|
|
119
|
+
handleClosed as EventListener
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
removeListeners = () => {
|
|
123
|
+
drawerElement.removeEventListener(
|
|
124
|
+
"drawer-state-change",
|
|
125
|
+
handleStateChange as EventListener
|
|
126
|
+
);
|
|
127
|
+
drawerElement.removeEventListener(
|
|
128
|
+
"drawer-expanded",
|
|
129
|
+
handleExpanded as EventListener
|
|
130
|
+
);
|
|
131
|
+
drawerElement.removeEventListener(
|
|
132
|
+
"drawer-shrunk",
|
|
133
|
+
handleShrunk as EventListener
|
|
134
|
+
);
|
|
135
|
+
drawerElement.removeEventListener(
|
|
136
|
+
"drawer-closed",
|
|
137
|
+
handleClosed as EventListener
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
eventsBound = true;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
onMount(async () => {
|
|
145
|
+
await import("@liwe3/webcomponents/drawer");
|
|
146
|
+
await customElements.whenDefined("liwe3-drawer");
|
|
147
|
+
|
|
148
|
+
isReady = true;
|
|
149
|
+
updateAttributes();
|
|
150
|
+
bindEvents();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
onDestroy(() => {
|
|
154
|
+
removeListeners?.();
|
|
155
|
+
removeListeners = null;
|
|
156
|
+
eventsBound = false;
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
$effect(() => {
|
|
160
|
+
if (!isReady) return;
|
|
161
|
+
updateAttributes();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
/** Expand the drawer programmatically. */
|
|
165
|
+
export const expand = () => {
|
|
166
|
+
drawerElement?.expand();
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** Shrink the drawer to its collapsed size. */
|
|
170
|
+
export const shrink = () => {
|
|
171
|
+
drawerElement?.shrink();
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/** Close the drawer and remove it from the DOM. */
|
|
175
|
+
export const close = () => {
|
|
176
|
+
drawerElement?.close();
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/** Toggle between expanded and shrunk states. */
|
|
180
|
+
export const toggle = () => {
|
|
181
|
+
drawerElement?.toggle();
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/** Return the current drawer state. */
|
|
185
|
+
export const getState = (): DrawerState => {
|
|
186
|
+
return drawerElement?.state ?? state;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/** Imperatively set the drawer state. */
|
|
190
|
+
export const setState = (nextState: DrawerState) => {
|
|
191
|
+
if (!drawerElement) return;
|
|
192
|
+
|
|
193
|
+
drawerElement.state = nextState;
|
|
194
|
+
state = nextState;
|
|
195
|
+
};
|
|
196
|
+
</script>
|
|
197
|
+
|
|
198
|
+
<!-- svelte-ignore a11y_unknown_aria_attribute -->
|
|
199
|
+
<liwe3-drawer bind:this={drawerElement} {...restProps}>
|
|
200
|
+
{@render children?.()}
|
|
201
|
+
</liwe3-drawer>
|