fwtoolkit 0.1.0-alpha.7 → 0.1.0-beta.1

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 (107) hide show
  1. package/dist/basic.d.ts +49 -36
  2. package/dist/basic.d.ts.map +1 -1
  3. package/dist/basic.js +58 -39
  4. package/dist/basic.js.map +1 -1
  5. package/dist/blob.d.ts +1 -1
  6. package/dist/blob.d.ts.map +1 -1
  7. package/dist/blob.js +0 -1
  8. package/dist/blob.js.map +1 -1
  9. package/dist/content_menu.d.ts +63 -20
  10. package/dist/content_menu.d.ts.map +1 -1
  11. package/dist/content_menu.js +21 -18
  12. package/dist/content_menu.js.map +1 -1
  13. package/dist/datatable_bulk.d.ts +34 -6
  14. package/dist/datatable_bulk.d.ts.map +1 -1
  15. package/dist/datatable_bulk.js +4 -5
  16. package/dist/datatable_bulk.js.map +1 -1
  17. package/dist/dialog.d.ts +82 -7
  18. package/dist/dialog.d.ts.map +1 -1
  19. package/dist/dialog.js +21 -16
  20. package/dist/dialog.js.map +1 -1
  21. package/dist/events.d.ts +1 -1
  22. package/dist/events.d.ts.map +1 -1
  23. package/dist/events.js +3 -3
  24. package/dist/events.js.map +1 -1
  25. package/dist/faq_dialog.d.ts +13 -4
  26. package/dist/faq_dialog.d.ts.map +1 -1
  27. package/dist/faq_dialog.js +4 -2
  28. package/dist/faq_dialog.js.map +1 -1
  29. package/dist/file/dialog.d.ts +33 -13
  30. package/dist/file/dialog.d.ts.map +1 -1
  31. package/dist/file/dialog.js +6 -8
  32. package/dist/file/dialog.js.map +1 -1
  33. package/dist/file/index.d.ts.map +1 -1
  34. package/dist/file/index.js +0 -1
  35. package/dist/file/index.js.map +1 -1
  36. package/dist/file/new_folder_dialog.d.ts +5 -2
  37. package/dist/file/new_folder_dialog.d.ts.map +1 -1
  38. package/dist/file/new_folder_dialog.js +1 -2
  39. package/dist/file/new_folder_dialog.js.map +1 -1
  40. package/dist/file/selector.d.ts +47 -14
  41. package/dist/file/selector.d.ts.map +1 -1
  42. package/dist/file/selector.js +11 -9
  43. package/dist/file/selector.js.map +1 -1
  44. package/dist/file/templates.d.ts +1 -1
  45. package/dist/file/templates.d.ts.map +1 -1
  46. package/dist/file/templates.js +0 -1
  47. package/dist/file/templates.js.map +1 -1
  48. package/dist/file/tools.d.ts +4 -4
  49. package/dist/file/tools.d.ts.map +1 -1
  50. package/dist/file/tools.js +4 -4
  51. package/dist/file/tools.js.map +1 -1
  52. package/dist/focus.d.ts +1 -1
  53. package/dist/focus.d.ts.map +1 -1
  54. package/dist/focus.js +5 -5
  55. package/dist/focus.js.map +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +0 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/network.d.ts +19 -7
  60. package/dist/network.d.ts.map +1 -1
  61. package/dist/network.js +15 -12
  62. package/dist/network.js.map +1 -1
  63. package/dist/overview_menu.d.ts +77 -18
  64. package/dist/overview_menu.d.ts.map +1 -1
  65. package/dist/overview_menu.js +53 -34
  66. package/dist/overview_menu.js.map +1 -1
  67. package/dist/settings.d.ts +7 -2
  68. package/dist/settings.d.ts.map +1 -1
  69. package/dist/settings.js +0 -1
  70. package/dist/settings.js.map +1 -1
  71. package/dist/user.d.ts +8 -2
  72. package/dist/user.d.ts.map +1 -1
  73. package/dist/user.js +1 -2
  74. package/dist/user.js.map +1 -1
  75. package/dist/worker.d.ts +1 -1
  76. package/dist/worker.d.ts.map +1 -1
  77. package/dist/worker.js +1 -2
  78. package/dist/worker.js.map +1 -1
  79. package/dist/ws.d.ts +59 -25
  80. package/dist/ws.d.ts.map +1 -1
  81. package/dist/ws.js +19 -15
  82. package/dist/ws.js.map +1 -1
  83. package/package.json +1 -1
  84. package/src/basic.ts +136 -69
  85. package/src/blob.ts +1 -2
  86. package/src/content_menu.ts +125 -42
  87. package/src/datatable_bulk.ts +72 -35
  88. package/src/dialog.ts +156 -61
  89. package/src/diff-dom.d.ts +16 -0
  90. package/src/events.ts +3 -3
  91. package/src/faq_dialog.ts +25 -11
  92. package/src/file/dialog.ts +48 -14
  93. package/src/file/index.ts +0 -1
  94. package/src/file/new_folder_dialog.ts +7 -5
  95. package/src/file/selector.ts +86 -36
  96. package/src/file/templates.ts +2 -3
  97. package/src/file/tools.ts +17 -8
  98. package/src/focus.ts +11 -13
  99. package/src/global.d.ts +11 -4
  100. package/src/index.ts +0 -1
  101. package/src/network.ts +58 -20
  102. package/src/overview_menu.ts +182 -108
  103. package/src/settings.ts +9 -4
  104. package/src/user.ts +10 -5
  105. package/src/w3c-keyname.d.ts +3 -0
  106. package/src/worker.ts +1 -2
  107. package/src/ws.ts +115 -50
