|
28 | 28 | type InputChipEvent = {
|
29 | 29 | add: { event: SubmitEvent; chipIndex: number; chipValue: string };
|
30 | 30 | remove: { event: MouseEvent; chipIndex: number; chipValue: string };
|
| 31 | + addManually: { chipIndex: number; chipValue: string }; |
| 32 | + removeManually: { chipValue: string }; |
31 | 33 | invalid: { event: SubmitEvent; input: string };
|
| 34 | + invalidManually: { input: string }; |
32 | 35 | };
|
33 | 36 | const dispatch = createEventDispatcher<InputChipEvent>();
|
34 | 37 |
|
|
174 | 177 | inputValid = true;
|
175 | 178 | }
|
176 | 179 |
|
177 |
| - function validate(): boolean { |
178 |
| - if (!input) return false; |
| 180 | + function validateCustom(chip: string) { |
| 181 | + return validation === undefined || validation(chip); |
| 182 | + } |
| 183 | +
|
| 184 | + function validateCount() { |
| 185 | + return max === -1 || value.length < max; |
| 186 | + } |
| 187 | +
|
| 188 | + function validateLength(chip: string) { |
| 189 | + return (minlength === -1 || chip.length >= minlength) && (maxlength === -1 || chip.length <= maxlength); |
| 190 | + } |
| 191 | +
|
| 192 | + function validateWhiteList(chip: string) { |
| 193 | + return whitelist.length === 0 || whitelist.includes(chip); |
| 194 | + } |
| 195 | +
|
| 196 | + function validateDuplicates(chip: string) { |
| 197 | + return allowDuplicates || !value.includes(chip); |
| 198 | + } |
| 199 | +
|
| 200 | + function validate(chip: string = ''): boolean { |
| 201 | + if (!chip && !input) return false; |
179 | 202 | // Format: trim value
|
180 |
| - input = input.trim(); |
181 |
| - // Custom validation |
182 |
| - if (validation !== undefined && !validation(input)) return false; |
183 |
| - // Maximum |
184 |
| - if (max !== -1 && value.length >= max) return false; |
185 |
| - // Minimum Character Length |
186 |
| - if (minlength !== -1 && input.length < minlength) return false; |
187 |
| - // Maximum Character Length |
188 |
| - if (maxlength !== -1 && input.length > maxlength) return false; |
189 |
| - // Whitelist (if available) |
190 |
| - if (whitelist.length > 0 && !whitelist.includes(input)) return false; |
191 |
| - // Value is unique |
192 |
| - if (allowDuplicates === false && value.includes(input)) return false; |
193 |
| - // State is valid |
194 |
| - return true; |
| 203 | + chip = chip !== '' ? chip.trim() : input.trim(); |
| 204 | + return validateCustom(chip) && validateCount() && validateLength(chip) && validateWhiteList(chip) && validateDuplicates(chip); |
| 205 | + } |
| 206 | +
|
| 207 | + function addChipCommon(chip: string) { |
| 208 | + // Format: to lowercase (if enabled) |
| 209 | + chip = allowUpperCase ? chip : chip.toLowerCase(); |
| 210 | + // Append value to array |
| 211 | + value.push(chip); |
| 212 | + value = value; |
| 213 | + chipValues.push({ val: chip, id: Math.random() }); |
| 214 | + chipValues = chipValues; |
| 215 | + } |
| 216 | +
|
| 217 | + function removeChipCommon(chip: string) { |
| 218 | + let chipIndex = value.indexOf(chip); |
| 219 | + // Remove value from array |
| 220 | + value.splice(chipIndex, 1); |
| 221 | + value = value; |
| 222 | + chipValues.splice(chipIndex, 1); |
| 223 | + chipValues = chipValues; |
195 | 224 | }
|
196 | 225 |
|
197 |
| - function addChip(event: SvelteEvent<SubmitEvent, HTMLFormElement>): void { |
| 226 | + function addChipInternally(event: SvelteEvent<SubmitEvent, HTMLFormElement>): void { |
198 | 227 | event.preventDefault();
|
199 | 228 | // Validate
|
200 | 229 | inputValid = validate();
|
|
204 | 233 | dispatch('invalid', { event, input });
|
205 | 234 | return;
|
206 | 235 | }
|
207 |
| - // Format: to lowercase (if enabled) |
208 |
| - input = allowUpperCase ? input : input.toLowerCase(); |
209 |
| - // Append value to array |
210 |
| - value.push(input); |
211 |
| - value = value; |
212 |
| - chipValues.push({ val: input, id: Math.random() }); |
213 |
| - chipValues = chipValues; |
| 236 | + addChipCommon(input); |
214 | 237 | /** @event {{ event: Event, chipIndex: number, chipValue: string }} add - Fires when a chip is added. */
|
215 | 238 | dispatch('add', { event, chipIndex: value.length - 1, chipValue: input });
|
216 | 239 | // Clear input value
|
217 | 240 | input = '';
|
218 | 241 | }
|
219 | 242 |
|
220 |
| - function removeChip(event: SvelteEvent<MouseEvent, HTMLButtonElement>, chipIndex: number, chipValue: string): void { |
| 243 | + function removeChipInternally(event: SvelteEvent<MouseEvent, HTMLButtonElement>, chipIndex: number, chipValue: string): void { |
221 | 244 | if ($$restProps.disabled) return;
|
222 |
| - // Remove value from array |
223 |
| - value.splice(chipIndex, 1); |
224 |
| - value = value; |
225 |
| - chipValues.splice(chipIndex, 1); |
226 |
| - chipValues = chipValues; |
| 245 | + removeChipCommon(chipValue); |
227 | 246 | /** @event {{ event: Event, chipIndex: number, chipValue: string }} remove - Fires when a chip is removed. */
|
228 | 247 | dispatch('remove', { event, chipIndex, chipValue });
|
229 | 248 | }
|
230 | 249 |
|
| 250 | + // Export functions |
| 251 | + export function addChip(chip: string) { |
| 252 | + // Validate |
| 253 | + inputValid = validate(chip); |
| 254 | + // When the onInvalid hook is present |
| 255 | + if (inputValid === false) { |
| 256 | + /** @event {{ input: string }} invalidManually - Fires when the manually added value is invalid. */ |
| 257 | + dispatch('invalidManually', { input: chip }); |
| 258 | + return; |
| 259 | + } |
| 260 | + addChipCommon(chip); |
| 261 | + /** @event {{ chipIndex: number, chipValue: string }} addManually - Fires when a chip is added manually. */ |
| 262 | + dispatch('addManually', { chipIndex: value.length - 1, chipValue: chip }); |
| 263 | + } |
| 264 | +
|
| 265 | + export function removeChip(chip: string) { |
| 266 | + if ($$restProps.disabled) return; |
| 267 | + removeChipCommon(chip); |
| 268 | + /** @event {{ chipValue: string }} removeManually - Fires when a chip is removed manually. */ |
| 269 | + dispatch('removeManually', { chipValue: chip }); |
| 270 | + } |
| 271 | +
|
231 | 272 | // State
|
232 | 273 | $: classesInvalid = inputValid === false ? invalid : '';
|
233 | 274 | // Reactive
|
|
253 | 294 | <!-- Chip Wrapper -->
|
254 | 295 | <div class="input-chip-wrapper {classesChipWrapper}">
|
255 | 296 | <!-- Input Field -->
|
256 |
| - <form on:submit={addChip}> |
| 297 | + <form on:submit={addChipInternally}> |
257 | 298 | <input
|
258 | 299 | type="text"
|
259 | 300 | bind:value={input}
|
|
279 | 320 | <button
|
280 | 321 | type="button"
|
281 | 322 | class="chip {chips}"
|
282 |
| - on:click={(e) => { |
283 |
| - removeChip(e, i, val); |
284 |
| - }} |
| 323 | + on:click={(e) => removeChipInternally(e, i, val)} |
285 | 324 | on:click
|
286 | 325 | on:keypress
|
287 | 326 | on:keydown
|
|
0 commit comments