+ {#if titleText && !hideLabel}
{/if}
- {#if invalid}
-
- {/if}
- {#if !invalid && warn}
-
- {/if}
-
+ >
+ {
+ if (key === 'Enter') {
+ open = !open;
+
+ if (
+ highlightedIndex > -1 &&
+ filteredItems[highlightedIndex]?.id !== selectedId
+ ) {
+ open = false;
+ if (filteredItems[highlightedIndex]) {
+ inputValue = filteredItems[highlightedIndex].text;
+ selectedItem = filteredItems[highlightedIndex];
+ selectedId = filteredItems[highlightedIndex].id;
+ }
+ } else {
+ open = false;
+ if (filteredItems[0]) {
+ inputValue = filteredItems[0].text;
+ selectedItem = filteredItems[0];
+ selectedId = filteredItems[0].id;
+ }
+ }
+ highlightedIndex = -1;
+ } else if (key === 'Tab') {
+ open = false;
+ } else if (key === 'ArrowDown') {
+ change(1);
+ } else if (key === 'ArrowUp') {
+ change(-1);
+ } else if (key === 'Escape') {
+ open = false;
+ }
+ }}"
+ on:keyup
+ on:focus
+ on:blur
+ on:blur="{({ relatedTarget }) => {
+ if (!open || !relatedTarget) return;
+ if (
+ relatedTarget &&
+ !['INPUT', 'SELECT', 'TEXTAREA'].includes(relatedTarget.tagName) &&
+ relatedTarget.getAttribute('role') !== 'button' &&
+ relatedTarget.getAttribute('role') !== 'searchbox'
+ ) {
+ ref.focus();
+ }
+ }}"
+ />
+ {#if invalid}
+
+ {/if}
+ {#if !invalid && warn}
+
+ {/if}
+ {#if inputValue}
+
+ {/if}
+
+
{#if open}
-
+
{#each filteredItems as item, i (item.id)}
{itemToString(item)}
+ {#if selectedItem && selectedItem.id === item.id}
+
+ {/if}
{/each}
{/if}
- {#if !inline && !invalid && !warn && helperText}
+ {#if !invalid && helperText && !warn}
{/if}
-
-
diff --git a/src/Editor/Editor.svelte b/src/Editor/Editor.svelte
new file mode 100644
index 00000000..1ab22c10
--- /dev/null
+++ b/src/Editor/Editor.svelte
@@ -0,0 +1,114 @@
+
+
+{#if titleText}
+
+{/if}
+{#if disabled}
+ {@html html}
+{:else}
+
+{/if}
+{#if invalid}
+
{invalidText}
+{/if}
+{#if !invalid && warn}
+
{warnText}
+{/if}
+{#if !invalid && !warn && helperText}
+
+ {helperText}
+
+{/if}
+
{invalidText}
+
+
diff --git a/src/Editor/EditorSkeleton.svelte b/src/Editor/EditorSkeleton.svelte
new file mode 100644
index 00000000..76588c07
--- /dev/null
+++ b/src/Editor/EditorSkeleton.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+ {#if !hideLabel}
+
+ {/if}
+
+
diff --git a/src/Editor/index.js b/src/Editor/index.js
new file mode 100644
index 00000000..4b448254
--- /dev/null
+++ b/src/Editor/index.js
@@ -0,0 +1,3 @@
+export { default as Editor } from "./Editor.svelte";
+export { default as EditorSkeleton } from "./EditorSkeleton.svelte";
+export { quill } from "./quill";
diff --git a/src/Editor/quill.js b/src/Editor/quill.js
new file mode 100644
index 00000000..140a84c6
--- /dev/null
+++ b/src/Editor/quill.js
@@ -0,0 +1,32 @@
+// https://github.com/lagden/svelte-editor-quill
+
+import Quill from "quill";
+
+export function quill(node, params) {
+ const quill = new Quill(node, {
+ ...params.options,
+ });
+
+ if (params.html) {
+ const delta = quill.clipboard.convert(params.html);
+ quill.setContents(delta, "silent");
+ }
+
+ const onTextChange = () => {
+ const customEvent = new CustomEvent("text-change", {
+ detail: {
+ html: quill.root.innerHTML,
+ text: quill.getText(),
+ },
+ });
+ node.dispatchEvent(customEvent);
+ };
+
+ quill.on("text-change", onTextChange);
+
+ return {
+ destroy() {
+ quill.off("text-change", onTextChange);
+ },
+ };
+}
diff --git a/types/AutoComplete/AutoComplete.svelte.d.ts b/types/AutoComplete/AutoComplete.svelte.d.ts
index c1a147fc..48e70934 100644
--- a/types/AutoComplete/AutoComplete.svelte.d.ts
+++ b/types/AutoComplete/AutoComplete.svelte.d.ts
@@ -11,13 +11,7 @@ export interface AutoCompleteItem {
}
export interface AutoCompleteProps
- extends svelte.JSX.HTMLAttributes
{
- /**
- * Set the full list of items
- * @default []
- */
- items?: AutoCompleteItem[];
-
+ extends svelte.JSX.HTMLAttributes {
/**
* Override the display of a dropdown item
* @default (item) => item.text || item.id
@@ -37,10 +31,10 @@ export interface AutoCompleteProps
selectedItem?: AutoCompleteItem;
/**
- * Specify the type of dropdown
- * @default "default"
+ * Determine if an item should be filtered given the current combobox value
+ * @default () => []
*/
- type?: "default" | "inline";
+ shouldFilterItem?: (value: string) => AutoCompleteItem[];
/**
* Specify the direction of the dropdown menu
@@ -60,12 +54,6 @@ export interface AutoCompleteProps
*/
open?: boolean;
- /**
- * Set to `true` to use the inline variant
- * @default false
- */
- inline?: boolean;
-
/**
* Set to `true` to enable the light variant
* @default false
@@ -149,6 +137,12 @@ export interface AutoCompleteProps
* @default null
*/
placeholder?: undefined;
+
+ /**
+ * Obtain a reference to the list HTML element
+ * @default null
+ */
+ listRef?: null | HTMLDivElement;
}
export default class AutoComplete extends SvelteComponentTyped<
@@ -158,11 +152,17 @@ export default class AutoComplete extends SvelteComponentTyped<
selectedId: AutoCompleteItemId;
selectedItem: AutoCompleteItem;
}>;
- change: WindowEventMap["change"];
+ keydown: WindowEventMap["keydown"];
+ keyup: WindowEventMap["keyup"];
focus: WindowEventMap["focus"];
blur: WindowEventMap["blur"];
- input: WindowEventMap["input"];
- clear: CustomEvent;
+ clear: WindowEventMap["clear"];
+ scroll: WindowEventMap["scroll"];
},
{ default: { item: AutoCompleteItem; index: number } }
-> {}
+> {
+ /**
+ * Clear the combo box programmatically
+ */
+ clear: (options?: { focus?: boolean }) => void;
+}
diff --git a/types/Editor/Editor.svelte.d.ts b/types/Editor/Editor.svelte.d.ts
new file mode 100644
index 00000000..3852fd79
--- /dev/null
+++ b/types/Editor/Editor.svelte.d.ts
@@ -0,0 +1,83 @@
+///
+import type { SvelteComponentTyped } from "svelte";
+
+export interface EditorProps {
+ /**
+ * Set to `true` to disable the dropdown
+ * @default false
+ */
+ disabled?: boolean;
+
+ /**
+ * Specify the title text
+ * @default ""
+ */
+ titleText?: string;
+
+ /**
+ * Set to `true` to indicate an invalid state
+ * @default false
+ */
+ invalid?: boolean;
+
+ /**
+ * Specify the invalid state text
+ * @default ""
+ */
+ invalidText?: string;
+
+ /**
+ * Set to `true` to indicate an warning state
+ * @default false
+ */
+ warn?: boolean;
+
+ /**
+ * Specify the warning state text
+ * @default ""
+ */
+ warnText?: string;
+
+ /**
+ * Specify the helper text
+ * @default ""
+ */
+ helperText?: string;
+
+ /**
+ * Set to `true` to visually hide the label text
+ * @default false
+ */
+ hideLabel?: boolean;
+
+ /**
+ * Set an id for the list box component
+ * @default "ccs-" + Math.random().toString(36)
+ */
+ id?: string;
+
+ /**
+ * Specify the placeholder text
+ * @default null
+ */
+ placeholder?: undefined;
+
+ /**
+ * Specify the html
+ * @default undefined
+ */
+ html?: string;
+
+ /**
+ * Specify the text
+ * @default undefined
+ */
+ text?: string;
+
+ /**
+ * @default { modules: { toolbar }, theme: 'snow', placeholder }
+ */
+ options?: { modules: { toolbar }; theme: "snow"; placeholder };
+}
+
+export default class Editor extends SvelteComponentTyped {}
diff --git a/types/Editor/EditorSkeleton.svelte.d.ts b/types/Editor/EditorSkeleton.svelte.d.ts
new file mode 100644
index 00000000..692f83ff
--- /dev/null
+++ b/types/Editor/EditorSkeleton.svelte.d.ts
@@ -0,0 +1,22 @@
+///
+import type { SvelteComponentTyped } from "svelte";
+
+export interface EditorSkeletonProps
+ extends svelte.JSX.HTMLAttributes {
+ /**
+ * Set to `true` to hide the label text
+ * @default false
+ */
+ hideLabel?: boolean;
+}
+
+export default class EditorSkeleton extends SvelteComponentTyped<
+ EditorSkeletonProps,
+ {
+ click: WindowEventMap["click"];
+ mouseover: WindowEventMap["mouseover"];
+ mouseenter: WindowEventMap["mouseenter"];
+ mouseleave: WindowEventMap["mouseleave"];
+ },
+ {}
+> {}