svelte-multiselect 11.5.0 → 11.5.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/dist/CircleSpinner.svelte +29 -0
- package/dist/CircleSpinner.svelte.d.ts +8 -0
- package/dist/CmdPalette.svelte +74 -0
- package/dist/CmdPalette.svelte.d.ts +76 -0
- package/dist/CodeExample.svelte +85 -0
- package/dist/CodeExample.svelte.d.ts +25 -0
- package/dist/CopyButton.svelte +67 -0
- package/dist/CopyButton.svelte.d.ts +25 -0
- package/dist/FileDetails.svelte +65 -0
- package/dist/FileDetails.svelte.d.ts +22 -0
- package/dist/GitHubCorner.svelte +82 -0
- package/dist/GitHubCorner.svelte.d.ts +13 -0
- package/dist/Icon.svelte +23 -0
- package/dist/Icon.svelte.d.ts +8 -0
- package/dist/MultiSelect.svelte +1725 -0
- package/dist/MultiSelect.svelte.d.ts +25 -0
- package/dist/Nav.svelte +627 -0
- package/dist/Nav.svelte.d.ts +43 -0
- package/dist/PrevNext.svelte +105 -0
- package/dist/PrevNext.svelte.d.ts +56 -0
- package/dist/Toggle.svelte +77 -0
- package/dist/Toggle.svelte.d.ts +11 -0
- package/dist/Wiggle.svelte +22 -0
- package/dist/Wiggle.svelte.d.ts +18 -0
- package/dist/attachments.d.ts +72 -0
- package/dist/attachments.js +698 -0
- package/dist/heading-anchors.d.ts +14 -0
- package/dist/heading-anchors.js +120 -0
- package/dist/icons.d.ts +55 -0
- package/dist/icons.js +54 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +43 -0
- package/dist/types.d.ts +246 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +63 -0
- package/package.json +20 -17
- package/readme.md +25 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @type {() => import('svelte/compiler').PreprocessorGroup} */
|
|
2
|
+
export declare function heading_ids(): {
|
|
3
|
+
name: string;
|
|
4
|
+
markup({ content }: {
|
|
5
|
+
content: string;
|
|
6
|
+
}): {
|
|
7
|
+
code: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export interface HeadingAnchorsOptions {
|
|
11
|
+
selector?: string;
|
|
12
|
+
icon_svg?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const heading_anchors: (options?: HeadingAnchorsOptions) => (node: Element) => (() => void) | undefined;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Svelte preprocessor that adds IDs to headings at build time for SSR support
|
|
2
|
+
// This ensures fragment navigation (#heading-id) works on initial page load
|
|
3
|
+
// Match headings in two contexts:
|
|
4
|
+
// 1. Start of line (for .svelte files with formatted HTML)
|
|
5
|
+
// 2. After > (for mdsvex output where HTML is on single line, e.g., "</p> <h2>")
|
|
6
|
+
// Avoid matching inside src={...} attributes by requiring these specific contexts
|
|
7
|
+
// Note: [^>]* for attributes won't match if an attribute value contains > (e.g., data-foo="a>b")
|
|
8
|
+
// This edge case is rare in practice and would require significantly more complex parsing
|
|
9
|
+
const heading_regex_line_start = /^(\s*)<(h[2-6])([^>]*)>([\s\S]*?)<\/\2>/gim;
|
|
10
|
+
const heading_regex_after_tag = /(>)(\s*)<(h[2-6])([^>]*)>([\s\S]*?)<\/\3>/gi;
|
|
11
|
+
// Remove Svelte expressions handling nested braces (e.g., {fn({a: 1})})
|
|
12
|
+
// Treats unmatched } as literal text to avoid dropping content
|
|
13
|
+
function strip_svelte_expressions(str) {
|
|
14
|
+
let result = ``;
|
|
15
|
+
let depth = 0;
|
|
16
|
+
for (const char of str) {
|
|
17
|
+
if (char === `{`)
|
|
18
|
+
depth++;
|
|
19
|
+
else if (char === `}` && depth > 0)
|
|
20
|
+
depth--;
|
|
21
|
+
else if (depth === 0)
|
|
22
|
+
result += char;
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
// Generate URL-friendly slug from text
|
|
27
|
+
const slugify = (text) => text
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(/\s+/g, `-`)
|
|
30
|
+
.replace(/[^\w-]/g, ``)
|
|
31
|
+
.replace(/-+/g, `-`) // collapse multiple dashes
|
|
32
|
+
.replace(/^-|-$/g, ``); // trim leading/trailing dashes
|
|
33
|
+
/** @type {() => import('svelte/compiler').PreprocessorGroup} */
|
|
34
|
+
export function heading_ids() {
|
|
35
|
+
return {
|
|
36
|
+
name: `heading-ids`,
|
|
37
|
+
markup({ content }) {
|
|
38
|
+
const seen_ids = new Map();
|
|
39
|
+
let result = content;
|
|
40
|
+
const process_heading = (attrs, inner) => {
|
|
41
|
+
// Skip if already has an id (use ^|\s to avoid matching data-id, aria-id, etc.)
|
|
42
|
+
if (/(^|\s)id\s*=/.test(attrs))
|
|
43
|
+
return null;
|
|
44
|
+
const text = strip_svelte_expressions(inner.replace(/<[^>]+>/g, ``)).trim();
|
|
45
|
+
if (!text)
|
|
46
|
+
return null;
|
|
47
|
+
const base_id = slugify(text);
|
|
48
|
+
if (!base_id)
|
|
49
|
+
return null;
|
|
50
|
+
// Handle duplicates within same file
|
|
51
|
+
const count = seen_ids.get(base_id) ?? 0;
|
|
52
|
+
seen_ids.set(base_id, count + 1);
|
|
53
|
+
return count ? `${base_id}-${count}` : base_id;
|
|
54
|
+
};
|
|
55
|
+
// Pass 1: Match headings at start of line (for .svelte files)
|
|
56
|
+
result = result.replace(heading_regex_line_start, (match, indent, tag, attrs, inner) => {
|
|
57
|
+
const id = process_heading(attrs, inner);
|
|
58
|
+
return id ? `${indent}<${tag} id="${id}"${attrs}>${inner}</${tag}>` : match;
|
|
59
|
+
});
|
|
60
|
+
// Pass 2: Match headings after closing tag (for mdsvex single-line output)
|
|
61
|
+
result = result.replace(heading_regex_after_tag, (match, gt, space, tag, attrs, inner) => {
|
|
62
|
+
const id = process_heading(attrs, inner);
|
|
63
|
+
return id ? `${gt}${space}<${tag} id="${id}"${attrs}>${inner}</${tag}>` : match;
|
|
64
|
+
});
|
|
65
|
+
return { code: result };
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// SVG link icon for heading anchors
|
|
70
|
+
const link_svg = `<svg width="16" height="16" viewBox="0 0 16 16" aria-label="Link to heading" role="img"><path d="M7.775 3.275a.75.75 0 0 0 1.06 1.06l1.25-1.25a2 2 0 1 1 2.83 2.83l-2.5 2.5a2 2 0 0 1-2.83 0 .75.75 0 0 0-1.06 1.06 3.5 3.5 0 0 0 4.95 0l2.5-2.5a3.5 3.5 0 0 0-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 0 1 0-2.83l2.5-2.5a2 2 0 0 1 2.83 0 .75.75 0 0 0 1.06-1.06 3.5 3.5 0 0 0-4.95 0l-2.5 2.5a3.5 3.5 0 0 0 4.95 4.95l1.25-1.25a.75.75 0 0 0-1.06-1.06l-1.25 1.25a2 2 0 0 1-2.83 0z" fill="currentColor"/></svg>`;
|
|
71
|
+
// Add anchor link to a single heading element
|
|
72
|
+
function add_anchor_to_heading(heading, icon_svg = link_svg) {
|
|
73
|
+
if (heading.querySelector(`a[aria-hidden="true"]`))
|
|
74
|
+
return;
|
|
75
|
+
if (!heading.id) {
|
|
76
|
+
// Generate ID from text content (fallback for dynamic headings)
|
|
77
|
+
const base_id = slugify((heading.textContent ?? ``).trim());
|
|
78
|
+
if (!base_id)
|
|
79
|
+
return;
|
|
80
|
+
// Ensure unique ID in document
|
|
81
|
+
let counter = 0;
|
|
82
|
+
while (document.getElementById(counter ? `${base_id}-${counter}` : base_id))
|
|
83
|
+
counter++;
|
|
84
|
+
heading.id = counter ? `${base_id}-${counter}` : base_id;
|
|
85
|
+
}
|
|
86
|
+
const anchor = document.createElement(`a`);
|
|
87
|
+
anchor.href = `#${heading.id}`;
|
|
88
|
+
anchor.setAttribute(`aria-hidden`, `true`);
|
|
89
|
+
anchor.innerHTML = icon_svg;
|
|
90
|
+
heading.appendChild(anchor);
|
|
91
|
+
}
|
|
92
|
+
// Svelte 5 attachment that adds anchor links to headings within a container
|
|
93
|
+
// Uses MutationObserver to handle dynamically added headings
|
|
94
|
+
export const heading_anchors = (options = {}) => (node) => {
|
|
95
|
+
if (typeof document === `undefined`)
|
|
96
|
+
return;
|
|
97
|
+
const selector = options.selector ?? `h2, h3, h4, h5, h6`;
|
|
98
|
+
const icon_svg = options.icon_svg ?? link_svg;
|
|
99
|
+
// Process existing headings
|
|
100
|
+
for (const heading of Array.from(node.querySelectorAll(selector))) {
|
|
101
|
+
add_anchor_to_heading(heading, icon_svg);
|
|
102
|
+
}
|
|
103
|
+
// Watch for new headings
|
|
104
|
+
const observer = new MutationObserver((mutations) => {
|
|
105
|
+
for (const { addedNodes } of mutations) {
|
|
106
|
+
for (const added of Array.from(addedNodes)) {
|
|
107
|
+
if (added.nodeType !== Node.ELEMENT_NODE)
|
|
108
|
+
continue;
|
|
109
|
+
const el = added;
|
|
110
|
+
if (el.matches?.(selector))
|
|
111
|
+
add_anchor_to_heading(el, icon_svg);
|
|
112
|
+
for (const hdn of Array.from(el.querySelectorAll(selector))) {
|
|
113
|
+
add_anchor_to_heading(hdn, icon_svg);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
observer.observe(node, { childList: true, subtree: true });
|
|
119
|
+
return () => observer.disconnect();
|
|
120
|
+
};
|
package/dist/icons.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export declare const icon_data: {
|
|
2
|
+
readonly Alert: {
|
|
3
|
+
readonly viewBox: "0 0 16 16";
|
|
4
|
+
readonly path: "M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z";
|
|
5
|
+
};
|
|
6
|
+
readonly Check: {
|
|
7
|
+
readonly viewBox: "0 0 12 16";
|
|
8
|
+
readonly path: "M12 5l-8 8l-4-4l1.5-1.5L4 10l6.5-6.5L12 5z";
|
|
9
|
+
};
|
|
10
|
+
readonly ChevronExpand: {
|
|
11
|
+
readonly viewBox: "0 0 16 16";
|
|
12
|
+
readonly path: "M3.646 9.146a.5.5 0 0 1 .708 0L8 12.793l3.646-3.647a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 0-.708zm0-2.292a.5.5 0 0 0 .708 0L8 3.207l3.646 3.647a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 0 0 0 .708z";
|
|
13
|
+
};
|
|
14
|
+
readonly ChevronRight: {
|
|
15
|
+
readonly viewBox: "0 0 16 16";
|
|
16
|
+
readonly path: "M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8L4.646 2.354a.5.5 0 0 1 0-.708z";
|
|
17
|
+
};
|
|
18
|
+
readonly ChevronDown: {
|
|
19
|
+
readonly viewBox: "0 0 16 16";
|
|
20
|
+
readonly path: "M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z";
|
|
21
|
+
};
|
|
22
|
+
readonly Collapse: {
|
|
23
|
+
readonly viewBox: "0 0 24 24";
|
|
24
|
+
readonly path: "M12 7.59L7.05 2.64L5.64 4.05L12 10.41l6.36-6.36l-1.41-1.41L12 7.59zM5.64 19.95l1.41 1.41L12 16.41l4.95 4.95l1.41-1.41L12 13.59l-6.36 6.36z";
|
|
25
|
+
};
|
|
26
|
+
readonly Copy: {
|
|
27
|
+
readonly viewBox: "0 0 16 16";
|
|
28
|
+
readonly path: "M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z";
|
|
29
|
+
};
|
|
30
|
+
readonly Cross: {
|
|
31
|
+
readonly viewBox: "0 0 24 24";
|
|
32
|
+
readonly path: "M18.3 5.71a.996.996 0 0 0-1.41 0L12 10.59L7.11 5.7A.996.996 0 1 0 5.7 7.11L10.59 12L5.7 16.89a.996.996 0 1 0 1.41 1.41L12 13.41l4.89 4.89a.996.996 0 1 0 1.41-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z";
|
|
33
|
+
};
|
|
34
|
+
readonly Disabled: {
|
|
35
|
+
readonly viewBox: "0 0 24 24";
|
|
36
|
+
readonly path: "M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2S2 6.477 2 12s4.477 10 10 10Zm-4.906-3.68L18.32 7.094A8 8 0 0 1 7.094 18.32ZM5.68 16.906A8 8 0 0 1 16.906 5.68L5.68 16.906Z";
|
|
37
|
+
};
|
|
38
|
+
readonly Expand: {
|
|
39
|
+
readonly viewBox: "0 0 24 24";
|
|
40
|
+
readonly path: "m12 19.24l-4.95-4.95l-1.41 1.42L12 22.07l6.36-6.36l-1.41-1.42L12 19.24zM5.64 8.29l1.41 1.42L12 4.76l4.95 4.95l1.41-1.42L12 1.93L5.64 8.29z";
|
|
41
|
+
};
|
|
42
|
+
readonly GitHub: {
|
|
43
|
+
readonly viewBox: "0 0 24 24";
|
|
44
|
+
readonly path: "M8.422 20.081c0 .896.01 1.753.016 2.285a.617.617 0 0 0 .422.58c2.078.686 4.317.718 6.414.091l.292-.087a.67.67 0 0 0 .478-.638c.005-.733.017-2.017.017-3.53c0-1.372-.477-2.25-1.031-2.707c3.399-.366 6.97-1.61 6.97-7.227c0-1.61-.592-2.91-1.566-3.934c.153-.366.688-1.866-.153-3.878c0 0-1.28-.403-4.201 1.5a14.76 14.76 0 0 0-3.82-.494c-1.298 0-2.597.165-3.819.494C5.52.65 4.24 1.036 4.24 1.036c-.84 2.012-.306 3.512-.153 3.878a5.565 5.565 0 0 0-1.566 3.934c0 5.598 3.552 6.86 6.951 7.227c-.439.366-.84 1.006-.973 1.957c-.879.384-3.075 1.006-4.45-1.207c-.286-.44-1.146-1.519-2.349-1.5c-1.28.018-.516.695.02.97c.648.347 1.393 1.646 1.565 2.067c.306.823 1.299 2.396 5.137 1.72Z";
|
|
45
|
+
};
|
|
46
|
+
readonly StackBlitz: {
|
|
47
|
+
readonly viewBox: "0 0 24 24";
|
|
48
|
+
readonly path: "M10.797 14.182H3.635L16.728 0l-3.525 9.818h7.162L7.272 24l3.524-9.818Z";
|
|
49
|
+
};
|
|
50
|
+
readonly Svelte: {
|
|
51
|
+
readonly viewBox: "0 0 24 24";
|
|
52
|
+
readonly path: "M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767a4.109 4.109 0 0 1-.703-3.107a3.898 3.898 0 0 1 .134-.522l.105-.321l.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063l-.02.208a1.253 1.253 0 0 0 .226.83a1.337 1.337 0 0 0 1.435.533a1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778a1.242 1.242 0 0 0-.211-.937a1.338 1.338 0 0 0-1.435-.533a1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499a4.44 4.44 0 0 1-4.765-1.766a4.108 4.108 0 0 1-.702-3.108a3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499a4.44 4.44 0 0 1 4.765 1.767a4.109 4.109 0 0 1 .703 3.107a3.943 3.943 0 0 1-.134.522l-.105.321l-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063l.02-.207a1.255 1.255 0 0 0-.226-.831a1.337 1.337 0 0 0-1.435-.532a1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778a1.24 1.24 0 0 0 .211.937a1.338 1.338 0 0 0 1.435.533a1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498a4.44 4.44 0 0 1 4.765 1.766a4.108 4.108 0 0 1 .702 3.108a3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295a6.753 6.753 0 0 0 .666 4.336a6.43 6.43 0 0 0-.96 2.396a6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295a6.756 6.756 0 0 0-.665-4.336a6.429 6.429 0 0 0 .958-2.396a6.831 6.831 0 0 0-1.167-5.168Z";
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
export type IconName = keyof typeof icon_data;
|
package/dist/icons.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const icon_data = {
|
|
2
|
+
Alert: {
|
|
3
|
+
viewBox: `0 0 16 16`,
|
|
4
|
+
path: `M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z`,
|
|
5
|
+
},
|
|
6
|
+
Check: {
|
|
7
|
+
viewBox: `0 0 12 16`,
|
|
8
|
+
path: `M12 5l-8 8l-4-4l1.5-1.5L4 10l6.5-6.5L12 5z`,
|
|
9
|
+
},
|
|
10
|
+
ChevronExpand: {
|
|
11
|
+
viewBox: `0 0 16 16`,
|
|
12
|
+
path: `M3.646 9.146a.5.5 0 0 1 .708 0L8 12.793l3.646-3.647a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 0-.708zm0-2.292a.5.5 0 0 0 .708 0L8 3.207l3.646 3.647a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 0 0 0 .708z`,
|
|
13
|
+
},
|
|
14
|
+
ChevronRight: {
|
|
15
|
+
viewBox: `0 0 16 16`,
|
|
16
|
+
path: `M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8L4.646 2.354a.5.5 0 0 1 0-.708z`,
|
|
17
|
+
},
|
|
18
|
+
ChevronDown: {
|
|
19
|
+
viewBox: `0 0 16 16`,
|
|
20
|
+
path: `M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z`,
|
|
21
|
+
},
|
|
22
|
+
Collapse: {
|
|
23
|
+
viewBox: `0 0 24 24`,
|
|
24
|
+
path: `M12 7.59L7.05 2.64L5.64 4.05L12 10.41l6.36-6.36l-1.41-1.41L12 7.59zM5.64 19.95l1.41 1.41L12 16.41l4.95 4.95l1.41-1.41L12 13.59l-6.36 6.36z`,
|
|
25
|
+
},
|
|
26
|
+
Copy: {
|
|
27
|
+
viewBox: `0 0 16 16`,
|
|
28
|
+
path: `M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z`,
|
|
29
|
+
},
|
|
30
|
+
Cross: {
|
|
31
|
+
viewBox: `0 0 24 24`,
|
|
32
|
+
path: `M18.3 5.71a.996.996 0 0 0-1.41 0L12 10.59L7.11 5.7A.996.996 0 1 0 5.7 7.11L10.59 12L5.7 16.89a.996.996 0 1 0 1.41 1.41L12 13.41l4.89 4.89a.996.996 0 1 0 1.41-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z`,
|
|
33
|
+
},
|
|
34
|
+
Disabled: {
|
|
35
|
+
viewBox: `0 0 24 24`,
|
|
36
|
+
path: `M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2S2 6.477 2 12s4.477 10 10 10Zm-4.906-3.68L18.32 7.094A8 8 0 0 1 7.094 18.32ZM5.68 16.906A8 8 0 0 1 16.906 5.68L5.68 16.906Z`,
|
|
37
|
+
},
|
|
38
|
+
Expand: {
|
|
39
|
+
viewBox: `0 0 24 24`,
|
|
40
|
+
path: `m12 19.24l-4.95-4.95l-1.41 1.42L12 22.07l6.36-6.36l-1.41-1.42L12 19.24zM5.64 8.29l1.41 1.42L12 4.76l4.95 4.95l1.41-1.42L12 1.93L5.64 8.29z`,
|
|
41
|
+
},
|
|
42
|
+
GitHub: {
|
|
43
|
+
viewBox: `0 0 24 24`,
|
|
44
|
+
path: `M8.422 20.081c0 .896.01 1.753.016 2.285a.617.617 0 0 0 .422.58c2.078.686 4.317.718 6.414.091l.292-.087a.67.67 0 0 0 .478-.638c.005-.733.017-2.017.017-3.53c0-1.372-.477-2.25-1.031-2.707c3.399-.366 6.97-1.61 6.97-7.227c0-1.61-.592-2.91-1.566-3.934c.153-.366.688-1.866-.153-3.878c0 0-1.28-.403-4.201 1.5a14.76 14.76 0 0 0-3.82-.494c-1.298 0-2.597.165-3.819.494C5.52.65 4.24 1.036 4.24 1.036c-.84 2.012-.306 3.512-.153 3.878a5.565 5.565 0 0 0-1.566 3.934c0 5.598 3.552 6.86 6.951 7.227c-.439.366-.84 1.006-.973 1.957c-.879.384-3.075 1.006-4.45-1.207c-.286-.44-1.146-1.519-2.349-1.5c-1.28.018-.516.695.02.97c.648.347 1.393 1.646 1.565 2.067c.306.823 1.299 2.396 5.137 1.72Z`,
|
|
45
|
+
},
|
|
46
|
+
StackBlitz: {
|
|
47
|
+
viewBox: `0 0 24 24`,
|
|
48
|
+
path: `M10.797 14.182H3.635L16.728 0l-3.525 9.818h7.162L7.272 24l3.524-9.818Z`,
|
|
49
|
+
},
|
|
50
|
+
Svelte: {
|
|
51
|
+
viewBox: `0 0 24 24`,
|
|
52
|
+
path: `M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767a4.109 4.109 0 0 1-.703-3.107a3.898 3.898 0 0 1 .134-.522l.105-.321l.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063l-.02.208a1.253 1.253 0 0 0 .226.83a1.337 1.337 0 0 0 1.435.533a1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778a1.242 1.242 0 0 0-.211-.937a1.338 1.338 0 0 0-1.435-.533a1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499a4.44 4.44 0 0 1-4.765-1.766a4.108 4.108 0 0 1-.702-3.108a3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499a4.44 4.44 0 0 1 4.765 1.767a4.109 4.109 0 0 1 .703 3.107a3.943 3.943 0 0 1-.134.522l-.105.321l-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063l.02-.207a1.255 1.255 0 0 0-.226-.831a1.337 1.337 0 0 0-1.435-.532a1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778a1.24 1.24 0 0 0 .211.937a1.338 1.338 0 0 0 1.435.533a1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498a4.44 4.44 0 0 1 4.765 1.766a4.108 4.108 0 0 1 .702 3.108a3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295a6.753 6.753 0 0 0 .666 4.336a6.43 6.43 0 0 0-.96 2.396a6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295a6.756 6.756 0 0 0-.665-4.336a6.429 6.429 0 0 0 .958-2.396a6.831 6.831 0 0 0-1.167-5.168Z`,
|
|
53
|
+
},
|
|
54
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './attachments';
|
|
2
|
+
export * from './heading-anchors';
|
|
3
|
+
export { default as CircleSpinner } from './CircleSpinner.svelte';
|
|
4
|
+
export { default as CmdPalette } from './CmdPalette.svelte';
|
|
5
|
+
export { default as CodeExample } from './CodeExample.svelte';
|
|
6
|
+
export { default as CopyButton } from './CopyButton.svelte';
|
|
7
|
+
export { default as FileDetails } from './FileDetails.svelte';
|
|
8
|
+
export { default as GitHubCorner } from './GitHubCorner.svelte';
|
|
9
|
+
export { default as Icon } from './Icon.svelte';
|
|
10
|
+
export { default, default as MultiSelect } from './MultiSelect.svelte';
|
|
11
|
+
export { default as Nav } from './Nav.svelte';
|
|
12
|
+
export { default as PrevNext } from './PrevNext.svelte';
|
|
13
|
+
export { default as Toggle } from './Toggle.svelte';
|
|
14
|
+
export * from './types';
|
|
15
|
+
export * from './utils';
|
|
16
|
+
export { default as Wiggle } from './Wiggle.svelte';
|
|
17
|
+
export declare function scroll_into_view_if_needed_polyfill(element: Element, centerIfNeeded?: boolean): IntersectionObserver;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export * from './attachments';
|
|
2
|
+
export * from './heading-anchors';
|
|
3
|
+
export { default as CircleSpinner } from './CircleSpinner.svelte';
|
|
4
|
+
export { default as CmdPalette } from './CmdPalette.svelte';
|
|
5
|
+
export { default as CodeExample } from './CodeExample.svelte';
|
|
6
|
+
export { default as CopyButton } from './CopyButton.svelte';
|
|
7
|
+
export { default as FileDetails } from './FileDetails.svelte';
|
|
8
|
+
export { default as GitHubCorner } from './GitHubCorner.svelte';
|
|
9
|
+
export { default as Icon } from './Icon.svelte';
|
|
10
|
+
export { default, default as MultiSelect } from './MultiSelect.svelte';
|
|
11
|
+
export { default as Nav } from './Nav.svelte';
|
|
12
|
+
export { default as PrevNext } from './PrevNext.svelte';
|
|
13
|
+
export { default as Toggle } from './Toggle.svelte';
|
|
14
|
+
export * from './types';
|
|
15
|
+
export * from './utils';
|
|
16
|
+
export { default as Wiggle } from './Wiggle.svelte';
|
|
17
|
+
// Firefox lacks support for scrollIntoViewIfNeeded (https://caniuse.com/scrollintoviewifneeded).
|
|
18
|
+
// See https://github.com/janosh/svelte-multiselect/issues/87
|
|
19
|
+
// Polyfill copied from
|
|
20
|
+
// https://github.com/nuxodin/lazyfill/blob/a8e63/polyfills/Element/prototype/scrollIntoViewIfNeeded.js
|
|
21
|
+
// exported for testing
|
|
22
|
+
export function scroll_into_view_if_needed_polyfill(element, centerIfNeeded = true) {
|
|
23
|
+
const observer = new IntersectionObserver(([entry], obs) => {
|
|
24
|
+
const ratio = entry.intersectionRatio;
|
|
25
|
+
if (ratio < 1) {
|
|
26
|
+
const place = ratio <= 0 && centerIfNeeded ? `center` : `nearest`;
|
|
27
|
+
element.scrollIntoView({
|
|
28
|
+
block: place,
|
|
29
|
+
inline: place,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
obs.disconnect();
|
|
33
|
+
});
|
|
34
|
+
observer.observe(element);
|
|
35
|
+
return observer; // return for testing
|
|
36
|
+
}
|
|
37
|
+
if (typeof Element !== `undefined` &&
|
|
38
|
+
!Element.prototype?.scrollIntoViewIfNeeded &&
|
|
39
|
+
typeof IntersectionObserver !== `undefined`) {
|
|
40
|
+
Element.prototype.scrollIntoViewIfNeeded = function scrollIntoViewIfNeeded() {
|
|
41
|
+
scroll_into_view_if_needed_polyfill(this);
|
|
42
|
+
};
|
|
43
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { FlipParams } from 'svelte/animate';
|
|
3
|
+
import type { HTMLAttributes, HTMLInputAttributes } from 'svelte/elements';
|
|
4
|
+
export type Option = string | number | ObjectOption;
|
|
5
|
+
export type OptionStyle = string | {
|
|
6
|
+
option: string;
|
|
7
|
+
selected: string;
|
|
8
|
+
};
|
|
9
|
+
export type ObjectOption = {
|
|
10
|
+
label: string | number;
|
|
11
|
+
value?: unknown;
|
|
12
|
+
title?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
preselected?: boolean;
|
|
15
|
+
disabledTitle?: string;
|
|
16
|
+
selectedTitle?: string;
|
|
17
|
+
style?: OptionStyle;
|
|
18
|
+
group?: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
export type PlaceholderConfig = {
|
|
22
|
+
text: string;
|
|
23
|
+
persistent?: boolean;
|
|
24
|
+
};
|
|
25
|
+
export interface MultiSelectEvents<T extends Option = Option> {
|
|
26
|
+
onadd?: (data: {
|
|
27
|
+
option: T;
|
|
28
|
+
}) => unknown;
|
|
29
|
+
oncreate?: (data: {
|
|
30
|
+
option: T;
|
|
31
|
+
}) => unknown;
|
|
32
|
+
onremove?: (data: {
|
|
33
|
+
option: T;
|
|
34
|
+
}) => unknown;
|
|
35
|
+
onremoveAll?: (data: {
|
|
36
|
+
options: T[];
|
|
37
|
+
}) => unknown;
|
|
38
|
+
onselectAll?: (data: {
|
|
39
|
+
options: T[];
|
|
40
|
+
}) => unknown;
|
|
41
|
+
onreorder?: (data: {
|
|
42
|
+
options: T[];
|
|
43
|
+
}) => unknown;
|
|
44
|
+
onchange?: (data: {
|
|
45
|
+
option?: T;
|
|
46
|
+
options?: T[];
|
|
47
|
+
type: `add` | `remove` | `removeAll` | `selectAll` | `reorder`;
|
|
48
|
+
}) => unknown;
|
|
49
|
+
onopen?: (data: {
|
|
50
|
+
event: Event;
|
|
51
|
+
}) => unknown;
|
|
52
|
+
onclose?: (data: {
|
|
53
|
+
event: Event;
|
|
54
|
+
}) => unknown;
|
|
55
|
+
ongroupToggle?: (data: {
|
|
56
|
+
group: string;
|
|
57
|
+
collapsed: boolean;
|
|
58
|
+
}) => unknown;
|
|
59
|
+
oncollapseAll?: (data: {
|
|
60
|
+
groups: string[];
|
|
61
|
+
}) => unknown;
|
|
62
|
+
onexpandAll?: (data: {
|
|
63
|
+
groups: string[];
|
|
64
|
+
}) => unknown;
|
|
65
|
+
onsearch?: (data: {
|
|
66
|
+
searchText: string;
|
|
67
|
+
matchingCount: number;
|
|
68
|
+
}) => unknown;
|
|
69
|
+
onmaxreached?: (data: {
|
|
70
|
+
selected: T[];
|
|
71
|
+
maxSelect: number;
|
|
72
|
+
attemptedOption: T;
|
|
73
|
+
}) => unknown;
|
|
74
|
+
onduplicate?: (data: {
|
|
75
|
+
option: T;
|
|
76
|
+
}) => unknown;
|
|
77
|
+
onactivate?: (data: {
|
|
78
|
+
option: T | null;
|
|
79
|
+
index: number | null;
|
|
80
|
+
}) => unknown;
|
|
81
|
+
}
|
|
82
|
+
export interface LoadOptionsParams {
|
|
83
|
+
search: string;
|
|
84
|
+
offset: number;
|
|
85
|
+
limit: number;
|
|
86
|
+
}
|
|
87
|
+
export interface LoadOptionsResult<T extends Option = Option> {
|
|
88
|
+
options: T[];
|
|
89
|
+
hasMore: boolean;
|
|
90
|
+
}
|
|
91
|
+
export type LoadOptionsFn<T extends Option = Option> = (params: LoadOptionsParams) => Promise<LoadOptionsResult<T>>;
|
|
92
|
+
export interface LoadOptionsConfig<T extends Option = Option> {
|
|
93
|
+
fetch: LoadOptionsFn<T>;
|
|
94
|
+
debounceMs?: number;
|
|
95
|
+
batchSize?: number;
|
|
96
|
+
onOpen?: boolean;
|
|
97
|
+
}
|
|
98
|
+
export type LoadOptions<T extends Option = Option> = LoadOptionsFn<T> | LoadOptionsConfig<T>;
|
|
99
|
+
type AfterInputProps = Pick<MultiSelectProps, `selected` | `disabled` | `invalid` | `id` | `placeholder` | `open` | `required`>;
|
|
100
|
+
type UserMsgProps = {
|
|
101
|
+
searchText: string;
|
|
102
|
+
msgType: false | `dupe` | `create` | `no-match`;
|
|
103
|
+
msg: null | string;
|
|
104
|
+
};
|
|
105
|
+
export type GroupHeaderProps<T extends Option = Option> = {
|
|
106
|
+
group: string;
|
|
107
|
+
options: T[];
|
|
108
|
+
collapsed: boolean;
|
|
109
|
+
};
|
|
110
|
+
export type GroupedOptions<T extends Option = Option> = {
|
|
111
|
+
group: string | null;
|
|
112
|
+
options: T[];
|
|
113
|
+
collapsed: boolean;
|
|
114
|
+
};
|
|
115
|
+
export interface MultiSelectSnippets<T extends Option = Option> {
|
|
116
|
+
expandIcon?: Snippet<[{
|
|
117
|
+
open: boolean;
|
|
118
|
+
}]>;
|
|
119
|
+
selectedItem?: Snippet<[{
|
|
120
|
+
option: T;
|
|
121
|
+
idx: number;
|
|
122
|
+
}]>;
|
|
123
|
+
children?: Snippet<[{
|
|
124
|
+
option: T;
|
|
125
|
+
idx: number;
|
|
126
|
+
}]>;
|
|
127
|
+
removeIcon?: Snippet;
|
|
128
|
+
afterInput?: Snippet<[AfterInputProps]>;
|
|
129
|
+
spinner?: Snippet;
|
|
130
|
+
disabledIcon?: Snippet;
|
|
131
|
+
option?: Snippet<[{
|
|
132
|
+
option: T;
|
|
133
|
+
idx: number;
|
|
134
|
+
}]>;
|
|
135
|
+
userMsg?: Snippet<[UserMsgProps]>;
|
|
136
|
+
groupHeader?: Snippet<[GroupHeaderProps<T>]>;
|
|
137
|
+
}
|
|
138
|
+
export interface PortalParams {
|
|
139
|
+
target_node?: HTMLElement | null;
|
|
140
|
+
active?: boolean;
|
|
141
|
+
}
|
|
142
|
+
export interface MultiSelectProps<T extends Option = Option> extends MultiSelectEvents<T>, MultiSelectSnippets<T>, Omit<HTMLAttributes<HTMLDivElement>, `children` | `onchange` | `onclose` | `placeholder`> {
|
|
143
|
+
activeIndex?: number | null;
|
|
144
|
+
activeOption?: T | null;
|
|
145
|
+
createOptionMsg?: string | null;
|
|
146
|
+
allowUserOptions?: boolean | `append`;
|
|
147
|
+
allowEmpty?: boolean;
|
|
148
|
+
autocomplete?: HTMLInputAttributes[`autocomplete`];
|
|
149
|
+
autoScroll?: boolean;
|
|
150
|
+
breakpoint?: number;
|
|
151
|
+
defaultDisabledTitle?: string;
|
|
152
|
+
disabled?: boolean;
|
|
153
|
+
disabledInputTitle?: string;
|
|
154
|
+
duplicateOptionMsg?: string;
|
|
155
|
+
duplicates?: boolean;
|
|
156
|
+
keepSelectedInDropdown?: false | `plain` | `checkboxes`;
|
|
157
|
+
key?: (opt: T) => unknown;
|
|
158
|
+
filterFunc?: (opt: T, searchText: string) => boolean;
|
|
159
|
+
fuzzy?: boolean;
|
|
160
|
+
closeDropdownOnSelect?: boolean | `if-mobile` | `retain-focus`;
|
|
161
|
+
form_input?: HTMLInputElement | null;
|
|
162
|
+
highlightMatches?: boolean;
|
|
163
|
+
id?: string | null;
|
|
164
|
+
input?: HTMLInputElement | null;
|
|
165
|
+
inputClass?: string;
|
|
166
|
+
inputStyle?: string | null;
|
|
167
|
+
inputmode?: HTMLInputAttributes[`inputmode`] | null;
|
|
168
|
+
invalid?: boolean;
|
|
169
|
+
liActiveOptionClass?: string;
|
|
170
|
+
liActiveUserMsgClass?: string;
|
|
171
|
+
liOptionClass?: string;
|
|
172
|
+
liOptionStyle?: string | null;
|
|
173
|
+
liSelectedClass?: string;
|
|
174
|
+
liSelectedStyle?: string | null;
|
|
175
|
+
liUserMsgClass?: string;
|
|
176
|
+
loading?: boolean;
|
|
177
|
+
matchingOptions?: T[];
|
|
178
|
+
maxOptions?: number | undefined;
|
|
179
|
+
maxSelect?: number | null;
|
|
180
|
+
maxSelectMsg?: ((current: number, max: number) => string) | null;
|
|
181
|
+
maxSelectMsgClass?: string;
|
|
182
|
+
name?: string | null;
|
|
183
|
+
noMatchingOptionsMsg?: string;
|
|
184
|
+
open?: boolean;
|
|
185
|
+
options?: T[];
|
|
186
|
+
outerDiv?: HTMLDivElement | null;
|
|
187
|
+
outerDivClass?: string;
|
|
188
|
+
parseLabelsAsHtml?: boolean;
|
|
189
|
+
pattern?: string | null;
|
|
190
|
+
placeholder?: string | PlaceholderConfig | null;
|
|
191
|
+
removeAllTitle?: string;
|
|
192
|
+
removeBtnTitle?: string;
|
|
193
|
+
minSelect?: number | null;
|
|
194
|
+
required?: boolean | number;
|
|
195
|
+
resetFilterOnAdd?: boolean;
|
|
196
|
+
searchText?: string;
|
|
197
|
+
selected?: T[];
|
|
198
|
+
sortSelected?: boolean | ((op1: T, op2: T) => number);
|
|
199
|
+
selectedOptionsDraggable?: boolean;
|
|
200
|
+
style?: string | null;
|
|
201
|
+
ulOptionsClass?: string;
|
|
202
|
+
ulSelectedClass?: string;
|
|
203
|
+
ulSelectedStyle?: string | null;
|
|
204
|
+
ulOptionsStyle?: string | null;
|
|
205
|
+
value?: T | T[] | null;
|
|
206
|
+
portal?: PortalParams;
|
|
207
|
+
selectAllOption?: boolean | string;
|
|
208
|
+
liSelectAllClass?: string;
|
|
209
|
+
loadOptions?: LoadOptions<T>;
|
|
210
|
+
selectedFlipParams?: FlipParams;
|
|
211
|
+
collapsibleGroups?: boolean;
|
|
212
|
+
collapsedGroups?: Set<string>;
|
|
213
|
+
groupSelectAll?: boolean;
|
|
214
|
+
ungroupedPosition?: `first` | `last`;
|
|
215
|
+
groupSortOrder?: `none` | `asc` | `desc` | ((a: string, b: string) => number);
|
|
216
|
+
searchExpandsCollapsedGroups?: boolean;
|
|
217
|
+
searchMatchesGroups?: boolean;
|
|
218
|
+
keyboardExpandsCollapsedGroups?: boolean;
|
|
219
|
+
stickyGroupHeaders?: boolean;
|
|
220
|
+
liGroupHeaderClass?: string;
|
|
221
|
+
liGroupHeaderStyle?: string | null;
|
|
222
|
+
collapseAllGroups?: () => void;
|
|
223
|
+
expandAllGroups?: () => void;
|
|
224
|
+
shortcuts?: Partial<KeyboardShortcuts>;
|
|
225
|
+
}
|
|
226
|
+
export interface KeyboardShortcuts {
|
|
227
|
+
select_all?: string | null;
|
|
228
|
+
clear_all?: string | null;
|
|
229
|
+
open?: string | null;
|
|
230
|
+
close?: string | null;
|
|
231
|
+
}
|
|
232
|
+
export interface NavRouteObject {
|
|
233
|
+
href: string;
|
|
234
|
+
label?: string;
|
|
235
|
+
children?: string[];
|
|
236
|
+
disabled?: boolean | string;
|
|
237
|
+
separator?: boolean;
|
|
238
|
+
align?: `left` | `right`;
|
|
239
|
+
external?: boolean;
|
|
240
|
+
tooltip?: string;
|
|
241
|
+
class?: string;
|
|
242
|
+
style?: string;
|
|
243
|
+
[key: string]: unknown;
|
|
244
|
+
}
|
|
245
|
+
export type NavRoute = string | [string, string] | [string, string[]] | NavRouteObject;
|
|
246
|
+
export {};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Option } from './types';
|
|
2
|
+
export declare const is_object: (val: unknown) => val is Record<string, unknown>;
|
|
3
|
+
export declare const has_group: <T extends Option>(opt: T) => opt is T & {
|
|
4
|
+
group: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const get_label: (opt: Option) => string | number;
|
|
7
|
+
export declare function get_style(option: Option, key?: `selected` | `option` | null | undefined): string;
|
|
8
|
+
export declare function fuzzy_match(search_text: string, target_text: string): boolean;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Type guard for checking if a value is a non-null object
|
|
2
|
+
export const is_object = (val) => typeof val === `object` && val !== null;
|
|
3
|
+
// Type guard for checking if an option has a group key
|
|
4
|
+
export const has_group = (opt) => is_object(opt) && typeof opt.group === `string`;
|
|
5
|
+
// Get the label key from an option object or the option itself
|
|
6
|
+
// if it's a string or number
|
|
7
|
+
export const get_label = (opt) => {
|
|
8
|
+
if (is_object(opt)) {
|
|
9
|
+
if (opt.label === undefined) {
|
|
10
|
+
const opt_str = JSON.stringify(opt);
|
|
11
|
+
console.error(`MultiSelect: option is an object but has no label key`, opt_str);
|
|
12
|
+
}
|
|
13
|
+
return opt.label;
|
|
14
|
+
}
|
|
15
|
+
return `${opt}`;
|
|
16
|
+
};
|
|
17
|
+
// This function is used extract CSS strings from a {selected, option} style
|
|
18
|
+
// object to be used in the style attribute of the option.
|
|
19
|
+
// If the style is a string, it will be returned as is
|
|
20
|
+
export function get_style(option, key = null) {
|
|
21
|
+
if (key === undefined)
|
|
22
|
+
key = null;
|
|
23
|
+
let css_str = ``;
|
|
24
|
+
const valid_key = key === null || key === `selected` || key === `option`;
|
|
25
|
+
if (!valid_key)
|
|
26
|
+
console.error(`MultiSelect: Invalid key=${key} for get_style`);
|
|
27
|
+
if (typeof option === `object` && option.style) {
|
|
28
|
+
if (typeof option.style === `string`)
|
|
29
|
+
css_str = option.style;
|
|
30
|
+
if (typeof option.style === `object`) {
|
|
31
|
+
if (key && key in option.style)
|
|
32
|
+
return option.style[key] ?? ``;
|
|
33
|
+
else {
|
|
34
|
+
console.error(`MultiSelect: invalid style object for option`, option);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// ensure css_str ends with a semicolon
|
|
39
|
+
if (css_str.trim() && !css_str.trim().endsWith(`;`))
|
|
40
|
+
css_str += `;`;
|
|
41
|
+
return css_str;
|
|
42
|
+
}
|
|
43
|
+
// Fuzzy string matching function
|
|
44
|
+
// Returns true if the search string can be found as a subsequence in the target string
|
|
45
|
+
// e.g., "tageoo" matches "tasks/geo-opt" because t-a-g-e-o-o appears in order
|
|
46
|
+
export function fuzzy_match(search_text, target_text) {
|
|
47
|
+
// Handle null/undefined inputs first
|
|
48
|
+
if (search_text === null || search_text === undefined || target_text === null ||
|
|
49
|
+
target_text === undefined)
|
|
50
|
+
return false;
|
|
51
|
+
if (!search_text)
|
|
52
|
+
return true;
|
|
53
|
+
if (!target_text)
|
|
54
|
+
return false;
|
|
55
|
+
const [search, target] = [search_text.toLowerCase(), target_text.toLowerCase()];
|
|
56
|
+
let [search_idx, target_idx] = [0, 0];
|
|
57
|
+
while (search_idx < search.length && target_idx < target.length) {
|
|
58
|
+
if (search[search_idx] === target[target_idx])
|
|
59
|
+
search_idx++;
|
|
60
|
+
target_idx++;
|
|
61
|
+
}
|
|
62
|
+
return search_idx === search.length;
|
|
63
|
+
}
|