Skip to content

Commit

Permalink
fix: multiple select component
Browse files Browse the repository at this point in the history
  • Loading branch information
si3nloong committed Feb 23, 2021
1 parent 719a18e commit da68ead
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 77 deletions.
103 changes: 44 additions & 59 deletions components/select/src/MultipleSelect.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
<script context="module" lang="ts">
const queue: [Node, Function][] = [];
const runIfContains = (node: Node, cb: Function) => {
queue.push([node, cb]);
};
window.addEventListener("click", (e: Event) => {
const el = e.target! as Node;
queue.forEach(([node, cb]) => {
if (!node.contains(el)) cb();
});
});
</script>

<script lang="ts">
import { zoom } from "@wetix/animation";
import { getNodeAttribute } from "@wetix/utils";
Expand All @@ -30,81 +17,79 @@
export let disabled = false;
export let readonly = false;
const maxHeight = 25 + size * 20;
onMount(() => {
runIfContains(ref as Node, () => {
show = false;
});
});
const maxHeight = 15 + size * 24;
type Item = { label: string; value: string };
let items: Item[] = [];
const dict = new Map();
$: {
options.forEach((opt) => {
dict.set(opt.value, opt);
});
}
let input: null | HTMLInputElement;
let show = false;
let clientHeight = 0;
onMount(() => {
const onClick = () => {
show = false;
};
window.addEventListener("click", onClick);
return () => {
window.removeEventListener("click", onClick);
};
});
const onSelect = (e: Event) => {
const data = getNodeAttribute(e, "data-option");
if (data) {
console.log(data);
const [index, item] = <[number, Item]>JSON.parse(data);
const pos = items.findIndex((v) => v.value === item.value);
const pos = value.findIndex((v) => v === item.value);
if (pos > -1) {
// options[index].selected = false;
items = items.filter((v) => v.value !== item.value);
value.splice(pos, 1);
} else {
// options[index].selected = true;
items = [...items, item];
value.push(item.value);
}
options = [...options];
value.push(item.value);
input && input.focus();
dispatch(
"change",
items.map((v) => v.value)
);
value = [...value];
input!.focus();
dispatch("change", { value });
}
};
const onRemove = (e: Event) => {
const value = getNodeAttribute(e, "data-value");
if (value) {
e.stopPropagation();
items = items.filter((v) => v.value !== value);
dispatch(
"change",
items.map((v) => v.value)
);
const val = getNodeAttribute(e, "data-value");
if (val) {
value = value.filter((v) => v !== val);
dispatch("change", { value });
}
};
</script>

<div class="responsive-ui-select--multiple {className}" bind:this={ref}>
<div class="responsive-ui-select-input" on:click={() => (show = !show)}>
<input
{name}
type="hidden"
value={items.reduce((acc, { value }, i) => {
if (i > 0) acc += ",";
return (acc += value);
}, "")}
/>
<span class="responsive-ui-select__tags" on:click={onRemove}>
{#each items as item}
<div class="responsive-ui-select-input">
<input {name} type="hidden" value={value.join(",")} />
<span
class="responsive-ui-select__tags"
on:click|stopPropagation={onRemove}
>
{#each value as item}
<span
class="responsive-ui-select__tag"
data-value={item.value}
data-value={item}
in:zoom
out:zoom
>
<span>{item.label}</span>
<span>{dict.get(item).label}</span>
<i class="responsive-ui-select__close" />
</span>
{/each}
<input
bind:this={input}
type="text"
on:focus|stopPropagation={() => (show = true)}
autocomplete="off"
on:blur
{disabled}
Expand All @@ -114,17 +99,17 @@
</div>
<div
class="responsive-ui-select__dropdown"
on:click={onSelect}
on:click|stopPropagation={onSelect}
style={`height:${show ? clientHeight : 0}px;max-height:${maxHeight}px;`}
>
<div bind:clientHeight style="padding:10px 0">
{#each options as item, i}
<div
class="responsive-ui-select__option"
class:responsive-ui-select__option--disabled={item.disabled}
class:responsive-ui-select__option--selected={value.includes(
item.value
)}
class:responsive-ui-select__option--disabled={item.disabled}
data-option={JSON.stringify([i, item])}
>
{item.label || ""}
Expand Down Expand Up @@ -173,10 +158,9 @@
}
&__tag {
// float: left;
cursor: default;
font-size: var(--font-size-sm, 12px);
padding: 3px 6px;
padding: 3px 8px;
border-radius: var(--border-radius-sm, 3px);
margin-right: 4px;
margin-bottom: 4px;
Expand All @@ -192,6 +176,7 @@
&__close {
cursor: pointer;
position: relative;
margin-left: 3px;
vertical-align: middle;
display: inline-block;
width: 12px;
Expand Down Expand Up @@ -255,7 +240,7 @@
}
&--selected {
background: rgba(252, 68, 81, 0.3) !important;
background: rgba(252, 68, 81, 0.1) !important;
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions components/select/src/Select.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
let className = "";
export { className as class };
export let name = "";
export let value = "";
export let value: string | string[] = "";
export let size = 10;
export let multiple = false;
export let disabled = false;
Expand All @@ -20,8 +19,8 @@
<Select {...$$props} {size} class={className} on:change on:blur />
{:else}
<select
{...$$restProps}
class="responsive-ui-select {className}"
{name}
{size}
{readonly}
{disabled}
Expand Down
20 changes: 6 additions & 14 deletions components/select/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,22 @@ import type { SvelteComponentTyped } from "svelte/internal";
export type SelectOption = {
label: string;
disabled?: boolean;
value: any;
value: string;
};

interface SelectProp {
interface SelectProps {
id?: string;
ref?: null | HTMLSelectElement;
name?: string;
size?: number;
multiple?: false;
value?: string | string[];
disabled?: boolean;
readonly?: boolean;
options: SelectOption[];
style?: string;
}

interface SingleSelectProps extends SelectProp {
value?: string;
multiple: false | undefined;
}

interface MultipleSelectProps extends SelectProp {
value?: string[];
multiple: true;
}

export type SelectProps = SingleSelectProps | MultipleSelectProps;

export interface SelectEvents {
change?: any;
blur?: any;
Expand Down
2 changes: 1 addition & 1 deletion components/textarea/src/Textarea.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
&__text-length {
display: block;
text-align: right;
font-size: var(--font-size-xs, 10px);
font-size: var(--font-size-xs, 11px);
}
}
</style>
1 change: 1 addition & 0 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@
<Select
multiple={true}
size={5}
value={["b", "c"]}
options={[
{ label: "CC", value: "cc" },
{ label: "Option A", value: "a", disabled: true },
Expand Down

0 comments on commit da68ead

Please sign in to comment.