Skip to content

Commit 4947f4d

Browse files
authored
Refactor, feat: Select dialog (#1275)
* refactor: select dialog * feat: checkbox to select dialog * fix: forget logs * docs(select dialog): add missing JSDoc comments - Add missing `checkbox` property in jsDoc. * Update(select dialog): Add extra condition to if statement * fix(select dialog): format * format
1 parent fdbf2e5 commit 4947f4d

File tree

1 file changed

+84
-58
lines changed

1 file changed

+84
-58
lines changed

src/dialogs/select.js

Lines changed: 84 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Checkbox from "components/checkbox";
12
import tile from "components/tile";
23
import actionStack from "lib/actionStack";
34
import restoreTheme from "lib/restoreTheme";
@@ -11,84 +12,110 @@ import restoreTheme from "lib/restoreTheme";
1112
* @property {function():void} [onHide]
1213
*/
1314

15+
/**
16+
* @typedef {object} SelectItem
17+
* @property {string} [value]
18+
* @property {string} [text]
19+
* @property {string} [icon]
20+
* @property {boolean} [disabled]
21+
* @property {string} [letters]
22+
* @property {boolean} [checkbox]
23+
*/
24+
1425
/**
1526
* Create a select dialog
1627
* @param {string} title Title of the select
17-
* @param {string[]} options [value, text, icon, disable?] or string
18-
* @param {SelectOptions | boolean} opts options or rejectOnCancel
28+
* @param {string | string[] | SelectItem} items Object or [value, text, icon, disable?, letters?, checkbox?] or String
29+
* @param {SelectOptions | boolean} options options or rejectOnCancel
1930
* @returns {Promise<string>}
2031
*/
21-
function select(title, options, opts = {}) {
32+
function select(title, items, options = {}) {
2233
let rejectOnCancel = false;
23-
if (typeof opts === "boolean") {
24-
rejectOnCancel = opts;
25-
opts = {};
34+
if (typeof options === "boolean") {
35+
rejectOnCancel = options;
36+
options = {};
2637
}
27-
return new Promise((resolve, reject) => {
28-
const $titleSpan = title ? (
29-
<strong className="title">{title}</strong>
30-
) : null;
31-
const $list = (
32-
<ul
33-
className={`scroll ${opts.textTransform === false ? " no-text-transform" : ""}`}
34-
></ul>
35-
);
36-
const selectDiv = (
38+
39+
return new Promise((res, rej) => {
40+
const { textTransform = false, hideOnSelect = true } = options;
41+
let $defaultVal;
42+
43+
// elements
44+
const $mask = <span className="mask" onclick={cancel}></span>;
45+
const $list = tag("ul", {
46+
className: "scroll" + !textTransform ? " no-text-transform" : "",
47+
});
48+
const $select = (
3749
<div className="prompt select">
38-
{$titleSpan ? [$titleSpan, $list] : $list}
50+
{title ? <strong className="title">{title}</strong> : ""}
51+
{$list}
3952
</div>
4053
);
41-
const mask = <span className="mask" onclick={cancel}></span>;
42-
let $defaultVal;
4354

44-
if (opts.hideOnSelect === undefined) opts.hideOnSelect = true;
45-
46-
options.map((option) => {
47-
let value = null;
48-
let text = null;
49-
let lead = null;
50-
let disabled = false;
51-
if (Array.isArray(option)) {
52-
value = option[0];
53-
text = option[1];
54-
55-
if (option.length > 2 && typeof option[2] === "string") {
56-
const icon = option[2];
57-
if (icon === "letters") {
58-
const letters = option[4];
59-
lead = <i className="icon letters" data-letters={letters}></i>;
60-
} else {
61-
lead = <i className={`icon ${icon}`}></i>;
62-
}
55+
items.map((item) => {
56+
let lead,
57+
tail,
58+
itemOptions = {
59+
value: null,
60+
text: null,
61+
icon: null,
62+
disabled: false,
63+
letters: "",
64+
checkbox: null,
65+
};
66+
67+
// init item options
68+
if (typeof item === "object") {
69+
if (Array.isArray(item)) {
70+
Object.keys(itemOptions).forEach(
71+
(key, i) => (itemOptions[key] = item[i]),
72+
);
73+
} else {
74+
itemOptions = Object.assign({}, itemOptions, item);
75+
}
76+
} else {
77+
itemOptions.value = item;
78+
itemOptions.text = item;
79+
}
80+
81+
// handle icon
82+
if (itemOptions.icon) {
83+
if (itemOptions.icon === "letters" && !!itemOptions.letters) {
84+
lead = (
85+
<i className="icon letters" data-letters={itemOptions.letters}></i>
86+
);
87+
} else {
88+
lead = <i className={`icon ${itemOptions.icon}`}></i>;
6389
}
90+
}
6491

65-
option.map((o, i) => {
66-
if (typeof o === "boolean" && i > 1) disabled = !o;
92+
// handle checkbox
93+
if (itemOptions.checkbox != null) {
94+
tail = Checkbox({
95+
checked: itemOptions.checkbox,
6796
});
68-
} else {
69-
value = text = option;
7097
}
7198

7299
const $item = tile({
73100
lead,
74-
text: <span className="text" innerHTML={text}></span>,
101+
tail,
102+
text: <span className="text" innerHTML={itemOptions.text}></span>,
75103
});
76104

77-
if (opts.default === value) {
105+
$item.tabIndex = "0";
106+
if (itemOptions.disabled) $item.classList.add("disabled");
107+
if (options.default === itemOptions.value) {
78108
$item.classList.add("selected");
79109
$defaultVal = $item;
80110
}
81111

82-
$item.tabIndex = "0";
83-
112+
// handle events
84113
$item.onclick = function () {
85-
if (value === undefined) return;
86-
if (opts.hideOnSelect) hide();
87-
resolve(value);
114+
if (!itemOptions.value) return;
115+
if (hideOnSelect) hide();
116+
res(itemOptions.value);
88117
};
89118

90-
if (disabled) $item.classList.add("disabled");
91-
92119
$list.append($item);
93120
});
94121

@@ -97,31 +124,30 @@ function select(title, options, opts = {}) {
97124
action: cancel,
98125
});
99126

100-
app.append(selectDiv, mask);
127+
app.append($select, $mask);
101128
if ($defaultVal) $defaultVal.scrollIntoView();
102129

103130
const $firstChild = $defaultVal || $list.firstChild;
104131
if ($firstChild && $firstChild.focus) $firstChild.focus();
105-
106132
restoreTheme(true);
107133

108134
function cancel() {
109135
hide();
110-
if (typeof opts.onCancel === "function") opts.onCancel();
136+
if (typeof options.onCancel === "function") options.onCancel();
111137
if (rejectOnCancel) reject();
112138
}
113139

114140
function hideSelect() {
115-
selectDiv.classList.add("hide");
141+
$select.classList.add("hide");
116142
restoreTheme();
117143
setTimeout(() => {
118-
selectDiv.remove();
119-
mask.remove();
144+
$select.remove();
145+
$mask.remove();
120146
}, 300);
121147
}
122148

123149
function hide() {
124-
if (typeof opts.onHide === "function") opts.onHide();
150+
if (typeof options.onHide === "function") options.onHide();
125151
actionStack.remove("select");
126152
hideSelect();
127153
let listItems = [...$list.children];

0 commit comments

Comments
 (0)