Skip to content

Commit 184dffa

Browse files
committed
fix: when data array is null it shouldn't throw
- fix null data error thrown & couple of other fixes
1 parent d3147eb commit 184dffa

File tree

10 files changed

+469
-39
lines changed

10 files changed

+469
-39
lines changed

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
tsconfig.json
2+
tsconfig.tsbuildinfo

demo/src/options/options26.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ export default class Example {
77
mount() {
88
this.ms1 = multipleSelect('#basic', {
99
styler: (row: OptionRowData | OptGroupRowData) => {
10-
if (+row.value === 1) {
10+
if (+(row?.value ?? 0) === 1) {
1111
return 'background-color: #ffee00; color: #ff0000;';
1212
}
13-
if (+row.value === 6) {
13+
if (+(row?.value ?? 0) === 6) {
1414
return 'background-color: #000; color: #fff;';
1515
}
1616
return null;
@@ -19,10 +19,10 @@ export default class Example {
1919

2020
this.ms2 = multipleSelect('#group', {
2121
styler: (row: OptionRowData | OptGroupRowData) => {
22-
if (row.type === 'optgroup') {
22+
if (row?.type === 'optgroup') {
2323
return 'color: #777; font-weight: normal;';
2424
}
25-
if (+row.value === 1) {
25+
if (+(row?.value ?? 0) === 1) {
2626
return 'color: blue;';
2727
}
2828
return null;

demo/src/options/options27.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ <h2 class="bd-title">
1717
</span>
1818
</span>
1919
</h2>
20-
<div class="demo-subtitle">Use <code>textTemplate</code> to custom the text template.</div>
20+
<div class="demo-subtitle">Use <code>textTemplate</code> to customize the text template.</div>
2121
</div>
2222
</div>
2323

lib/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
"scripts": {
4141
"clean": "rimraf dist",
4242
"build": "pnpm build:all && pnpm build:types:prod",
43+
"builder": "vite build && vite build --config vite-locales.config.ts",
44+
"build:vite": "vite build",
45+
"build:vite2": "vite build --config vite-locales.config.ts",
4346
"postbuild": "run-s sass:build sass:copy --npm-path pnpm",
4447
"dev:init": "pnpm sass:build && pnpm build:locales && pnpm sass:copy && pnpm build:types && pnpm build:esm",
4548
"build:all": "node build-prod.mjs && pnpm build:types:prod",
@@ -67,6 +70,8 @@
6770
"postcss": "^8.4.21",
6871
"postcss-cli": "^10.1.0",
6972
"sass": "^1.58.3",
70-
"typescript": "^5.0.0-beta"
73+
"typescript": "^5.0.0-rc",
74+
"vite": "^4.1.2",
75+
"vite-plugin-dts": "^2.0.2"
7176
}
7277
}

lib/src/MultipleSelectInstance.ts

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
} from './utils/domUtils';
1616
import { BindingEventService, VirtualScroll } from './services';
1717
import { MultipleSelectOption } from './interfaces/multipleSelectOption.interface';
18-
import { MultipleSelectLocales, OptGroupRowData, OptionRowData } from './interfaces';
18+
import { MultipleSelectLocales, OptGroupRowData, OptionDataObject, OptionRowData } from './interfaces';
1919

2020
export class MultipleSelectInstance {
2121
protected _bindEventService: BindingEventService;
@@ -25,7 +25,7 @@ export class MultipleSelectInstance {
2525
protected closeElm?: HTMLElement | null;
2626
protected filterText = '';
2727
protected updateData: any[] = [];
28-
protected data: OptionRowData[] = [];
28+
protected data?: Array<OptionRowData | OptGroupRowData> = [];
2929
protected dataTotal?: any;
3030
protected dropElm!: HTMLDivElement;
3131
protected okButtonElm?: HTMLButtonElement;
@@ -253,7 +253,7 @@ export class MultipleSelectInstance {
253253
}
254254

255255
protected initData() {
256-
const data: any[] = [];
256+
const data: Array<OptionRowData> = [];
257257

258258
if (this.options.data) {
259259
if (Array.isArray(this.options.data)) {
@@ -267,10 +267,10 @@ export class MultipleSelectInstance {
267267
return it;
268268
});
269269
} else if (typeof this.options.data === 'object') {
270-
for (const [value, text] of Object.entries(this.options.data)) {
270+
for (const [value, text] of Object.entries(this.options.data as OptionDataObject)) {
271271
data.push({
272272
value,
273-
text,
273+
text: `${text}`,
274274
});
275275
}
276276
this.data = data;
@@ -288,7 +288,7 @@ export class MultipleSelectInstance {
288288
this.fromHtml = true;
289289
}
290290

291-
this.dataTotal = setDataKeys(this.data);
291+
this.dataTotal = setDataKeys(this.data || []);
292292
}
293293

294294
protected initRow(elm: HTMLOptionElement, groupDisabled?: boolean) {
@@ -361,7 +361,7 @@ export class MultipleSelectInstance {
361361

362362
let length = 0;
363363
for (const option of this.data || []) {
364-
if (option.type === 'optgroup') {
364+
if ((option as OptGroupRowData).type === 'optgroup') {
365365
length += (option as OptGroupRowData).children.length;
366366
} else {
367367
length += 1;
@@ -436,8 +436,8 @@ export class MultipleSelectInstance {
436436
if (this.updateDataStart < 0) {
437437
this.updateDataStart = 0;
438438
}
439-
if (this.updateDataEnd > this.data.length) {
440-
this.updateDataEnd = this.data.length;
439+
if (this.updateDataEnd > (this.data?.length ?? 0)) {
440+
this.updateDataEnd = this.data?.length ?? 0;
441441
}
442442
}
443443
};
@@ -476,7 +476,7 @@ export class MultipleSelectInstance {
476476
const rows = [];
477477

478478
this.updateData = [];
479-
this.data.forEach((row) => {
479+
this.data?.forEach((row) => {
480480
rows.push(...this.initListItem(row));
481481
});
482482

@@ -572,7 +572,7 @@ export class MultipleSelectInstance {
572572
let selectedTotal = 0;
573573

574574
for (const row of this.data || []) {
575-
if (row.type === 'optgroup') {
575+
if ((row as OptGroupRowData).type === 'optgroup') {
576576
const selectedCount = (row as OptGroupRowData).children.filter((child) => {
577577
return child && child.selected && !child.disabled && child.visible;
578578
}).length;
@@ -593,9 +593,9 @@ export class MultipleSelectInstance {
593593
}
594594

595595
this.allSelected =
596-
this.data.filter((row: OptionRowData) => {
596+
this.data?.filter((row: OptionRowData | OptGroupRowData) => {
597597
return row.selected && !row.disabled && row.visible;
598-
}).length === this.data.filter((row) => !row.disabled && row.visible && !row.divider).length;
598+
}).length === this.data?.filter((row) => !row.disabled && row.visible && !row.divider).length;
599599

600600
if (!ignoreTrigger) {
601601
if (this.allSelected) {
@@ -806,7 +806,7 @@ export class MultipleSelectInstance {
806806
this.noResultsElm.style.display = 'none';
807807
}
808808

809-
if (!this.data.length) {
809+
if (!this.data?.length) {
810810
if (this.selectAllElm?.parentElement) {
811811
this.selectAllElm.parentElement.style.display = 'none';
812812
}
@@ -849,7 +849,7 @@ export class MultipleSelectInstance {
849849
const multElms = this.dropElm.querySelectorAll<HTMLDivElement>('.multiple');
850850
multElms.forEach((multElm) => (multElm.style.width = `${this.options.multipleWidth}px`));
851851

852-
if (this.data.length && this.options.filter) {
852+
if (this.data?.length && this.options.filter) {
853853
if (this.searchInputElm) {
854854
this.searchInputElm.value = '';
855855
this.searchInputElm.focus();
@@ -988,7 +988,7 @@ export class MultipleSelectInstance {
988988
}
989989
}
990990

991-
const noResult = this.data.filter((row) => row.visible).length === 0;
991+
const noResult = this.data?.filter((row) => row.visible).length === 0;
992992

993993
if (this.selectAllElm) {
994994
this.selectAllElm.checked = this.allSelected;
@@ -1037,7 +1037,7 @@ export class MultipleSelectInstance {
10371037
getSelects(type = 'value') {
10381038
const values = [];
10391039
for (const row of this.data || []) {
1040-
if (row.type === 'optgroup') {
1040+
if ((row as OptGroupRowData).type === 'optgroup') {
10411041
const selectedChildren = (row as OptGroupRowData).children.filter((child) => child?.selected);
10421042
if (!selectedChildren.length) {
10431043
continue;
@@ -1052,13 +1052,13 @@ export class MultipleSelectInstance {
10521052
} else {
10531053
const value = [];
10541054
value.push('[');
1055-
value.push(row.label);
1055+
value.push((row as OptGroupRowData).label);
10561056
value.push(`: ${selectedChildren.map((child: any) => child[type]).join(', ')}`);
10571057
value.push(']');
10581058
values.push(value.join(''));
10591059
}
10601060
} else if (row.selected) {
1061-
values.push(type === 'value' ? row._value || row[type] : (row as any)[type]);
1061+
values.push(type === 'value' ? row._value || (row as OptionRowData)[type] : (row as any)[type]);
10621062
}
10631063
}
10641064
return values;
@@ -1085,7 +1085,7 @@ export class MultipleSelectInstance {
10851085
};
10861086

10871087
for (const row of this.data || []) {
1088-
if (row.type === 'optgroup') {
1088+
if ((row as OptGroupRowData).type === 'optgroup') {
10891089
_setSelects((row as OptGroupRowData).children);
10901090
} else {
10911091
_setSelects([row]);
@@ -1143,7 +1143,7 @@ export class MultipleSelectInstance {
11431143

11441144
protected _checkAll(checked: boolean, ignoreUpdate?: boolean) {
11451145
for (const row of this.data || []) {
1146-
if (row.type === 'optgroup') {
1146+
if ((row as OptGroupRowData).type === 'optgroup') {
11471147
this._checkGroup(row, checked, true);
11481148
} else if (!row.disabled && !row.divider && (ignoreUpdate || row.visible)) {
11491149
row.selected = checked;
@@ -1177,7 +1177,7 @@ export class MultipleSelectInstance {
11771177
return;
11781178
}
11791179
for (const row of this.data || []) {
1180-
if (row.type === 'optgroup') {
1180+
if ((row as OptGroupRowData).type === 'optgroup') {
11811181
for (const child of (row as OptGroupRowData).children) {
11821182
if (child) {
11831183
if (!child.divider) {
@@ -1221,9 +1221,9 @@ export class MultipleSelectInstance {
12211221
this.filterText = text;
12221222

12231223
for (const row of this.data || []) {
1224-
if (row.type === 'optgroup') {
1224+
if ((row as OptGroupRowData).type === 'optgroup') {
12251225
if (this.options.filterGroup) {
1226-
const rowLabel = `${row?.label ?? ''}`;
1226+
const rowLabel = `${(row as OptGroupRowData)?.label ?? ''}`;
12271227
if (row !== undefined && row !== null) {
12281228
const visible = this.options.customFilter(
12291229
removeDiacritics(rowLabel.toLowerCase()),
@@ -1242,7 +1242,7 @@ export class MultipleSelectInstance {
12421242
} else {
12431243
for (const child of (row as OptGroupRowData).children) {
12441244
if (child !== undefined && child !== null) {
1245-
const childText = `${child?.text ?? ''}`;
1245+
const childText = `${(child as OptionRowData)?.text ?? ''}`;
12461246
child.visible = this.options.customFilter(
12471247
removeDiacritics(childText.toLowerCase()),
12481248
removeDiacritics(text),
@@ -1254,7 +1254,7 @@ export class MultipleSelectInstance {
12541254
row.visible = (row as OptGroupRowData).children.filter((child: any) => child?.visible).length > 0;
12551255
}
12561256
} else {
1257-
const rowText = `${row?.text ?? ''}`;
1257+
const rowText = `${(row as OptionRowData)?.text ?? ''}`;
12581258
row.visible = this.options.customFilter(
12591259
removeDiacritics(rowText.toLowerCase()),
12601260
removeDiacritics(text),

lib/src/interfaces/interfaces.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1+
export type OptionDataObject = { [value: string]: number | string | boolean };
12
export interface OptionRowData {
2-
label?: string;
33
text: string;
44
value: string | number | boolean;
5-
type?: 'option' | 'optgroup';
65
divider?: string;
76
disabled?: boolean;
87
selected?: boolean | number;
98
visible?: boolean | string;
9+
type?: 'option' | 'optgroup';
1010
_key?: string;
1111
_value?: string | number | boolean;
1212
}
1313

14-
export interface OptGroupRowData extends OptionRowData {
15-
children: Array<OptionRowData | OptGroupRowData>;
14+
export interface OptGroupRowData extends Omit<OptionRowData, 'text' | 'value'> {
15+
label: string;
16+
value?: string | number | boolean;
17+
children: Array<OptionRowData>;
1618
}
1719

1820
export interface VirtualScrollOption {

lib/src/interfaces/multipleSelectOption.interface.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export interface MultipleSelectOption extends MultipleSelectLocale {
2626
countSelectedText?: string;
2727

2828
/** provide custom data */
29-
data?: any | any[];
29+
data?: { [value: string]: number | string | boolean } | Array<number | string | boolean | OptionRowData | OptGroupRowData>;
3030

3131
/** Delimiter to be displayed between each option */
3232
displayDelimiter: string;
@@ -153,10 +153,10 @@ export interface MultipleSelectOption extends MultipleSelectLocale {
153153
styler: (value: OptionRowData | OptGroupRowData) => string | boolean | null;
154154

155155
/** Returns HTML label attribute of a DOM element */
156-
labelTemplate: (elm: any) => any;
156+
labelTemplate: (elm: any) => string;
157157

158158
/** Returns HTML text template of a DOM element */
159-
textTemplate: (elm: any) => any;
159+
textTemplate: (elm: any) => string;
160160

161161
// --
162162
// Events

lib/vite-locales.config.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { defineConfig } from 'vite';
2+
import { resolve } from 'path';
3+
import path from 'node:path';
4+
import glob from 'glob';
5+
6+
const dirname = path.dirname(__filename);
7+
const localeFiles: string[] = glob.sync('src/locales/**/*.ts');
8+
const localeEntryPoints: string[] = [];
9+
const locales: string[] = [resolve(dirname, `src/locales/all-locales-index.ts`)];
10+
const localeInputs: { [locale: string]: string } = {
11+
all: resolve(dirname, `src/locales/all-locales-index.ts`),
12+
};
13+
14+
for (const localeFile of localeFiles) {
15+
// eslint-disable-next-line no-unused-vars
16+
const [_, locale] = localeFile.match(/multiple-select-(.*)\.ts$/) || [];
17+
if (locale && locale.length === 5) {
18+
// locales.push(locale);
19+
localeInputs[locale] = resolve(dirname, `src/locales/multiple-select-${locale}.ts`);
20+
localeEntryPoints.push(resolve(dirname, `src/locales/multiple-select-${locale}.ts`));
21+
}
22+
}
23+
24+
export default defineConfig({
25+
base: './',
26+
mode: 'library',
27+
build: {
28+
emptyOutDir: false,
29+
minify: true,
30+
sourcemap: false,
31+
lib: {
32+
entry: locales.map((locale) => resolve(dirname, `src/locales/multiple-select-${locale}.ts`)),
33+
// entry: [
34+
// resolve(dirname, 'src/locales/multiple-select-en-US.ts'),
35+
// resolve(dirname, 'src/locales/multiple-select-es-ES.ts'),
36+
// ],
37+
formats: ['es', 'cjs'],
38+
// name: 'multiple-select-all-locales',
39+
// fileName: ' multiple-select-all-locales',
40+
fileName: (format, entryName) => {
41+
if (entryName === 'all') {
42+
return `multiple-select-all-locales.${format === 'cjs' ? 'cjs' : 'js'}`;
43+
}
44+
return `locales/multiple-select-${entryName}.${format === 'cjs' ? 'cjs' : 'js'}`;
45+
},
46+
},
47+
rollupOptions: {
48+
input: localeInputs,
49+
// input: {
50+
// // inlineDynamicImports: false,
51+
// // all: resolve(dirname, 'src/locales/all-locales-index.ts'),
52+
// 'en-US': resolve(dirname, 'src/locales/multiple-select-en-US.ts'),
53+
// 'es-ES': resolve(dirname, 'src/locales/multiple-select-es-ES.ts'),
54+
// },
55+
// output: [
56+
// {
57+
// format: 'umd',
58+
// name: '[name]',
59+
// inlineDynamicImports: true,
60+
// entryFileNames: '[name].bundle.[format].js',
61+
// // entryFileNames: 'multiple-select.[format].js',
62+
// },
63+
// ],
64+
},
65+
},
66+
});

0 commit comments

Comments
 (0)