@coreui/data-grid 0.1.0-rc.0 → 0.3.0-rc.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/README.md +9 -6
- package/dist/css/data-grid.css +156 -38
- package/dist/css/data-grid.css.map +1 -1
- package/dist/css/data-grid.min.css +2 -2
- package/dist/css/data-grid.min.css.map +1 -1
- package/dist/css/data-grid.standalone.css +1066 -0
- package/dist/css/data-grid.standalone.css.map +1 -0
- package/dist/css/data-grid.standalone.min.css +5 -0
- package/dist/css/data-grid.standalone.min.css.map +1 -0
- package/dist/js/clipboard.cjs +56 -0
- package/dist/js/clipboard.cjs.map +1 -0
- package/dist/js/clipboard.mjs +54 -0
- package/dist/js/clipboard.mjs.map +1 -0
- package/dist/js/csv.cjs +36 -59
- package/dist/js/csv.cjs.map +1 -1
- package/dist/js/csv.mjs +35 -55
- package/dist/js/csv.mjs.map +1 -1
- package/dist/js/data-grid.esm.js +14108 -9331
- package/dist/js/data-grid.esm.js.map +1 -1
- package/dist/js/data-grid.esm.min.js +6 -6
- package/dist/js/data-grid.esm.min.js.map +1 -1
- package/dist/js/data-grid.js +14408 -9634
- package/dist/js/data-grid.js.map +1 -1
- package/dist/js/data-grid.lite.esm.js +10507 -0
- package/dist/js/data-grid.lite.esm.js.map +1 -0
- package/dist/js/data-grid.lite.esm.min.js +8 -0
- package/dist/js/data-grid.lite.esm.min.js.map +1 -0
- package/dist/js/data-grid.lite.js +10520 -0
- package/dist/js/data-grid.lite.js.map +1 -0
- package/dist/js/data-grid.lite.min.js +8 -0
- package/dist/js/data-grid.lite.min.js.map +1 -0
- package/dist/js/data-grid.lite.mjs +10507 -0
- package/dist/js/data-grid.lite.mjs.map +1 -0
- package/dist/js/data-grid.min.js +6 -6
- package/dist/js/data-grid.min.js.map +1 -1
- package/dist/js/data-grid.mjs +14108 -9331
- package/dist/js/data-grid.mjs.map +1 -1
- package/dist/js/direction.cjs +26 -0
- package/dist/js/direction.cjs.map +1 -0
- package/dist/js/direction.mjs +24 -0
- package/dist/js/direction.mjs.map +1 -0
- package/dist/js/drag.cjs +467 -0
- package/dist/js/drag.cjs.map +1 -0
- package/dist/js/drag.mjs +464 -0
- package/dist/js/drag.mjs.map +1 -0
- package/dist/js/export-table-BdabEbJG.mjs +26 -0
- package/dist/js/export-table-BdabEbJG.mjs.map +1 -0
- package/dist/js/export-table-D762wrZ1.cjs +55 -0
- package/dist/js/export-table-D762wrZ1.cjs.map +1 -0
- package/dist/js/filters.cjs +89 -132
- package/dist/js/filters.cjs.map +1 -1
- package/dist/js/filters.mjs +88 -128
- package/dist/js/filters.mjs.map +1 -1
- package/dist/js/labels.cjs +65 -70
- package/dist/js/labels.cjs.map +1 -1
- package/dist/js/labels.mjs +64 -66
- package/dist/js/labels.mjs.map +1 -1
- package/dist/js/print.cjs +66 -0
- package/dist/js/print.cjs.map +1 -0
- package/dist/js/print.mjs +64 -0
- package/dist/js/print.mjs.map +1 -0
- package/dist/js/validate.cjs +43 -0
- package/dist/js/validate.cjs.map +1 -0
- package/dist/js/validate.mjs +42 -0
- package/dist/js/validate.mjs.map +1 -0
- package/dist/js/xlsx.cjs +240 -0
- package/dist/js/xlsx.cjs.map +1 -0
- package/dist/js/xlsx.mjs +238 -0
- package/dist/js/xlsx.mjs.map +1 -0
- package/dist/types/base-component.d.ts +28 -18
- package/dist/types/data-grid.d.ts +26 -13
- package/dist/types/dom/data.d.ts +15 -0
- package/dist/types/dom/event-handler.d.ts +21 -10
- package/dist/types/dom/manipulator.d.ts +15 -8
- package/dist/types/engine/active-cell.d.ts +1 -0
- package/dist/types/engine/data-source.d.ts +1 -1
- package/dist/types/engine/features-lite.d.ts +25 -0
- package/dist/types/engine/features.d.ts +35 -0
- package/dist/types/engine/table.d.ts +3 -3
- package/dist/types/engine/validate.d.mts +1 -0
- package/dist/types/engine/validate.d.ts +20 -0
- package/dist/types/engine/virtualizer.d.ts +2 -0
- package/dist/types/icons.d.ts +6 -4
- package/dist/types/index-lite.d.mts +1 -0
- package/dist/types/index-lite.d.ts +19 -0
- package/dist/types/index.d.ts +11 -2
- package/dist/types/types.d.ts +53 -31
- package/dist/types/ui/body.d.ts +6 -3
- package/dist/types/ui/header.d.ts +3 -2
- package/dist/types/ui/loading.d.ts +1 -1
- package/dist/types/ui/pinning.d.ts +1 -1
- package/dist/types/ui/toolbar.d.ts +10 -2
- package/dist/types/util/clipboard.d.mts +1 -0
- package/dist/types/util/clipboard.d.ts +29 -0
- package/dist/types/util/config.d.ts +27 -10
- package/dist/types/util/csv.d.ts +5 -5
- package/dist/types/util/direction.d.mts +1 -0
- package/dist/types/util/direction.d.ts +17 -0
- package/dist/types/util/drag.d.mts +1 -0
- package/dist/types/util/drag.d.ts +48 -0
- package/dist/types/util/export-table.d.ts +47 -0
- package/dist/types/util/index.d.ts +66 -10
- package/dist/types/util/print.d.mts +1 -0
- package/dist/types/util/print.d.ts +32 -0
- package/dist/types/util/sanitizer.d.ts +15 -11
- package/dist/types/util/xlsx.d.mts +1 -0
- package/dist/types/util/xlsx.d.ts +17 -0
- package/dist/types/util/zip.d.ts +11 -0
- package/package.json +101 -10
- package/scss/_base.scss +13 -0
- package/scss/_config.scss +14 -0
- package/scss/_functions.scss +1 -0
- package/scss/_mixins.scss +1 -0
- package/scss/base/_buttons.scss +113 -0
- package/scss/base/_forms.scss +157 -0
- package/scss/base/_helpers.scss +24 -0
- package/scss/base/_pagination.scss +100 -0
- package/scss/base/_reboot.scss +93 -0
- package/scss/base/_root.scss +85 -0
- package/scss/base/_spinner.scss +45 -0
- package/scss/base/_table.scss +78 -0
- package/scss/components/_data-grid.scss +807 -0
- package/scss/data-grid.scss +7 -555
- package/scss/data-grid.standalone.scss +16 -0
- package/scss/functions/_defaults.scss +25 -0
- package/scss/mixins/_tokens.scss +12 -0
- package/src/{base-component.js → base-component.ts} +21 -17
- package/src/data-grid.ts +523 -201
- package/src/dom/{data.js → data.ts} +13 -10
- package/src/dom/event-handler.ts +380 -0
- package/src/dom/{manipulator.js → manipulator.ts} +11 -11
- package/src/engine/active-cell.ts +10 -3
- package/src/engine/data-source.ts +7 -3
- package/src/engine/features-lite.ts +47 -0
- package/src/engine/features.ts +68 -0
- package/src/engine/table.ts +86 -45
- package/src/engine/validate.ts +64 -0
- package/src/engine/virtualizer.ts +17 -1
- package/src/icons.ts +11 -5
- package/src/index-lite.ts +85 -0
- package/src/index.ts +30 -2
- package/src/labels.ts +6 -4
- package/src/types.ts +87 -32
- package/src/ui/body.ts +73 -17
- package/src/ui/header.ts +51 -26
- package/src/ui/loading.ts +2 -2
- package/src/ui/pinning.ts +16 -16
- package/src/ui/toolbar.ts +27 -3
- package/src/util/clipboard.ts +112 -0
- package/src/util/{config.js → config.ts} +25 -11
- package/src/util/csv.ts +11 -30
- package/src/util/direction.ts +37 -0
- package/src/util/drag.ts +832 -0
- package/src/util/export-table.ts +86 -0
- package/src/util/{index.js → index.ts} +55 -35
- package/src/util/print.ts +125 -0
- package/src/util/{sanitizer.js → sanitizer.ts} +17 -13
- package/src/util/xlsx.ts +183 -0
- package/src/util/zip.ts +170 -0
- package/src/base-component.d.ts +0 -19
- package/src/dom/event-handler.d.ts +0 -11
- package/src/dom/event-handler.js +0 -331
- package/src/dom/manipulator.d.ts +0 -9
- package/src/util/config.d.ts +0 -11
- package/src/util/index.d.ts +0 -10
- package/src/util/sanitizer.d.ts +0 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// Vendored from https://github.com/coreui/coreui-pro/blob/
|
|
1
|
+
// Vendored from https://github.com/coreui/coreui-pro/blob/e9355580e/js/src/dom/data.ts — sync manually
|
|
2
2
|
/**
|
|
3
3
|
* --------------------------------------------------------------------------
|
|
4
|
-
* CoreUI dom/data.
|
|
4
|
+
* CoreUI dom/data.ts
|
|
5
5
|
* Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE)
|
|
6
6
|
*
|
|
7
7
|
* This is a modified version of the Bootstrap's dom/data.js
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
* Constants
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
const elementMap = new Map()
|
|
16
|
+
const elementMap = new Map<Element, Map<string, unknown>>()
|
|
17
17
|
|
|
18
18
|
export default {
|
|
19
|
-
set(element, key, instance) {
|
|
19
|
+
set(element: Element, key: string, instance: unknown): void {
|
|
20
20
|
if (!elementMap.has(element)) {
|
|
21
21
|
elementMap.set(element, new Map())
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const instanceMap = elementMap.get(element)
|
|
24
|
+
const instanceMap = elementMap.get(element)!
|
|
25
25
|
|
|
26
26
|
// make it clear we only want one instance per element
|
|
27
27
|
// can be removed later when multiple key/instances are fine to be used
|
|
@@ -34,20 +34,23 @@ export default {
|
|
|
34
34
|
instanceMap.set(key, instance)
|
|
35
35
|
},
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
// Callers pass the result of getElement(), which can be null; Map.has(null)
|
|
38
|
+
// is simply false at runtime, so the parameter is widened without adding a
|
|
39
|
+
// guard that would change the emitted code.
|
|
40
|
+
get(element: Element | null, key: string): any {
|
|
41
|
+
if (elementMap.has(element as Element)) {
|
|
42
|
+
return elementMap.get(element as Element)!.get(key) || null
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
return null
|
|
43
46
|
},
|
|
44
47
|
|
|
45
|
-
remove(element, key) {
|
|
48
|
+
remove(element: Element, key: string): void {
|
|
46
49
|
if (!elementMap.has(element)) {
|
|
47
50
|
return
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
const instanceMap = elementMap.get(element)
|
|
53
|
+
const instanceMap = elementMap.get(element)!
|
|
51
54
|
|
|
52
55
|
instanceMap.delete(key)
|
|
53
56
|
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
// Vendored from https://github.com/coreui/coreui-pro/blob/e9355580e/js/src/dom/event-handler.ts — sync manually
|
|
2
|
+
/**
|
|
3
|
+
* --------------------------------------------------------------------------
|
|
4
|
+
* CoreUI dom/event-handler.ts
|
|
5
|
+
* Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE)
|
|
6
|
+
*
|
|
7
|
+
* This is a modified version of the Bootstrap's dom/event-handler.ts
|
|
8
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
9
|
+
* --------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { getjQuery } from '../util/index.js'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Types
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
type CoreUIEvent = Event & Record<string, any>
|
|
19
|
+
|
|
20
|
+
type EventCallable = (this: any, event: CoreUIEvent) => any
|
|
21
|
+
|
|
22
|
+
interface WrappedHandler {
|
|
23
|
+
(this: Element, event: Event): any
|
|
24
|
+
oneOff?: boolean
|
|
25
|
+
uidEvent?: string | number
|
|
26
|
+
callable?: EventCallable
|
|
27
|
+
delegationSelector?: string | null
|
|
28
|
+
handlerTypeEvent?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface NormalizedParameters {
|
|
32
|
+
isDelegated: boolean
|
|
33
|
+
callable: EventCallable
|
|
34
|
+
typeEvent: string
|
|
35
|
+
handlerTypeEvent: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type ElementEvents = Record<string, Record<string, WrappedHandler>>
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Constants
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
const namespaceRegex = /[^.]*(?=\..*)\.|.*/
|
|
45
|
+
const stripNameRegex = /\..*/
|
|
46
|
+
const stripUidRegex = /::\d+$/
|
|
47
|
+
const eventRegistry: Record<string | number, ElementEvents> = {} // Events storage
|
|
48
|
+
let uidEvent = 1
|
|
49
|
+
const customEvents: Record<string, string> = {
|
|
50
|
+
mouseenter: 'mouseover',
|
|
51
|
+
mouseleave: 'mouseout'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const nativeEvents = new Set([
|
|
55
|
+
'click',
|
|
56
|
+
'dblclick',
|
|
57
|
+
'mouseup',
|
|
58
|
+
'mousedown',
|
|
59
|
+
'contextmenu',
|
|
60
|
+
'mousewheel',
|
|
61
|
+
'DOMMouseScroll',
|
|
62
|
+
'mouseover',
|
|
63
|
+
'mouseout',
|
|
64
|
+
'mousemove',
|
|
65
|
+
'selectstart',
|
|
66
|
+
'selectend',
|
|
67
|
+
'keydown',
|
|
68
|
+
'keypress',
|
|
69
|
+
'keyup',
|
|
70
|
+
'beforeinput',
|
|
71
|
+
'copy',
|
|
72
|
+
'cut',
|
|
73
|
+
'paste',
|
|
74
|
+
'orientationchange',
|
|
75
|
+
'touchstart',
|
|
76
|
+
'touchmove',
|
|
77
|
+
'touchend',
|
|
78
|
+
'touchcancel',
|
|
79
|
+
'pointerdown',
|
|
80
|
+
'pointermove',
|
|
81
|
+
'pointerup',
|
|
82
|
+
'pointerleave',
|
|
83
|
+
'pointercancel',
|
|
84
|
+
// Local addition over the coreui-pro source: HTML5 drag & drop events used
|
|
85
|
+
// by the data grid's column reordering.
|
|
86
|
+
'drag',
|
|
87
|
+
'dragstart',
|
|
88
|
+
'dragend',
|
|
89
|
+
'dragenter',
|
|
90
|
+
'dragleave',
|
|
91
|
+
'dragover',
|
|
92
|
+
'drop',
|
|
93
|
+
'gesturestart',
|
|
94
|
+
'gesturechange',
|
|
95
|
+
'gestureend',
|
|
96
|
+
'focus',
|
|
97
|
+
'blur',
|
|
98
|
+
'change',
|
|
99
|
+
'input',
|
|
100
|
+
'reset',
|
|
101
|
+
'select',
|
|
102
|
+
'submit',
|
|
103
|
+
'focusin',
|
|
104
|
+
'focusout',
|
|
105
|
+
'load',
|
|
106
|
+
'unload',
|
|
107
|
+
'beforeunload',
|
|
108
|
+
'resize',
|
|
109
|
+
'move',
|
|
110
|
+
'DOMContentLoaded',
|
|
111
|
+
'readystatechange',
|
|
112
|
+
'error',
|
|
113
|
+
'abort',
|
|
114
|
+
'scroll'
|
|
115
|
+
])
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Private methods
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
function makeEventUid(element: any, uid?: string): string | number {
|
|
122
|
+
return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function getElementEvents(element: Element & { uidEvent?: string | number }): ElementEvents {
|
|
126
|
+
const uid = makeEventUid(element)
|
|
127
|
+
|
|
128
|
+
element.uidEvent = uid
|
|
129
|
+
eventRegistry[uid] = eventRegistry[uid] || {}
|
|
130
|
+
|
|
131
|
+
return eventRegistry[uid]
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// `mouseenter` and `mouseleave` ride on `mouseover` and `mouseout`, which also fire when
|
|
135
|
+
// the pointer moves between descendants of the listening element. Drop those events, so the
|
|
136
|
+
// handler only sees the pointer entering or leaving `delegateTarget` itself.
|
|
137
|
+
// `Node.contains()` is inclusive, so this also covers `relatedTarget === delegateTarget`.
|
|
138
|
+
function isMouseEventWithinTarget(event: CoreUIEvent): boolean {
|
|
139
|
+
const { delegateTarget, relatedTarget } = event
|
|
140
|
+
|
|
141
|
+
return Boolean(relatedTarget && delegateTarget.contains(relatedTarget))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function bootstrapHandler(element: Element, fn: EventCallable, handlerTypeEvent: string): WrappedHandler {
|
|
145
|
+
const isCustomMouseEvent = handlerTypeEvent in customEvents
|
|
146
|
+
|
|
147
|
+
return function handler(event: Event) {
|
|
148
|
+
const coreuiEvent = hydrateObj(event, { delegateTarget: element })
|
|
149
|
+
|
|
150
|
+
if (isCustomMouseEvent && isMouseEventWithinTarget(coreuiEvent)) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if ((handler as WrappedHandler).oneOff) {
|
|
155
|
+
EventHandler.off(element, handlerTypeEvent, fn)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return fn.apply(element, [coreuiEvent])
|
|
159
|
+
} as WrappedHandler
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function bootstrapDelegationHandler(element: Element, selector: string, fn: EventCallable, handlerTypeEvent: string): WrappedHandler {
|
|
163
|
+
const isCustomMouseEvent = handlerTypeEvent in customEvents
|
|
164
|
+
|
|
165
|
+
return function handler(this: Element, event: Event) {
|
|
166
|
+
const domElements = element.querySelectorAll(selector)
|
|
167
|
+
|
|
168
|
+
for (let { target } = event; target && target !== this; target = (target as Node).parentNode) {
|
|
169
|
+
for (const domElement of domElements) {
|
|
170
|
+
if (domElement !== target) {
|
|
171
|
+
continue
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const coreuiEvent = hydrateObj(event, { delegateTarget: target })
|
|
175
|
+
|
|
176
|
+
if (isCustomMouseEvent && isMouseEventWithinTarget(coreuiEvent)) {
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if ((handler as WrappedHandler).oneOff) {
|
|
181
|
+
EventHandler.off(element, handlerTypeEvent, selector, fn)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return fn.apply(target, [coreuiEvent])
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
} as WrappedHandler
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function findHandler(events: Record<string, WrappedHandler>, callable: EventCallable, handlerTypeEvent: string, delegationSelector: string | null = null): WrappedHandler | undefined {
|
|
191
|
+
return Object.values(events)
|
|
192
|
+
.find(event => event.callable === callable && event.handlerTypeEvent === handlerTypeEvent && event.delegationSelector === delegationSelector)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// `typeEvent` is the DOM event type the listener is registered under. `handlerTypeEvent` is
|
|
196
|
+
// the type the caller asked for. The two differ only for `mouseenter` and `mouseleave`, which
|
|
197
|
+
// the registry must keep apart from the `mouseover` and `mouseout` listeners they share.
|
|
198
|
+
function normalizeParameters(originalTypeEvent: string, handler?: string | EventCallable, delegationFunction?: EventCallable): NormalizedParameters {
|
|
199
|
+
const isDelegated = typeof handler === 'string'
|
|
200
|
+
// TODO: tooltip passes `false` instead of selector, so we need to check
|
|
201
|
+
const callable = (isDelegated ? delegationFunction : (handler || delegationFunction)) as EventCallable
|
|
202
|
+
// Strip the namespace to get the plain event ('click.coreui.button' --> 'click')
|
|
203
|
+
const baseTypeEvent = originalTypeEvent.replace(stripNameRegex, '')
|
|
204
|
+
let typeEvent = customEvents[baseTypeEvent] || baseTypeEvent
|
|
205
|
+
|
|
206
|
+
if (!nativeEvents.has(typeEvent)) {
|
|
207
|
+
typeEvent = originalTypeEvent
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const handlerTypeEvent = baseTypeEvent in customEvents ? baseTypeEvent : typeEvent
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
isDelegated, callable, typeEvent, handlerTypeEvent
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function addHandler(element: Element, originalTypeEvent: string, handler?: string | EventCallable, delegationFunction?: EventCallable, oneOff?: boolean): void {
|
|
218
|
+
if (typeof originalTypeEvent !== 'string' || !element) {
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const { isDelegated, callable, typeEvent, handlerTypeEvent } = normalizeParameters(originalTypeEvent, handler, delegationFunction)
|
|
223
|
+
const events = getElementEvents(element)
|
|
224
|
+
const handlers = events[typeEvent] || (events[typeEvent] = {})
|
|
225
|
+
const previousFunction = findHandler(handlers, callable, handlerTypeEvent, isDelegated ? (handler as string) : null)
|
|
226
|
+
|
|
227
|
+
if (previousFunction) {
|
|
228
|
+
previousFunction.oneOff = previousFunction.oneOff && oneOff
|
|
229
|
+
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''))
|
|
234
|
+
const fn = isDelegated ?
|
|
235
|
+
bootstrapDelegationHandler(element, handler as string, callable, handlerTypeEvent) :
|
|
236
|
+
bootstrapHandler(element, callable, handlerTypeEvent)
|
|
237
|
+
|
|
238
|
+
fn.delegationSelector = isDelegated ? (handler as string) : null
|
|
239
|
+
fn.callable = callable
|
|
240
|
+
fn.handlerTypeEvent = handlerTypeEvent
|
|
241
|
+
fn.oneOff = oneOff
|
|
242
|
+
fn.uidEvent = uid
|
|
243
|
+
handlers[uid] = fn
|
|
244
|
+
|
|
245
|
+
element.addEventListener(typeEvent, fn, isDelegated)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function removeHandler(element: Element, events: ElementEvents, typeEvent: string, handler: WrappedHandler): void {
|
|
249
|
+
element.removeEventListener(typeEvent, handler, Boolean(handler.delegationSelector))
|
|
250
|
+
delete events[typeEvent][handler.uidEvent!]
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function removeNamespacedHandlers(element: Element, events: ElementEvents, typeEvent: string, namespace: string): void {
|
|
254
|
+
const storeElementEvent = events[typeEvent] || {}
|
|
255
|
+
|
|
256
|
+
for (const [handlerKey, event] of Object.entries(storeElementEvent)) {
|
|
257
|
+
if (handlerKey.includes(namespace)) {
|
|
258
|
+
removeHandler(element, events, typeEvent, event)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function getTypeEvent(event: string): string {
|
|
264
|
+
// allow to get the native events from namespaced events ('click.coreui.button' --> 'click')
|
|
265
|
+
event = event.replace(stripNameRegex, '')
|
|
266
|
+
return customEvents[event] || event
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const EventHandler = {
|
|
270
|
+
on(element: EventTarget | null, event: string, handler?: string | EventCallable, delegationFunction?: EventCallable): void {
|
|
271
|
+
addHandler(element as Element, event, handler, delegationFunction, false)
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
one(element: EventTarget | null, event: string, handler?: string | EventCallable, delegationFunction?: EventCallable): void {
|
|
275
|
+
addHandler(element as Element, event, handler, delegationFunction, true)
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
off(element: EventTarget | null, originalTypeEvent: string, handler?: string | EventCallable, delegationFunction?: EventCallable): void {
|
|
279
|
+
if (typeof originalTypeEvent !== 'string' || !element) {
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const { isDelegated, callable, typeEvent, handlerTypeEvent } = normalizeParameters(originalTypeEvent, handler, delegationFunction)
|
|
284
|
+
// The caller gave a namespace when neither event type matches what they passed in.
|
|
285
|
+
// `handlerTypeEvent` must take part, or plain `mouseenter` looks namespaced next to `mouseover`.
|
|
286
|
+
const inNamespace = typeEvent !== originalTypeEvent && handlerTypeEvent !== originalTypeEvent
|
|
287
|
+
const events = getElementEvents(element as Element)
|
|
288
|
+
const storeElementEvent = events[typeEvent] || {}
|
|
289
|
+
const isNamespace = originalTypeEvent.startsWith('.')
|
|
290
|
+
|
|
291
|
+
if (typeof callable !== 'undefined') {
|
|
292
|
+
// Simplest case: handler is passed, remove that listener ONLY.
|
|
293
|
+
if (!Object.keys(storeElementEvent).length) {
|
|
294
|
+
return
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const fn = findHandler(storeElementEvent, callable, handlerTypeEvent, isDelegated ? (handler as string) : null)
|
|
298
|
+
|
|
299
|
+
if (fn) {
|
|
300
|
+
removeHandler(element as Element, events, typeEvent, fn)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (isNamespace) {
|
|
307
|
+
for (const elementEvent of Object.keys(events)) {
|
|
308
|
+
removeNamespacedHandlers(element as Element, events, elementEvent, originalTypeEvent.slice(1))
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {
|
|
313
|
+
const handlerKey = keyHandlers.replace(stripUidRegex, '')
|
|
314
|
+
|
|
315
|
+
if (event.handlerTypeEvent === handlerTypeEvent && (!inNamespace || originalTypeEvent.includes(handlerKey))) {
|
|
316
|
+
removeHandler(element as Element, events, typeEvent, event)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
trigger(element: EventTarget | null, event: string, args?: Record<string, unknown>): CoreUIEvent | null {
|
|
322
|
+
if (typeof event !== 'string' || !element) {
|
|
323
|
+
return null
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const $ = getjQuery()
|
|
327
|
+
const typeEvent = getTypeEvent(event)
|
|
328
|
+
const inNamespace = event !== typeEvent
|
|
329
|
+
|
|
330
|
+
let jQueryEvent = null
|
|
331
|
+
let bubbles = true
|
|
332
|
+
let nativeDispatch = true
|
|
333
|
+
let defaultPrevented = false
|
|
334
|
+
|
|
335
|
+
if (inNamespace && $) {
|
|
336
|
+
jQueryEvent = $.Event(event, args)
|
|
337
|
+
|
|
338
|
+
$(element).trigger(jQueryEvent)
|
|
339
|
+
bubbles = !jQueryEvent.isPropagationStopped()
|
|
340
|
+
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()
|
|
341
|
+
defaultPrevented = jQueryEvent.isDefaultPrevented()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)
|
|
345
|
+
|
|
346
|
+
if (defaultPrevented) {
|
|
347
|
+
evt.preventDefault()
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (nativeDispatch) {
|
|
351
|
+
element.dispatchEvent(evt)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (evt.defaultPrevented && jQueryEvent) {
|
|
355
|
+
jQueryEvent.preventDefault()
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return evt
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function hydrateObj<T extends object>(obj: T, meta: Record<string, unknown> = {}): T & Record<string, any> {
|
|
363
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
364
|
+
try {
|
|
365
|
+
(obj as Record<string, unknown>)[key] = value
|
|
366
|
+
} catch {
|
|
367
|
+
Object.defineProperty(obj, key, {
|
|
368
|
+
configurable: true,
|
|
369
|
+
get() {
|
|
370
|
+
return value
|
|
371
|
+
}
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return obj
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export default EventHandler
|
|
380
|
+
export type { CoreUIEvent, EventCallable }
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
// Vendored from https://github.com/coreui/coreui-pro/blob/
|
|
1
|
+
// Vendored from https://github.com/coreui/coreui-pro/blob/e9355580e/js/src/dom/manipulator.ts — sync manually
|
|
2
2
|
/**
|
|
3
3
|
* --------------------------------------------------------------------------
|
|
4
|
-
* CoreUI dom/manipulator.
|
|
4
|
+
* CoreUI dom/manipulator.ts
|
|
5
5
|
* Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE)
|
|
6
6
|
*
|
|
7
|
-
* This is a modified version of the Bootstrap's dom/manipulator.
|
|
7
|
+
* This is a modified version of the Bootstrap's dom/manipulator.ts
|
|
8
8
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
9
9
|
* --------------------------------------------------------------------------
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
function normalizeData(value) {
|
|
12
|
+
function normalizeData(value: string | null | undefined): unknown {
|
|
13
13
|
if (value === 'true') {
|
|
14
14
|
return true
|
|
15
15
|
}
|
|
@@ -37,25 +37,25 @@ function normalizeData(value) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function normalizeDataKey(key) {
|
|
40
|
+
function normalizeDataKey(key: string): string {
|
|
41
41
|
return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const Manipulator = {
|
|
45
|
-
setDataAttribute(element, key, value) {
|
|
46
|
-
element.setAttribute(`data-coreui-${normalizeDataKey(key)}`, value)
|
|
45
|
+
setDataAttribute(element: Element, key: string, value: unknown): void {
|
|
46
|
+
element.setAttribute(`data-coreui-${normalizeDataKey(key)}`, value as string)
|
|
47
47
|
},
|
|
48
48
|
|
|
49
|
-
removeDataAttribute(element, key) {
|
|
49
|
+
removeDataAttribute(element: Element, key: string): void {
|
|
50
50
|
element.removeAttribute(`data-coreui-${normalizeDataKey(key)}`)
|
|
51
51
|
},
|
|
52
52
|
|
|
53
|
-
getDataAttributes(element) {
|
|
53
|
+
getDataAttributes(element: HTMLElement | null): Record<string, unknown> {
|
|
54
54
|
if (!element) {
|
|
55
55
|
return {}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const attributes = {}
|
|
58
|
+
const attributes: Record<string, unknown> = {}
|
|
59
59
|
const coreuiKeys = Object.keys(element.dataset).filter(key => key.startsWith('coreui') && !key.startsWith('coreuiConfig'))
|
|
60
60
|
|
|
61
61
|
for (const key of coreuiKeys) {
|
|
@@ -67,7 +67,7 @@ const Manipulator = {
|
|
|
67
67
|
return attributes
|
|
68
68
|
},
|
|
69
69
|
|
|
70
|
-
getDataAttribute(element, key) {
|
|
70
|
+
getDataAttribute(element: Element, key: string): unknown {
|
|
71
71
|
return normalizeData(element.getAttribute(`data-coreui-${normalizeDataKey(key)}`))
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -23,6 +23,9 @@ export interface ActiveCellContext {
|
|
|
23
23
|
// page size (paginated).
|
|
24
24
|
pageStep: number
|
|
25
25
|
paginated: boolean
|
|
26
|
+
// Writing direction of the grid. Arrow keys are physical, column order is
|
|
27
|
+
// logical, so under RTL the two horizontal keys trade places.
|
|
28
|
+
rtl?: boolean
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
export interface NavigationResult {
|
|
@@ -72,7 +75,7 @@ export const resolveNavigation = (
|
|
|
72
75
|
current: ActiveCell,
|
|
73
76
|
context: ActiveCellContext
|
|
74
77
|
): NavigationResult | null => {
|
|
75
|
-
const { columnIds, rowCount, pageStep, paginated } = context
|
|
78
|
+
const { columnIds, rowCount, pageStep, paginated, rtl } = context
|
|
76
79
|
const columnIndex = columnIds.indexOf(current.columnId)
|
|
77
80
|
if (columnIndex === -1 || columnIds.length === 0) {
|
|
78
81
|
return null
|
|
@@ -86,11 +89,15 @@ export const resolveNavigation = (
|
|
|
86
89
|
|
|
87
90
|
switch (key) {
|
|
88
91
|
case 'ArrowLeft': {
|
|
89
|
-
return
|
|
92
|
+
return rtl ?
|
|
93
|
+
cell(current.rowIndex, Math.min(columnIndex + 1, lastColumn)) :
|
|
94
|
+
cell(current.rowIndex, Math.max(columnIndex - 1, 0))
|
|
90
95
|
}
|
|
91
96
|
|
|
92
97
|
case 'ArrowRight': {
|
|
93
|
-
return
|
|
98
|
+
return rtl ?
|
|
99
|
+
cell(current.rowIndex, Math.max(columnIndex - 1, 0)) :
|
|
100
|
+
cell(current.rowIndex, Math.min(columnIndex + 1, lastColumn))
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
case 'ArrowUp': {
|
|
@@ -12,7 +12,10 @@ const FETCH_DEBOUNCE_MS = 100
|
|
|
12
12
|
export interface GridDataSourceContext {
|
|
13
13
|
getRequest: () => DataGridDataRequest
|
|
14
14
|
onError: (error: unknown) => void
|
|
15
|
-
|
|
15
|
+
// The request is handed back so an appending consumer can tell a first page
|
|
16
|
+
// (replace) from a follow-up one (append) without re-reading table state,
|
|
17
|
+
// which may already have moved on.
|
|
18
|
+
onLoad: (response: DataGridDataResponse, request: DataGridDataRequest) => void
|
|
16
19
|
onLoadingChange: (loading: boolean) => void
|
|
17
20
|
provider: (request: DataGridDataRequest) => Promise<DataGridDataResponse>
|
|
18
21
|
}
|
|
@@ -36,12 +39,13 @@ export const createDataSource = (context: GridDataSourceContext): GridDataSource
|
|
|
36
39
|
context.onLoadingChange(true)
|
|
37
40
|
|
|
38
41
|
try {
|
|
39
|
-
const
|
|
42
|
+
const request = context.getRequest()
|
|
43
|
+
const response = await context.provider(request)
|
|
40
44
|
if (id !== requestId) {
|
|
41
45
|
return
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
context.onLoad(response)
|
|
48
|
+
context.onLoad(response, request)
|
|
45
49
|
} catch (error) {
|
|
46
50
|
if (id !== requestId) {
|
|
47
51
|
return
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* CoreUI PRO data-grid engine/features-lite.ts
|
|
4
|
+
* License (https://coreui.io/pro/license/)
|
|
5
|
+
* --------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
columnFilteringFeature,
|
|
10
|
+
createFilteredRowModel,
|
|
11
|
+
createPaginatedRowModel,
|
|
12
|
+
createSortedRowModel,
|
|
13
|
+
filterFn_includesString as includesStringFilterFn,
|
|
14
|
+
globalFilteringFeature,
|
|
15
|
+
rowPaginationFeature,
|
|
16
|
+
rowSortingFeature,
|
|
17
|
+
sortFn_alphanumeric as alphanumericSortFn,
|
|
18
|
+
sortFn_datetime as datetimeSortFn,
|
|
19
|
+
sortFn_text as textSortFn,
|
|
20
|
+
tableFeatures
|
|
21
|
+
} from '@tanstack/table-core'
|
|
22
|
+
import { storeReactivityBindings } from '@tanstack/table-core/store-reactivity-bindings'
|
|
23
|
+
|
|
24
|
+
// The smallest set the grid renders with: sorting, filtering (incl. the
|
|
25
|
+
// toolbar search) and pagination. Everything column-shape related (visibility,
|
|
26
|
+
// ordering, pinning, sizing) and selection/faceting stays out - the grid
|
|
27
|
+
// falls back to core APIs for those. sortFns/filterFns stay in so a lite grid
|
|
28
|
+
// sorts and searches exactly like a full one. Kept in its own module so the
|
|
29
|
+
// lite bundle entry never reaches the full set.
|
|
30
|
+
export const dataGridLiteFeatures = tableFeatures({
|
|
31
|
+
coreReactivityFeature: storeReactivityBindings(),
|
|
32
|
+
columnFilteringFeature,
|
|
33
|
+
globalFilteringFeature,
|
|
34
|
+
rowPaginationFeature,
|
|
35
|
+
rowSortingFeature,
|
|
36
|
+
filteredRowModel: createFilteredRowModel(),
|
|
37
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
38
|
+
sortedRowModel: createSortedRowModel(),
|
|
39
|
+
filterFns: { includesString: includesStringFilterFn },
|
|
40
|
+
sortFns: {
|
|
41
|
+
alphanumeric: alphanumericSortFn,
|
|
42
|
+
datetime: datetimeSortFn,
|
|
43
|
+
text: textSortFn
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
export type DataGridLiteFeatures = typeof dataGridLiteFeatures
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --------------------------------------------------------------------------
|
|
3
|
+
* CoreUI PRO data-grid engine/features.ts
|
|
4
|
+
* License (https://coreui.io/pro/license/)
|
|
5
|
+
* --------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
cellSelectionFeature,
|
|
10
|
+
columnFacetingFeature,
|
|
11
|
+
columnFilteringFeature,
|
|
12
|
+
columnOrderingFeature,
|
|
13
|
+
columnPinningFeature,
|
|
14
|
+
columnResizingFeature,
|
|
15
|
+
columnSizingFeature,
|
|
16
|
+
columnVisibilityFeature,
|
|
17
|
+
createFacetedRowModel,
|
|
18
|
+
createFacetedUniqueValues,
|
|
19
|
+
createFilteredRowModel,
|
|
20
|
+
createPaginatedRowModel,
|
|
21
|
+
createSortedRowModel,
|
|
22
|
+
filterFn_includesString as includesStringFilterFn,
|
|
23
|
+
globalFilteringFeature,
|
|
24
|
+
rowPaginationFeature,
|
|
25
|
+
rowSelectionFeature,
|
|
26
|
+
rowSortingFeature,
|
|
27
|
+
sortFn_alphanumeric as alphanumericSortFn,
|
|
28
|
+
sortFn_datetime as datetimeSortFn,
|
|
29
|
+
sortFn_text as textSortFn,
|
|
30
|
+
tableFeatures
|
|
31
|
+
} from '@tanstack/table-core'
|
|
32
|
+
import { storeReactivityBindings } from '@tanstack/table-core/store-reactivity-bindings'
|
|
33
|
+
|
|
34
|
+
// v9 exposes an API only when its feature is registered, so this is the full
|
|
35
|
+
// set of table-core behavior the grid can reach - options gate the behavior,
|
|
36
|
+
// not the registration. Prerequisites must precede dependents: sizing before
|
|
37
|
+
// resizing, filtering before global filtering and faceting, every row-model
|
|
38
|
+
// slot after its feature.
|
|
39
|
+
export const dataGridFeatures = tableFeatures({
|
|
40
|
+
coreReactivityFeature: storeReactivityBindings(),
|
|
41
|
+
cellSelectionFeature,
|
|
42
|
+
columnFilteringFeature,
|
|
43
|
+
globalFilteringFeature,
|
|
44
|
+
columnFacetingFeature,
|
|
45
|
+
columnOrderingFeature,
|
|
46
|
+
columnPinningFeature,
|
|
47
|
+
columnSizingFeature,
|
|
48
|
+
columnResizingFeature,
|
|
49
|
+
columnVisibilityFeature,
|
|
50
|
+
rowPaginationFeature,
|
|
51
|
+
rowSelectionFeature,
|
|
52
|
+
rowSortingFeature,
|
|
53
|
+
facetedRowModel: createFacetedRowModel(),
|
|
54
|
+
facetedUniqueValues: createFacetedUniqueValues(),
|
|
55
|
+
filteredRowModel: createFilteredRowModel(),
|
|
56
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
57
|
+
sortedRowModel: createSortedRowModel(),
|
|
58
|
+
filterFns: { includesString: includesStringFilterFn },
|
|
59
|
+
// The names column.getAutoSortFn() resolves for sampled value types; without
|
|
60
|
+
// them every column would silently fall back to the basic comparator.
|
|
61
|
+
sortFns: {
|
|
62
|
+
alphanumeric: alphanumericSortFn,
|
|
63
|
+
datetime: datetimeSortFn,
|
|
64
|
+
text: textSortFn
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
export type DataGridFeatures = typeof dataGridFeatures
|