@@ -1,4 +1,59 @@
1
- // @ts-nocheck
1
+ export type ContentMenuItemTitle = string | ((page: unknown) => string)
2
+
3
+ export interface ContentMenuBaseItem {
4
+ type?: "header" | "separator" | "action"
5
+ title?: ContentMenuItemTitle
6
+ tooltip?: string
7
+ action?: (page: unknown) => void
8
+ disabled?: (page: unknown) => boolean
9
+ selected?: boolean
10
+ order?: number
11
+ icon?: string
12
+ }
13
+
14
+ export interface ContentMenuHeaderItem extends ContentMenuBaseItem {
15
+ type: "header"
16
+ title: ContentMenuItemTitle
17
+ }
18
+
19
+ export interface ContentMenuSeparatorItem extends ContentMenuBaseItem {
20
+ type: "separator"
21
+ }
22
+
23
+ export interface ContentMenuActionItem extends ContentMenuBaseItem {
24
+ type?: "action"
25
+ title: ContentMenuItemTitle
26
+ action: (page: unknown) => void
27
+ }
28
+
29
+ export type ContentMenuItem =
30
+ | ContentMenuHeaderItem
31
+ | ContentMenuSeparatorItem
32
+ | ContentMenuActionItem
33
+
34
+ export interface ContentMenuInit {
35
+ content: ContentMenuItem[]
36
+ }
37
+
38
+ export interface ContentMenuPosition {
39
+ X: number
40
+ Y: number
41
+ }
42
+
43
+ export interface ContentMenuOptions {
44
+ id?: string | false
45
+ page?: unknown | false
46
+ classes?: string | false
47
+ menu?: ContentMenuInit
48
+ height?: number | false
49
+ width?: number | false
50
+ onClose?: (() => void) | false
51
+ scroll?: boolean | false
52
+ dialogEl?: HTMLElement | false
53
+ backdropEl?: HTMLElement | false
54
+ menuPos?: ContentMenuPosition | false
55
+ }
56
+
2
57
  const menuTemplate = ({
3
58
  id,
4
59
  classes,
@@ -8,6 +63,15 @@ const menuTemplate = ({
8
63
  menu,
9
64
  scroll,
10
65
  page
66
+ }: {
67
+ id: string | false
68
+ classes: string | false
69
+ height: string
70
+ width: string
71
+ zIndex: number
72
+ menu: ContentMenuInit
73
+ scroll: boolean | false
74
+ page: unknown | false
11
75
  }) =>
12
76
  `<div tabindex="-1" role="incontent_menu"
13
77
  class="ui-content-menu ui-corner-all ui-widget ui-widget-content ui-front"
@@ -19,7 +83,7 @@ const menuTemplate = ({
19
83
  .map((menuItem, index) => {
20
84
  switch (menuItem.type) {
21
85
  case "header":
22
- return `<li><span class="content-menu-item-header" title="${menuItem.tooltip}">${
86
+ return `<li><span class="content-menu-item-header" title="${menuItem.tooltip || ""}">${
23
87
  typeof menuItem.title === "function"
24
88
  ? menuItem.title(page)
25
89
  : menuItem.title
@@ -33,7 +97,7 @@ const menuTemplate = ({
33
97
  : menuItem.selected
34
98
  ? " selected"
35
99
  : ""
36
- }" title='${menuItem.tooltip}'>
100
+ }" title='${menuItem.tooltip || ""}'>
37
101
  ${
38
102
  typeof menuItem.title === "function"
39
103
  ? menuItem.title(page)
@@ -54,6 +118,21 @@ const menuTemplate = ({
54
118
  <div class="ui-widget-overlay ui-front" style="z-index: ${zIndex - 1}"></div>`
55
119
 
56
120
  export class ContentMenu {
121
+ id: string | false
122
+ page: unknown | false
123
+ classes: string | false
124
+ menu: ContentMenuInit
125
+ height: string
126
+ width: string
127
+ onClose: (() => void) | false
128
+ scroll: boolean | false
129
+ dialogEl!: HTMLElement
130
+ backdropEl!: HTMLElement
131
+ menuPos: ContentMenuPosition | false
132
+
133
+ focusedIndex: number
134
+ previouslyFocusedElement: Element | null
135
+
57
136
  constructor({
58
137
  id = false,
59
138
  page = false,
@@ -66,7 +145,7 @@ export class ContentMenu {
66
145
  dialogEl = false,
67
146
  backdropEl = false,
68
147
  menuPos = false
69
- }) {
148
+ }: ContentMenuOptions = {}) {
70
149
  this.id = id
71
150
  this.page = page
72
151
  this.classes = classes
@@ -75,15 +154,15 @@ export class ContentMenu {
75
154
  this.width = width ? `${width}px` : "auto"
76
155
  this.onClose = onClose
77
156
  this.scroll = scroll
78
- this.dialogEl = dialogEl
79
- this.backdropEl = backdropEl
157
+ this.dialogEl = (dialogEl || null) as HTMLElement
158
+ this.backdropEl = (backdropEl || null) as HTMLElement
80
159
  this.menuPos = menuPos
81
160
 
82
161
  this.focusedIndex = 0
83
162
  this.previouslyFocusedElement = null
84
163
  }
85
164
 
86
- open() {
165
+ open(): void {
87
166
  if (this.dialogEl) {
88
167
  return
89
168
  }
@@ -103,9 +182,10 @@ export class ContentMenu {
103
182
  page: this.page
104
183
  })
105
184
  )
106
- this.backdropEl = document.body.lastElementChild
107
- this.dialogEl = this.backdropEl.previousElementSibling
108
- if (this.menuPos?.X && this.menuPos?.Y) {
185
+ this.backdropEl = document.body.lastElementChild as HTMLElement
186
+ this.dialogEl = this.backdropEl
187
+ .previousElementSibling as HTMLElement
188
+ if (this.menuPos && this.menuPos.X && this.menuPos.Y) {
109
189
  this.positionDialog()
110
190
  } else {
111
191
  this.centerDialog()
@@ -115,7 +195,7 @@ export class ContentMenu {
115
195
  this.focusFirstMenuItem()
116
196
  }
117
197
 
118
- renderColumnsHtml(columns) {
198
+ renderColumnsHtml(columns: number): string {
119
199
  const itemsPerColumn = Math.ceil(this.menu.content.length / columns)
120
200
  let html = '<div class="content-menu-columns">'
121
201
  for (let col = 0; col < columns; col++) {
@@ -132,7 +212,7 @@ export class ContentMenu {
132
212
  const menuItem = this.menu.content[i]
133
213
  switch (menuItem.type) {
134
214
  case "header":
135
- html += `<li><span class="content-menu-item-header" title="${menuItem.tooltip}">${
215
+ html += `<li><span class="content-menu-item-header" title="${menuItem.tooltip || ""}">${
136
216
  typeof menuItem.title === "function"
137
217
  ? menuItem.title(this.page)
138
218
  : menuItem.title
@@ -149,7 +229,7 @@ export class ContentMenu {
149
229
  : menuItem.selected
150
230
  ? " selected"
151
231
  : ""
152
- }" title='${menuItem.tooltip}'>
232
+ }" title='${menuItem.tooltip || ""}'>
153
233
  ${
154
234
  typeof menuItem.title === "function"
155
235
  ? menuItem.title(this.page)
@@ -168,7 +248,7 @@ export class ContentMenu {
168
248
  return html
169
249
  }
170
250
 
171
- checkAndAddColumns() {
251
+ checkAndAddColumns(): void {
172
252
  const dialogRect = this.dialogEl.getBoundingClientRect()
173
253
  const viewportHeight = window.innerHeight
174
254
  const viewportWidth = window.innerWidth
@@ -178,8 +258,8 @@ export class ContentMenu {
178
258
  if (dialogRect.height >= maxHeight) {
179
259
  const contentEl = this.dialogEl.querySelector(
180
260
  ".ui-content-menu-content"
181
- )
182
- const contentDiv = contentEl.querySelector(":scope > div")
261
+ ) as HTMLElement
262
+ const contentDiv = contentEl.querySelector(":scope > div") as HTMLElement
183
263
  let columns = 2
184
264
  while (columns <= 6) {
185
265
  contentDiv.innerHTML = this.renderColumnsHtml(columns)
@@ -192,7 +272,7 @@ export class ContentMenu {
192
272
  }
193
273
  const newRect = this.dialogEl.getBoundingClientRect()
194
274
  if (newRect.height < maxHeight && newRect.width < maxWidth) {
195
- if (this.menuPos?.X && this.menuPos?.Y) {
275
+ if (this.menuPos && this.menuPos.X && this.menuPos.Y) {
196
276
  this.positionDialog()
197
277
  } else {
198
278
  this.centerDialog()
@@ -205,9 +285,9 @@ export class ContentMenu {
205
285
  contentDiv.innerHTML = `<ul class="content-menu-list">${this.renderSingleColumnHtml()}</ul>`
206
286
  contentEl.style.width = this.width
207
287
  this.dialogEl
208
- .querySelector(".ui-content-menu-content")
288
+ .querySelector(".ui-content-menu-content")!
209
289
  .classList.add("ui-scrollable")
210
- if (this.menuPos?.X && this.menuPos?.Y) {
290
+ if (this.menuPos && this.menuPos.X && this.menuPos.Y) {
211
291
  this.positionDialog()
212
292
  } else {
213
293
  this.centerDialog()
@@ -215,12 +295,12 @@ export class ContentMenu {
215
295
  }
216
296
  }
217
297
 
218
- renderSingleColumnHtml() {
298
+ renderSingleColumnHtml(): string {
219
299
  return this.menu.content
220
300
  .map((menuItem, index) => {
221
301
  switch (menuItem.type) {
222
302
  case "header":
223
- return `<li><span class="content-menu-item-header" title="${menuItem.tooltip}">${
303
+ return `<li><span class="content-menu-item-header" title="${menuItem.tooltip || ""}">${
224
304
  typeof menuItem.title === "function"
225
305
  ? menuItem.title(this.page)
226
306
  : menuItem.title
@@ -234,7 +314,7 @@ export class ContentMenu {
234
314
  : menuItem.selected
235
315
  ? " selected"
236
316
  : ""
237
- }" title='${menuItem.tooltip}'>
317
+ }" title='${menuItem.tooltip || ""}'>
238
318
  ${
239
319
  typeof menuItem.title === "function"
240
320
  ? menuItem.title(this.page)
@@ -250,7 +330,7 @@ export class ContentMenu {
250
330
  .join("")
251
331
  }
252
332
 
253
- centerDialog() {
333
+ centerDialog(): void {
254
334
  const totalWidth = window.innerWidth,
255
335
  totalHeight = window.innerHeight,
256
336
  dialogRect = this.dialogEl.getBoundingClientRect(),
@@ -262,7 +342,7 @@ export class ContentMenu {
262
342
  this.dialogEl.style.left = `${(totalWidth - dialogWidth) / 2 + scrollLeftOffset}px`
263
343
  }
264
344
 
265
- positionDialog() {
345
+ positionDialog(): void {
266
346
  const dialogHeight = this.dialogEl.getBoundingClientRect().height + 10,
267
347
  dialogWidth = this.dialogEl.getBoundingClientRect().width + 10,
268
348
  scrollTopOffset = window.pageYOffset,
@@ -271,8 +351,8 @@ export class ContentMenu {
271
351
 
272
352
  // We try to ensure that the menu is seen in the browser at the preferred location.
273
353
  // Adjustments are made in case it doesn't fit.
274
- let top = this.menuPos.Y,
275
- left = this.menuPos.X
354
+ let top = this.menuPos ? this.menuPos.Y : 0,
355
+ left = this.menuPos ? this.menuPos.X : 0
276
356
 
277
357
  if (top + dialogHeight > scrollTopOffset + clientHeight) {
278
358
  top -= top + dialogHeight - (scrollTopOffset + clientHeight)
@@ -290,7 +370,7 @@ export class ContentMenu {
290
370
  this.dialogEl.style.left = `${left}px`
291
371
  }
292
372
 
293
- bind() {
373
+ bind(): void {
294
374
  this.backdropEl.addEventListener("click", () => this.close())
295
375
  this.dialogEl.addEventListener("click", event => this.onclick(event))
296
376
  this.dialogEl.addEventListener("keydown", event =>
@@ -299,34 +379,34 @@ export class ContentMenu {
299
379
  this.dialogEl.focus()
300
380
  }
301
381
 
302
- getHighestDialogZIndex() {
382
+ getHighestDialogZIndex(): number {
303
383
  let zIndex = 100
304
384
  document
305
385
  .querySelectorAll("div.ui-content-menu")
306
386
  .forEach(
307
- dialogEl => (zIndex = Math.max(zIndex, dialogEl.style.zIndex))
387
+ dialogEl => (zIndex = Math.max(zIndex, parseInt((dialogEl as HTMLElement).style.zIndex) || 100))
308
388
  )
309
389
  document
310
390
  .querySelectorAll("div.ui-dialog")
311
391
  .forEach(
312
- dialogEl => (zIndex = Math.max(zIndex, dialogEl.style.zIndex))
392
+ dialogEl => (zIndex = Math.max(zIndex, parseInt((dialogEl as HTMLElement).style.zIndex) || 100))
313
393
  )
314
394
  return zIndex
315
395
  }
316
396
 
317
- close() {
397
+ close(): void {
318
398
  if (!this.dialogEl || !this.dialogEl.parentElement) {
319
399
  return
320
400
  }
321
401
  this.dialogEl.parentElement.removeChild(this.dialogEl)
322
- this.backdropEl.parentElement.removeChild(this.backdropEl)
402
+ this.backdropEl.parentElement!.removeChild(this.backdropEl)
323
403
 
324
404
  // Restore focus to the previously focused element
325
405
  if (
326
406
  this.previouslyFocusedElement &&
327
- this.previouslyFocusedElement.focus
407
+ (this.previouslyFocusedElement as HTMLElement).focus
328
408
  ) {
329
- this.previouslyFocusedElement.focus()
409
+ (this.previouslyFocusedElement as HTMLElement).focus()
330
410
  }
331
411
 
332
412
  if (this.onClose) {
@@ -334,13 +414,16 @@ export class ContentMenu {
334
414
  }
335
415
  }
336
416
 
337
- onclick(event) {
417
+ onclick(event: MouseEvent): void {
338
418
  event.preventDefault()
339
419
  event.stopImmediatePropagation()
340
- const target = event.target.closest("li.content-menu-item")
420
+ const target = (event.target as Element).closest("li.content-menu-item") as HTMLElement
341
421
  if (target) {
342
422
  const menuNumber = target.dataset.index
343
- const menuItem = this.menu.content[menuNumber]
423
+ if (menuNumber === undefined) {
424
+ return
425
+ }
426
+ const menuItem = this.menu.content[parseInt(menuNumber)] as ContentMenuActionItem
344
427
  if (menuItem.disabled?.(this.page)) {
345
428
  return
346
429
  }
@@ -349,7 +432,7 @@ export class ContentMenu {
349
432
  }
350
433
  }
351
434
 
352
- onKeyDown(event) {
435
+ onKeyDown(event: KeyboardEvent): void {
353
436
  const {key} = event
354
437
  const menuItems = this.dialogEl.querySelectorAll(
355
438
  "li.content-menu-item:not(.disabled)"
@@ -445,7 +528,7 @@ export class ContentMenu {
445
528
  case "Enter":
446
529
  case " ": {
447
530
  event.preventDefault()
448
- const menuItem = this.menu.content[this.focusedIndex]
531
+ const menuItem = this.menu.content[this.focusedIndex] as ContentMenuActionItem
449
532
  if (!menuItem.disabled?.(this.page)) {
450
533
  menuItem.action(this.page)
451
534
  this.close()
@@ -455,7 +538,7 @@ export class ContentMenu {
455
538
  }
456
539
  }
457
540
 
458
- focusFirstMenuItem() {
541
+ focusFirstMenuItem(): void {
459
542
  const menuItems = this.dialogEl.querySelectorAll(
460
543
  "li.content-menu-item:not(.disabled)"
461
544
  )
@@ -465,12 +548,12 @@ export class ContentMenu {
465
548
  }
466
549
  }
467
550
 
468
- focusMenuItem(index) {
551
+ focusMenuItem(index: number): void {
469
552
  const menuItems = this.dialogEl.querySelectorAll(
470
553
  "li.content-menu-item:not(.disabled)"
471
554
  )
472
555
  if (menuItems[index]) {
473
- menuItems[index].focus()
556
+ (menuItems[index] as HTMLElement).focus()
474
557
  }
475
558
  }
476
559
  }
@@ -1,13 +1,50 @@
1
- // @ts-nocheck
2
1
  import {keyName} from "w3c-keyname"
3
2
 
4
3
  import {whenReady} from "./basic.js"
5
- import {ContentMenu} from "./content_menu.js"
4
+ import {ContentMenu, ContentMenuInit} from "./content_menu.js"
5
+
6
+ export interface DataTableCell {
7
+ data: unknown
8
+ text: string
9
+ }
10
+
11
+ export interface DataTableRow {
12
+ cells: DataTableCell[]
13
+ }
14
+
15
+ export interface DataTableData {
16
+ data: DataTableRow[]
17
+ }
18
+
19
+ export interface DataTable {
20
+ dom: HTMLElement
21
+ data: DataTableData
22
+ update: () => void
23
+ }
24
+
25
+ export interface DatatableBulkPage {
26
+ dom: HTMLElement
27
+ getSelected: () => unknown[]
28
+ }
6
29
 
7
30
  let bulkId = 0
8
31
 
9
32
  export class DatatableBulk {
10
- constructor(page, model, checkboxColumn) {
33
+ page: DatatableBulkPage
34
+ model: ContentMenuInit
35
+ checkboxColumn: number
36
+
37
+ id: string
38
+ table: DataTable | undefined
39
+ boundOnClick: ((event: MouseEvent) => void) | undefined
40
+ boundOnTableCheckChange: ((event: Event) => void) | undefined
41
+ boundOnKeyDown: ((event: KeyboardEvent) => void) | undefined
42
+
43
+ constructor(
44
+ page: DatatableBulkPage,
45
+ model: ContentMenuInit,
46
+ checkboxColumn: number
47
+ ) {
11
48
  this.page = page
12
49
  this.model = model
13
50
  this.checkboxColumn = checkboxColumn
@@ -15,31 +52,31 @@ export class DatatableBulk {
15
52
  this.id = `dt-bulk-${++bulkId}`
16
53
  }
17
54
 
18
- init(table) {
55
+ init(table: DataTable): void {
19
56
  this.table = table
20
57
  whenReady().then(() => this.bindEvents())
21
58
  }
22
59
 
23
- update() {
60
+ update(): void {
24
61
  this.model.content = this.model.content.sort(
25
- (a, b) => a.order - b.order
62
+ (a, b) => (a.order || 0) - (b.order || 0)
26
63
  )
27
64
  }
28
65
 
29
- bindEvents() {
66
+ bindEvents(): void {
30
67
  // Store the bound functions as instance variables so we can remove them later
31
68
  this.boundOnClick = this.onClick.bind(this)
32
69
  this.boundOnTableCheckChange = this.onTableCheckChange.bind(this)
33
70
  this.boundOnKeyDown = this.onKeyDown.bind(this)
34
71
 
35
72
  this.page.dom.addEventListener("click", this.boundOnClick)
36
- this.table.dom.addEventListener("change", this.boundOnTableCheckChange)
37
- this.table.dom.addEventListener("keydown", this.boundOnKeyDown)
73
+ this.table!.dom.addEventListener("change", this.boundOnTableCheckChange)
74
+ this.table!.dom.addEventListener("keydown", this.boundOnKeyDown)
38
75
  this.onTableCheckChange()
39
76
  }
40
77
 
41
78
  // The new destroy() method removes all event listeners that were added and cleans up DOM elements.
42
- destroy() {
79
+ destroy(): void {
43
80
  if (this.page && this.page.dom && this.boundOnClick) {
44
81
  this.page.dom.removeEventListener("click", this.boundOnClick)
45
82
  }
@@ -65,12 +102,12 @@ export class DatatableBulk {
65
102
  }
66
103
 
67
104
  // Clear any references to help garbage collection
68
- this.page = null
69
- this.table = null
70
- this.model = null
105
+ this.page = null as unknown as DatatableBulkPage
106
+ this.table = undefined
107
+ this.model = {content: []}
71
108
  }
72
109
 
73
- onKeyDown(event) {
110
+ onKeyDown(event: KeyboardEvent): void {
74
111
  const key = keyName(event)
75
112
  const el = this.page.dom.querySelector(`#${this.id}`)
76
113
 
@@ -89,8 +126,8 @@ export class DatatableBulk {
89
126
  width: 280,
90
127
  page: this.page,
91
128
  menuPos: {
92
- X: Number.parseInt(el.getBoundingClientRect().left),
93
- Y: Number.parseInt(el.getBoundingClientRect().bottom)
129
+ X: Number.parseInt(el.getBoundingClientRect().left as unknown as string),
130
+ Y: Number.parseInt(el.getBoundingClientRect().bottom as unknown as string)
94
131
  }
95
132
  })
96
133
  contentMenu.open()
@@ -115,7 +152,7 @@ export class DatatableBulk {
115
152
  }
116
153
  }
117
154
 
118
- toggleSelectAll(checked) {
155
+ toggleSelectAll(checked: boolean): void {
119
156
  // Update the DataTable instance
120
157
  if (this.table) {
121
158
  this.table.data.data.forEach(row => {
@@ -130,26 +167,26 @@ export class DatatableBulk {
130
167
  this.onTableCheckChange()
131
168
  }
132
169
 
133
- onTableCheckChange() {
170
+ onTableCheckChange(): void {
134
171
  const el = this.page.dom.querySelector(`#${this.id}`)
135
172
  if (!el) {
136
173
  return
137
174
  }
138
175
 
139
176
  const allChecked = this.isAllChecked()
140
- el.querySelector("input[type=checkbox]").checked = allChecked
177
+ ;(el.querySelector("input[type=checkbox]") as HTMLInputElement).checked = allChecked
141
178
  }
142
179
 
143
- isAllChecked() {
180
+ isAllChecked(): boolean {
144
181
  const checkboxes = Array.from(
145
- this.table.dom.querySelectorAll("input.entry-select[type=checkbox]")
182
+ this.table!.dom.querySelectorAll("input.entry-select[type=checkbox]")
146
183
  )
147
- const unchecked = checkboxes.filter(box => !box.checked)
148
- return !unchecked.length && checkboxes.length
184
+ const unchecked = checkboxes.filter(box => !(box as HTMLInputElement).checked)
185
+ return !unchecked.length && checkboxes.length > 0
149
186
  }
150
187
 
151
- onClick(event) {
152
- const target = event.target
188
+ onClick(event: MouseEvent): void {
189
+ const target = event.target as Element
153
190
  if (target.matches(`#${this.id} *`)) {
154
191
  event.preventDefault()
155
192
  event.stopImmediatePropagation()
@@ -164,8 +201,8 @@ export class DatatableBulk {
164
201
  width: 280,
165
202
  page: this.page,
166
203
  menuPos: {
167
- X: Number.parseInt(event.pageX),
168
- Y: Number.parseInt(event.pageY)
204
+ X: Number.parseInt(event.pageX as unknown as string),
205
+ Y: Number.parseInt(event.pageY as unknown as string)
169
206
  }
170
207
  })
171
208
  contentMenu.open()
@@ -176,9 +213,9 @@ export class DatatableBulk {
176
213
  // Click on bulk checkbox
177
214
  const isChecked = this.isAllChecked()
178
215
  this.toggleSelectAll(!isChecked)
179
- target
180
- .closest("div.datatable-wrapper")
181
- .querySelector("input[type=checkbox]").checked = !isChecked
216
+ ;(target
217
+ .closest("div.datatable-wrapper")!
218
+ .querySelector("input[type=checkbox]") as HTMLInputElement).checked = !isChecked
182
219
  this.onTableCheckChange()
183
220
  }
184
221
  } else if (target.matches(".fw-data-table .entry-select + label")) {
@@ -186,18 +223,18 @@ export class DatatableBulk {
186
223
  event.preventDefault()
187
224
  event.stopImmediatePropagation()
188
225
  event.stopPropagation()
189
- const tr = target.closest("tr")
190
- const index = parseInt(tr.dataset.index)
191
- const row = this.table.data.data[index]
226
+ const tr = target.closest("tr") as HTMLTableRowElement
227
+ const index = parseInt(tr.dataset.index!)
228
+ const row = this.table!.data.data[index]
192
229
  const cell = row.cells[this.checkboxColumn]
193
230
  cell.data = !cell.data
194
231
  cell.text = String(cell.data)
195
- this.table.update()
232
+ this.table!.update()
196
233
  this.onTableCheckChange()
197
234
  }
198
235
  }
199
236
 
200
- getHTML() {
237
+ getHTML(): string {
201
238
  return `<div id="${this.id}" class="dt-bulk" role="group" aria-label="Bulk actions">
202
239
  <input type="checkbox" id="${this.id}_check" class="fw-check" aria-label="Select all">
203
240
  <label for="${this.id}_check"></label>