Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Yegor G committed Oct 11, 2023
2 parents f118bc0 + 3306490 commit 22ea1c8
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 17 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.10.2 (\_\_\_)

**Fixes**:

-[SelectControl](src/controls/select.ts). [SelectManyControl](src/controls/selectMany.ts). _Error message in console if `$options.items = new Promise` & `$initValue = ...`_

## 0.10.1 (Oct 10, 2023)

**BREAKING CHANGES**:
Expand All @@ -13,7 +19,7 @@
- **Text based controls**
- _Label doesn't go to top on browser autofill_
- _Value missed & undo/redo failed on browser autofill_
- [SelectManyControl](src/controls/selectMany.ts).
- [SelectManyControl](src/controls/selectMany.ts)
- _Showing button[clear] on hover changes height_
- _Focus sometimes is wrong when user removes item & reverts changes via click on button[clear=back]_

Expand Down
2 changes: 2 additions & 0 deletions demo/src/components/controls/check.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
transition: background-color var(--anim);
}
}

// todo change hover style
}

[wupdark] .anotherStyle {
Expand Down
6 changes: 4 additions & 2 deletions demo/src/components/controls/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ export default function SelectControlView() {
if (el) {
el.$options.name = "withPending";
el.$options.label = "With pending (set Promise to $options.items)";
el.$options.items = () => new Promise((resolve) => setTimeout(() => resolve(items), 3000));
// el.$initValue = 13;
setTimeout(() => {
el.$options.items = () => new Promise((res) => setTimeout(() => res(items), 3000));
el.$initValue = 13; // was issue here - items not fetched yet
}, 100);
}
}}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/controls/password.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export default class WUPPasswordControl<
:host input[type='password'] {
font-family: Verdana, sans-serif;
letter-spacing: 0.125;
${"margin-bottom: -1px;" /* font Verdana affects on height */}
${"margin-bottom: -1px;" /* font Verdana affects on height // todo somehow it's wrong on other apps */}
}
:host button[eye] {
cursor: pointer;
Expand Down
25 changes: 14 additions & 11 deletions src/controls/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ export default class WUPSelectControl<
/** Called to get/fetch items based on $options.items */
fetchItems(): Promise<WUP.Select.MenuItems<ValueType>> | WUP.Select.MenuItems<ValueType> {
this._cachedItems = undefined;
this.#findValT && clearTimeout(this.#findValT); // prevent setIinputValue if fetchItems is started
this.#findValT = undefined;
const { items } = this._opts;

let d: any = items;
Expand All @@ -298,14 +300,16 @@ export default class WUPSelectControl<
const act = (): void => {
this._onPendingInitValue?.call(this);
delete this._onPendingInitValue;
this.setInputValue(this.$value, SetValueReasons.clear);
this.setInputValue(this.$value, SetValueReasons.clear); // NiceToHave: .clear is wrong need new reason
this.setupInputReadonly(); // call it because opt readonlyInput can depends on items.length
};
if (d instanceof Promise) {
return promiseWait(d, 300, (v) => this.changePending(v)).then((data) => {
this._cachedItems = data || [];
act();
this.$isFocused && setTimeout(() => this.goShowMenu(ShowCases.onFocus, null)); // timeout required to showMenu after pending changes
Promise.resolve().finally(() => {
this._cachedItems = data || [];
act();
this.$isFocused && this.goShowMenu(ShowCases.onFocus, null);
}); // empty promise required to showMenu after pending changes
return data;
});
}
Expand Down Expand Up @@ -477,14 +481,13 @@ export default class WUPSelectControl<
protected override setInputValue(v: ValueType | undefined, reason: SetValueReasons): void {
this.#findValT && clearTimeout(this.#findValT);
this.#findValT = undefined;
if (this._cachedItems) {
if (reason === SetValueReasons.manual || reason === SetValueReasons.initValue) {
this.#findValT = setTimeout(() => super.setInputValue(v, reason), 2); // timeout to fix case when el.$options.items=... el.$value=...
} else {
super.setInputValue(v, reason);
}
if (this.$isPending) {
return; // decline because setInputValue will be fired after pending
}
if (reason === SetValueReasons.manual || reason === SetValueReasons.initValue) {
this.#findValT = setTimeout(() => super.setInputValue(v, reason), 2); // timeout to fix case when el.$options.items=... el.$value=...
} else {
// skip because it's fired from fetchItems()
super.setInputValue(v, reason);
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/controls/selectMany.ts
Original file line number Diff line number Diff line change
Expand Up @@ -744,3 +744,6 @@ when popup is opened => don't change bottom...top if menu or control height chan
*/

// NiceToHave: Ctrl+Z must should work for the whole control. Not only for `input`

// todo don't allow items affects on width - sometimes flex: wrap doesn't work
// todo add option autoheight & use vert-scroll if it's disabled (now it works with autoheight: true)
2 changes: 2 additions & 0 deletions src/controls/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,3 +772,5 @@ export default class WUPTextControl<
customElements.define(tagName, WUPTextControl);
// todo example how to create bult-in dropdown before the main input (like phone-number with ability to select countryCode)
// gotInput > setMask > parseValue >... setValue ....> toString > setInput > setMask

// todo fix when hover changes control size because btnClear appears
3 changes: 3 additions & 0 deletions test/jest/controls/control.select.com.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -642,11 +642,14 @@ describe("control.select common", () => {
await h.wait(1);
expect(el.$refInput.readOnly).toBe(true);

el.$options.readOnlyInput = false;
el.$options.items = Promise.resolve(getItems());
jest.advanceTimersByTime(1); // WARN: jest can catch exception here after tests are finished
expect(el.$isPending).toBe(true);
expect(el.$refInput.readOnly).toBe(true); // because isPending
await h.wait();
expect(el.$isPending).toBe(false);
expect(el.$isReadOnly).toBe(false);
expect(el.$refInput.readOnly).toBe(false);
});
});
Expand Down
46 changes: 44 additions & 2 deletions test/jest/controls/control.select.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe("control.select", () => {
expect(el.$refInput.value).toBe("Donny");
});

test("$options.items & $value", () => {
test("$options.items & $value", async () => {
el = document.body.appendChild(document.createElement(el.tagName));
const onErr = h.mockConsoleError();
// before ready
Expand Down Expand Up @@ -132,6 +132,46 @@ describe("control.select", () => {
el.$value = { id: 2 };
jest.advanceTimersByTime(2);
expect(el.$refInput.value).toBe("Diana");

// different $initValue & items
onErr.mockClear();
el = document.body.appendChild(document.createElement(el.tagName));
el.$options.items = [
{ text: "Helica", value: 1 },
{ text: "Diana", value: 2 },
{ text: "Ann", value: 3 },
];
el.$initValue = 2;
await h.wait();
expect(el.$refInput.value).toBe("Diana");
expect(onErr).toBeCalledTimes(0);
// set init value after a time
el.$options.items = [
{ text: "A", value: 4 },
{ text: "B", value: 5 },
];
el.$initValue = 4;
await h.wait();
expect(el.$refInput.value).toBe("A");
expect(onErr).toBeCalledTimes(0);
// set items as Promise
el.$options.items = new Promise((res) => {
setTimeout(
() =>
res([
{ text: "C", value: 10 },
{ text: "D", value: 20 },
{ text: "f", value: 30 },
]),
100
);
});
el.$initValue = 30;
await h.wait();
expect(el.$refInput.value).toBe("f");
expect(onErr).toBeCalledTimes(0);

h.unMockConsoleError();
});

test("pending state", async () => {
Expand Down Expand Up @@ -160,7 +200,7 @@ describe("control.select", () => {
const mockRequest = jest.fn();
el.$options.items = () => {
mockRequest();
return new Promise((resolve) => setTimeout(() => resolve(getItems()), 100));
return new Promise((res) => setTimeout(() => res(getItems()), 100));
};
await h.wait(1);
expect(el.$refInput.value).toBe("");
Expand All @@ -173,6 +213,7 @@ describe("control.select", () => {
// await h.userClick(el); // WARN; somehow it blocks Promise.resolve - it's test-issue
await h.wait();
expect(el.$isShown).toBe(false);
expect(el.$isPending).toBe(false);
expect(el.$refInput.value).toBe("Donny");
expect(mockRequest).toBeCalledTimes(1);

Expand All @@ -198,6 +239,7 @@ describe("control.select", () => {
await h.wait();
expect(el.$isShown).toBe(false);

el.$value = undefined;
el.$options.items = () => Promise.resolve(null);
await h.wait();
expect(el._cachedItems).toStrictEqual([]); // empty array to avoid future bugs if somehow fetch returns nothing
Expand Down

0 comments on commit 22ea1c8

Please sign in to comment.