@inglorious/web 2.4.0 → 2.6.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.
@@ -1,14 +1,34 @@
1
1
  /* eslint-disable no-magic-numbers */
2
2
 
3
+ /**
4
+ * @typedef {import('../../types/table').TableEntity} TableEntity
5
+ * @typedef {import('../../types/table').TableColumn} TableColumn
6
+ */
7
+
3
8
  export const logic = {
9
+ /**
10
+ * Initializes the table entity.
11
+ * @param {TableEntity} entity
12
+ */
4
13
  init(entity) {
5
14
  initTable(entity)
6
15
  },
7
16
 
8
- create(entity) {
17
+ /**
18
+ * Resets the table entity when a 'create' event payload matches its ID.
19
+ * @param {TableEntity} entity
20
+ * @param {string|number} id
21
+ */
22
+ create(entity, id) {
23
+ if (id !== entity.id) return
9
24
  initTable(entity)
10
25
  },
11
26
 
27
+ /**
28
+ * Toggles sorting for a column.
29
+ * @param {TableEntity} entity
30
+ * @param {string} columnId
31
+ */
12
32
  sortChange(entity, columnId) {
13
33
  const column = entity.columns.find((c) => c.id === columnId)
14
34
  if (!column?.isSortable) return
@@ -34,10 +54,19 @@ export const logic = {
34
54
  }
35
55
  },
36
56
 
57
+ /**
58
+ * Clears all sorts.
59
+ * @param {TableEntity} entity
60
+ */
37
61
  sortsClear(entity) {
38
62
  entity.sorts = []
39
63
  },
40
64
 
65
+ /**
66
+ * Updates a filter value for a column.
67
+ * @param {TableEntity} entity
68
+ * @param {{ columnId: string, value: any }} payload
69
+ */
41
70
  filterChange(entity, { columnId, value }) {
42
71
  if (value == null || value === "") {
43
72
  delete entity.filters[columnId]
@@ -51,6 +80,10 @@ export const logic = {
51
80
  }
52
81
  },
53
82
 
83
+ /**
84
+ * Clears all filters.
85
+ * @param {TableEntity} entity
86
+ */
54
87
  filtersClear(entity) {
55
88
  entity.filters = {}
56
89
  if (entity.pagination) {
@@ -58,10 +91,20 @@ export const logic = {
58
91
  }
59
92
  },
60
93
 
94
+ /**
95
+ * Updates the search term.
96
+ * @param {TableEntity} entity
97
+ * @param {string} search
98
+ */
61
99
  searchChange(entity, search) {
62
100
  entity.search.value = search
63
101
  },
64
102
 
103
+ /**
104
+ * Changes the current page.
105
+ * @param {TableEntity} entity
106
+ * @param {number} page
107
+ */
65
108
  pageChange(entity, page) {
66
109
  if (!entity.pagination) return
67
110
 
@@ -71,6 +114,10 @@ export const logic = {
71
114
  entity.pagination.page = Math.max(0, Math.min(page, totalPages - 1))
72
115
  },
73
116
 
117
+ /**
118
+ * Moves to the next page.
119
+ * @param {TableEntity} entity
120
+ */
74
121
  pageNext(entity) {
75
122
  if (!entity.pagination) return
76
123
  const totalPages = Math.ceil(
@@ -82,11 +129,20 @@ export const logic = {
82
129
  )
83
130
  },
84
131
 
132
+ /**
133
+ * Moves to the previous page.
134
+ * @param {TableEntity} entity
135
+ */
85
136
  pagePrev(entity) {
86
137
  if (!entity.pagination) return
87
138
  entity.pagination.page = Math.max(entity.pagination.page - 1, 0)
88
139
  },
89
140
 
141
+ /**
142
+ * Changes the page size.
143
+ * @param {TableEntity} entity
144
+ * @param {number} pageSize
145
+ */
90
146
  pageSizeChange(entity, pageSize) {
91
147
  if (!entity.pagination) return
92
148
 
@@ -94,6 +150,11 @@ export const logic = {
94
150
  entity.pagination.page = 0
95
151
  },
96
152
 
153
+ /**
154
+ * Selects a row.
155
+ * @param {TableEntity} entity
156
+ * @param {string|number} rowId
157
+ */
97
158
  rowSelect(entity, rowId) {
98
159
  if (!entity.isMultiSelect) {
99
160
  entity.selection = []
@@ -104,6 +165,11 @@ export const logic = {
104
165
  }
105
166
  },
106
167
 
168
+ /**
169
+ * Deselects a row.
170
+ * @param {TableEntity} entity
171
+ * @param {string|number} rowId
172
+ */
107
173
  rowDeselect(entity, rowId) {
108
174
  const index = entity.selection.indexOf(rowId)
109
175
  if (index !== -1) {
@@ -111,6 +177,11 @@ export const logic = {
111
177
  }
112
178
  },
113
179
 
180
+ /**
181
+ * Toggles row selection.
182
+ * @param {TableEntity} entity
183
+ * @param {string|number} rowId
184
+ */
114
185
  rowToggle(entity, rowId) {
115
186
  const index = entity.selection.indexOf(rowId)
116
187
 
@@ -125,6 +196,10 @@ export const logic = {
125
196
  }
126
197
  },
127
198
 
199
+ /**
200
+ * Toggles selection of all currently visible rows.
201
+ * @param {TableEntity} entity
202
+ */
128
203
  rowsToggleAll(entity) {
129
204
  const rows = getRows(entity)
130
205
  const allSelected = rows.every((row) => entity.selection.includes(row.id))
@@ -145,6 +220,10 @@ export const logic = {
145
220
  }
146
221
  },
147
222
 
223
+ /**
224
+ * Selects all currently visible rows.
225
+ * @param {TableEntity} entity
226
+ */
148
227
  rowsSelectAll(entity) {
149
228
  const rows = getRows(entity)
150
229
  rows.forEach((row) => {
@@ -154,13 +233,22 @@ export const logic = {
154
233
  })
155
234
  },
156
235
 
236
+ /**
237
+ * Clears all row selections.
238
+ * @param {TableEntity} entity
239
+ */
157
240
  selectionClear(entity) {
158
241
  entity.selection.length = 0
159
242
  },
160
243
  }
161
244
 
162
- // Helper functions outside the type (like form helpers)
245
+ // Helper functions
163
246
 
247
+ /**
248
+ * Gets the processed rows (filtered, searched, sorted, paginated).
249
+ * @param {TableEntity} entity
250
+ * @returns {any[]}
251
+ */
164
252
  export function getRows(entity) {
165
253
  let rows = entity.data
166
254
  rows = applyFilters(entity, rows)
@@ -171,6 +259,11 @@ export function getRows(entity) {
171
259
  return rows
172
260
  }
173
261
 
262
+ /**
263
+ * Gets the total number of rows after filtering and searching.
264
+ * @param {TableEntity} entity
265
+ * @returns {number}
266
+ */
174
267
  export function getTotalRows(entity) {
175
268
  let rows = entity.data
176
269
  rows = applyFilters(entity, rows)
@@ -178,6 +271,11 @@ export function getTotalRows(entity) {
178
271
  return rows.length
179
272
  }
180
273
 
274
+ /**
275
+ * Gets pagination information.
276
+ * @param {TableEntity} entity
277
+ * @returns {object|null}
278
+ */
181
279
  export function getPaginationInfo(entity) {
182
280
  if (!entity.pagination) return null
183
281
 
@@ -199,28 +297,62 @@ export function getPaginationInfo(entity) {
199
297
  }
200
298
  }
201
299
 
300
+ /**
301
+ * Gets the sort direction for a column.
302
+ * @param {TableEntity} entity
303
+ * @param {string} columnId
304
+ * @returns {"asc"|"desc"|null}
305
+ */
202
306
  export function getSortDirection(entity, columnId) {
203
307
  const sort = entity.sorts.find((s) => s.column === columnId)
204
308
  return sort?.direction || null
205
309
  }
206
310
 
311
+ /**
312
+ * Gets the sort index (priority) for a column.
313
+ * @param {TableEntity} entity
314
+ * @param {string} columnId
315
+ * @returns {number}
316
+ */
207
317
  export function getSortIndex(entity, columnId) {
208
318
  return entity.sorts.findIndex((s) => s.column === columnId)
209
319
  }
210
320
 
321
+ /**
322
+ * Gets the filter value for a column.
323
+ * @param {TableEntity} entity
324
+ * @param {string} columnId
325
+ * @returns {any}
326
+ */
211
327
  export function getFilter(entity, columnId) {
212
328
  return entity.filters[columnId]
213
329
  }
214
330
 
331
+ /**
332
+ * Checks if a row is selected.
333
+ * @param {TableEntity} entity
334
+ * @param {string|number} rowId
335
+ * @returns {boolean}
336
+ */
215
337
  export function isRowSelected(entity, rowId) {
216
338
  return entity.selection.includes(rowId)
217
339
  }
218
340
 
341
+ /**
342
+ * Checks if all visible rows are selected.
343
+ * @param {TableEntity} entity
344
+ * @returns {boolean}
345
+ */
219
346
  export function isAllSelected(entity) {
220
347
  const rows = getRows(entity)
221
348
  return rows.length && rows.every((row) => entity.selection.includes(row.id))
222
349
  }
223
350
 
351
+ /**
352
+ * Checks if some (but not all) visible rows are selected.
353
+ * @param {TableEntity} entity
354
+ * @returns {boolean}
355
+ */
224
356
  export function isSomeSelected(entity) {
225
357
  const rows = getRows(entity)
226
358
  const selectedCount = rows.filter((row) =>
@@ -229,6 +361,12 @@ export function isSomeSelected(entity) {
229
361
  return selectedCount && selectedCount < rows.length
230
362
  }
231
363
 
364
+ // Private helper functions
365
+
366
+ /**
367
+ * Initializes the table state.
368
+ * @param {TableEntity} entity
369
+ */
232
370
  function initTable(entity) {
233
371
  entity.data ??= []
234
372
 
@@ -276,6 +414,11 @@ function initTable(entity) {
276
414
  }
277
415
  }
278
416
 
417
+ /**
418
+ * Infers the column type from a value.
419
+ * @param {any} value
420
+ * @returns {string}
421
+ */
279
422
  function getDefaultColumnType(value) {
280
423
  if (typeof value === "number") return "number"
281
424
  if (typeof value === "boolean") return "boolean"
@@ -283,6 +426,11 @@ function getDefaultColumnType(value) {
283
426
  return "string"
284
427
  }
285
428
 
429
+ /**
430
+ * Gets the default filter configuration for a column type.
431
+ * @param {string} type
432
+ * @returns {object}
433
+ */
286
434
  function getDefaultColumnFilter(type) {
287
435
  if (type === "number") return { type: "range" }
288
436
  if (type === "boolean")
@@ -291,6 +439,11 @@ function getDefaultColumnFilter(type) {
291
439
  return { type: "text" }
292
440
  }
293
441
 
442
+ /**
443
+ * Gets the default column width based on filter type.
444
+ * @param {string} filterType
445
+ * @returns {number}
446
+ */
294
447
  function getDefaultColumnWidth(filterType) {
295
448
  if (filterType === "number") return 70
296
449
  if (filterType === "range") return 100
@@ -301,6 +454,12 @@ function getDefaultColumnWidth(filterType) {
301
454
  return 200
302
455
  }
303
456
 
457
+ /**
458
+ * Applies filters to the data.
459
+ * @param {TableEntity} entity
460
+ * @param {any[]} rows
461
+ * @returns {any[]}
462
+ */
304
463
  function applyFilters(entity, rows) {
305
464
  if (!Object.keys(entity.filters).length) {
306
465
  return rows
@@ -338,6 +497,12 @@ function applyFilters(entity, rows) {
338
497
  })
339
498
  }
340
499
 
500
+ /**
501
+ * Applies search to the data.
502
+ * @param {TableEntity} entity
503
+ * @param {any[]} rows
504
+ * @returns {any[]}
505
+ */
341
506
  function applySearch(entity, rows) {
342
507
  if (!entity.search?.value) {
343
508
  return rows
@@ -354,6 +519,12 @@ function applySearch(entity, rows) {
354
519
  )
355
520
  }
356
521
 
522
+ /**
523
+ * Applies sorting to the data.
524
+ * @param {TableEntity} entity
525
+ * @param {any[]} rows
526
+ * @returns {any[]}
527
+ */
357
528
  function applySorts(entity, rows) {
358
529
  if (!entity.sorts.length) {
359
530
  return rows
@@ -385,6 +556,12 @@ function applySorts(entity, rows) {
385
556
  })
386
557
  }
387
558
 
559
+ /**
560
+ * Applies pagination to the data.
561
+ * @param {TableEntity} entity
562
+ * @param {any[]} rows
563
+ * @returns {any[]}
564
+ */
388
565
  function applyPagination(entity, rows) {
389
566
  if (!entity.pagination) {
390
567
  return rows
@@ -395,6 +572,11 @@ function applyPagination(entity, rows) {
395
572
  return rows.slice(start, start + pageSize)
396
573
  }
397
574
 
575
+ /**
576
+ * Capitalizes the first letter of a string.
577
+ * @param {string} str
578
+ * @returns {string}
579
+ */
398
580
  function capitalize(str) {
399
581
  const [firstChar, ...rest] = str
400
582
  return [firstChar.toUpperCase(), ...rest].join("")
package/types/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
+ export * from "./form"
1
2
  export * from "./mount"
2
3
  export * from "./router"
4
+ export * from "./select"
5
+ export * from "./table"
@@ -0,0 +1,136 @@
1
+ import type { TemplateResult } from "lit-html"
2
+ import type { Api } from "./mount"
3
+
4
+ /**
5
+ * Represents an option in the select component.
6
+ * Can be a simple string/number or an object with value and label.
7
+ */
8
+ export type SelectOption =
9
+ | string
10
+ | number
11
+ | {
12
+ value: string | number
13
+ label?: string
14
+ disabled?: boolean
15
+ [key: string]: any
16
+ }
17
+
18
+ /**
19
+ * Represents the state of a select entity.
20
+ */
21
+ export interface SelectEntity {
22
+ /** A unique identifier for the select entity. */
23
+ id: string | number
24
+ /** The entity type (usually 'select'). */
25
+ type: string
26
+ /** The list of options available for selection. */
27
+ options: SelectOption[]
28
+ /** Whether the dropdown is currently open. */
29
+ isOpen: boolean
30
+ /** The current search term entered by the user. */
31
+ searchTerm: string
32
+ /** The index of the currently focused option (for keyboard navigation). */
33
+ focusedIndex: number
34
+ /** Whether multiple options can be selected. */
35
+ isMulti: boolean
36
+ /** The currently selected value(s). */
37
+ selectedValue: string | number | (string | number)[] | null
38
+ /** Whether the options are currently loading. */
39
+ isLoading: boolean
40
+ /** Whether the select component is disabled. */
41
+ isDisabled: boolean
42
+ /** Whether the user can search through options. */
43
+ isSearchable: boolean
44
+ /** Whether the selection can be cleared. */
45
+ isClearable: boolean
46
+ /** Whether new options can be created by the user. */
47
+ isCreatable: boolean
48
+ /** Placeholder text to display when no value is selected. */
49
+ placeholder: string
50
+ /** Message to display when no options match the search term. */
51
+ noOptionsMessage: string
52
+ /** Message to display while options are loading. */
53
+ loadingMessage: string
54
+ /** Property name to group options by. */
55
+ groupBy: string | null
56
+ }
57
+
58
+ /**
59
+ * The select type implementation.
60
+ */
61
+ export declare const select: {
62
+ /**
63
+ * Initializes the select entity with default state.
64
+ * @param entity The select entity.
65
+ */
66
+ init(entity: SelectEntity): void
67
+
68
+ /**
69
+ * Renders the select component.
70
+ * @param entity The select entity.
71
+ * @param api The store API.
72
+ */
73
+ render(entity: SelectEntity, api: Api): TemplateResult
74
+
75
+ /**
76
+ * Opens the select dropdown.
77
+ * @param entity The select entity.
78
+ */
79
+ open(entity: SelectEntity): void
80
+
81
+ /**
82
+ * Closes the select dropdown.
83
+ * @param entity The select entity.
84
+ */
85
+ close(entity: SelectEntity): void
86
+
87
+ /**
88
+ * Toggles the select dropdown open/closed state.
89
+ * @param entity The select entity.
90
+ */
91
+ toggle(entity: SelectEntity): void
92
+
93
+ /**
94
+ * Selects an option.
95
+ * @param entity The select entity.
96
+ * @param option The option to select.
97
+ */
98
+ optionSelect(entity: SelectEntity, option: SelectOption): void
99
+
100
+ /**
101
+ * Clears the current selection.
102
+ * @param entity The select entity.
103
+ */
104
+ clear(entity: SelectEntity): void
105
+
106
+ /**
107
+ * Updates the search term and filters options.
108
+ * @param entity The select entity.
109
+ * @param term The new search term.
110
+ */
111
+ searchChange(entity: SelectEntity, term: string): void
112
+
113
+ /**
114
+ * Moves focus to the next option.
115
+ * @param entity The select entity.
116
+ */
117
+ focusNext(entity: SelectEntity): void
118
+
119
+ /**
120
+ * Moves focus to the previous option.
121
+ * @param entity The select entity.
122
+ */
123
+ focusPrev(entity: SelectEntity): void
124
+
125
+ /**
126
+ * Moves focus to the first option.
127
+ * @param entity The select entity.
128
+ */
129
+ focusFirst(entity: SelectEntity): void
130
+
131
+ /**
132
+ * Moves focus to the last option.
133
+ * @param entity The select entity.
134
+ */
135
+ focusLast(entity: SelectEntity): void
136
+ }