@websline/system-components 1.3.10 → 1.3.12
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/components/atoms/icon/index.js +12 -17
- package/dist/components/molecules/richTextEditor/RichTextEditor.svelte +35 -21
- package/dist/components/molecules/richTextEditor/RichTextEditor.svelte.d.ts +2 -0
- package/dist/components/organisms/dialog/dialog.variants.js +4 -4
- package/dist/components/organisms/modal/modal.variants.js +2 -1
- package/package.json +13 -13
|
@@ -10,6 +10,13 @@ const moduleRegistry = import.meta.glob("./**/*.svelte", {
|
|
|
10
10
|
|
|
11
11
|
const registry = {};
|
|
12
12
|
|
|
13
|
+
// e.g. for backwards compatibility
|
|
14
|
+
const synonyms = {
|
|
15
|
+
"checkbox-stack": "checkboxStack",
|
|
16
|
+
"file-pdf": "filePDF",
|
|
17
|
+
unlink: "connectCrossed",
|
|
18
|
+
};
|
|
19
|
+
|
|
13
20
|
const addIconsToRegistry = (pathModuleRecord) => {
|
|
14
21
|
const map = Object.fromEntries(
|
|
15
22
|
Object.entries(pathModuleRecord).map(([path, module]) => {
|
|
@@ -28,26 +35,14 @@ const addIconsToRegistry = (pathModuleRecord) => {
|
|
|
28
35
|
}),
|
|
29
36
|
);
|
|
30
37
|
Object.assign(registry, map);
|
|
31
|
-
};
|
|
32
38
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
// attach synonyms to registry
|
|
40
|
+
Object.entries(synonyms).map(([k, v]) => {
|
|
41
|
+
if (registry[k]) return;
|
|
42
|
+
registry[k] = registry[v];
|
|
43
|
+
});
|
|
38
44
|
};
|
|
39
45
|
|
|
40
46
|
addIconsToRegistry(moduleRegistry);
|
|
41
47
|
|
|
42
|
-
// attach synonyms to registry, with error handling for duplicates
|
|
43
|
-
Object.entries(synonyms).map(([k, v]) => {
|
|
44
|
-
if (registry[k]) {
|
|
45
|
-
console.error(
|
|
46
|
-
`skipping synonym "${k}" because it already exists in the registry`,
|
|
47
|
-
);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
registry[k] = registry[v];
|
|
51
|
-
});
|
|
52
|
-
|
|
53
48
|
export { addIconsToRegistry, registry, synonyms };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {
|
|
2
|
+
import { setContext, untrack } from "svelte";
|
|
3
3
|
import RichTextEditorToolbar from "./toolbar/RichTextEditorToolbar.svelte";
|
|
4
4
|
import { richTextEditorVariants } from "./richTextEditor.variants.js";
|
|
5
5
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
content = "",
|
|
9
9
|
fieldName = "",
|
|
10
10
|
hideToolbar = false,
|
|
11
|
+
oninput,
|
|
11
12
|
placeholder = "",
|
|
12
13
|
size = "medium",
|
|
13
14
|
toolbarConfig = {
|
|
@@ -41,9 +42,11 @@
|
|
|
41
42
|
...rest
|
|
42
43
|
} = $props();
|
|
43
44
|
|
|
45
|
+
let DOMPurify;
|
|
44
46
|
let element = $state();
|
|
45
|
-
|
|
47
|
+
/** @type {import("@tiptap/core").Editor} */
|
|
46
48
|
let editor = $state.raw();
|
|
49
|
+
let htmlInputValue = $state();
|
|
47
50
|
|
|
48
51
|
let styles = $derived(richTextEditorVariants({ hideToolbar, size }));
|
|
49
52
|
|
|
@@ -57,7 +60,7 @@
|
|
|
57
60
|
const { TextStyle } = await import("@tiptap/extension-text-style");
|
|
58
61
|
const Highlight = (await import("@tiptap/extension-highlight")).default;
|
|
59
62
|
const Placeholder = (await import("@tiptap/extension-placeholder")).default;
|
|
60
|
-
|
|
63
|
+
DOMPurify = (await import("dompurify")).default;
|
|
61
64
|
|
|
62
65
|
editor = new Editor({
|
|
63
66
|
element: element,
|
|
@@ -85,40 +88,40 @@
|
|
|
85
88
|
editorProps: {
|
|
86
89
|
handlePaste(view, event) {
|
|
87
90
|
const html = event.clipboardData.getData("text/html");
|
|
91
|
+
const sanitized = sanitizeContent(html);
|
|
92
|
+
if (!sanitized) return false;
|
|
88
93
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
ALLOWED_TAGS: ["b", "strong", "i", "em", "u", "s", "strike", "p", "br"],
|
|
92
|
-
ALLOWED_ATTR: [],
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const normalized = cleanHTMLWhitespace(cleaned);
|
|
96
|
-
|
|
97
|
-
editor.commands.insertContent(normalized);
|
|
98
|
-
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return false;
|
|
94
|
+
editor.commands.insertContent(sanitized);
|
|
95
|
+
return true;
|
|
103
96
|
},
|
|
104
97
|
},
|
|
105
|
-
content,
|
|
106
98
|
onUpdate: () => {
|
|
107
99
|
htmlInputValue = editor.getHTML();
|
|
100
|
+
oninput?.(htmlInputValue);
|
|
108
101
|
},
|
|
109
102
|
});
|
|
110
103
|
|
|
111
104
|
editor.commands.focus("end");
|
|
112
105
|
};
|
|
113
106
|
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
$effect(() => {
|
|
108
|
+
element;
|
|
109
|
+
placeholder;
|
|
110
|
+
untrack(initEditor);
|
|
116
111
|
|
|
117
112
|
return () => {
|
|
118
113
|
editor?.destroy();
|
|
119
114
|
};
|
|
120
115
|
});
|
|
121
116
|
|
|
117
|
+
$effect(() => {
|
|
118
|
+
content;
|
|
119
|
+
if (editor) {
|
|
120
|
+
const sanitized = untrack(() => sanitizeContent(content));
|
|
121
|
+
editor.commands.setContent(sanitized ?? "");
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
122
125
|
const cleanHTMLWhitespace = (html) => {
|
|
123
126
|
const dom = document.createElement("div");
|
|
124
127
|
dom.innerHTML = html;
|
|
@@ -141,6 +144,17 @@
|
|
|
141
144
|
|
|
142
145
|
return dom.innerHTML.trim();
|
|
143
146
|
};
|
|
147
|
+
|
|
148
|
+
const sanitizeContent = (html) => {
|
|
149
|
+
if (typeof html !== "string" || !DOMPurify) return;
|
|
150
|
+
|
|
151
|
+
const cleaned = DOMPurify.sanitize(html, {
|
|
152
|
+
ALLOWED_TAGS: ["b", "strong", "i", "em", "u", "s", "strike", "p", "br"],
|
|
153
|
+
ALLOWED_ATTR: [],
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return cleanHTMLWhitespace(cleaned);
|
|
157
|
+
};
|
|
144
158
|
</script>
|
|
145
159
|
|
|
146
160
|
<div class={styles.base({ class: classes.base })} {...rest}>
|
|
@@ -150,7 +164,7 @@
|
|
|
150
164
|
</div>
|
|
151
165
|
{/if}
|
|
152
166
|
{#if fieldName}
|
|
153
|
-
<input type="hidden" name={fieldName}
|
|
167
|
+
<input type="hidden" name={fieldName} value={htmlInputValue} />
|
|
154
168
|
{/if}
|
|
155
169
|
<div
|
|
156
170
|
class={styles.field({ class: classes.field })}
|
|
@@ -8,6 +8,7 @@ declare const RichTextEditor: import("svelte").Component<{
|
|
|
8
8
|
content?: string;
|
|
9
9
|
fieldName?: string;
|
|
10
10
|
hideToolbar?: boolean;
|
|
11
|
+
oninput: any;
|
|
11
12
|
placeholder?: string;
|
|
12
13
|
size?: string;
|
|
13
14
|
toolbarConfig?: Record<string, any>;
|
|
@@ -17,6 +18,7 @@ type $$ComponentProps = {
|
|
|
17
18
|
content?: string;
|
|
18
19
|
fieldName?: string;
|
|
19
20
|
hideToolbar?: boolean;
|
|
21
|
+
oninput: any;
|
|
20
22
|
placeholder?: string;
|
|
21
23
|
size?: string;
|
|
22
24
|
toolbarConfig?: Record<string, any>;
|
|
@@ -7,12 +7,12 @@ const dialogVariants = tv({
|
|
|
7
7
|
"my-4 grid max-h-[calc(100vh-32px)] w-[calc(100vw-32px)] min-w-xs grid-rows-[1fr_auto] gap-4 overflow-hidden rounded-lg bg-white px-4 py-3 leading-[1.486] shadow-sm dark:bg-neutral-800 dark:text-neutral-200",
|
|
8
8
|
overlay: "fixed inset-0 z-modal-backdrop bg-black/25",
|
|
9
9
|
positioner:
|
|
10
|
-
"fixed inset-0 z-
|
|
10
|
+
"fixed inset-0 z-modal grid items-center justify-items-center overflow-auto",
|
|
11
11
|
trigger: "cursor-pointer",
|
|
12
12
|
formActions: [
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
13
|
+
"*:data-[role=dismiss]:order-1 *:data-[role=dismiss]:mr-auto",
|
|
14
|
+
"*:data-[role=secondary]:order-2",
|
|
15
|
+
"*:data-[role=cta]:order-3",
|
|
16
16
|
],
|
|
17
17
|
},
|
|
18
18
|
variants: {
|
|
@@ -9,7 +9,8 @@ const modalVariants = tv({
|
|
|
9
9
|
"flex items-end border-b border-neutral-300 px-4 py-3 ui-title-2 dark:border-neutral-700",
|
|
10
10
|
body: "h-full overflow-auto",
|
|
11
11
|
overlay: "fixed inset-0 z-modal-backdrop bg-black/25",
|
|
12
|
-
positioner:
|
|
12
|
+
positioner:
|
|
13
|
+
"fixed inset-0 z-modal grid items-center justify-items-center overflow-auto",
|
|
13
14
|
trigger: "cursor-pointer",
|
|
14
15
|
},
|
|
15
16
|
variants: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@websline/system-components",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.12",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@tiptap/extension-text-style": "^3.20.0",
|
|
35
35
|
"@tiptap/pm": "^3.20.0",
|
|
36
36
|
"@tiptap/starter-kit": "^3.20.0",
|
|
37
|
-
"bits-ui": "^2.16.
|
|
37
|
+
"bits-ui": "^2.16.3",
|
|
38
38
|
"dompurify": "^3.3.1",
|
|
39
39
|
"tailwind-variants": "^3.2.2",
|
|
40
40
|
"uuid": "^13.0.0"
|
|
@@ -45,32 +45,32 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@eslint/compat": "^2.0.2",
|
|
47
47
|
"@eslint/js": "^9.39.3",
|
|
48
|
-
"@storybook/addon-a11y": "^10.2.
|
|
49
|
-
"@storybook/addon-docs": "^10.2.
|
|
48
|
+
"@storybook/addon-a11y": "^10.2.15",
|
|
49
|
+
"@storybook/addon-docs": "^10.2.15",
|
|
50
50
|
"@storybook/addon-svelte-csf": "^5.0.11",
|
|
51
|
-
"@storybook/sveltekit": "^10.2.
|
|
51
|
+
"@storybook/sveltekit": "^10.2.15",
|
|
52
52
|
"@sveltejs/adapter-auto": "^7.0.1",
|
|
53
|
-
"@sveltejs/kit": "^2.53.
|
|
53
|
+
"@sveltejs/kit": "^2.53.4",
|
|
54
54
|
"@sveltejs/package": "^2.5.7",
|
|
55
55
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
56
56
|
"@tailwindcss/forms": "^0.5.11",
|
|
57
57
|
"@tailwindcss/typography": "^0.5.19",
|
|
58
58
|
"@tailwindcss/vite": "^4.2.1",
|
|
59
|
-
"@types/node": "^25.3.
|
|
59
|
+
"@types/node": "^25.3.3",
|
|
60
60
|
"@vitest/browser": "^4.0.18",
|
|
61
61
|
"eslint": "^9.39.3",
|
|
62
62
|
"eslint-config-prettier": "^10.1.8",
|
|
63
|
-
"eslint-plugin-storybook": "^10.2.
|
|
63
|
+
"eslint-plugin-storybook": "^10.2.15",
|
|
64
64
|
"eslint-plugin-svelte": "^3.15.0",
|
|
65
|
-
"globals": "^17.
|
|
65
|
+
"globals": "^17.4.0",
|
|
66
66
|
"playwright": "^1.58.2",
|
|
67
67
|
"postcss-url": "^10.1.3",
|
|
68
68
|
"prettier": "^3.8.1",
|
|
69
|
-
"prettier-plugin-svelte": "^3.5.
|
|
69
|
+
"prettier-plugin-svelte": "^3.5.1",
|
|
70
70
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
71
|
-
"publint": "^0.3.
|
|
72
|
-
"storybook": "^10.2.
|
|
73
|
-
"svelte": "^5.53.
|
|
71
|
+
"publint": "^0.3.18",
|
|
72
|
+
"storybook": "^10.2.15",
|
|
73
|
+
"svelte": "^5.53.7",
|
|
74
74
|
"tailwindcss": "^4.2.1",
|
|
75
75
|
"typescript": "^5.9.3",
|
|
76
76
|
"vite": "^7.3.1",
|