@mackin.com/styleguide 9.2.0 → 9.2.3

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.
Files changed (3) hide show
  1. package/index.d.ts +0 -1
  2. package/index.js +48 -19
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -1097,7 +1097,6 @@ interface AutoCompleteConfig {
1097
1097
  debounceMs?: number;
1098
1098
  }
1099
1099
 
1100
- /** Extracted logic around autocomplete functionality for Autocomplete.tsx. */
1101
1100
  declare class AutocompleteController {
1102
1101
  constructor(getOptions: (value: string | undefined) => Promise<string[]>, config?: AutoCompleteConfig);
1103
1102
  get value(): string | undefined;
package/index.js CHANGED
@@ -1012,21 +1012,24 @@ const Autocomplete = (p) => {
1012
1012
  listBorderRadius = theme.controls.borderRadius || '0.5rem';
1013
1013
  }
1014
1014
  const onPickValue = (v) => {
1015
- p.onPick(v);
1016
- // wait for the re-render. the value will not update if the control has focus
1015
+ var _a;
1016
+ // the TextInput will not respond to outer value changes if it has focus.
1017
+ // here we clear first and then onPickValue will re-focus after all updates.
1018
+ (_a = input.current) === null || _a === void 0 ? void 0 : _a.blur();
1017
1019
  setTimeout(() => {
1018
- var _a;
1019
- (_a = input.current) === null || _a === void 0 ? void 0 : _a.focus();
1020
+ // blur is now complete
1021
+ p.onPick(v);
1022
+ // wait for the re-render. the value will not update if the control has focus
1023
+ setTimeout(() => {
1024
+ var _a;
1025
+ (_a = input.current) === null || _a === void 0 ? void 0 : _a.focus();
1026
+ }, 0);
1020
1027
  }, 0);
1021
1028
  };
1022
1029
  return (React__namespace.createElement("div", { onClick: e => {
1023
1030
  e.stopPropagation();
1024
1031
  }, onKeyDown: e => {
1025
- var _a;
1026
1032
  if (e.key === 'Escape') {
1027
- // the TextInput will not respond to outer value changes if it has focus.
1028
- // here we clear first and then onPickValue will re-focus after all updates.
1029
- (_a = input.current) === null || _a === void 0 ? void 0 : _a.blur();
1030
1033
  onPickValue(undefined);
1031
1034
  }
1032
1035
  }, ref: element, className: css.cx(css.css({
@@ -4656,7 +4659,6 @@ const TabContainer = (p) => {
4656
4659
  };
4657
4660
 
4658
4661
  const defaultMinChars = 3;
4659
- /** Extracted logic around autocomplete functionality for Autocomplete.tsx. */
4660
4662
  class AutocompleteController {
4661
4663
  constructor(getOptions, config) {
4662
4664
  var _a;
@@ -4664,10 +4666,7 @@ class AutocompleteController {
4664
4666
  this._options = [];
4665
4667
  this._minChars = (_a = config === null || config === void 0 ? void 0 : config.minChars) !== null && _a !== void 0 ? _a : defaultMinChars;
4666
4668
  if (config === null || config === void 0 ? void 0 : config.debounceMs) {
4667
- this.getOptions = lodash.debounce(getOptions, config.debounceMs, {
4668
- leading: false,
4669
- trailing: true
4670
- });
4669
+ this.getOptions = createDebouncedPromise(getOptions, config === null || config === void 0 ? void 0 : config.debounceMs);
4671
4670
  }
4672
4671
  else {
4673
4672
  this.getOptions = getOptions;
@@ -4680,7 +4679,6 @@ class AutocompleteController {
4680
4679
  return this._options;
4681
4680
  }
4682
4681
  async onChange(newValue) {
4683
- var _a;
4684
4682
  // don't make getOptions calls if the value hasn't changed.
4685
4683
  if (newValue === this.value) {
4686
4684
  return;
@@ -4699,19 +4697,46 @@ class AutocompleteController {
4699
4697
  }
4700
4698
  try {
4701
4699
  this._value = newValue;
4702
- // debounce (if used) will return undefined until the actual function is executed.
4703
- // after that it will return the result of the last execution.
4704
- this._options = (_a = (await this.getOptions(newValue))) !== null && _a !== void 0 ? _a : [];
4700
+ this._options = (await this.getOptions(newValue));
4705
4701
  }
4706
4702
  catch (err) {
4707
- // the getOptions method needs to handle it's own errors
4703
+ // this method will throw errors on debounce rejections. that is to be expected.
4704
+ // for actual getOptions exceptions, the owner of that function will need to handle errors.
4708
4705
  }
4709
4706
  }
4710
4707
  onPick(newValue) {
4711
4708
  this._value = newValue;
4712
4709
  this._options = [];
4713
4710
  }
4714
- }
4711
+ }
4712
+ const createDebouncedPromise = (originalFunction, trailingTimeoutMs) => {
4713
+ let timer;
4714
+ let onCancel;
4715
+ return (value) => {
4716
+ if (timer) {
4717
+ clearTimeout(timer);
4718
+ }
4719
+ if (onCancel) {
4720
+ onCancel('Promise cancelled due to in-progress debounce call.');
4721
+ onCancel = undefined;
4722
+ }
4723
+ return new Promise((res, rej) => {
4724
+ onCancel = rej;
4725
+ timer = setTimeout(() => {
4726
+ originalFunction(value)
4727
+ .then(values => {
4728
+ res(values);
4729
+ })
4730
+ .catch(err => {
4731
+ rej(err);
4732
+ })
4733
+ .finally(() => {
4734
+ clearTimeout(timer);
4735
+ });
4736
+ }, trailingTimeoutMs);
4737
+ });
4738
+ };
4739
+ };
4715
4740
 
4716
4741
  /** Extracted logic around autocomplete functionality for Autocomplete.tsx that supports Entity (id/name) mapping. */
4717
4742
  class AutocompleteEntityController {
@@ -4736,7 +4761,11 @@ class AutocompleteEntityController {
4736
4761
  return this._options.map(o => o.name);
4737
4762
  }
4738
4763
  async onChange(newValue) {
4764
+ const clearEntity = newValue !== this._ctrl.value;
4739
4765
  await this._ctrl.onChange(newValue);
4766
+ if (clearEntity) {
4767
+ this._pickedEntity = undefined;
4768
+ }
4740
4769
  this.trySyncCtrlOptions();
4741
4770
  }
4742
4771
  onPick(newValue) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mackin.com/styleguide",
3
- "version": "9.2.0",
3
+ "version": "9.2.3",
4
4
  "description": "",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",