vanilla-jui 1.3.10 → 1.4.0
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/dist/index.d.ts +2927 -0
- package/dist/index.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +4 -3
- package/src/components/accordion.ts +522 -0
- package/src/components/drop.ts +497 -0
- package/src/components/flow.ts +1579 -0
- package/src/components/form.ts +953 -0
- package/src/components/{icons.js → icons.ts} +24 -11
- package/src/components/menu.ts +615 -0
- package/src/components/{modal.js → modal.ts} +560 -237
- package/src/components/offcanvas.ts +496 -0
- package/src/components/{pagination.js → pagination.ts} +251 -76
- package/src/components/parabola.ts +335 -0
- package/src/components/{sticky.js → sticky.ts} +123 -98
- package/src/components/{swiper.js → swiper.ts} +510 -232
- package/src/components/tabs.ts +984 -0
- package/src/components/theme.ts +437 -0
- package/src/components/toast.ts +371 -0
- package/src/components/toc.ts +385 -0
- package/src/components/tooltip.ts +179 -0
- package/src/components/validator.ts +596 -0
- package/src/core/{Component.js → Component.ts} +134 -27
- package/src/css/accordion.css +2 -2
- package/src/css/animation.css +31 -1
- package/src/css/breadcrumb.css +1 -1
- package/src/css/button.css +5 -5
- package/src/css/card.css +7 -7
- package/src/css/color.css +865 -1028
- package/src/css/color_p3.css +871 -1036
- package/src/css/components.css +1 -0
- package/src/css/drop.css +1 -1
- package/src/css/flow.css +1 -1
- package/src/css/form.css +21 -21
- package/src/css/gradient.css +17 -4
- package/src/css/icon.css +17 -1
- package/src/css/index.css +3 -3
- package/src/css/layout.css +1 -1
- package/src/css/menu.css +27 -27
- package/src/css/modal.css +10 -27
- package/src/css/offcanvas.css +2 -2
- package/src/css/pagination.css +1 -1
- package/src/css/popup.css +2 -2
- package/src/css/swiper.css +12 -12
- package/src/css/tabs.css +3 -2
- package/src/css/tag.css +3 -4
- package/src/css/theme-palette.css +6 -6
- package/src/css/tip.css +1 -1
- package/src/css/toast.css +8 -8
- package/src/css/tokens.css +197 -226
- package/src/css/toolbar.css +3 -3
- package/src/css/tooltip.css +1 -1
- package/src/index.ts +37 -0
- package/src/locales/{index.js → index.ts} +1 -2
- package/src/types.d.ts +1 -0
- package/src/utilities/browser.ts +131 -0
- package/src/utilities/cache.ts +57 -0
- package/src/utilities/core.ts +614 -0
- package/src/utilities/dom.ts +468 -0
- package/src/utilities/events.ts +106 -0
- package/src/utilities/http.ts +35 -0
- package/src/utilities/storage.ts +46 -0
- package/src/components/accordion.js +0 -373
- package/src/components/drop.js +0 -437
- package/src/components/flow.js +0 -1133
- package/src/components/form.js +0 -585
- package/src/components/menu.js +0 -422
- package/src/components/offcanvas.js +0 -332
- package/src/components/parabola.js +0 -295
- package/src/components/tabs.js +0 -746
- package/src/components/theme.js +0 -353
- package/src/components/toast.js +0 -329
- package/src/components/toc.js +0 -226
- package/src/components/tooltip.js +0 -86
- package/src/components/validator.js +0 -586
- package/src/css/toast.min.css +0 -1
- package/src/index.js +0 -45
- package/src/locales/index.min.js +0 -1
- package/src/utilities/browser.js +0 -111
- package/src/utilities/cache.js +0 -159
- package/src/utilities/core.js +0 -502
- package/src/utilities/debug.js +0 -103
- package/src/utilities/dom.js +0 -313
- package/src/utilities/events.js +0 -69
- package/src/utilities/http.js +0 -30
- package/src/utilities/legacy-dom.js +0 -179
- package/src/utilities/storage.js +0 -46
- /package/src/{components/components.js → css/themes/index.css} +0 -0
- /package/src/icons/{index.js → index.ts} +0 -0
|
@@ -7,30 +7,149 @@ import {
|
|
|
7
7
|
jsx,
|
|
8
8
|
} from 'vanilla-signal';
|
|
9
9
|
|
|
10
|
-
import Component
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import Component, {
|
|
11
|
+
type ComponentDOM,
|
|
12
|
+
type ComponentRuntime,
|
|
13
|
+
} from '../core/Component.ts';
|
|
14
|
+
import {
|
|
15
|
+
type ResolveSchema,
|
|
16
|
+
hasOwn,
|
|
17
|
+
resolveProps,
|
|
18
|
+
validateParam,
|
|
19
|
+
} from '../utilities/core.ts';
|
|
20
|
+
import { type DOMReference, q, requireContainer } from '../utilities/dom.ts';
|
|
21
|
+
import { icon } from './icons.ts';
|
|
22
|
+
|
|
23
|
+
export interface PaginationPage {
|
|
24
|
+
size: number;
|
|
25
|
+
current: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface PaginationCount {
|
|
29
|
+
sibling: number;
|
|
30
|
+
boundary: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface PaginationClassNames {
|
|
34
|
+
root: string;
|
|
35
|
+
list: string;
|
|
36
|
+
item: string;
|
|
37
|
+
more: string;
|
|
38
|
+
button: string;
|
|
39
|
+
buttonIcon: string;
|
|
40
|
+
buttonGhost: string;
|
|
41
|
+
active: string;
|
|
42
|
+
loading: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type PaginationClassNameConfig = Partial<PaginationClassNames>;
|
|
46
|
+
|
|
47
|
+
export interface PaginationProps extends Record<string, unknown> {
|
|
48
|
+
total?: number;
|
|
49
|
+
page?: Partial<PaginationPage>;
|
|
50
|
+
count?: Partial<PaginationCount>;
|
|
51
|
+
lock?: boolean;
|
|
52
|
+
onChange?:
|
|
53
|
+
| ((page: number, instance: Pagination) => void | Promise<unknown>)
|
|
54
|
+
| null;
|
|
55
|
+
className?: PaginationClassNameConfig;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface ResolvedPaginationProps extends Record<string, unknown> {
|
|
59
|
+
total: number;
|
|
60
|
+
page: PaginationPage;
|
|
61
|
+
count: PaginationCount;
|
|
62
|
+
lock: boolean;
|
|
63
|
+
onChange: NonNullable<PaginationProps['onChange']> | null;
|
|
64
|
+
className: PaginationClassNames;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface PaginationState extends Record<string, unknown> {
|
|
68
|
+
total: number;
|
|
69
|
+
page: PaginationPage;
|
|
70
|
+
count: PaginationCount;
|
|
71
|
+
pageCount: number;
|
|
72
|
+
locked: boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
interface PageItem {
|
|
76
|
+
type: 'page';
|
|
77
|
+
key: string;
|
|
78
|
+
page: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface MoreItem {
|
|
82
|
+
type: 'more';
|
|
83
|
+
key: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
type PaginationItem = PageItem | MoreItem;
|
|
87
|
+
type PageAction = 'prev' | 'next';
|
|
88
|
+
type Dispose = () => void;
|
|
89
|
+
type EffectDispose = { dispose: () => void };
|
|
90
|
+
|
|
91
|
+
interface PaginationDOM extends ComponentDOM {
|
|
92
|
+
root: HTMLElement | null;
|
|
93
|
+
container: Element | null;
|
|
94
|
+
list: HTMLElement | null;
|
|
95
|
+
prev: HTMLElement | null;
|
|
96
|
+
next: HTMLElement | null;
|
|
97
|
+
pageNodes: HTMLElement[];
|
|
98
|
+
items: PaginationItem[];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface PaginationRuntime extends ComponentRuntime {
|
|
102
|
+
built: boolean;
|
|
103
|
+
itemsKey: string;
|
|
104
|
+
changeId: number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface PaginationCleanupExtras {
|
|
108
|
+
controls?: Dispose | null;
|
|
109
|
+
itemsEffect?: EffectDispose | null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const DEFAULT_CLASS_NAMES: PaginationClassNames = {
|
|
113
|
+
root: 'j-pagination',
|
|
114
|
+
list: 'pagination',
|
|
115
|
+
item: 'item',
|
|
116
|
+
more: 'more',
|
|
117
|
+
button: 'j-button',
|
|
118
|
+
buttonIcon: 'is-icon',
|
|
119
|
+
buttonGhost: 'is-ghost',
|
|
120
|
+
active: 'is-active',
|
|
121
|
+
loading: 'animate-spin',
|
|
122
|
+
};
|
|
14
123
|
|
|
15
124
|
const PAGE_RULE = {
|
|
16
125
|
type: 'object',
|
|
17
126
|
required: true,
|
|
18
|
-
validate: (value) =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
127
|
+
validate: (value: unknown) => {
|
|
128
|
+
const page = value as Partial<PaginationPage>;
|
|
129
|
+
return (
|
|
130
|
+
!!page &&
|
|
131
|
+
Number.isInteger(page.size) &&
|
|
132
|
+
Number(page.size) > 0 &&
|
|
133
|
+
Number.isInteger(page.current) &&
|
|
134
|
+
Number(page.current) > 0
|
|
135
|
+
);
|
|
136
|
+
},
|
|
23
137
|
message: 'expects { size, current } with positive integers.',
|
|
24
138
|
};
|
|
25
139
|
|
|
26
140
|
const COUNT_RULE = {
|
|
27
141
|
type: 'object',
|
|
28
142
|
required: true,
|
|
29
|
-
validate: (value) =>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
143
|
+
validate: (value: unknown) => {
|
|
144
|
+
const count = value as Partial<PaginationCount>;
|
|
145
|
+
return (
|
|
146
|
+
!!count &&
|
|
147
|
+
Number.isInteger(count.sibling) &&
|
|
148
|
+
Number(count.sibling) >= 0 &&
|
|
149
|
+
Number.isInteger(count.boundary) &&
|
|
150
|
+
Number(count.boundary) >= 0
|
|
151
|
+
);
|
|
152
|
+
},
|
|
34
153
|
message:
|
|
35
154
|
'expects { sibling, boundary } with integers greater than or equal 0.',
|
|
36
155
|
};
|
|
@@ -39,7 +158,7 @@ const PAGINATION_PROPS_SCHEMA = {
|
|
|
39
158
|
total: {
|
|
40
159
|
default: 0,
|
|
41
160
|
type: 'number',
|
|
42
|
-
validate: (value) => Number.isFinite(value) && value >= 0,
|
|
161
|
+
validate: (value: unknown) => Number.isFinite(value) && Number(value) >= 0,
|
|
43
162
|
message: 'expects a non-negative finite number.',
|
|
44
163
|
},
|
|
45
164
|
page: {
|
|
@@ -54,40 +173,53 @@ const PAGINATION_PROPS_SCHEMA = {
|
|
|
54
173
|
},
|
|
55
174
|
lock: { default: true, type: 'boolean' },
|
|
56
175
|
onChange: { default: null, types: ['function', 'null'] },
|
|
57
|
-
|
|
176
|
+
className: {
|
|
177
|
+
default: DEFAULT_CLASS_NAMES,
|
|
178
|
+
type: 'object',
|
|
179
|
+
normalize: (value: unknown) => ({
|
|
180
|
+
...DEFAULT_CLASS_NAMES,
|
|
181
|
+
...(value && typeof value === 'object' ? value : {}),
|
|
182
|
+
}),
|
|
183
|
+
},
|
|
184
|
+
} satisfies ResolveSchema<PaginationProps>;
|
|
58
185
|
|
|
59
|
-
function clamp(value, min, max) {
|
|
186
|
+
function clamp(value: number, min: number, max: number): number {
|
|
60
187
|
return Math.min(Math.max(value, min), max);
|
|
61
188
|
}
|
|
62
189
|
|
|
63
|
-
function normalizeProps(input = {}) {
|
|
190
|
+
function normalizeProps(input: PaginationProps = {}): ResolvedPaginationProps {
|
|
64
191
|
const props = resolveProps(
|
|
65
192
|
input,
|
|
66
193
|
PAGINATION_PROPS_SCHEMA,
|
|
67
194
|
'Pagination.props'
|
|
68
|
-
);
|
|
195
|
+
) as ResolvedPaginationProps;
|
|
69
196
|
return {
|
|
70
197
|
...props,
|
|
71
198
|
page: { ...props.page },
|
|
72
199
|
count: { ...props.count },
|
|
200
|
+
className: { ...props.className },
|
|
73
201
|
};
|
|
74
202
|
}
|
|
75
203
|
|
|
76
|
-
function createMoreItem(key) {
|
|
204
|
+
function createMoreItem(key: string): MoreItem {
|
|
77
205
|
return { type: 'more', key };
|
|
78
206
|
}
|
|
79
207
|
|
|
80
|
-
function createPageItem(page) {
|
|
208
|
+
function createPageItem(page: number): PageItem {
|
|
81
209
|
return { type: 'page', key: `page-${page}`, page };
|
|
82
210
|
}
|
|
83
211
|
|
|
84
|
-
function pageRange(start, end) {
|
|
85
|
-
const pages = [];
|
|
212
|
+
function pageRange(start: number, end: number): number[] {
|
|
213
|
+
const pages: number[] = [];
|
|
86
214
|
for (let page = start; page <= end; page++) pages.push(page);
|
|
87
215
|
return pages;
|
|
88
216
|
}
|
|
89
217
|
|
|
90
|
-
function resolvePageItems(
|
|
218
|
+
function resolvePageItems(
|
|
219
|
+
current: number,
|
|
220
|
+
pageCount: number,
|
|
221
|
+
count: PaginationCount
|
|
222
|
+
): PaginationItem[] {
|
|
91
223
|
if (pageCount <= 0) return [];
|
|
92
224
|
|
|
93
225
|
const boundary = Math.max(0, count.boundary);
|
|
@@ -98,7 +230,7 @@ function resolvePageItems(current, pageCount, count) {
|
|
|
98
230
|
return pageRange(1, pageCount).map(createPageItem);
|
|
99
231
|
}
|
|
100
232
|
|
|
101
|
-
const pages = new Set();
|
|
233
|
+
const pages = new Set<number>();
|
|
102
234
|
|
|
103
235
|
for (let page = 1; page <= Math.min(boundary, pageCount); page++) {
|
|
104
236
|
pages.add(page);
|
|
@@ -121,10 +253,10 @@ function resolvePageItems(current, pageCount, count) {
|
|
|
121
253
|
}
|
|
122
254
|
|
|
123
255
|
const sorted = Array.from(pages).sort((a, b) => a - b);
|
|
124
|
-
const items = [];
|
|
256
|
+
const items: PaginationItem[] = [];
|
|
125
257
|
|
|
126
258
|
for (const page of sorted) {
|
|
127
|
-
const previous = items.
|
|
259
|
+
const previous = items[items.length - 1];
|
|
128
260
|
if (previous?.type === 'page' && page - previous.page > 1) {
|
|
129
261
|
if (page - previous.page === 2) {
|
|
130
262
|
items.push(createPageItem(previous.page + 1));
|
|
@@ -144,13 +276,17 @@ function resolvePageItems(current, pageCount, count) {
|
|
|
144
276
|
* 构造器只验证和保存配置;调用 build() 后才挂载 DOM 和绑定交互。
|
|
145
277
|
*/
|
|
146
278
|
export class Pagination extends Component {
|
|
279
|
+
declare props: ResolvedPaginationProps;
|
|
280
|
+
declare state: PaginationState;
|
|
281
|
+
declare dom: PaginationDOM;
|
|
282
|
+
declare runtime: PaginationRuntime;
|
|
283
|
+
declare cleanup: Component['cleanup'] & PaginationCleanupExtras;
|
|
284
|
+
|
|
147
285
|
/**
|
|
148
286
|
* @param {Element|Node|string|Array} container 挂载容器。
|
|
149
287
|
* @param {object} [input={}] 分页配置。
|
|
150
288
|
*/
|
|
151
|
-
constructor(container, input = {}) {
|
|
152
|
-
requireRenderDOM('Pagination');
|
|
153
|
-
|
|
289
|
+
constructor(container: DOMReference, input: PaginationProps = {}) {
|
|
154
290
|
const el = requireContainer(container, 'Pagination.container');
|
|
155
291
|
const props = normalizeProps(input);
|
|
156
292
|
super(props);
|
|
@@ -190,28 +326,32 @@ export class Pagination extends Component {
|
|
|
190
326
|
* 构建分页 DOM 并绑定事件。
|
|
191
327
|
* @returns {Pagination} 当前实例。
|
|
192
328
|
*/
|
|
193
|
-
build() {
|
|
329
|
+
build(): this {
|
|
194
330
|
this._assertActive('build');
|
|
195
331
|
if (this.runtime.built) return this;
|
|
196
332
|
|
|
197
333
|
this.init(this.props);
|
|
198
334
|
this.root = jsx('div', {
|
|
199
|
-
className:
|
|
335
|
+
className: this.props.className.root,
|
|
200
336
|
role: 'navigation',
|
|
201
337
|
'aria-label': 'Pagination',
|
|
338
|
+
'data-pagination': 'root',
|
|
202
339
|
children: jsx('ul', {
|
|
203
|
-
className:
|
|
340
|
+
className: this.props.className.list,
|
|
341
|
+
'data-pagination-list': '',
|
|
204
342
|
'aria-live': 'polite',
|
|
205
343
|
}),
|
|
206
|
-
});
|
|
344
|
+
}) as HTMLElement;
|
|
207
345
|
|
|
208
|
-
this.dom.list =
|
|
346
|
+
this.dom.list = q<HTMLElement>('[data-pagination-list]', this.root);
|
|
209
347
|
this.dom.prev = this._buildControlItem('prev');
|
|
210
348
|
this.dom.next = this._buildControlItem('next');
|
|
211
|
-
this.dom.list
|
|
349
|
+
this.dom.list?.append(this.dom.prev, this.dom.next);
|
|
212
350
|
|
|
213
|
-
this.dom.container
|
|
214
|
-
|
|
351
|
+
const container = this.dom.container;
|
|
352
|
+
if (!container) return this;
|
|
353
|
+
container.textContent = '';
|
|
354
|
+
container.appendChild(this.root);
|
|
215
355
|
this.runtime.built = true;
|
|
216
356
|
|
|
217
357
|
this._bindControlState();
|
|
@@ -225,7 +365,7 @@ export class Pagination extends Component {
|
|
|
225
365
|
* @param {number} page 新页码。
|
|
226
366
|
* @returns {Pagination} 当前实例。
|
|
227
367
|
*/
|
|
228
|
-
go(page) {
|
|
368
|
+
go(page: number): this {
|
|
229
369
|
this._assertActive('go');
|
|
230
370
|
validateParam(
|
|
231
371
|
'page',
|
|
@@ -256,7 +396,7 @@ export class Pagination extends Component {
|
|
|
256
396
|
this.props.page.current = nextPage;
|
|
257
397
|
|
|
258
398
|
if (typeof this.props.onChange === 'function') {
|
|
259
|
-
let result
|
|
399
|
+
let result: void | Promise<unknown>;
|
|
260
400
|
try {
|
|
261
401
|
result = this.props.onChange(nextPage, this);
|
|
262
402
|
} catch (error) {
|
|
@@ -292,7 +432,7 @@ export class Pagination extends Component {
|
|
|
292
432
|
* @param {object} [newProps={}] 新配置,会与当前 props 合并。
|
|
293
433
|
* @returns {Pagination} 当前实例。
|
|
294
434
|
*/
|
|
295
|
-
update(newProps = {}) {
|
|
435
|
+
update(newProps: PaginationProps = {}): this {
|
|
296
436
|
this._assertActive('update');
|
|
297
437
|
validateParam(
|
|
298
438
|
'newProps',
|
|
@@ -303,10 +443,14 @@ export class Pagination extends Component {
|
|
|
303
443
|
|
|
304
444
|
const props = normalizeProps({
|
|
305
445
|
total: newProps.total ?? this.props.total,
|
|
306
|
-
lock:
|
|
307
|
-
onChange:
|
|
446
|
+
lock: hasOwn(newProps, 'lock') ? newProps.lock : this.props.lock,
|
|
447
|
+
onChange: hasOwn(newProps, 'onChange')
|
|
308
448
|
? newProps.onChange
|
|
309
449
|
: this.props.onChange,
|
|
450
|
+
className: {
|
|
451
|
+
...this.props.className,
|
|
452
|
+
...newProps.className,
|
|
453
|
+
},
|
|
310
454
|
page: {
|
|
311
455
|
...this.props.page,
|
|
312
456
|
...newProps.page,
|
|
@@ -333,11 +477,11 @@ export class Pagination extends Component {
|
|
|
333
477
|
return this;
|
|
334
478
|
}
|
|
335
479
|
|
|
336
|
-
_getPageCount(total, size) {
|
|
480
|
+
_getPageCount(total: number, size: number): number {
|
|
337
481
|
return Math.max(1, Math.ceil(total / size));
|
|
338
482
|
}
|
|
339
483
|
|
|
340
|
-
_getPageItems() {
|
|
484
|
+
_getPageItems(): PaginationItem[] {
|
|
341
485
|
return resolvePageItems(
|
|
342
486
|
this.state.page.current,
|
|
343
487
|
this.state.pageCount,
|
|
@@ -345,7 +489,7 @@ export class Pagination extends Component {
|
|
|
345
489
|
);
|
|
346
490
|
}
|
|
347
491
|
|
|
348
|
-
_getItemsKey() {
|
|
492
|
+
_getItemsKey(): string {
|
|
349
493
|
return [
|
|
350
494
|
this.state.page.current,
|
|
351
495
|
this._isLocked() ? 'locked' : 'unlocked',
|
|
@@ -353,66 +497,84 @@ export class Pagination extends Component {
|
|
|
353
497
|
].join('|');
|
|
354
498
|
}
|
|
355
499
|
|
|
356
|
-
_isLocked() {
|
|
500
|
+
_isLocked(): boolean {
|
|
357
501
|
return this.props.lock && this.state.locked;
|
|
358
502
|
}
|
|
359
503
|
|
|
360
|
-
_isPrevDisabled() {
|
|
504
|
+
_isPrevDisabled(): boolean {
|
|
361
505
|
return this._isLocked() || this.state.page.current <= 1;
|
|
362
506
|
}
|
|
363
507
|
|
|
364
|
-
_isNextDisabled() {
|
|
508
|
+
_isNextDisabled(): boolean {
|
|
365
509
|
return this._isLocked() || this.state.page.current >= this.state.pageCount;
|
|
366
510
|
}
|
|
367
511
|
|
|
368
|
-
|
|
512
|
+
_buttonClass(...extra: string[]): string {
|
|
513
|
+
const { button, buttonIcon, buttonGhost } = this.props.className;
|
|
514
|
+
return [button, buttonIcon, buttonGhost, ...extra]
|
|
515
|
+
.filter(Boolean)
|
|
516
|
+
.join(' ');
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
_buildControlItem(type: PageAction): HTMLElement {
|
|
369
520
|
const item = jsx('li', {
|
|
370
|
-
className:
|
|
521
|
+
className: this.props.className.item,
|
|
522
|
+
'data-pagination-control': type,
|
|
371
523
|
children: jsx('button', {
|
|
372
|
-
className:
|
|
524
|
+
className: this._buttonClass(),
|
|
373
525
|
type: 'button',
|
|
374
526
|
'data-page-action': type,
|
|
375
527
|
children: icon(type === 'prev' ? 'arrow-left' : 'arrow-right'),
|
|
376
528
|
}),
|
|
377
|
-
});
|
|
529
|
+
}) as HTMLElement;
|
|
378
530
|
|
|
379
531
|
return item;
|
|
380
532
|
}
|
|
381
533
|
|
|
382
|
-
_buildPageItem(item) {
|
|
534
|
+
_buildPageItem(item: PaginationItem): HTMLElement {
|
|
383
535
|
const disabled = this._isLocked();
|
|
384
536
|
|
|
385
537
|
if (item.type === 'more') {
|
|
386
538
|
return jsx('li', {
|
|
387
|
-
className:
|
|
539
|
+
className: [this.props.className.item, this.props.className.more]
|
|
540
|
+
.filter(Boolean)
|
|
541
|
+
.join(' '),
|
|
542
|
+
'data-pagination-more': item.key,
|
|
388
543
|
'aria-hidden': 'true',
|
|
389
544
|
children: jsx('button', {
|
|
390
|
-
className:
|
|
545
|
+
className: this._buttonClass(),
|
|
391
546
|
type: 'button',
|
|
392
547
|
disabled,
|
|
393
548
|
children: icon('more'),
|
|
394
549
|
}),
|
|
395
|
-
});
|
|
550
|
+
}) as HTMLElement;
|
|
396
551
|
}
|
|
397
552
|
|
|
398
553
|
return jsx('li', {
|
|
399
|
-
className:
|
|
554
|
+
className: this.props.className.item,
|
|
555
|
+
'data-pagination-item': String(item.page),
|
|
400
556
|
children:
|
|
401
557
|
item.page === this.state.page.current
|
|
402
558
|
? jsx('span', {
|
|
403
|
-
className:
|
|
559
|
+
className: [
|
|
560
|
+
this.props.className.button,
|
|
561
|
+
this.props.className.buttonIcon,
|
|
562
|
+
this.props.className.active,
|
|
563
|
+
]
|
|
564
|
+
.filter(Boolean)
|
|
565
|
+
.join(' '),
|
|
404
566
|
'data-current-page': String(item.page),
|
|
405
567
|
'aria-current': 'page',
|
|
406
568
|
'aria-label': `Page ${item.page}, current page`,
|
|
407
569
|
children: disabled
|
|
408
570
|
? jsx('i', {
|
|
409
|
-
className:
|
|
571
|
+
className: this.props.className.loading,
|
|
410
572
|
children: icon('loader'),
|
|
411
573
|
})
|
|
412
574
|
: String(item.page),
|
|
413
575
|
})
|
|
414
576
|
: jsx('button', {
|
|
415
|
-
className:
|
|
577
|
+
className: this._buttonClass(),
|
|
416
578
|
type: 'button',
|
|
417
579
|
'data-page': String(item.page),
|
|
418
580
|
'aria-label': `Go to page ${item.page}`,
|
|
@@ -421,17 +583,20 @@ export class Pagination extends Component {
|
|
|
421
583
|
tabindex: disabled ? '-1' : null,
|
|
422
584
|
children: String(item.page),
|
|
423
585
|
}),
|
|
424
|
-
});
|
|
586
|
+
}) as HTMLElement;
|
|
425
587
|
}
|
|
426
588
|
|
|
427
|
-
_bindControlState() {
|
|
589
|
+
_bindControlState(): void {
|
|
428
590
|
this.cleanup.controls?.();
|
|
429
591
|
this.cleanup.controls = createRoot((dispose) => {
|
|
430
|
-
const prev = this.dom.prev
|
|
431
|
-
|
|
592
|
+
const prev = this.dom.prev
|
|
593
|
+
? q<HTMLButtonElement>('[data-page-action]', this.dom.prev)
|
|
594
|
+
: null;
|
|
595
|
+
const next = this.dom.next
|
|
596
|
+
? q<HTMLButtonElement>('[data-page-action]', this.dom.next)
|
|
597
|
+
: null;
|
|
432
598
|
|
|
433
599
|
if (prev) {
|
|
434
|
-
// bindClass(prev, 'is-disabled', () => this._isPrevDisabled());
|
|
435
600
|
bindAttr(prev, 'disabled', () => this._isPrevDisabled());
|
|
436
601
|
bindAttr(prev, 'aria-disabled', () =>
|
|
437
602
|
this._isPrevDisabled() ? 'true' : 'false'
|
|
@@ -443,7 +608,6 @@ export class Pagination extends Component {
|
|
|
443
608
|
}
|
|
444
609
|
|
|
445
610
|
if (next) {
|
|
446
|
-
// bindClass(next, 'is-disabled', () => this._isNextDisabled());
|
|
447
611
|
bindAttr(next, 'disabled', () => this._isNextDisabled());
|
|
448
612
|
bindAttr(next, 'aria-disabled', () =>
|
|
449
613
|
this._isNextDisabled() ? 'true' : 'false'
|
|
@@ -458,7 +622,7 @@ export class Pagination extends Component {
|
|
|
458
622
|
});
|
|
459
623
|
}
|
|
460
624
|
|
|
461
|
-
_bindPageItems() {
|
|
625
|
+
_bindPageItems(): void {
|
|
462
626
|
this.cleanup.itemsEffect?.dispose();
|
|
463
627
|
this.cleanup.itemsEffect = createEffect(() => {
|
|
464
628
|
const nextKey = this._getItemsKey();
|
|
@@ -469,8 +633,9 @@ export class Pagination extends Component {
|
|
|
469
633
|
});
|
|
470
634
|
}
|
|
471
635
|
|
|
472
|
-
_renderPageItems() {
|
|
636
|
+
_renderPageItems(): void {
|
|
473
637
|
this.dom.items = [];
|
|
638
|
+
if (!this.dom.list || !this.dom.next) return;
|
|
474
639
|
|
|
475
640
|
const items = this._getPageItems();
|
|
476
641
|
const nodes = items.map((item) => this._buildPageItem(item));
|
|
@@ -480,10 +645,17 @@ export class Pagination extends Component {
|
|
|
480
645
|
for (const node of nodes) this.dom.list.insertBefore(node, this.dom.next);
|
|
481
646
|
}
|
|
482
647
|
|
|
483
|
-
_bindEvents() {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
648
|
+
_bindEvents(): void {
|
|
649
|
+
const root = this.root;
|
|
650
|
+
if (!root) return;
|
|
651
|
+
this.cleanup.events.on('click', root, 'click', (event) => {
|
|
652
|
+
const source = event.target;
|
|
653
|
+
if (!(source instanceof Element)) return;
|
|
654
|
+
|
|
655
|
+
const target = source.closest<HTMLElement>(
|
|
656
|
+
'[data-page], [data-page-action]'
|
|
657
|
+
);
|
|
658
|
+
if (!target || !root.contains(target)) return;
|
|
487
659
|
|
|
488
660
|
event.preventDefault();
|
|
489
661
|
|
|
@@ -504,13 +676,13 @@ export class Pagination extends Component {
|
|
|
504
676
|
});
|
|
505
677
|
}
|
|
506
678
|
|
|
507
|
-
_assertActive(method) {
|
|
679
|
+
_assertActive(method: string): void {
|
|
508
680
|
if (this.runtime.destroyed) {
|
|
509
681
|
throw new Error(`Pagination.${method}: instance has been destroyed.`);
|
|
510
682
|
}
|
|
511
683
|
}
|
|
512
684
|
|
|
513
|
-
onDestroy() {
|
|
685
|
+
protected onDestroy(): void {
|
|
514
686
|
this.cleanup.events.clear();
|
|
515
687
|
this.cleanup.controls?.();
|
|
516
688
|
this.cleanup.itemsEffect?.dispose();
|
|
@@ -531,6 +703,9 @@ export class Pagination extends Component {
|
|
|
531
703
|
}
|
|
532
704
|
}
|
|
533
705
|
|
|
534
|
-
export function createPagination(
|
|
706
|
+
export function createPagination(
|
|
707
|
+
container: DOMReference,
|
|
708
|
+
props: PaginationProps = {}
|
|
709
|
+
): Pagination {
|
|
535
710
|
return new Pagination(container, props);
|
|
536
711
|
}
|