@x33025/sveltely 0.0.28 → 0.0.31
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/ChipInput.svelte +94 -3
- package/dist/style.css +3 -0
- package/package.json +1 -1
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
let inputValue = $state('');
|
|
21
21
|
let showInput = $state(false);
|
|
22
22
|
let inputEl = $state<HTMLInputElement | null>(null);
|
|
23
|
+
let editingTag = $state<string | null>(null);
|
|
24
|
+
let editingValue = $state('');
|
|
25
|
+
let editingEl = $state<HTMLInputElement | null>(null);
|
|
23
26
|
const selectionEnabled = $derived(selection !== undefined);
|
|
24
27
|
|
|
25
28
|
const addTag = (rawValue: string) => {
|
|
@@ -47,6 +50,12 @@
|
|
|
47
50
|
return;
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
if (event.key === 'Enter' && !inputValue.trim()) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
showInput = false;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
50
59
|
if (event.key === 'Escape') {
|
|
51
60
|
inputValue = '';
|
|
52
61
|
showInput = false;
|
|
@@ -54,7 +63,8 @@
|
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
if (event.key === 'Backspace' && !inputValue && tags.length > 0) {
|
|
57
|
-
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
startEditing(tags[tags.length - 1]);
|
|
58
68
|
}
|
|
59
69
|
};
|
|
60
70
|
|
|
@@ -64,6 +74,74 @@
|
|
|
64
74
|
inputEl?.focus();
|
|
65
75
|
};
|
|
66
76
|
|
|
77
|
+
const startEditing = async (tag: string) => {
|
|
78
|
+
editingTag = tag;
|
|
79
|
+
editingValue = tag;
|
|
80
|
+
await tick();
|
|
81
|
+
editingEl?.focus();
|
|
82
|
+
editingEl?.select();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const commitEdit = async (source: 'enter' | 'blur' | 'advance', targetTag: string) => {
|
|
86
|
+
if (!editingTag || editingTag !== targetTag) return;
|
|
87
|
+
|
|
88
|
+
const previous = editingTag;
|
|
89
|
+
const next = editingValue.trim();
|
|
90
|
+
editingTag = null;
|
|
91
|
+
|
|
92
|
+
if (!next) {
|
|
93
|
+
if (source === 'enter' || source === 'advance') {
|
|
94
|
+
const previousIndex = tags.indexOf(previous);
|
|
95
|
+
const nextTags = tags.filter((tag) => tag !== previous);
|
|
96
|
+
tags = nextTags;
|
|
97
|
+
if (selection?.includes(previous)) {
|
|
98
|
+
selection = selection.filter((tag) => tag !== previous);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (source === 'advance' && nextTags.length > 0) {
|
|
102
|
+
const nextIndex = Math.min(previousIndex, nextTags.length - 1);
|
|
103
|
+
await startEditing(nextTags[nextIndex]);
|
|
104
|
+
} else if (nextTags.length === 0) {
|
|
105
|
+
inputValue = '';
|
|
106
|
+
await openInput();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (next === previous) return;
|
|
113
|
+
if (tags.includes(next)) return;
|
|
114
|
+
|
|
115
|
+
tags = tags.map((tag) => (tag === previous ? next : tag));
|
|
116
|
+
if (selection?.includes(previous)) {
|
|
117
|
+
selection = selection.map((tag) => (tag === previous ? next : tag));
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const cancelEdit = () => {
|
|
122
|
+
editingTag = null;
|
|
123
|
+
editingValue = '';
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const onEditKeydown = async (event: KeyboardEvent, tag: string) => {
|
|
127
|
+
if (event.key === 'Enter') {
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
await commitEdit('enter', tag);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if ((event.key === 'Backspace' || event.key === 'Delete') && !editingValue.trim()) {
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
await commitEdit('advance', tag);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (event.key === 'Escape') {
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
cancelEdit();
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
67
145
|
const onBlur = () => {
|
|
68
146
|
if (!inputValue.trim()) {
|
|
69
147
|
showInput = false;
|
|
@@ -82,18 +160,31 @@
|
|
|
82
160
|
<div class="w-full max-w-lg">
|
|
83
161
|
<div class="tag-row flex flex-wrap items-center">
|
|
84
162
|
{#each tags as tag (tag)}
|
|
85
|
-
{#if
|
|
163
|
+
{#if editingTag === tag}
|
|
164
|
+
<input
|
|
165
|
+
bind:this={editingEl}
|
|
166
|
+
bind:value={editingValue}
|
|
167
|
+
class="tag-surface tag-input-field min-w-20 outline-none"
|
|
168
|
+
onblur={() => commitEdit('blur', tag)}
|
|
169
|
+
onkeydown={(event) => onEditKeydown(event, tag)}
|
|
170
|
+
/>
|
|
171
|
+
{:else if selectionEnabled}
|
|
86
172
|
<button
|
|
87
173
|
type="button"
|
|
88
174
|
class="tag-surface inline-flex items-center gap-2"
|
|
89
175
|
class:tag-selected={selection?.includes(tag)}
|
|
90
176
|
onclick={() => toggleSelected(tag)}
|
|
177
|
+
ondblclick={() => startEditing(tag)}
|
|
91
178
|
aria-pressed={selection?.includes(tag)}
|
|
92
179
|
>
|
|
93
180
|
{tag}
|
|
94
181
|
</button>
|
|
95
182
|
{:else}
|
|
96
|
-
<
|
|
183
|
+
<button
|
|
184
|
+
type="button"
|
|
185
|
+
class="tag-surface inline-flex items-center gap-2"
|
|
186
|
+
ondblclick={() => startEditing(tag)}>{tag}</button
|
|
187
|
+
>
|
|
97
188
|
{/if}
|
|
98
189
|
{/each}
|
|
99
190
|
|
package/dist/style.css
CHANGED