@websline/system-components 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/README.md +0 -0
- package/dist/components/atoms/avatar/Avatar.svelte +78 -0
- package/dist/components/atoms/avatar/Avatar.svelte.d.ts +65 -0
- package/dist/components/atoms/avatar/avatar.variants.d.ts +37 -0
- package/dist/components/atoms/avatar/avatar.variants.js +20 -0
- package/dist/components/atoms/closeButton/CloseButton.svelte +92 -0
- package/dist/components/atoms/closeButton/CloseButton.svelte.d.ts +25 -0
- package/dist/components/atoms/closeButton/closeButton.variants.d.ts +37 -0
- package/dist/components/atoms/closeButton/closeButton.variants.js +21 -0
- package/dist/components/atoms/form/button/Button.svelte +67 -0
- package/dist/components/atoms/form/button/Button.svelte.d.ts +81 -0
- package/dist/components/atoms/form/button/button.variants.d.ts +58 -0
- package/dist/components/atoms/form/button/button.variants.js +82 -0
- package/dist/components/atoms/form/formField/FormField.svelte +69 -0
- package/dist/components/atoms/form/formField/FormField.svelte.d.ts +73 -0
- package/dist/components/atoms/form/helperText/HelperText.svelte +18 -0
- package/dist/components/atoms/form/helperText/HelperText.svelte.d.ts +15 -0
- package/dist/components/atoms/form/iconButton/IconButton.svelte +69 -0
- package/dist/components/atoms/form/iconButton/IconButton.svelte.d.ts +89 -0
- package/dist/components/atoms/form/iconButton/iconButton.variants.d.ts +64 -0
- package/dist/components/atoms/form/iconButton/iconButton.variants.js +91 -0
- package/dist/components/atoms/form/input/Input.svelte +65 -0
- package/dist/components/atoms/form/input/Input.svelte.d.ts +89 -0
- package/dist/components/atoms/form/input/input.variants.d.ts +22 -0
- package/dist/components/atoms/form/input/input.variants.js +15 -0
- package/dist/components/atoms/form/label/Label.svelte +36 -0
- package/dist/components/atoms/form/label/Label.svelte.d.ts +41 -0
- package/dist/components/atoms/form/textarea/Textarea.svelte +64 -0
- package/dist/components/atoms/form/textarea/Textarea.svelte.d.ts +89 -0
- package/dist/components/atoms/form/textarea/textarea.variants.d.ts +37 -0
- package/dist/components/atoms/form/textarea/textarea.variants.js +20 -0
- package/dist/components/atoms/icon/Icon.svelte +41 -0
- package/dist/components/atoms/icon/Icon.svelte.d.ts +21 -0
- package/dist/components/atoms/icon/components/Academy.svelte +27 -0
- package/dist/components/atoms/icon/components/Academy.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/Bold.svelte +27 -0
- package/dist/components/atoms/icon/components/Bold.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/Close.svelte +27 -0
- package/dist/components/atoms/icon/components/Close.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/Italic.svelte +27 -0
- package/dist/components/atoms/icon/components/Italic.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/Link.svelte +27 -0
- package/dist/components/atoms/icon/components/Link.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/ListOrdered.svelte +27 -0
- package/dist/components/atoms/icon/components/ListOrdered.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/ListUnordered.svelte +26 -0
- package/dist/components/atoms/icon/components/ListUnordered.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/Refresh.svelte +27 -0
- package/dist/components/atoms/icon/components/Refresh.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/components/Underline.svelte +26 -0
- package/dist/components/atoms/icon/components/Underline.svelte.d.ts +41 -0
- package/dist/components/atoms/icon/index.d.ts +20 -0
- package/dist/components/atoms/icon/index.js +21 -0
- package/dist/components/atoms/loading/spinner/Spinner.svelte +40 -0
- package/dist/components/atoms/loading/spinner/Spinner.svelte.d.ts +25 -0
- package/dist/components/molecules/notification/Notification.svelte +42 -0
- package/dist/components/molecules/notification/Notification.svelte.d.ts +57 -0
- package/dist/components/molecules/notification/notification.variants.d.ts +67 -0
- package/dist/components/molecules/notification/notification.variants.js +30 -0
- package/dist/components/molecules/richTextEditor/RichTextEditor.svelte +144 -0
- package/dist/components/molecules/richTextEditor/RichTextEditor.svelte.d.ts +87 -0
- package/dist/components/molecules/richTextEditor/RichTextEditorToolbar.svelte +5 -0
- package/dist/components/molecules/richTextEditor/RichTextEditorToolbar.svelte.d.ts +11 -0
- package/dist/components/molecules/richTextEditor/richTextEditor.variants.d.ts +64 -0
- package/dist/components/molecules/richTextEditor/richTextEditor.variants.js +30 -0
- package/dist/components/molecules/toggleGroup/ToggleGroup.svelte +61 -0
- package/dist/components/molecules/toggleGroup/ToggleGroup.svelte.d.ts +49 -0
- package/dist/components/molecules/toggleGroup/ToggleGroupItem.svelte +47 -0
- package/dist/components/molecules/toggleGroup/ToggleGroupItem.svelte.d.ts +25 -0
- package/dist/components/molecules/toggleGroup/toggleGroup.variants.d.ts +35 -0
- package/dist/components/molecules/toggleGroup/toggleGroup.variants.js +21 -0
- package/dist/components/molecules/toggleGroup/toggleGroupItem.variants.d.ts +110 -0
- package/dist/components/molecules/toggleGroup/toggleGroupItem.variants.js +69 -0
- package/dist/components/organisms/notificationGroup/NotificationGroup.svelte +68 -0
- package/dist/components/organisms/notificationGroup/NotificationGroup.svelte.d.ts +6 -0
- package/dist/components/organisms/notificationGroup/notificationGroup.variants.d.ts +24 -0
- package/dist/components/organisms/notificationGroup/notificationGroup.variants.js +11 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +32 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/notification.d.ts +1 -0
- package/dist/utils/notification.js +11 -0
- package/package.json +95 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { onMount, onDestroy } from "svelte";
|
|
3
|
+
import RichTextEditorToolbar from "./RichTextEditorToolbar.svelte";
|
|
4
|
+
import { richTextEditorVariants } from "./richTextEditor.variants.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* TODO: Transform into runes. Currently not possible because re-rendering is not executed correctly. Best to check, for example, whether the Bold button is correctly marked when set.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} Props
|
|
12
|
+
* @property {classes} [classes] CSS class overrides for editor parts
|
|
13
|
+
* @property {string} [content=""] The initial content of the editor
|
|
14
|
+
* @property {string} [fieldName=""] The name of the field for form submissions
|
|
15
|
+
* @property {boolean} [hideToolbar=false] Whether to hide the toolbar
|
|
16
|
+
* @property {"small" | "medium" | "large"} [size="medium"] RichTextEditor size
|
|
17
|
+
* @property {string} [placeholder=""] Placeholder text for the editor
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** @type {Props} */
|
|
21
|
+
|
|
22
|
+
export let classes = {};
|
|
23
|
+
export let content = "";
|
|
24
|
+
export let fieldName = "";
|
|
25
|
+
export let hideToolbar = false;
|
|
26
|
+
export let placeholder = "Beginne mit dem Schreiben..."; // Placeholder text for the editor
|
|
27
|
+
export let size = "medium";
|
|
28
|
+
|
|
29
|
+
let element;
|
|
30
|
+
let editor;
|
|
31
|
+
let htmlInputValue;
|
|
32
|
+
|
|
33
|
+
const initEditor = async () => {
|
|
34
|
+
const { Editor } = await import("@tiptap/core");
|
|
35
|
+
const StarterKit = (await import("@tiptap/starter-kit")).default;
|
|
36
|
+
const Link = (await import("@tiptap/extension-link")).default;
|
|
37
|
+
const TextAlign = (await import("@tiptap/extension-text-align")).default;
|
|
38
|
+
const Color = (await import("@tiptap/extension-color")).default;
|
|
39
|
+
const TextStyle = (await import("@tiptap/extension-text-style")).default;
|
|
40
|
+
const Highlight = (await import("@tiptap/extension-highlight")).default;
|
|
41
|
+
const Underline = (await import("@tiptap/extension-underline")).default;
|
|
42
|
+
const Placeholder = (await import("@tiptap/extension-placeholder")).default;
|
|
43
|
+
const DOMPurify = (await import("dompurify")).default;
|
|
44
|
+
|
|
45
|
+
editor = new Editor({
|
|
46
|
+
element: element,
|
|
47
|
+
extensions: [
|
|
48
|
+
StarterKit,
|
|
49
|
+
TextStyle,
|
|
50
|
+
Color,
|
|
51
|
+
Highlight.configure({
|
|
52
|
+
multicolor: true,
|
|
53
|
+
}),
|
|
54
|
+
Link.configure({
|
|
55
|
+
openOnClick: false,
|
|
56
|
+
}),
|
|
57
|
+
TextAlign.configure({
|
|
58
|
+
types: ["paragraph", "heading"],
|
|
59
|
+
}),
|
|
60
|
+
Underline,
|
|
61
|
+
Placeholder.configure({
|
|
62
|
+
placeholder,
|
|
63
|
+
showOnlyWhenEditable: true,
|
|
64
|
+
showOnlyCurrent: true,
|
|
65
|
+
}),
|
|
66
|
+
],
|
|
67
|
+
editorProps: {
|
|
68
|
+
handlePaste(view, event) {
|
|
69
|
+
const html = event.clipboardData.getData("text/html");
|
|
70
|
+
|
|
71
|
+
if (html) {
|
|
72
|
+
const cleaned = DOMPurify.sanitize(html, {
|
|
73
|
+
ALLOWED_TAGS: ["b", "strong", "i", "em", "u", "s", "strike", "p", "br"],
|
|
74
|
+
ALLOWED_ATTR: [],
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const normalized = cleanHTMLWhitespace(cleaned);
|
|
78
|
+
|
|
79
|
+
editor.commands.insertContent(normalized);
|
|
80
|
+
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return false;
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
content,
|
|
88
|
+
onTransaction: () => {
|
|
89
|
+
editor = editor;
|
|
90
|
+
htmlInputValue = editor.getHTML();
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
editor.commands.focus("end");
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
onMount(() => {
|
|
98
|
+
initEditor();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
onDestroy(() => {
|
|
102
|
+
if (editor) {
|
|
103
|
+
editor.destroy();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const cleanHTMLWhitespace = (html) => {
|
|
108
|
+
const dom = document.createElement("div");
|
|
109
|
+
dom.innerHTML = html;
|
|
110
|
+
|
|
111
|
+
// remove empty paragraphs
|
|
112
|
+
dom.querySelectorAll("p").forEach((p) => {
|
|
113
|
+
if (!p.textContent.trim() || p.innerHTML.trim() === " ") {
|
|
114
|
+
p.remove();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// reduce multiple spaces to a single space
|
|
119
|
+
const walker = document.createTreeWalker(dom, NodeFilter.SHOW_TEXT, null, false);
|
|
120
|
+
while (walker.nextNode()) {
|
|
121
|
+
const node = walker.currentNode;
|
|
122
|
+
node.nodeValue = node.nodeValue
|
|
123
|
+
.replace(/\s*\n\s*/g, " ")
|
|
124
|
+
.replace(/\s{2,}/g, " ");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return dom.innerHTML.trim();
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
let { base, field, toolbar } = richTextEditorVariants();
|
|
131
|
+
</script>
|
|
132
|
+
|
|
133
|
+
<div class={base({ class: classes.base })}>
|
|
134
|
+
{#if !hideToolbar}
|
|
135
|
+
<div class={toolbar({ class: classes.toolbar })}>
|
|
136
|
+
<RichTextEditorToolbar {editor} />
|
|
137
|
+
</div>
|
|
138
|
+
{/if}
|
|
139
|
+
{#if fieldName}
|
|
140
|
+
<input type="hidden" name={fieldName} bind:value={htmlInputValue} />
|
|
141
|
+
{/if}
|
|
142
|
+
<div class={field({ class: classes.field, hideToolbar, size })} bind:this={element}>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export default RichTextEditor;
|
|
2
|
+
type RichTextEditor = SvelteComponent<{
|
|
3
|
+
size?: string;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
content?: string;
|
|
6
|
+
hideToolbar?: boolean;
|
|
7
|
+
classes?: Props;
|
|
8
|
+
fieldName?: string;
|
|
9
|
+
}, {
|
|
10
|
+
[evt: string]: CustomEvent<any>;
|
|
11
|
+
}, {}> & {
|
|
12
|
+
$$bindings?: string;
|
|
13
|
+
};
|
|
14
|
+
declare const RichTextEditor: $$__sveltets_2_IsomorphicComponent<{
|
|
15
|
+
size?: string;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
content?: string;
|
|
18
|
+
hideToolbar?: boolean;
|
|
19
|
+
classes?: {
|
|
20
|
+
/**
|
|
21
|
+
* CSS class overrides for editor parts
|
|
22
|
+
*/
|
|
23
|
+
classes?: any;
|
|
24
|
+
/**
|
|
25
|
+
* The initial content of the editor
|
|
26
|
+
*/
|
|
27
|
+
content?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The name of the field for form submissions
|
|
30
|
+
*/
|
|
31
|
+
fieldName?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Whether to hide the toolbar
|
|
34
|
+
*/
|
|
35
|
+
hideToolbar?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* RichTextEditor size
|
|
38
|
+
*/
|
|
39
|
+
size?: "small" | "medium" | "large";
|
|
40
|
+
/**
|
|
41
|
+
* Placeholder text for the editor
|
|
42
|
+
*/
|
|
43
|
+
placeholder?: string;
|
|
44
|
+
};
|
|
45
|
+
fieldName?: string;
|
|
46
|
+
}, {
|
|
47
|
+
[evt: string]: CustomEvent<any>;
|
|
48
|
+
}, {}, {}, string>;
|
|
49
|
+
type Props = {
|
|
50
|
+
/**
|
|
51
|
+
* CSS class overrides for editor parts
|
|
52
|
+
*/
|
|
53
|
+
classes?: any;
|
|
54
|
+
/**
|
|
55
|
+
* The initial content of the editor
|
|
56
|
+
*/
|
|
57
|
+
content?: string;
|
|
58
|
+
/**
|
|
59
|
+
* The name of the field for form submissions
|
|
60
|
+
*/
|
|
61
|
+
fieldName?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Whether to hide the toolbar
|
|
64
|
+
*/
|
|
65
|
+
hideToolbar?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* RichTextEditor size
|
|
68
|
+
*/
|
|
69
|
+
size?: "small" | "medium" | "large";
|
|
70
|
+
/**
|
|
71
|
+
* Placeholder text for the editor
|
|
72
|
+
*/
|
|
73
|
+
placeholder?: string;
|
|
74
|
+
};
|
|
75
|
+
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> {
|
|
76
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
77
|
+
$$bindings?: Bindings;
|
|
78
|
+
} & Exports;
|
|
79
|
+
(internal: unknown, props: Props & {
|
|
80
|
+
$$events?: Events;
|
|
81
|
+
$$slots?: Slots;
|
|
82
|
+
}): Exports & {
|
|
83
|
+
$set?: any;
|
|
84
|
+
$on?: any;
|
|
85
|
+
};
|
|
86
|
+
z_$$bindings?: Bindings;
|
|
87
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default RichTextEditorToolbar;
|
|
2
|
+
type RichTextEditorToolbar = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const RichTextEditorToolbar: import("svelte").Component<{
|
|
7
|
+
editor: any;
|
|
8
|
+
}, {}, "">;
|
|
9
|
+
type $$ComponentProps = {
|
|
10
|
+
editor: any;
|
|
11
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export const richTextEditorVariants: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
hideToolbar: {
|
|
3
|
+
true: {
|
|
4
|
+
field: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
size: {
|
|
8
|
+
small: {
|
|
9
|
+
field: string;
|
|
10
|
+
};
|
|
11
|
+
medium: {
|
|
12
|
+
field: string;
|
|
13
|
+
};
|
|
14
|
+
large: {
|
|
15
|
+
field: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}, {
|
|
19
|
+
base: string;
|
|
20
|
+
toolbar: string;
|
|
21
|
+
field: string;
|
|
22
|
+
}, undefined, {
|
|
23
|
+
hideToolbar: {
|
|
24
|
+
true: {
|
|
25
|
+
field: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
size: {
|
|
29
|
+
small: {
|
|
30
|
+
field: string;
|
|
31
|
+
};
|
|
32
|
+
medium: {
|
|
33
|
+
field: string;
|
|
34
|
+
};
|
|
35
|
+
large: {
|
|
36
|
+
field: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}, {
|
|
40
|
+
base: string;
|
|
41
|
+
toolbar: string;
|
|
42
|
+
field: string;
|
|
43
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
44
|
+
hideToolbar: {
|
|
45
|
+
true: {
|
|
46
|
+
field: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
size: {
|
|
50
|
+
small: {
|
|
51
|
+
field: string;
|
|
52
|
+
};
|
|
53
|
+
medium: {
|
|
54
|
+
field: string;
|
|
55
|
+
};
|
|
56
|
+
large: {
|
|
57
|
+
field: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
}, {
|
|
61
|
+
base: string;
|
|
62
|
+
toolbar: string;
|
|
63
|
+
field: string;
|
|
64
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { tv } from "tailwind-variants";
|
|
2
|
+
|
|
3
|
+
const richTextEditorVariants = tv({
|
|
4
|
+
slots: {
|
|
5
|
+
base: "body-default text-neutral-800 dark:text-white",
|
|
6
|
+
toolbar: "px-5 py-4 border-neutral-500 border border-b-0 rounded-t-sm",
|
|
7
|
+
field:
|
|
8
|
+
"[&>div]:transition-[border] [&>div]:duration-300 [&>div]:border [&>div]:border-neutral-500 [&>div]:rounded-b-sm [&>div]:hover:border-neutral-800 [&>div]:outline-none [&>div]:p-5 [&>div]:h-full [&>.ProseMirror-focused]:!border-blue-500 [&>div]:dark:hover:border-neutral-200 [&>.ProseMirror-focused]:dark:!border-blue-400 [&>div>p.is-empty]:before:content-[attr(data-placeholder)] [&>div>p.is-empty]:before:float-left [&>div>p.is-empty]:before:h-0 [&>div>p.is-empty]:before:text-neutral-500",
|
|
9
|
+
},
|
|
10
|
+
variants: {
|
|
11
|
+
hideToolbar: {
|
|
12
|
+
true: {
|
|
13
|
+
field: "[&>div]:rounded-t-sm",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
size: {
|
|
17
|
+
small: {
|
|
18
|
+
field: "h-auto",
|
|
19
|
+
},
|
|
20
|
+
medium: {
|
|
21
|
+
field: "h-40",
|
|
22
|
+
},
|
|
23
|
+
large: {
|
|
24
|
+
field: "h-64",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export { richTextEditorVariants };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { setContext } from "svelte";
|
|
3
|
+
import { crossfade } from "svelte/transition";
|
|
4
|
+
import { cubicInOut } from "svelte/easing";
|
|
5
|
+
import {
|
|
6
|
+
toggleGroupVariants,
|
|
7
|
+
toggleGroupTabVariants,
|
|
8
|
+
} from "./toggleGroup.variants.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} Props
|
|
12
|
+
* @property {"default" | "raised"} [appearance="default"] The appearance variant of the component
|
|
13
|
+
* @property {string} [class=""] Additional CSS classes to apply to the component
|
|
14
|
+
* @property {"small" | "medium"} [size="medium"] The size variant of the component
|
|
15
|
+
* @property {string} [value=""] The value of the toggle group
|
|
16
|
+
* @property {"default" | "tabs"} [variant="default"] The variant of the toggle group
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const [send, receive] = crossfade({
|
|
20
|
+
duration: 250,
|
|
21
|
+
easing: cubicInOut,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/** @type {Props} */
|
|
25
|
+
let {
|
|
26
|
+
appearance = "default",
|
|
27
|
+
children,
|
|
28
|
+
class: className = "",
|
|
29
|
+
size = "medium",
|
|
30
|
+
value,
|
|
31
|
+
variant = "default",
|
|
32
|
+
} = $props();
|
|
33
|
+
|
|
34
|
+
let toggleGroupEl;
|
|
35
|
+
|
|
36
|
+
setContext("toggle-group-store", () => {
|
|
37
|
+
return {
|
|
38
|
+
appearance,
|
|
39
|
+
send,
|
|
40
|
+
receive,
|
|
41
|
+
size,
|
|
42
|
+
update: (newValue) => {
|
|
43
|
+
value = newValue;
|
|
44
|
+
},
|
|
45
|
+
value,
|
|
46
|
+
variant,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
let stylesByVariant = $derived.by(() => {
|
|
51
|
+
if (variant === "tabs") {
|
|
52
|
+
return toggleGroupTabVariants({ appearance, class: className, size, variant });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return toggleGroupVariants({ appearance, class: className, size, variant });
|
|
56
|
+
});
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<div bind:this={toggleGroupEl} class={stylesByVariant} role="tablist">
|
|
60
|
+
{@render children?.()}
|
|
61
|
+
</div>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export default ToggleGroup;
|
|
2
|
+
type ToggleGroup = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<Props>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const ToggleGroup: import("svelte").Component<{
|
|
7
|
+
/**
|
|
8
|
+
* The appearance variant of the component
|
|
9
|
+
*/
|
|
10
|
+
appearance?: "default" | "raised";
|
|
11
|
+
/**
|
|
12
|
+
* Additional CSS classes to apply to the component
|
|
13
|
+
*/
|
|
14
|
+
class?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The size variant of the component
|
|
17
|
+
*/
|
|
18
|
+
size?: "small" | "medium";
|
|
19
|
+
/**
|
|
20
|
+
* The value of the toggle group
|
|
21
|
+
*/
|
|
22
|
+
value?: string;
|
|
23
|
+
/**
|
|
24
|
+
* The variant of the toggle group
|
|
25
|
+
*/
|
|
26
|
+
variant?: "default" | "tabs";
|
|
27
|
+
}, {}, "">;
|
|
28
|
+
type Props = {
|
|
29
|
+
/**
|
|
30
|
+
* The appearance variant of the component
|
|
31
|
+
*/
|
|
32
|
+
appearance?: "default" | "raised";
|
|
33
|
+
/**
|
|
34
|
+
* Additional CSS classes to apply to the component
|
|
35
|
+
*/
|
|
36
|
+
class?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The size variant of the component
|
|
39
|
+
*/
|
|
40
|
+
size?: "small" | "medium";
|
|
41
|
+
/**
|
|
42
|
+
* The value of the toggle group
|
|
43
|
+
*/
|
|
44
|
+
value?: string;
|
|
45
|
+
/**
|
|
46
|
+
* The variant of the toggle group
|
|
47
|
+
*/
|
|
48
|
+
variant?: "default" | "tabs";
|
|
49
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from "svelte";
|
|
3
|
+
import {
|
|
4
|
+
toggleGroupItemVariants,
|
|
5
|
+
toggleGroupItemTabVariants,
|
|
6
|
+
} from "./toggleGroupItem.variants.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} Props
|
|
10
|
+
* @property {string} [class=""] Additional CSS classes to apply to the component
|
|
11
|
+
* @property {string} [value=""] The value of the toggle group item
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** @type {Props} */
|
|
15
|
+
let { children, class: className = "", value: localeValue } = $props();
|
|
16
|
+
|
|
17
|
+
let store = getContext("toggle-group-store");
|
|
18
|
+
let { appearance, send, receive, size, variant } = $derived(store());
|
|
19
|
+
let isActive = $derived(store().value === localeValue);
|
|
20
|
+
|
|
21
|
+
let stylesByVariant = $derived.by(() => {
|
|
22
|
+
if (variant === "tabs") {
|
|
23
|
+
return toggleGroupItemTabVariants();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return toggleGroupItemVariants();
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<div class={stylesByVariant.base()}>
|
|
31
|
+
<button
|
|
32
|
+
class={stylesByVariant.button({ appearance, class: className, isActive, size })}
|
|
33
|
+
role="tab"
|
|
34
|
+
onclick={() => {
|
|
35
|
+
store().update(localeValue);
|
|
36
|
+
}}
|
|
37
|
+
type="button">
|
|
38
|
+
<span class={stylesByVariant.span()}>{@render children?.()}</span>
|
|
39
|
+
{#if isActive}
|
|
40
|
+
<div
|
|
41
|
+
class={stylesByVariant.trigger({ appearance })}
|
|
42
|
+
in:send={{ key: "active-tab" }}
|
|
43
|
+
out:receive={{ key: "active-tab" }}>
|
|
44
|
+
</div>
|
|
45
|
+
{/if}
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default ToggleGroupItem;
|
|
2
|
+
type ToggleGroupItem = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<Props>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const ToggleGroupItem: import("svelte").Component<{
|
|
7
|
+
/**
|
|
8
|
+
* Additional CSS classes to apply to the component
|
|
9
|
+
*/
|
|
10
|
+
class?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The value of the toggle group item
|
|
13
|
+
*/
|
|
14
|
+
value?: string;
|
|
15
|
+
}, {}, "">;
|
|
16
|
+
type Props = {
|
|
17
|
+
/**
|
|
18
|
+
* Additional CSS classes to apply to the component
|
|
19
|
+
*/
|
|
20
|
+
class?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The value of the toggle group item
|
|
23
|
+
*/
|
|
24
|
+
value?: string;
|
|
25
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const toggleGroupVariants: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
appearance: {
|
|
3
|
+
default: string;
|
|
4
|
+
raised: string;
|
|
5
|
+
};
|
|
6
|
+
size: {
|
|
7
|
+
small: string;
|
|
8
|
+
medium: string;
|
|
9
|
+
};
|
|
10
|
+
}, undefined, "flex rounded-sm gap-1", {
|
|
11
|
+
appearance: {
|
|
12
|
+
default: string;
|
|
13
|
+
raised: string;
|
|
14
|
+
};
|
|
15
|
+
size: {
|
|
16
|
+
small: string;
|
|
17
|
+
medium: string;
|
|
18
|
+
};
|
|
19
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
20
|
+
appearance: {
|
|
21
|
+
default: string;
|
|
22
|
+
raised: string;
|
|
23
|
+
};
|
|
24
|
+
size: {
|
|
25
|
+
small: string;
|
|
26
|
+
medium: string;
|
|
27
|
+
};
|
|
28
|
+
}, undefined, "flex rounded-sm gap-1", unknown, unknown, undefined>>;
|
|
29
|
+
export const toggleGroupTabVariants: import("tailwind-variants").TVReturnType<{} | {
|
|
30
|
+
[x: string]: {
|
|
31
|
+
[x: string]: import("tailwind-variants").ClassValue | {
|
|
32
|
+
base?: import("tailwind-variants").ClassValue;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}, undefined, "flex gap-5 h-10 border-b border-b-neutral-500", any, undefined, import("tailwind-variants").TVReturnType<any, undefined, "flex gap-5 h-10 border-b border-b-neutral-500", unknown, unknown, undefined>>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { tv } from "tailwind-variants";
|
|
2
|
+
|
|
3
|
+
const toggleGroupVariants = tv({
|
|
4
|
+
base: "flex rounded-sm gap-1",
|
|
5
|
+
variants: {
|
|
6
|
+
appearance: {
|
|
7
|
+
default: "bg-neutral-100 dark:bg-neutral-900",
|
|
8
|
+
raised: "bg-neutral-300 dark:bg-neutral-700",
|
|
9
|
+
},
|
|
10
|
+
size: {
|
|
11
|
+
small: "h-6 p-0.5",
|
|
12
|
+
medium: "h-10 p-1",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const toggleGroupTabVariants = tv({
|
|
18
|
+
base: "flex gap-5 h-10 border-b border-b-neutral-500",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { toggleGroupVariants, toggleGroupTabVariants };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
export const toggleGroupItemVariants: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
isActive: {
|
|
3
|
+
true: {
|
|
4
|
+
button: string;
|
|
5
|
+
};
|
|
6
|
+
false: {
|
|
7
|
+
button: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
size: {
|
|
11
|
+
small: {
|
|
12
|
+
button: string;
|
|
13
|
+
};
|
|
14
|
+
medium: {
|
|
15
|
+
button: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}, {
|
|
19
|
+
base: string;
|
|
20
|
+
button: string;
|
|
21
|
+
span: string;
|
|
22
|
+
trigger: string;
|
|
23
|
+
}, undefined, {
|
|
24
|
+
isActive: {
|
|
25
|
+
true: {
|
|
26
|
+
button: string;
|
|
27
|
+
};
|
|
28
|
+
false: {
|
|
29
|
+
button: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
size: {
|
|
33
|
+
small: {
|
|
34
|
+
button: string;
|
|
35
|
+
};
|
|
36
|
+
medium: {
|
|
37
|
+
button: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}, {
|
|
41
|
+
base: string;
|
|
42
|
+
button: string;
|
|
43
|
+
span: string;
|
|
44
|
+
trigger: string;
|
|
45
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
46
|
+
isActive: {
|
|
47
|
+
true: {
|
|
48
|
+
button: string;
|
|
49
|
+
};
|
|
50
|
+
false: {
|
|
51
|
+
button: string;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
size: {
|
|
55
|
+
small: {
|
|
56
|
+
button: string;
|
|
57
|
+
};
|
|
58
|
+
medium: {
|
|
59
|
+
button: string;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
}, {
|
|
63
|
+
base: string;
|
|
64
|
+
button: string;
|
|
65
|
+
span: string;
|
|
66
|
+
trigger: string;
|
|
67
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
68
|
+
export const toggleGroupItemTabVariants: import("tailwind-variants").TVReturnType<{
|
|
69
|
+
isActive: {
|
|
70
|
+
true: {
|
|
71
|
+
button: string;
|
|
72
|
+
};
|
|
73
|
+
false: {
|
|
74
|
+
button: string;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
}, {
|
|
78
|
+
base: string;
|
|
79
|
+
button: string;
|
|
80
|
+
span: string;
|
|
81
|
+
trigger: string;
|
|
82
|
+
}, undefined, {
|
|
83
|
+
isActive: {
|
|
84
|
+
true: {
|
|
85
|
+
button: string;
|
|
86
|
+
};
|
|
87
|
+
false: {
|
|
88
|
+
button: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
}, {
|
|
92
|
+
base: string;
|
|
93
|
+
button: string;
|
|
94
|
+
span: string;
|
|
95
|
+
trigger: string;
|
|
96
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
97
|
+
isActive: {
|
|
98
|
+
true: {
|
|
99
|
+
button: string;
|
|
100
|
+
};
|
|
101
|
+
false: {
|
|
102
|
+
button: string;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
}, {
|
|
106
|
+
base: string;
|
|
107
|
+
button: string;
|
|
108
|
+
span: string;
|
|
109
|
+
trigger: string;
|
|
110
|
+
}, undefined, unknown, unknown, undefined>>;
|