svelte-typeahead 4.1.0 → 4.2.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/lib/index.mjs CHANGED
@@ -292,22 +292,40 @@ function add_render_callback(fn) {
292
292
  function add_flush_callback(fn) {
293
293
  flush_callbacks.push(fn);
294
294
  }
295
- let flushing = false;
295
+ // flush() calls callbacks in this order:
296
+ // 1. All beforeUpdate callbacks, in order: parents before children
297
+ // 2. All bind:this callbacks, in reverse order: children before parents.
298
+ // 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
299
+ // for afterUpdates called during the initial onMount, which are called in
300
+ // reverse order: children before parents.
301
+ // Since callbacks might update component values, which could trigger another
302
+ // call to flush(), the following steps guard against this:
303
+ // 1. During beforeUpdate, any updated components will be added to the
304
+ // dirty_components array and will cause a reentrant call to flush(). Because
305
+ // the flush index is kept outside the function, the reentrant call will pick
306
+ // up where the earlier call left off and go through all dirty components. The
307
+ // current_component value is saved and restored so that the reentrant call will
308
+ // not interfere with the "parent" flush() call.
309
+ // 2. bind:this callbacks cannot trigger new flush() calls.
310
+ // 3. During afterUpdate, any updated components will NOT have their afterUpdate
311
+ // callback called a second time; the seen_callbacks set, outside the flush()
312
+ // function, guarantees this behavior.
296
313
  const seen_callbacks = new Set();
314
+ let flushidx = 0; // Do *not* move this inside the flush() function
297
315
  function flush() {
298
- if (flushing)
299
- return;
300
- flushing = true;
316
+ const saved_component = current_component;
301
317
  do {
302
318
  // first, call beforeUpdate functions
303
319
  // and update components
304
- for (let i = 0; i < dirty_components.length; i += 1) {
305
- const component = dirty_components[i];
320
+ while (flushidx < dirty_components.length) {
321
+ const component = dirty_components[flushidx];
322
+ flushidx++;
306
323
  set_current_component(component);
307
324
  update(component.$$);
308
325
  }
309
326
  set_current_component(null);
310
327
  dirty_components.length = 0;
328
+ flushidx = 0;
311
329
  while (binding_callbacks.length)
312
330
  binding_callbacks.pop()();
313
331
  // then, once components are updated, call
@@ -327,8 +345,8 @@ function flush() {
327
345
  flush_callbacks.pop()();
328
346
  }
329
347
  update_scheduled = false;
330
- flushing = false;
331
348
  seen_callbacks.clear();
349
+ set_current_component(saved_component);
332
350
  }
333
351
  function update($$) {
334
352
  if ($$.fragment !== null) {
@@ -697,7 +715,7 @@ fuzzy.filter = function(pattern, arr, opts) {
697
715
 
698
716
  var fuzzy = fuzzy$1.exports;
699
717
 
700
- /* node_modules/svelte-search/src/Search.svelte generated by Svelte v3.43.1 */
718
+ /* node_modules/svelte-search/src/Search.svelte generated by Svelte v3.46.4 */
701
719
 
702
720
  function add_css$1(target) {
703
721
  append_styles(target, "svelte-5m0wg6", ".hide-label.svelte-5m0wg6{position:absolute;height:1px;width:1px;overflow:hidden;clip:rect(1px 1px 1px 1px);clip:rect(1px, 1px, 1px, 1px);white-space:nowrap}");
@@ -1034,7 +1052,7 @@ class Search extends SvelteComponent {
1034
1052
 
1035
1053
  var Search$1 = Search;
1036
1054
 
1037
- /* src/Typeahead.svelte generated by Svelte v3.43.1 */
1055
+ /* src/Typeahead.svelte generated by Svelte v3.46.4 */
1038
1056
 
1039
1057
  function add_css(target) {
1040
1058
  append_styles(target, "svelte-j5n77y", "[data-svelte-typeahead].svelte-j5n77y{position:relative;background-color:#fff}ul.svelte-j5n77y{position:absolute;top:100%;left:0;width:100%;padding:0;list-style:none;background-color:inherit;box-shadow:0 4px 8px rgba(0, 0, 0, 0.1)}li.svelte-j5n77y,.no-results.svelte-j5n77y{padding:0.25rem 1rem}li.svelte-j5n77y{cursor:pointer}li.svelte-j5n77y:not(:last-of-type){border-bottom:1px solid #e0e0e0}li.svelte-j5n77y:hover{background-color:#e5e5e5}.selected.svelte-j5n77y{background-color:#e5e5e5}.selected.svelte-j5n77y:hover{background-color:#cacaca}.disabled.svelte-j5n77y{opacity:0.4;cursor:not-allowed}[data-svelte-search] label{margin-bottom:0.25rem;display:inline-flex;font-size:0.875rem}[data-svelte-search] input{width:100%;padding:0.5rem 0.75rem;background:none;font-size:1rem;border:0;border-radius:0;border:1px solid #e5e5e5}[data-svelte-search] input:focus{outline-color:#0f62fe;outline-offset:2px;outline-width:1px}");
@@ -1047,14 +1065,14 @@ const get_no_results_slot_changes = dirty => ({
1047
1065
 
1048
1066
  const get_no_results_slot_context = ctx => ({
1049
1067
  value: /*value*/ ctx[0],
1050
- result: /*result*/ ctx[39],
1051
- index: /*i*/ ctx[41]
1068
+ result: /*result*/ ctx[40],
1069
+ index: /*i*/ ctx[42]
1052
1070
  });
1053
1071
 
1054
1072
  function get_each_context(ctx, list, i) {
1055
1073
  const child_ctx = ctx.slice();
1056
- child_ctx[39] = list[i];
1057
- child_ctx[41] = i;
1074
+ child_ctx[40] = list[i];
1075
+ child_ctx[42] = i;
1058
1076
  return child_ctx;
1059
1077
  }
1060
1078
 
@@ -1064,12 +1082,12 @@ const get_default_slot_changes = dirty => ({
1064
1082
  });
1065
1083
 
1066
1084
  const get_default_slot_context = ctx => ({
1067
- result: /*result*/ ctx[39],
1068
- index: /*i*/ ctx[41],
1085
+ result: /*result*/ ctx[40],
1086
+ index: /*i*/ ctx[42],
1069
1087
  value: /*value*/ ctx[0]
1070
1088
  });
1071
1089
 
1072
- // (184:4) {#if !hideDropdown && results.length > 0}
1090
+ // (198:4) {#if !hideDropdown && results.length > 0}
1073
1091
  function create_if_block_1(ctx) {
1074
1092
  let each_1_anchor;
1075
1093
  let current;
@@ -1101,7 +1119,7 @@ function create_if_block_1(ctx) {
1101
1119
  current = true;
1102
1120
  },
1103
1121
  p(ctx, dirty) {
1104
- if (dirty[0] & /*id, selectedIndex, results, select, $$scope, value*/ 524487) {
1122
+ if (dirty[0] & /*id, selectedIndex, results, select, $$scope, value*/ 1048775) {
1105
1123
  each_value = /*results*/ ctx[1];
1106
1124
  let i;
1107
1125
 
@@ -1153,10 +1171,10 @@ function create_if_block_1(ctx) {
1153
1171
  };
1154
1172
  }
1155
1173
 
1156
- // (199:43)
1174
+ // (213:43)
1157
1175
  function fallback_block(ctx) {
1158
1176
  let html_tag;
1159
- let raw_value = /*result*/ ctx[39].string + "";
1177
+ let raw_value = /*result*/ ctx[40].string + "";
1160
1178
  let html_anchor;
1161
1179
 
1162
1180
  return {
@@ -1170,7 +1188,7 @@ function fallback_block(ctx) {
1170
1188
  insert(target, html_anchor, anchor);
1171
1189
  },
1172
1190
  p(ctx, dirty) {
1173
- if (dirty[0] & /*results*/ 2 && raw_value !== (raw_value = /*result*/ ctx[39].string + "")) html_tag.p(raw_value);
1191
+ if (dirty[0] & /*results*/ 2 && raw_value !== (raw_value = /*result*/ ctx[40].string + "")) html_tag.p(raw_value);
1174
1192
  },
1175
1193
  d(detaching) {
1176
1194
  if (detaching) detach(html_anchor);
@@ -1179,7 +1197,7 @@ function fallback_block(ctx) {
1179
1197
  };
1180
1198
  }
1181
1199
 
1182
- // (185:6) {#each results as result, i}
1200
+ // (199:6) {#each results as result, i}
1183
1201
  function create_each_block(ctx) {
1184
1202
  let li;
1185
1203
  let t;
@@ -1188,12 +1206,12 @@ function create_each_block(ctx) {
1188
1206
  let current;
1189
1207
  let mounted;
1190
1208
  let dispose;
1191
- const default_slot_template = /*#slots*/ ctx[20].default;
1192
- const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[19], get_default_slot_context);
1209
+ const default_slot_template = /*#slots*/ ctx[21].default;
1210
+ const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[20], get_default_slot_context);
1193
1211
  const default_slot_or_fallback = default_slot || fallback_block(ctx);
1194
1212
 
1195
1213
  function click_handler_1() {
1196
- return /*click_handler_1*/ ctx[34](/*result*/ ctx[39], /*i*/ ctx[41]);
1214
+ return /*click_handler_1*/ ctx[35](/*result*/ ctx[40], /*i*/ ctx[42]);
1197
1215
  }
1198
1216
 
1199
1217
  return {
@@ -1202,11 +1220,11 @@ function create_each_block(ctx) {
1202
1220
  if (default_slot_or_fallback) default_slot_or_fallback.c();
1203
1221
  t = space();
1204
1222
  attr(li, "role", "option");
1205
- attr(li, "id", li_id_value = "" + (/*id*/ ctx[2] + "-result-" + /*i*/ ctx[41]));
1206
- attr(li, "aria-selected", li_aria_selected_value = /*selectedIndex*/ ctx[6] === /*i*/ ctx[41]);
1223
+ attr(li, "id", li_id_value = "" + (/*id*/ ctx[2] + "-result-" + /*i*/ ctx[42]));
1224
+ attr(li, "aria-selected", li_aria_selected_value = /*selectedIndex*/ ctx[6] === /*i*/ ctx[42]);
1207
1225
  attr(li, "class", "svelte-j5n77y");
1208
- toggle_class(li, "selected", /*selectedIndex*/ ctx[6] === /*i*/ ctx[41]);
1209
- toggle_class(li, "disabled", /*result*/ ctx[39].disabled);
1226
+ toggle_class(li, "selected", /*selectedIndex*/ ctx[6] === /*i*/ ctx[42]);
1227
+ toggle_class(li, "disabled", /*result*/ ctx[40].disabled);
1210
1228
  },
1211
1229
  m(target, anchor) {
1212
1230
  insert(target, li, anchor);
@@ -1227,15 +1245,15 @@ function create_each_block(ctx) {
1227
1245
  ctx = new_ctx;
1228
1246
 
1229
1247
  if (default_slot) {
1230
- if (default_slot.p && (!current || dirty[0] & /*$$scope, results, value*/ 524291)) {
1248
+ if (default_slot.p && (!current || dirty[0] & /*$$scope, results, value*/ 1048579)) {
1231
1249
  update_slot_base(
1232
1250
  default_slot,
1233
1251
  default_slot_template,
1234
1252
  ctx,
1235
- /*$$scope*/ ctx[19],
1253
+ /*$$scope*/ ctx[20],
1236
1254
  !current
1237
- ? get_all_dirty_from_scope(/*$$scope*/ ctx[19])
1238
- : get_slot_changes(default_slot_template, /*$$scope*/ ctx[19], dirty, get_default_slot_changes),
1255
+ ? get_all_dirty_from_scope(/*$$scope*/ ctx[20])
1256
+ : get_slot_changes(default_slot_template, /*$$scope*/ ctx[20], dirty, get_default_slot_changes),
1239
1257
  get_default_slot_context
1240
1258
  );
1241
1259
  }
@@ -1245,20 +1263,20 @@ function create_each_block(ctx) {
1245
1263
  }
1246
1264
  }
1247
1265
 
1248
- if (!current || dirty[0] & /*id*/ 4 && li_id_value !== (li_id_value = "" + (/*id*/ ctx[2] + "-result-" + /*i*/ ctx[41]))) {
1266
+ if (!current || dirty[0] & /*id*/ 4 && li_id_value !== (li_id_value = "" + (/*id*/ ctx[2] + "-result-" + /*i*/ ctx[42]))) {
1249
1267
  attr(li, "id", li_id_value);
1250
1268
  }
1251
1269
 
1252
- if (!current || dirty[0] & /*selectedIndex*/ 64 && li_aria_selected_value !== (li_aria_selected_value = /*selectedIndex*/ ctx[6] === /*i*/ ctx[41])) {
1270
+ if (!current || dirty[0] & /*selectedIndex*/ 64 && li_aria_selected_value !== (li_aria_selected_value = /*selectedIndex*/ ctx[6] === /*i*/ ctx[42])) {
1253
1271
  attr(li, "aria-selected", li_aria_selected_value);
1254
1272
  }
1255
1273
 
1256
1274
  if (dirty[0] & /*selectedIndex*/ 64) {
1257
- toggle_class(li, "selected", /*selectedIndex*/ ctx[6] === /*i*/ ctx[41]);
1275
+ toggle_class(li, "selected", /*selectedIndex*/ ctx[6] === /*i*/ ctx[42]);
1258
1276
  }
1259
1277
 
1260
1278
  if (dirty[0] & /*results*/ 2) {
1261
- toggle_class(li, "disabled", /*result*/ ctx[39].disabled);
1279
+ toggle_class(li, "disabled", /*result*/ ctx[40].disabled);
1262
1280
  }
1263
1281
  },
1264
1282
  i(local) {
@@ -1279,12 +1297,12 @@ function create_each_block(ctx) {
1279
1297
  };
1280
1298
  }
1281
1299
 
1282
- // (205:4) {#if $$slots["no-results"] && !hideDropdown && value.length > 0 && results.length === 0}
1300
+ // (219:4) {#if $$slots["no-results"] && !hideDropdown && value.length > 0 && results.length === 0}
1283
1301
  function create_if_block(ctx) {
1284
1302
  let div;
1285
1303
  let current;
1286
- const no_results_slot_template = /*#slots*/ ctx[20]["no-results"];
1287
- const no_results_slot = create_slot(no_results_slot_template, ctx, /*$$scope*/ ctx[19], get_no_results_slot_context);
1304
+ const no_results_slot_template = /*#slots*/ ctx[21]["no-results"];
1305
+ const no_results_slot = create_slot(no_results_slot_template, ctx, /*$$scope*/ ctx[20], get_no_results_slot_context);
1288
1306
 
1289
1307
  return {
1290
1308
  c() {
@@ -1304,15 +1322,15 @@ function create_if_block(ctx) {
1304
1322
  },
1305
1323
  p(ctx, dirty) {
1306
1324
  if (no_results_slot) {
1307
- if (no_results_slot.p && (!current || dirty[0] & /*$$scope, value, results*/ 524291)) {
1325
+ if (no_results_slot.p && (!current || dirty[0] & /*$$scope, value, results*/ 1048579)) {
1308
1326
  update_slot_base(
1309
1327
  no_results_slot,
1310
1328
  no_results_slot_template,
1311
1329
  ctx,
1312
- /*$$scope*/ ctx[19],
1330
+ /*$$scope*/ ctx[20],
1313
1331
  !current
1314
- ? get_all_dirty_from_scope(/*$$scope*/ ctx[19])
1315
- : get_slot_changes(no_results_slot_template, /*$$scope*/ ctx[19], dirty, get_no_results_slot_changes),
1332
+ ? get_all_dirty_from_scope(/*$$scope*/ ctx[20])
1333
+ : get_slot_changes(no_results_slot_template, /*$$scope*/ ctx[20], dirty, get_no_results_slot_changes),
1316
1334
  get_no_results_slot_context
1317
1335
  );
1318
1336
  }
@@ -1354,7 +1372,7 @@ function create_fragment(ctx) {
1354
1372
  const search_spread_levels = [
1355
1373
  { id: /*id*/ ctx[2] },
1356
1374
  { removeFormAriaAttributes: true },
1357
- /*$$restProps*/ ctx[9],
1375
+ /*$$restProps*/ ctx[10],
1358
1376
  { "aria-autocomplete": "list" },
1359
1377
  {
1360
1378
  "aria-controls": "" + (/*id*/ ctx[2] + "-listbox")
@@ -1370,11 +1388,11 @@ function create_fragment(ctx) {
1370
1388
  ];
1371
1389
 
1372
1390
  function search_ref_binding(value) {
1373
- /*search_ref_binding*/ ctx[22](value);
1391
+ /*search_ref_binding*/ ctx[23](value);
1374
1392
  }
1375
1393
 
1376
1394
  function search_value_binding(value) {
1377
- /*search_value_binding*/ ctx[23](value);
1395
+ /*search_value_binding*/ ctx[24](value);
1378
1396
  }
1379
1397
 
1380
1398
  let search_props = {};
@@ -1394,18 +1412,18 @@ function create_fragment(ctx) {
1394
1412
  search = new Search$1({ props: search_props });
1395
1413
  binding_callbacks.push(() => bind(search, 'ref', search_ref_binding));
1396
1414
  binding_callbacks.push(() => bind(search, 'value', search_value_binding));
1397
- search.$on("type", /*type_handler*/ ctx[24]);
1398
- search.$on("input", /*input_handler*/ ctx[25]);
1399
- search.$on("change", /*change_handler*/ ctx[26]);
1400
- search.$on("focus", /*focus_handler*/ ctx[27]);
1401
- search.$on("focus", /*focus_handler_1*/ ctx[28]);
1402
- search.$on("clear", /*clear_handler*/ ctx[29]);
1403
- search.$on("clear", /*clear_handler_1*/ ctx[30]);
1404
- search.$on("blur", /*blur_handler*/ ctx[31]);
1405
- search.$on("keydown", /*keydown_handler*/ ctx[32]);
1406
- search.$on("keydown", /*keydown_handler_1*/ ctx[33]);
1415
+ search.$on("type", /*type_handler*/ ctx[25]);
1416
+ search.$on("input", /*input_handler*/ ctx[26]);
1417
+ search.$on("change", /*change_handler*/ ctx[27]);
1418
+ search.$on("focus", /*focus_handler*/ ctx[28]);
1419
+ search.$on("focus", /*focus_handler_1*/ ctx[29]);
1420
+ search.$on("clear", /*clear_handler*/ ctx[30]);
1421
+ search.$on("clear", /*clear_handler_1*/ ctx[31]);
1422
+ search.$on("blur", /*blur_handler*/ ctx[32]);
1423
+ search.$on("keydown", /*keydown_handler*/ ctx[33]);
1424
+ search.$on("keydown", /*keydown_handler_1*/ ctx[34]);
1407
1425
  let if_block0 = !/*hideDropdown*/ ctx[5] && /*results*/ ctx[1].length > 0 && create_if_block_1(ctx);
1408
- let if_block1 = /*$$slots*/ ctx[8]["no-results"] && !/*hideDropdown*/ ctx[5] && /*value*/ ctx[0].length > 0 && /*results*/ ctx[1].length === 0 && create_if_block(ctx);
1426
+ let if_block1 = /*$$slots*/ ctx[9]["no-results"] && !/*hideDropdown*/ ctx[5] && /*value*/ ctx[0].length > 0 && /*results*/ ctx[1].length === 0 && create_if_block(ctx);
1409
1427
 
1410
1428
  return {
1411
1429
  c() {
@@ -1438,20 +1456,20 @@ function create_fragment(ctx) {
1438
1456
  if (if_block0) if_block0.m(ul, null);
1439
1457
  append(ul, t1);
1440
1458
  if (if_block1) if_block1.m(ul, null);
1441
- /*div_binding*/ ctx[35](div);
1459
+ /*div_binding*/ ctx[36](div);
1442
1460
  current = true;
1443
1461
 
1444
1462
  if (!mounted) {
1445
- dispose = listen(window, "click", /*click_handler*/ ctx[21]);
1463
+ dispose = listen(window, "click", /*click_handler*/ ctx[22]);
1446
1464
  mounted = true;
1447
1465
  }
1448
1466
  },
1449
1467
  p(ctx, dirty) {
1450
- const search_changes = (dirty[0] & /*id, $$restProps, selectedIndex, hideDropdown, results*/ 614)
1468
+ const search_changes = (dirty[0] & /*id, $$restProps, selectedIndex, hideDropdown, results*/ 1126)
1451
1469
  ? get_spread_update(search_spread_levels, [
1452
1470
  dirty[0] & /*id*/ 4 && { id: /*id*/ ctx[2] },
1453
1471
  search_spread_levels[1],
1454
- dirty[0] & /*$$restProps*/ 512 && get_spread_object(/*$$restProps*/ ctx[9]),
1472
+ dirty[0] & /*$$restProps*/ 1024 && get_spread_object(/*$$restProps*/ ctx[10]),
1455
1473
  search_spread_levels[3],
1456
1474
  dirty[0] & /*id*/ 4 && {
1457
1475
  "aria-controls": "" + (/*id*/ ctx[2] + "-listbox")
@@ -1504,11 +1522,11 @@ function create_fragment(ctx) {
1504
1522
  check_outros();
1505
1523
  }
1506
1524
 
1507
- if (/*$$slots*/ ctx[8]["no-results"] && !/*hideDropdown*/ ctx[5] && /*value*/ ctx[0].length > 0 && /*results*/ ctx[1].length === 0) {
1525
+ if (/*$$slots*/ ctx[9]["no-results"] && !/*hideDropdown*/ ctx[5] && /*value*/ ctx[0].length > 0 && /*results*/ ctx[1].length === 0) {
1508
1526
  if (if_block1) {
1509
1527
  if_block1.p(ctx, dirty);
1510
1528
 
1511
- if (dirty[0] & /*$$slots, hideDropdown, value, results*/ 291) {
1529
+ if (dirty[0] & /*$$slots, hideDropdown, value, results*/ 547) {
1512
1530
  transition_in(if_block1, 1);
1513
1531
  }
1514
1532
  } else {
@@ -1569,7 +1587,7 @@ function create_fragment(ctx) {
1569
1587
  destroy_component(search);
1570
1588
  if (if_block0) if_block0.d();
1571
1589
  if (if_block1) if_block1.d();
1572
- /*div_binding*/ ctx[35](null);
1590
+ /*div_binding*/ ctx[36](null);
1573
1591
  mounted = false;
1574
1592
  dispose();
1575
1593
  }
@@ -1619,6 +1637,7 @@ function instance($$self, $$props, $$invalidate) {
1619
1637
 
1620
1638
  async function select() {
1621
1639
  const result = results[selectedIndex];
1640
+ if (result.disabled) return;
1622
1641
  const selectedValue = extract(result.original);
1623
1642
  const searchedValue = value;
1624
1643
  if (inputAfterSelect == "clear") $$invalidate(0, value = "");
@@ -1637,6 +1656,28 @@ function instance($$self, $$props, $$invalidate) {
1637
1656
  $$invalidate(5, hideDropdown = true);
1638
1657
  }
1639
1658
 
1659
+ /** @type {(direction: -1 | 1) => void} */
1660
+ function change(direction) {
1661
+ let index = direction === 1 && selectedIndex === results.length - 1
1662
+ ? 0
1663
+ : selectedIndex + direction;
1664
+
1665
+ if (index < 0) index = results.length - 1;
1666
+ let disabled = results[index].disabled;
1667
+
1668
+ while (disabled) {
1669
+ if (index === results.length) {
1670
+ index = 0;
1671
+ } else {
1672
+ index += direction;
1673
+ }
1674
+
1675
+ disabled = results[index].disabled;
1676
+ }
1677
+
1678
+ $$invalidate(6, selectedIndex = index);
1679
+ }
1680
+
1640
1681
  const click_handler = ({ target }) => {
1641
1682
  if (!hideDropdown && comboboxRef && !comboboxRef.contains(target)) {
1642
1683
  $$invalidate(5, hideDropdown = true);
@@ -1698,17 +1739,11 @@ function instance($$self, $$props, $$invalidate) {
1698
1739
  break;
1699
1740
  case "ArrowDown":
1700
1741
  e.preventDefault();
1701
- $$invalidate(6, selectedIndex += 1);
1702
- if (selectedIndex === results.length) {
1703
- $$invalidate(6, selectedIndex = 0);
1704
- }
1742
+ change(1);
1705
1743
  break;
1706
1744
  case "ArrowUp":
1707
1745
  e.preventDefault();
1708
- $$invalidate(6, selectedIndex -= 1);
1709
- if (selectedIndex < 0) {
1710
- $$invalidate(6, selectedIndex = results.length - 1);
1711
- }
1746
+ change(-1);
1712
1747
  break;
1713
1748
  case "Escape":
1714
1749
  e.preventDefault();
@@ -1735,34 +1770,34 @@ function instance($$self, $$props, $$invalidate) {
1735
1770
 
1736
1771
  $$self.$$set = $$new_props => {
1737
1772
  $$props = assign(assign({}, $$props), exclude_internal_props($$new_props));
1738
- $$invalidate(9, $$restProps = compute_rest_props($$props, omit_props_names));
1773
+ $$invalidate(10, $$restProps = compute_rest_props($$props, omit_props_names));
1739
1774
  if ('id' in $$new_props) $$invalidate(2, id = $$new_props.id);
1740
1775
  if ('value' in $$new_props) $$invalidate(0, value = $$new_props.value);
1741
- if ('data' in $$new_props) $$invalidate(10, data = $$new_props.data);
1742
- if ('extract' in $$new_props) $$invalidate(11, extract = $$new_props.extract);
1743
- if ('disable' in $$new_props) $$invalidate(12, disable = $$new_props.disable);
1744
- if ('filter' in $$new_props) $$invalidate(13, filter = $$new_props.filter);
1745
- if ('autoselect' in $$new_props) $$invalidate(14, autoselect = $$new_props.autoselect);
1746
- if ('inputAfterSelect' in $$new_props) $$invalidate(15, inputAfterSelect = $$new_props.inputAfterSelect);
1776
+ if ('data' in $$new_props) $$invalidate(11, data = $$new_props.data);
1777
+ if ('extract' in $$new_props) $$invalidate(12, extract = $$new_props.extract);
1778
+ if ('disable' in $$new_props) $$invalidate(13, disable = $$new_props.disable);
1779
+ if ('filter' in $$new_props) $$invalidate(14, filter = $$new_props.filter);
1780
+ if ('autoselect' in $$new_props) $$invalidate(15, autoselect = $$new_props.autoselect);
1781
+ if ('inputAfterSelect' in $$new_props) $$invalidate(16, inputAfterSelect = $$new_props.inputAfterSelect);
1747
1782
  if ('results' in $$new_props) $$invalidate(1, results = $$new_props.results);
1748
- if ('focusAfterSelect' in $$new_props) $$invalidate(16, focusAfterSelect = $$new_props.focusAfterSelect);
1749
- if ('limit' in $$new_props) $$invalidate(17, limit = $$new_props.limit);
1750
- if ('$$scope' in $$new_props) $$invalidate(19, $$scope = $$new_props.$$scope);
1783
+ if ('focusAfterSelect' in $$new_props) $$invalidate(17, focusAfterSelect = $$new_props.focusAfterSelect);
1784
+ if ('limit' in $$new_props) $$invalidate(18, limit = $$new_props.limit);
1785
+ if ('$$scope' in $$new_props) $$invalidate(20, $$scope = $$new_props.$$scope);
1751
1786
  };
1752
1787
 
1753
1788
  $$self.$$.update = () => {
1754
- if ($$self.$$.dirty[0] & /*extract*/ 2048) {
1755
- $$invalidate(18, options = { pre: "<mark>", post: "</mark>", extract });
1789
+ if ($$self.$$.dirty[0] & /*extract*/ 4096) {
1790
+ $$invalidate(19, options = { pre: "<mark>", post: "</mark>", extract });
1756
1791
  }
1757
1792
 
1758
- if ($$self.$$.dirty[0] & /*value, data, options, limit, filter, disable*/ 406529) {
1793
+ if ($$self.$$.dirty[0] & /*value, data, options, limit, filter, disable*/ 813057) {
1759
1794
  $$invalidate(1, results = fuzzy.filter(value, data, options).filter(({ score }) => score > 0).slice(0, limit).filter(result => !filter(result.original)).map(result => ({
1760
1795
  ...result,
1761
1796
  disabled: disable(result.original)
1762
1797
  })));
1763
1798
  }
1764
1799
 
1765
- if ($$self.$$.dirty[0] & /*results, extract*/ 2050) {
1800
+ if ($$self.$$.dirty[0] & /*results, extract*/ 4098) {
1766
1801
  resultsId = results.map(result => extract(result.original)).join("");
1767
1802
  }
1768
1803
  };
@@ -1776,6 +1811,7 @@ function instance($$self, $$props, $$invalidate) {
1776
1811
  hideDropdown,
1777
1812
  selectedIndex,
1778
1813
  select,
1814
+ change,
1779
1815
  $$slots,
1780
1816
  $$restProps,
1781
1817
  data,
@@ -1820,15 +1856,15 @@ class Typeahead extends SvelteComponent {
1820
1856
  {
1821
1857
  id: 2,
1822
1858
  value: 0,
1823
- data: 10,
1824
- extract: 11,
1825
- disable: 12,
1826
- filter: 13,
1827
- autoselect: 14,
1828
- inputAfterSelect: 15,
1859
+ data: 11,
1860
+ extract: 12,
1861
+ disable: 13,
1862
+ filter: 14,
1863
+ autoselect: 15,
1864
+ inputAfterSelect: 16,
1829
1865
  results: 1,
1830
- focusAfterSelect: 16,
1831
- limit: 17
1866
+ focusAfterSelect: 17,
1867
+ limit: 18
1832
1868
  },
1833
1869
  add_css,
1834
1870
  [-1, -1]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-typeahead",
3
- "version": "4.1.0",
3
+ "version": "4.2.2",
4
4
  "license": "MIT",
5
5
  "description": "Accessible, fuzzy search typeahead component",
6
6
  "author": "Eric Liu (https://github.com/metonym)",
@@ -21,10 +21,10 @@
21
21
  "svelte-search": "^1.1.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@rollup/plugin-commonjs": "^21.0.0",
25
- "svelte": "^3.43.1",
26
- "svelte-check": "^2.2.6",
27
- "svelte-readme": "^3.3.1"
24
+ "@rollup/plugin-commonjs": "^21.0.2",
25
+ "svelte": "^3.46.4",
26
+ "svelte-check": "^2.4.6",
27
+ "svelte-readme": "^3.6.3"
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
@@ -1,25 +1,21 @@
1
1
  <script>
2
2
  /**
3
- * @typedef {string | number | Record<string, any>} Item
4
- * @typedef {{ original: Item; index: number; score: number; string: string; }} FuzzyResult
5
- * @event {{ searched: string; selected: Item; selectedIndex: number; original: Item; originalIndex: number; }} select
6
- * @event {any} clear
7
- * @slot {{ result: FuzzyResult; index: number }}
3
+ * @template TItem = string | number | Record<string, any>
8
4
  */
9
5
 
10
6
  export let id = "typeahead-" + Math.random().toString(36);
11
7
  export let value = "";
12
8
 
13
- /** @type {Item[]} */
9
+ /** @type {TItem[]} */
14
10
  export let data = [];
15
11
 
16
- /** @type {(item: Item) => Item} */
12
+ /** @type {(item: TItem) => any} */
17
13
  export let extract = (item) => item;
18
14
 
19
- /** @type {(item: Item) => Item} */
15
+ /** @type {(item: TItem) => boolean} */
20
16
  export let disable = (item) => false;
21
17
 
22
- /** @type {(item: Item) => Item} */
18
+ /** @type {(item: TItem) => boolean} */
23
19
  export let filter = (item) => false;
24
20
 
25
21
  /** Set to `false` to prevent the first result from being selected */
@@ -31,7 +27,7 @@
31
27
  */
32
28
  export let inputAfterSelect = "update";
33
29
 
34
- /** @type {FuzzyResult[]} */
30
+ /** @type {{ original: TItem; index: number; score: number; string: string; disabled?: boolean; }[]} */
35
31
  export let results = [];
36
32
 
37
33
  /** Set to `true` to re-focus the input after selecting a result */
@@ -69,6 +65,9 @@
69
65
 
70
66
  async function select() {
71
67
  const result = results[selectedIndex];
68
+
69
+ if (result.disabled) return;
70
+
72
71
  const selectedValue = extract(result.original);
73
72
  const searchedValue = value;
74
73
 
@@ -90,6 +89,27 @@
90
89
  hideDropdown = true;
91
90
  }
92
91
 
92
+ /** @type {(direction: -1 | 1) => void} */
93
+ function change(direction) {
94
+ let index =
95
+ direction === 1 && selectedIndex === results.length - 1 ? 0 : selectedIndex + direction;
96
+ if (index < 0) index = results.length - 1;
97
+
98
+ let disabled = results[index].disabled;
99
+
100
+ while (disabled) {
101
+ if (index === results.length) {
102
+ index = 0;
103
+ } else {
104
+ index += direction;
105
+ }
106
+
107
+ disabled = results[index].disabled;
108
+ }
109
+
110
+ selectedIndex = index;
111
+ }
112
+
93
113
  $: options = { pre: "<mark>", post: "</mark>", extract };
94
114
  $: results = fuzzy
95
115
  .filter(value, data, options)
@@ -154,17 +174,11 @@
154
174
  break;
155
175
  case "ArrowDown":
156
176
  e.preventDefault();
157
- selectedIndex += 1;
158
- if (selectedIndex === results.length) {
159
- selectedIndex = 0;
160
- }
177
+ change(1);
161
178
  break;
162
179
  case "ArrowUp":
163
180
  e.preventDefault();
164
- selectedIndex -= 1;
165
- if (selectedIndex < 0) {
166
- selectedIndex = results.length - 1;
167
- }
181
+ change(-1);
168
182
  break;
169
183
  case "Escape":
170
184
  e.preventDefault();