@ims360/svelte-ivory 0.0.2
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/LICENCE +23 -0
- package/README.md +15 -0
- package/dist/components/ai/AiMessage.svelte +115 -0
- package/dist/components/ai/AiMessage.svelte.d.ts +18 -0
- package/dist/components/ai/AttachedFile.svelte +28 -0
- package/dist/components/ai/AttachedFile.svelte.d.ts +9 -0
- package/dist/components/ai/Chat.svelte +150 -0
- package/dist/components/ai/Chat.svelte.d.ts +40 -0
- package/dist/components/ai/Markdown.svelte +59 -0
- package/dist/components/ai/Markdown.svelte.d.ts +16 -0
- package/dist/components/ai/UserMessage.svelte +53 -0
- package/dist/components/ai/UserMessage.svelte.d.ts +16 -0
- package/dist/components/ai/index.d.ts +5 -0
- package/dist/components/ai/index.js +5 -0
- package/dist/components/basic/checkbox/Checkbox.svelte +79 -0
- package/dist/components/basic/checkbox/Checkbox.svelte.d.ts +18 -0
- package/dist/components/basic/index.d.ts +2 -0
- package/dist/components/basic/index.js +2 -0
- package/dist/components/basic/toggle/Toggle.svelte +47 -0
- package/dist/components/basic/toggle/Toggle.svelte.d.ts +12 -0
- package/dist/components/buttons/CopyToClipboardButton.svelte +33 -0
- package/dist/components/buttons/CopyToClipboardButton.svelte.d.ts +9 -0
- package/dist/components/index.d.ts +0 -0
- package/dist/components/index.js +1 -0
- package/dist/components/layout/heading/Heading.svelte +33 -0
- package/dist/components/layout/heading/Heading.svelte.d.ts +16 -0
- package/dist/components/layout/heading/index.d.ts +5 -0
- package/dist/components/layout/heading/index.js +5 -0
- package/dist/components/layout/hiddenBackground/HiddenBackground.svelte +48 -0
- package/dist/components/layout/hiddenBackground/HiddenBackground.svelte.d.ts +13 -0
- package/dist/components/layout/hiddenBackground/index.js +6 -0
- package/dist/components/layout/index.d.ts +7 -0
- package/dist/components/layout/index.js +7 -0
- package/dist/components/layout/modal/Modal.svelte +114 -0
- package/dist/components/layout/modal/Modal.svelte.d.ts +30 -0
- package/dist/components/layout/modal/ModalTest.svelte +16 -0
- package/dist/components/layout/modal/ModalTest.svelte.d.ts +9 -0
- package/dist/components/layout/popover/Popover.svelte +108 -0
- package/dist/components/layout/popover/Popover.svelte.d.ts +36 -0
- package/dist/components/layout/portal/Portal.svelte +23 -0
- package/dist/components/layout/portal/Portal.svelte.d.ts +15 -0
- package/dist/components/layout/tabs/Tab.svelte +80 -0
- package/dist/components/layout/tabs/Tab.svelte.d.ts +21 -0
- package/dist/components/layout/tabs/TabPanel.svelte +23 -0
- package/dist/components/layout/tabs/TabPanel.svelte.d.ts +10 -0
- package/dist/components/layout/tabs/Tabs.svelte +86 -0
- package/dist/components/layout/tabs/Tabs.svelte.d.ts +21 -0
- package/dist/components/layout/tabs/index.d.ts +26 -0
- package/dist/components/layout/tabs/index.js +8 -0
- package/dist/components/layout/tooltip/Tooltip.svelte +111 -0
- package/dist/components/layout/tooltip/Tooltip.svelte.d.ts +32 -0
- package/dist/components/toast/Toast.svelte +100 -0
- package/dist/components/toast/Toast.svelte.d.ts +16 -0
- package/dist/components/toast/index.d.ts +2 -0
- package/dist/components/toast/index.js +2 -0
- package/dist/components/toast/toasts.svelte.d.ts +26 -0
- package/dist/components/toast/toasts.svelte.js +67 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +2 -0
- package/dist/utils/actions/clickOutside.d.ts +11 -0
- package/dist/utils/actions/clickOutside.js +23 -0
- package/dist/utils/actions/focusTrap.d.ts +4 -0
- package/dist/utils/actions/focusTrap.js +64 -0
- package/dist/utils/actions/index.d.ts +5 -0
- package/dist/utils/actions/index.js +5 -0
- package/dist/utils/actions/portal.d.ts +9 -0
- package/dist/utils/actions/portal.js +39 -0
- package/dist/utils/actions/shortcut.d.ts +10 -0
- package/dist/utils/actions/shortcut.js +25 -0
- package/dist/utils/actions/visible.d.ts +5 -0
- package/dist/utils/actions/visible.js +14 -0
- package/dist/utils/functions/cookie.d.ts +12 -0
- package/dist/utils/functions/cookie.js +36 -0
- package/dist/utils/functions/index.d.ts +3 -0
- package/dist/utils/functions/index.js +3 -0
- package/dist/utils/functions/pseudoRandomId.d.ts +1 -0
- package/dist/utils/functions/pseudoRandomId.js +3 -0
- package/dist/utils/functions/queryParams.d.ts +1 -0
- package/dist/utils/functions/queryParams.js +14 -0
- package/package.json +107 -0
- package/src/lib/components/ai/AiMessage.svelte +115 -0
- package/src/lib/components/ai/AttachedFile.svelte +28 -0
- package/src/lib/components/ai/Chat.svelte +150 -0
- package/src/lib/components/ai/Markdown.svelte +59 -0
- package/src/lib/components/ai/UserMessage.svelte +53 -0
- package/src/lib/components/ai/index.ts +5 -0
- package/src/lib/components/basic/checkbox/Checkbox.svelte +79 -0
- package/src/lib/components/basic/checkbox/checkbox.svelte.spec.ts +39 -0
- package/src/lib/components/basic/index.ts +2 -0
- package/src/lib/components/basic/toggle/Toggle.svelte +47 -0
- package/src/lib/components/basic/toggle/toggle.svelte.spec.ts +19 -0
- package/src/lib/components/buttons/CopyToClipboardButton.svelte +33 -0
- package/src/lib/components/index.ts +0 -0
- package/src/lib/components/layout/heading/Heading.svelte +33 -0
- package/src/lib/components/layout/heading/index.ts +7 -0
- package/src/lib/components/layout/hiddenBackground/HiddenBackground.svelte +48 -0
- package/src/lib/components/layout/hiddenBackground/index.ts +8 -0
- package/src/lib/components/layout/index.ts +7 -0
- package/src/lib/components/layout/modal/Modal.svelte +114 -0
- package/src/lib/components/layout/modal/ModalTest.svelte +16 -0
- package/src/lib/components/layout/modal/modal.svelte.spec.ts +39 -0
- package/src/lib/components/layout/popover/Popover.svelte +108 -0
- package/src/lib/components/layout/portal/Portal.svelte +23 -0
- package/src/lib/components/layout/tabs/Tab.svelte +80 -0
- package/src/lib/components/layout/tabs/TabPanel.svelte +23 -0
- package/src/lib/components/layout/tabs/Tabs.svelte +86 -0
- package/src/lib/components/layout/tabs/Tabs.test.svelte +5 -0
- package/src/lib/components/layout/tabs/index.ts +10 -0
- package/src/lib/components/layout/tooltip/Tooltip.svelte +111 -0
- package/src/lib/components/toast/Toast.svelte +100 -0
- package/src/lib/components/toast/index.ts +2 -0
- package/src/lib/components/toast/toasts.svelte.ts +89 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/utils/actions/clickOutside.svelte.spec.ts +67 -0
- package/src/lib/utils/actions/clickOutside.ts +38 -0
- package/src/lib/utils/actions/focusTrap.ts +65 -0
- package/src/lib/utils/actions/index.ts +5 -0
- package/src/lib/utils/actions/portal.ts +43 -0
- package/src/lib/utils/actions/shortcut.svelte.spec.ts +19 -0
- package/src/lib/utils/actions/shortcut.ts +35 -0
- package/src/lib/utils/actions/visible.ts +28 -0
- package/src/lib/utils/functions/cookie.svelte.spec.ts +55 -0
- package/src/lib/utils/functions/cookie.ts +46 -0
- package/src/lib/utils/functions/index.ts +3 -0
- package/src/lib/utils/functions/pseudoRandomId.spec.ts +19 -0
- package/src/lib/utils/functions/pseudoRandomId.ts +4 -0
- package/src/lib/utils/functions/queryParams.spec.ts +25 -0
- package/src/lib/utils/functions/queryParams.ts +15 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Dispatch event on click outside of node */
|
|
2
|
+
export function clickOutside(node, params) {
|
|
3
|
+
function handleClick(event) {
|
|
4
|
+
if (!(event.target instanceof Node) ||
|
|
5
|
+
!node ||
|
|
6
|
+
node.contains(event.target) ||
|
|
7
|
+
event.defaultPrevented)
|
|
8
|
+
return;
|
|
9
|
+
if (typeof params === 'function') {
|
|
10
|
+
params(event);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (params.target?.contains(event.target))
|
|
14
|
+
return;
|
|
15
|
+
params.callback(event);
|
|
16
|
+
}
|
|
17
|
+
document.addEventListener('click', handleClick, true);
|
|
18
|
+
return {
|
|
19
|
+
destroy() {
|
|
20
|
+
document.removeEventListener('click', handleClick, true);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function focusTrap(node, enabled) {
|
|
2
|
+
const elementWhitelist = 'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
|
|
3
|
+
let firstElement;
|
|
4
|
+
let lastElement;
|
|
5
|
+
function onFirstElemKeydown(e) {
|
|
6
|
+
if (e.shiftKey && e.code === 'Tab') {
|
|
7
|
+
e.preventDefault();
|
|
8
|
+
lastElement.focus();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function onLastElemKeydown(e) {
|
|
12
|
+
if (!e.shiftKey && e.code === 'Tab') {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
firstElement.focus();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function scanElements(fromObserver) {
|
|
18
|
+
if (enabled === false)
|
|
19
|
+
return;
|
|
20
|
+
const focusableElems = Array.from(node.querySelectorAll(elementWhitelist));
|
|
21
|
+
if (focusableElems.length) {
|
|
22
|
+
// Set first/last focusable elements
|
|
23
|
+
firstElement = focusableElems[0];
|
|
24
|
+
lastElement = focusableElems[focusableElems.length - 1];
|
|
25
|
+
// Auto-focus first focusable element only when not called from mutation observer
|
|
26
|
+
if (!fromObserver)
|
|
27
|
+
firstElement.focus();
|
|
28
|
+
// Listen for keydown on first & last element
|
|
29
|
+
firstElement.addEventListener('keydown', onFirstElemKeydown);
|
|
30
|
+
lastElement.addEventListener('keydown', onLastElemKeydown);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
scanElements(false);
|
|
34
|
+
function cleanUp() {
|
|
35
|
+
if (firstElement)
|
|
36
|
+
firstElement.removeEventListener('keydown', onFirstElemKeydown);
|
|
37
|
+
if (lastElement)
|
|
38
|
+
lastElement.removeEventListener('keydown', onLastElemKeydown);
|
|
39
|
+
}
|
|
40
|
+
// Re-determine focusable elements when mutations are observed
|
|
41
|
+
const onObservationChange = (mutationRecords, observer) => {
|
|
42
|
+
if (mutationRecords.length) {
|
|
43
|
+
cleanUp();
|
|
44
|
+
scanElements(true);
|
|
45
|
+
}
|
|
46
|
+
return observer;
|
|
47
|
+
};
|
|
48
|
+
const observer = new MutationObserver(onObservationChange);
|
|
49
|
+
observer.observe(node, { childList: true, subtree: true });
|
|
50
|
+
// Lifecycle
|
|
51
|
+
return {
|
|
52
|
+
update(newArgs) {
|
|
53
|
+
enabled = newArgs;
|
|
54
|
+
if (newArgs)
|
|
55
|
+
scanElements(false);
|
|
56
|
+
else
|
|
57
|
+
cleanUp();
|
|
58
|
+
},
|
|
59
|
+
destroy() {
|
|
60
|
+
cleanUp();
|
|
61
|
+
observer.disconnect();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Places the element in a diffrent place in the DOM
|
|
3
|
+
*
|
|
4
|
+
* **Use sparingy as it can make the DOM structure confusing**
|
|
5
|
+
*/
|
|
6
|
+
export declare function portal(el: HTMLElement, target?: HTMLElement | string): {
|
|
7
|
+
update: (newTarget: HTMLElement | string) => Promise<void>;
|
|
8
|
+
destroy: () => void;
|
|
9
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { tick } from 'svelte';
|
|
2
|
+
/**
|
|
3
|
+
* Places the element in a diffrent place in the DOM
|
|
4
|
+
*
|
|
5
|
+
* **Use sparingy as it can make the DOM structure confusing**
|
|
6
|
+
*/
|
|
7
|
+
export function portal(el, target = 'body') {
|
|
8
|
+
let targetEl;
|
|
9
|
+
async function update(newTarget) {
|
|
10
|
+
target = newTarget;
|
|
11
|
+
if (typeof target === 'string') {
|
|
12
|
+
targetEl = document.querySelector(target);
|
|
13
|
+
if (targetEl === null) {
|
|
14
|
+
await tick();
|
|
15
|
+
targetEl = document.querySelector(target);
|
|
16
|
+
}
|
|
17
|
+
if (targetEl === null) {
|
|
18
|
+
throw new Error(`No element found matching css selector: "${target}"`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else if (target instanceof HTMLElement) {
|
|
22
|
+
targetEl = target;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
throw new TypeError(`Unknown portal target type: ${target === null ? 'null' : typeof target}. Allowed types: string (CSS selector) or HTMLElement.`);
|
|
26
|
+
}
|
|
27
|
+
targetEl.appendChild(el);
|
|
28
|
+
el.hidden = false;
|
|
29
|
+
}
|
|
30
|
+
function destroy() {
|
|
31
|
+
if (el.parentNode)
|
|
32
|
+
el.parentNode.removeChild(el);
|
|
33
|
+
}
|
|
34
|
+
update(target);
|
|
35
|
+
return {
|
|
36
|
+
update,
|
|
37
|
+
destroy
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const shortcut = (node, params) => {
|
|
2
|
+
if (!params)
|
|
3
|
+
return;
|
|
4
|
+
let handler;
|
|
5
|
+
const removeHandler = () => window.removeEventListener('keydown', handler);
|
|
6
|
+
const setHandler = () => {
|
|
7
|
+
removeHandler();
|
|
8
|
+
handler = (e) => {
|
|
9
|
+
if (!!params.alt != e.altKey ||
|
|
10
|
+
!!params.shift != e.shiftKey ||
|
|
11
|
+
!!params.control != (e.ctrlKey || e.metaKey) ||
|
|
12
|
+
params.code != e.code)
|
|
13
|
+
return;
|
|
14
|
+
e.preventDefault();
|
|
15
|
+
e.stopPropagation();
|
|
16
|
+
params.callback();
|
|
17
|
+
};
|
|
18
|
+
window.addEventListener('keydown', handler);
|
|
19
|
+
};
|
|
20
|
+
setHandler();
|
|
21
|
+
return {
|
|
22
|
+
update: setHandler,
|
|
23
|
+
destroy: removeHandler
|
|
24
|
+
};
|
|
25
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const onFirstVisible = (node, input) => {
|
|
2
|
+
const observer = new IntersectionObserver((e) => {
|
|
3
|
+
if (!e[0].isIntersecting) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
input.callback();
|
|
7
|
+
}, { root: null, threshold: 1, ...input.options });
|
|
8
|
+
observer.observe(node);
|
|
9
|
+
return {
|
|
10
|
+
destroy: () => {
|
|
11
|
+
observer.disconnect();
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare function getCookie(name: string): string;
|
|
2
|
+
interface CookieSetParams {
|
|
3
|
+
name: string;
|
|
4
|
+
value: string;
|
|
5
|
+
days?: number;
|
|
6
|
+
}
|
|
7
|
+
declare function setCookie(params: CookieSetParams): string;
|
|
8
|
+
export declare const cookie: {
|
|
9
|
+
get: typeof getCookie;
|
|
10
|
+
set: typeof setCookie;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function getCookie(name) {
|
|
2
|
+
const cname = name + '=';
|
|
3
|
+
let decodedCookie;
|
|
4
|
+
try {
|
|
5
|
+
decodedCookie = decodeURIComponent(document.cookie);
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
const ca = decodedCookie.split(';');
|
|
11
|
+
for (let c of ca) {
|
|
12
|
+
while (c.startsWith(' ')) {
|
|
13
|
+
c = c.substring(1);
|
|
14
|
+
}
|
|
15
|
+
if (c.startsWith(cname)) {
|
|
16
|
+
return c.substring(cname.length);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
function setCookie(params) {
|
|
22
|
+
const { name, value, days } = params;
|
|
23
|
+
let expires = '';
|
|
24
|
+
if (days) {
|
|
25
|
+
const date = new Date();
|
|
26
|
+
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
|
|
27
|
+
expires = '; expires=' + date.toUTCString();
|
|
28
|
+
}
|
|
29
|
+
const cookie = name + '=' + (value || '') + expires + '; path=/';
|
|
30
|
+
document.cookie = cookie;
|
|
31
|
+
return cookie;
|
|
32
|
+
}
|
|
33
|
+
export const cookie = {
|
|
34
|
+
get: getCookie,
|
|
35
|
+
set: setCookie
|
|
36
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const pseudoRandomId: (prefix?: string) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const queryParams: <T extends Record<string, string | number | undefined | null>>(params: T) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const queryParams = (params) => {
|
|
2
|
+
// create the string
|
|
3
|
+
let query = '?';
|
|
4
|
+
let isFirst = true;
|
|
5
|
+
for (const [key, value] of Object.entries(params)) {
|
|
6
|
+
if (value === undefined || value === null)
|
|
7
|
+
continue;
|
|
8
|
+
if (!isFirst)
|
|
9
|
+
query += '&';
|
|
10
|
+
query += `${key}=${value}`;
|
|
11
|
+
isFirst = false;
|
|
12
|
+
}
|
|
13
|
+
return isFirst ? '' : query;
|
|
14
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@floating-ui/dom": "^1.6.13",
|
|
4
|
+
"@lucide/svelte": "^0.503.0",
|
|
5
|
+
"@tailwindcss/forms": "^0.5.10",
|
|
6
|
+
"@tailwindcss/typography": "^0.5.16",
|
|
7
|
+
"dompurify": "^3.2.5",
|
|
8
|
+
"marked": "^15.0.11",
|
|
9
|
+
"tailwind-merge": "^3.2.0",
|
|
10
|
+
"tailwindcss": "^4.0.0"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@eslint/compat": "^1.2.5",
|
|
14
|
+
"@eslint/js": "^9.18.0",
|
|
15
|
+
"@sveltejs/adapter-auto": "^4.0.0",
|
|
16
|
+
"@sveltejs/package": "^2.0.0",
|
|
17
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
|
18
|
+
"@tailwindcss/vite": "^4.1.4",
|
|
19
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
20
|
+
"@testing-library/svelte": "^5.2.4",
|
|
21
|
+
"@testing-library/user-event": "^14.6.1",
|
|
22
|
+
"@vitest/browser": "^3.1.1",
|
|
23
|
+
"@vitest/coverage-v8": "^3.1.1",
|
|
24
|
+
"@vitest/spy": "^3.1.2",
|
|
25
|
+
"eslint": "^9.18.0",
|
|
26
|
+
"eslint-config-prettier": "^10.0.1",
|
|
27
|
+
"eslint-plugin-svelte": "^3.0.0",
|
|
28
|
+
"globals": "^16.0.0",
|
|
29
|
+
"jsdom": "^26.0.0",
|
|
30
|
+
"playwright": "^1.51.1",
|
|
31
|
+
"prettier": "^3.4.2",
|
|
32
|
+
"prettier-plugin-svelte": "^3.3.3",
|
|
33
|
+
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
34
|
+
"publint": "^0.3.2",
|
|
35
|
+
"svelte-check": "^4.0.0",
|
|
36
|
+
"typescript": "^5.0.0",
|
|
37
|
+
"typescript-eslint": "^8.20.0",
|
|
38
|
+
"vite": "^6.0.0",
|
|
39
|
+
"vitest": "^3.0.0"
|
|
40
|
+
},
|
|
41
|
+
"exports": {
|
|
42
|
+
".": {
|
|
43
|
+
"types": "./dist/index.d.ts",
|
|
44
|
+
"svelte": "./dist/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./components/ai": {
|
|
47
|
+
"types": "./dist/components/ai/index.d.ts",
|
|
48
|
+
"svelte": "./dist/components/ai/index.js"
|
|
49
|
+
},
|
|
50
|
+
"./components/basic": {
|
|
51
|
+
"types": "./dist/components/basic/index.d.ts",
|
|
52
|
+
"svelte": "./dist/components/basic/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./components/layout": {
|
|
55
|
+
"types": "./dist/components/layout/index.d.ts",
|
|
56
|
+
"svelte": "./dist/components/layout/index.js"
|
|
57
|
+
},
|
|
58
|
+
"./components/toast": {
|
|
59
|
+
"types": "./dist/components/toast/index.d.ts",
|
|
60
|
+
"svelte": "./dist/components/toast/index.js"
|
|
61
|
+
},
|
|
62
|
+
"./utils/actions": {
|
|
63
|
+
"types": "./dist/utils/actions/index.d.ts",
|
|
64
|
+
"svelte": "./dist/utils/actions/index.js"
|
|
65
|
+
},
|
|
66
|
+
"./utils/functions": {
|
|
67
|
+
"types": "./dist/utils/functions/index.d.ts",
|
|
68
|
+
"svelte": "./dist/utils/functions/index.js"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"files": [
|
|
72
|
+
"dist",
|
|
73
|
+
"src/lib",
|
|
74
|
+
"!dist/**/*.test.*",
|
|
75
|
+
"!dist/**/*.spec.*"
|
|
76
|
+
],
|
|
77
|
+
"keywords": [
|
|
78
|
+
"svelte"
|
|
79
|
+
],
|
|
80
|
+
"license": "MIT",
|
|
81
|
+
"name": "@ims360/svelte-ivory",
|
|
82
|
+
"peerDependencies": {
|
|
83
|
+
"@skeletonlabs/skeleton": "^3.1.1",
|
|
84
|
+
"@sveltejs/kit": "^2.16.0",
|
|
85
|
+
"svelte": "^5.0.0"
|
|
86
|
+
},
|
|
87
|
+
"scripts": {
|
|
88
|
+
"build": "vite build && npm run prepack",
|
|
89
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
90
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
91
|
+
"dev": "vite dev",
|
|
92
|
+
"format": "prettier --write .",
|
|
93
|
+
"lint": "prettier --check . && eslint .",
|
|
94
|
+
"prepack": "svelte-kit sync && svelte-package && publint",
|
|
95
|
+
"prepare": "svelte-kit sync || echo ''",
|
|
96
|
+
"preview": "vite preview",
|
|
97
|
+
"test": "npm run test:unit -- --run",
|
|
98
|
+
"test:unit": "vitest"
|
|
99
|
+
},
|
|
100
|
+
"sideEffects": [
|
|
101
|
+
"**/*.css"
|
|
102
|
+
],
|
|
103
|
+
"svelte": "./dist/index.js",
|
|
104
|
+
"type": "module",
|
|
105
|
+
"types": "./dist/index.d.ts",
|
|
106
|
+
"version": "0.0.2"
|
|
107
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
The default for AI Messages in the Chat component.
|
|
4
|
+
Can be customized using the `class` and `loading` props.
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { ThumbsDown, ThumbsUp } from '@lucide/svelte';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import type { Snippet } from 'svelte';
|
|
11
|
+
import type { ClassValue } from 'svelte/elements';
|
|
12
|
+
import { twMerge } from 'tailwind-merge';
|
|
13
|
+
import CopyToClipboardButton from '../buttons/CopyToClipboardButton.svelte';
|
|
14
|
+
import type { AiChatMessage } from './Chat.svelte';
|
|
15
|
+
import Markdown from './Markdown.svelte';
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
b_message: AiChatMessage;
|
|
19
|
+
messageText?: Snippet<[{ message: AiChatMessage }]>;
|
|
20
|
+
class?: ClassValue;
|
|
21
|
+
minHeight?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let {
|
|
25
|
+
b_message = $bindable(),
|
|
26
|
+
class: clazz,
|
|
27
|
+
messageText = defaultMessage,
|
|
28
|
+
minHeight
|
|
29
|
+
}: Props = $props();
|
|
30
|
+
|
|
31
|
+
// const uuidRegex =
|
|
32
|
+
// /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g;
|
|
33
|
+
// const icon = `<svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" class="h-[1em] origin-center overflow-visible align-[-0.125rem]" viewBox="0 0 512 512"><g transform="translate(256 256)" transform-origin="128 0"><path d="M336 0c-8.8 0-16 7.2-16 16s7.2 16 16 16l121.4 0L212.7 276.7c-6.2 6.2-6.2 16.4 0 22.6s16.4 6.2 22.6 0L480 54.6 480 176c0 8.8 7.2 16 16 16s16-7.2 16-16l0-160c0-8.8-7.2-16-16-16L336 0zM64 32C28.7 32 0 60.7 0 96L0 448c0 35.3 28.7 64 64 64l352 0c35.3 0 64-28.7 64-64l0-144c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 144c0 17.7-14.3 32-32 32L64 480c-17.7 0-32-14.3-32-32L32 96c0-17.7 14.3-32 32-32l144 0c8.8 0 16-7.2 16-16s-7.2-16-16-16L64 32z" fill="currentColor" transform="translate(-256 -256)"></path><!----></g></svg>`;
|
|
34
|
+
|
|
35
|
+
// async function replacerFactory(): Promise<(match: string) => string> {
|
|
36
|
+
// const docs = await documents.value;
|
|
37
|
+
// return (match: string) => {
|
|
38
|
+
// const doc = docs.find((d) => d.id === match);
|
|
39
|
+
|
|
40
|
+
// return `<span class="bg-surface-100-900 py-1 px-2 rounded flex flex-row items-center gap-2 hover:shadow-lg w-fit transition-all">
|
|
41
|
+
// ${doc?.title ?? 'Unbekanntes Dokument'}
|
|
42
|
+
// <a href="/documents/${doc?.id}" target="_blank">
|
|
43
|
+
// ${icon}
|
|
44
|
+
// </a>
|
|
45
|
+
// </span>`;
|
|
46
|
+
// };
|
|
47
|
+
// }
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<div
|
|
51
|
+
class={twMerge(clsx('group flex w-full flex-col items-start', clazz))}
|
|
52
|
+
style={minHeight ? `min-height: ${minHeight}px;` : undefined}
|
|
53
|
+
>
|
|
54
|
+
{@render messageText({
|
|
55
|
+
message: b_message
|
|
56
|
+
})}
|
|
57
|
+
<div
|
|
58
|
+
class={[
|
|
59
|
+
'text-surface-500 flex -translate-x-3 flex-row items-center transition-all group-hover:opacity-100',
|
|
60
|
+
b_message.liked || b_message.disliked ? 'opacity-100' : 'opacity-0'
|
|
61
|
+
]}
|
|
62
|
+
>
|
|
63
|
+
<CopyToClipboardButton
|
|
64
|
+
text={b_message.message}
|
|
65
|
+
toastMessage="Nachricht wurde in die Zwischenablage kopiert"
|
|
66
|
+
/>
|
|
67
|
+
<button
|
|
68
|
+
type="button"
|
|
69
|
+
class="btn-icon"
|
|
70
|
+
onclick={() => {
|
|
71
|
+
b_message.liked = !b_message.liked;
|
|
72
|
+
b_message.disliked = false;
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
<ThumbsUp class={[b_message.liked && 'fill-surface-500/50']} />
|
|
76
|
+
</button>
|
|
77
|
+
<button
|
|
78
|
+
type="button"
|
|
79
|
+
class="btn-icon"
|
|
80
|
+
onclick={() => {
|
|
81
|
+
b_message.liked = false;
|
|
82
|
+
b_message.disliked = !b_message.disliked;
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<ThumbsDown class={[b_message.disliked && 'fill-surface-500/50']} />
|
|
86
|
+
</button>
|
|
87
|
+
{#if b_message.time}
|
|
88
|
+
<p class="text-surface-400-600 pl-2">
|
|
89
|
+
{b_message.time.toLocaleString('de')}
|
|
90
|
+
</p>
|
|
91
|
+
{/if}
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
{#snippet defaultMessage({ message }: { message: AiChatMessage })}
|
|
96
|
+
{#if message}
|
|
97
|
+
<Markdown source={message.message} />
|
|
98
|
+
{:else}
|
|
99
|
+
<p class="flex flex-row">
|
|
100
|
+
<span class="h-4 animate-bounce rounded-full pl-1">.</span>
|
|
101
|
+
<span
|
|
102
|
+
class="h-4 animate-bounce rounded-full"
|
|
103
|
+
style="animation-delay: 125ms !important;"
|
|
104
|
+
>
|
|
105
|
+
.
|
|
106
|
+
</span>
|
|
107
|
+
<span
|
|
108
|
+
class="h-4 animate-bounce rounded-full"
|
|
109
|
+
style="animation-delay: 250ms !important;"
|
|
110
|
+
>
|
|
111
|
+
.
|
|
112
|
+
</span>
|
|
113
|
+
</p>
|
|
114
|
+
{/if}
|
|
115
|
+
{/snippet}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { X } from '@lucide/svelte';
|
|
3
|
+
import type { ClassValue } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
file: File;
|
|
7
|
+
onremove?: (f: File) => void;
|
|
8
|
+
class?: ClassValue;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { file, onremove, class: clazz }: Props = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
15
|
+
<svelte:element
|
|
16
|
+
this={onremove ? 'button' : 'div'}
|
|
17
|
+
type={onremove ? 'button' : undefined}
|
|
18
|
+
onclick={onremove ? () => onremove(file) : undefined}
|
|
19
|
+
class={[
|
|
20
|
+
'bg-primary-500/25 group flex flex-row items-center gap-1 overflow-hidden rounded-full px-4 py-1 whitespace-nowrap',
|
|
21
|
+
clazz
|
|
22
|
+
]}
|
|
23
|
+
>
|
|
24
|
+
<p>{file.name}</p>
|
|
25
|
+
{#if onremove}
|
|
26
|
+
<X size={16} class="group-hover:text-primary-500" />
|
|
27
|
+
{/if}
|
|
28
|
+
</svelte:element>
|