@coreui/data-grid 0.1.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.
Files changed (101) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +37 -0
  3. package/dist/css/data-grid.css +444 -0
  4. package/dist/css/data-grid.css.map +1 -0
  5. package/dist/css/data-grid.min.css +5 -0
  6. package/dist/css/data-grid.min.css.map +1 -0
  7. package/dist/js/csv.cjs +68 -0
  8. package/dist/js/csv.cjs.map +1 -0
  9. package/dist/js/csv.mjs +63 -0
  10. package/dist/js/csv.mjs.map +1 -0
  11. package/dist/js/data-grid.esm.js +9618 -0
  12. package/dist/js/data-grid.esm.js.map +1 -0
  13. package/dist/js/data-grid.esm.min.js +8 -0
  14. package/dist/js/data-grid.esm.min.js.map +1 -0
  15. package/dist/js/data-grid.js +9635 -0
  16. package/dist/js/data-grid.js.map +1 -0
  17. package/dist/js/data-grid.min.js +8 -0
  18. package/dist/js/data-grid.min.js.map +1 -0
  19. package/dist/js/data-grid.mjs +9618 -0
  20. package/dist/js/data-grid.mjs.map +1 -0
  21. package/dist/js/filters.cjs +143 -0
  22. package/dist/js/filters.cjs.map +1 -0
  23. package/dist/js/filters.mjs +137 -0
  24. package/dist/js/filters.mjs.map +1 -0
  25. package/dist/js/labels.cjs +76 -0
  26. package/dist/js/labels.cjs.map +1 -0
  27. package/dist/js/labels.mjs +71 -0
  28. package/dist/js/labels.mjs.map +1 -0
  29. package/dist/types/base-component.d.ts +19 -0
  30. package/dist/types/data-grid.d.ts +128 -0
  31. package/dist/types/dom/event-handler.d.ts +11 -0
  32. package/dist/types/dom/manipulator.d.ts +9 -0
  33. package/dist/types/engine/active-cell.d.ts +32 -0
  34. package/dist/types/engine/data-source.d.ts +19 -0
  35. package/dist/types/engine/scheduler.d.ts +11 -0
  36. package/dist/types/engine/table.d.ts +9 -0
  37. package/dist/types/engine/virtualizer.d.ts +21 -0
  38. package/dist/types/filters.d.mts +1 -0
  39. package/dist/types/filters.d.ts +13 -0
  40. package/dist/types/icons.d.ts +21 -0
  41. package/dist/types/index.d.mts +1 -0
  42. package/dist/types/index.d.ts +12 -0
  43. package/dist/types/labels.d.mts +1 -0
  44. package/dist/types/labels.d.ts +9 -0
  45. package/dist/types/types.d.ts +262 -0
  46. package/dist/types/ui/body.d.ts +34 -0
  47. package/dist/types/ui/column-chooser.d.ts +27 -0
  48. package/dist/types/ui/editor.d.ts +8 -0
  49. package/dist/types/ui/filter-menu.d.ts +21 -0
  50. package/dist/types/ui/header.d.ts +50 -0
  51. package/dist/types/ui/loading.d.ts +12 -0
  52. package/dist/types/ui/menu.d.ts +17 -0
  53. package/dist/types/ui/pagination.d.ts +17 -0
  54. package/dist/types/ui/pinning.d.ts +17 -0
  55. package/dist/types/ui/toolbar.d.ts +34 -0
  56. package/dist/types/ui/tooltip.d.ts +10 -0
  57. package/dist/types/util/config.d.ts +11 -0
  58. package/dist/types/util/csv.d.mts +1 -0
  59. package/dist/types/util/csv.d.ts +19 -0
  60. package/dist/types/util/debounce.d.ts +7 -0
  61. package/dist/types/util/index.d.ts +10 -0
  62. package/dist/types/util/sanitizer.d.ts +11 -0
  63. package/package.json +147 -0
  64. package/scss/data-grid.scss +559 -0
  65. package/src/base-component.d.ts +19 -0
  66. package/src/base-component.js +90 -0
  67. package/src/data-grid.ts +2208 -0
  68. package/src/dom/data.js +59 -0
  69. package/src/dom/event-handler.d.ts +11 -0
  70. package/src/dom/event-handler.js +331 -0
  71. package/src/dom/manipulator.d.ts +9 -0
  72. package/src/dom/manipulator.js +75 -0
  73. package/src/engine/active-cell.ts +195 -0
  74. package/src/engine/data-source.ts +63 -0
  75. package/src/engine/scheduler.ts +42 -0
  76. package/src/engine/table.ts +122 -0
  77. package/src/engine/virtualizer.ts +57 -0
  78. package/src/filters.ts +176 -0
  79. package/src/icons.ts +60 -0
  80. package/src/index.ts +56 -0
  81. package/src/labels.ts +70 -0
  82. package/src/types.ts +334 -0
  83. package/src/ui/body.ts +348 -0
  84. package/src/ui/column-chooser.ts +183 -0
  85. package/src/ui/editor.ts +98 -0
  86. package/src/ui/filter-menu.ts +398 -0
  87. package/src/ui/header.ts +441 -0
  88. package/src/ui/loading.ts +39 -0
  89. package/src/ui/menu.ts +218 -0
  90. package/src/ui/pagination.ts +150 -0
  91. package/src/ui/pinning.ts +53 -0
  92. package/src/ui/toolbar.ts +144 -0
  93. package/src/ui/tooltip.ts +113 -0
  94. package/src/util/config.d.ts +11 -0
  95. package/src/util/config.js +69 -0
  96. package/src/util/csv.ts +85 -0
  97. package/src/util/debounce.ts +18 -0
  98. package/src/util/index.d.ts +10 -0
  99. package/src/util/index.js +310 -0
  100. package/src/util/sanitizer.d.ts +11 -0
  101. package/src/util/sanitizer.js +162 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid engine/data-source.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import type { DataGridDataRequest, DataGridDataResponse } from '../types'
9
+
10
+ const FETCH_DEBOUNCE_MS = 100
11
+
12
+ export interface GridDataSourceContext {
13
+ getRequest: () => DataGridDataRequest
14
+ onError: (error: unknown) => void
15
+ onLoad: (response: DataGridDataResponse) => void
16
+ onLoadingChange: (loading: boolean) => void
17
+ provider: (request: DataGridDataRequest) => Promise<DataGridDataResponse>
18
+ }
19
+
20
+ export interface GridDataSource {
21
+ load: () => void
22
+ dispose: () => void
23
+ }
24
+
25
+ export const createDataSource = (context: GridDataSourceContext): GridDataSource => {
26
+ let requestId = 0
27
+ let timeout: ReturnType<typeof setTimeout> | undefined
28
+
29
+ return {
30
+ load() {
31
+ clearTimeout(timeout)
32
+ // Invalidate at call time, not when the debounce fires - an older
33
+ // in-flight response must not render inside the debounce window.
34
+ const id = ++requestId
35
+ timeout = setTimeout(async () => {
36
+ context.onLoadingChange(true)
37
+
38
+ try {
39
+ const response = await context.provider(context.getRequest())
40
+ if (id !== requestId) {
41
+ return
42
+ }
43
+
44
+ context.onLoad(response)
45
+ } catch (error) {
46
+ if (id !== requestId) {
47
+ return
48
+ }
49
+
50
+ context.onError(error)
51
+ } finally {
52
+ if (id === requestId) {
53
+ context.onLoadingChange(false)
54
+ }
55
+ }
56
+ }, FETCH_DEBOUNCE_MS)
57
+ },
58
+ dispose() {
59
+ clearTimeout(timeout)
60
+ requestId++
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid engine/scheduler.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ export interface Scheduler {
9
+ schedule: () => void
10
+ dispose: () => void
11
+ }
12
+
13
+ export const createScheduler = (flush: () => void): Scheduler => {
14
+ let scheduled = false
15
+ let disposed = false
16
+
17
+ const run = () => {
18
+ scheduled = false
19
+ if (!disposed) {
20
+ flush()
21
+ }
22
+ }
23
+
24
+ return {
25
+ schedule() {
26
+ if (scheduled || disposed) {
27
+ return
28
+ }
29
+
30
+ scheduled = true
31
+ if (typeof window.requestAnimationFrame === 'function') {
32
+ window.requestAnimationFrame(run)
33
+ return
34
+ }
35
+
36
+ setTimeout(run, 16)
37
+ },
38
+ dispose() {
39
+ disposed = true
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid engine/table.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import {
9
+ createTable,
10
+ getCoreRowModel,
11
+ getFacetedRowModel,
12
+ getFacetedUniqueValues,
13
+ getFilteredRowModel,
14
+ getPaginationRowModel,
15
+ getSortedRowModel,
16
+ type FilterFn,
17
+ type Table,
18
+ type TableState,
19
+ type Updater
20
+ } from '@tanstack/table-core'
21
+ import { evaluateColumnFilter } from '../filters'
22
+ import type {
23
+ DataGridColumn, DataGridColumnFilterValue, DataGridItem, DataGridOptions
24
+ } from '../types'
25
+ import { isGlobalFilterEnabled } from '../ui/toolbar'
26
+
27
+ const toTanStackFilterFn = (column: DataGridColumn): FilterFn<DataGridItem> => {
28
+ const { filterFn } = column
29
+ if (filterFn) {
30
+ return (row, columnId, filterValue) => filterFn(row.getValue(columnId), filterValue, row.original)
31
+ }
32
+
33
+ return (row, columnId, filterValue) =>
34
+ evaluateColumnFilter(row.getValue(columnId), filterValue as DataGridColumnFilterValue, column.filterType)
35
+ }
36
+
37
+ export const createGridTable = (
38
+ options: DataGridOptions,
39
+ onStateChange: (previous: TableState, next: TableState) => void
40
+ ): Table<DataGridItem> => {
41
+ const sortingOptions = typeof options.sorting === 'object' ? options.sorting : {}
42
+ const sizingOptions = typeof options.columnSizing === 'object' ? options.columnSizing : {}
43
+ const paginationOptions = typeof options.pagination === 'object' ? options.pagination : {}
44
+ const serverSide = Boolean(options.dataProvider)
45
+ const sizingEnabled = Boolean(options.columnSizing)
46
+ const pinningEnabled = Boolean(options.columnPinning)
47
+ // Pinning offsets come from column.getSize(); sticky positioning is only
48
+ // pixel-correct when the rendered widths equal those sizes, so both features
49
+ // seed and apply explicit widths.
50
+ const widthsEnabled = sizingEnabled || pinningEnabled
51
+ const paginated = Boolean(options.pagination) || serverSide
52
+
53
+ const initialState: Partial<TableState> = {
54
+ ...(paginated && {
55
+ pagination: { pageIndex: 0, pageSize: paginationOptions.pageSize ?? 10 }
56
+ }),
57
+ ...(typeof options.columnPinning === 'object' && { columnPinning: options.columnPinning }),
58
+ ...(Array.isArray(options.columnOrder) && { columnOrder: options.columnOrder }),
59
+ ...(typeof options.columnVisibility === 'object' && { columnVisibility: options.columnVisibility })
60
+ }
61
+
62
+ const table = createTable<DataGridItem>({
63
+ columns: options.columns.map(column => {
64
+ const size = column.width ?? null
65
+ return {
66
+ accessorKey: column.key,
67
+ enableColumnFilter: column.filterable !== false,
68
+ enableHiding: column.hideable !== false,
69
+ enableResizing: column.resizable !== false,
70
+ enableSorting: column.sortable !== false,
71
+ filterFn: toTanStackFilterFn(column),
72
+ id: column.key,
73
+ meta: { label: column.label, formatter: column.formatter },
74
+ ...(widthsEnabled && size !== null && { size })
75
+ }
76
+ }),
77
+ columnResizeMode: sizingOptions.mode ?? 'onChange',
78
+ data: serverSide ? [] : options.items,
79
+ enableColumnFilters: Boolean(options.columnFilters),
80
+ enableColumnPinning: pinningEnabled,
81
+ enableColumnResizing: sizingEnabled,
82
+ enableGlobalFilter: isGlobalFilterEnabled(options),
83
+ enableHiding: Boolean(options.columnVisibility),
84
+ enableMultiSort: sortingOptions.multiple !== false,
85
+ enableRowSelection: Boolean(options.rowSelection),
86
+ enableSorting: Boolean(options.sorting),
87
+ enableSortingRemoval: Boolean(sortingOptions.resetable),
88
+ getCoreRowModel: getCoreRowModel(),
89
+ // Faceting powers custom filter UIs (column.getFacetedUniqueValues()).
90
+ getFacetedRowModel: getFacetedRowModel(),
91
+ getFacetedUniqueValues: getFacetedUniqueValues(),
92
+ getFilteredRowModel: getFilteredRowModel(),
93
+ getSortedRowModel: getSortedRowModel(),
94
+ globalFilterFn: 'includesString',
95
+ ...(serverSide && {
96
+ manualFiltering: true,
97
+ manualPagination: true,
98
+ manualSorting: true,
99
+ rowCount: 0
100
+ }),
101
+ ...(paginated && { getPaginationRowModel: getPaginationRowModel() }),
102
+ ...(options.itemKey && { getRowId: options.itemKey }),
103
+ initialState,
104
+ onStateChange() {},
105
+ renderFallbackValue: null,
106
+ state: {}
107
+ })
108
+
109
+ let state = table.initialState
110
+ table.setOptions(previous => ({
111
+ ...previous,
112
+ state,
113
+ onStateChange(updater: Updater<TableState>) {
114
+ const previousState = state
115
+ state = typeof updater === 'function' ? updater(state) : updater
116
+ table.setOptions(current => ({ ...current, state }))
117
+ onStateChange(previousState, state)
118
+ }
119
+ }))
120
+
121
+ return table
122
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid engine/virtualizer.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import {
9
+ elementScroll,
10
+ observeElementOffset,
11
+ observeElementRect,
12
+ Virtualizer
13
+ } from '@tanstack/virtual-core'
14
+
15
+ export type GridVirtualizerInstance = Virtualizer<HTMLDivElement, Element>
16
+
17
+ export interface GridVirtualizer {
18
+ instance: GridVirtualizerInstance
19
+ setCount: (count: number) => void
20
+ destroy: () => void
21
+ }
22
+
23
+ export interface GridVirtualizerOptions {
24
+ count: number
25
+ getScrollElement: () => HTMLDivElement
26
+ onChange: () => void
27
+ overscan: number
28
+ rowHeight: number
29
+ }
30
+
31
+ export const createGridVirtualizer = (options: GridVirtualizerOptions): GridVirtualizer => {
32
+ const instance: GridVirtualizerInstance = new Virtualizer({
33
+ count: options.count,
34
+ estimateSize: () => options.rowHeight,
35
+ getScrollElement: options.getScrollElement,
36
+ observeElementOffset,
37
+ observeElementRect,
38
+ onChange: options.onChange,
39
+ overscan: options.overscan,
40
+ scrollToFn: elementScroll
41
+ })
42
+
43
+ const unmount = instance._didMount()
44
+ instance._willUpdate()
45
+
46
+ return {
47
+ instance,
48
+ setCount(count: number) {
49
+ if (count !== instance.options.count) {
50
+ instance.setOptions({ ...instance.options, count })
51
+ }
52
+ },
53
+ destroy() {
54
+ unmount()
55
+ }
56
+ }
57
+ }
package/src/filters.ts ADDED
@@ -0,0 +1,176 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid filters.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ * Pure filter-operator logic, built as the dependency-free
7
+ * `@coreui/data-grid/filters` subpath so the framework bindings share one
8
+ * implementation without pulling in the vanilla component runtime.
9
+ */
10
+
11
+ import type {
12
+ DataGridColumnFilterValue,
13
+ DataGridFilterCondition,
14
+ DataGridFilterOperator,
15
+ DataGridFilterType
16
+ } from './types'
17
+
18
+ export const FILTER_OPERATORS: Record<Exclude<DataGridFilterType, 'select'>, DataGridFilterOperator[]> = {
19
+ text: ['contains', 'notContains', 'equals', 'notEquals', 'startsWith', 'endsWith', 'blank', 'notBlank'],
20
+ number: [
21
+ 'equals',
22
+ 'notEquals',
23
+ 'greaterThan',
24
+ 'greaterThanOrEqual',
25
+ 'lessThan',
26
+ 'lessThanOrEqual',
27
+ 'between',
28
+ 'blank',
29
+ 'notBlank'
30
+ ],
31
+ date: [
32
+ 'equals',
33
+ 'notEquals',
34
+ 'greaterThan',
35
+ 'greaterThanOrEqual',
36
+ 'lessThan',
37
+ 'lessThanOrEqual',
38
+ 'between',
39
+ 'blank',
40
+ 'notBlank'
41
+ ]
42
+ }
43
+
44
+ export const VALUELESS_OPERATORS: ReadonlySet<DataGridFilterOperator> = new Set(['blank', 'notBlank'])
45
+
46
+ const isBlank = (value: unknown): boolean =>
47
+ value === null || value === undefined || String(value).trim() === ''
48
+
49
+ const toComparable = (value: unknown, filterType: DataGridFilterType): number | null => {
50
+ if (filterType === 'date') {
51
+ const time = value instanceof Date ? value.getTime() : new Date(String(value)).getTime()
52
+ return Number.isNaN(time) ? null : time
53
+ }
54
+
55
+ const numeric = typeof value === 'number' ? value : Number(value)
56
+ return Number.isFinite(numeric) ? numeric : null
57
+ }
58
+
59
+ const evaluateCondition = (
60
+ cellValue: unknown,
61
+ condition: DataGridFilterCondition,
62
+ filterType: DataGridFilterType
63
+ ): boolean => {
64
+ const { operator } = condition
65
+
66
+ if (operator === 'blank') {
67
+ return isBlank(cellValue)
68
+ }
69
+
70
+ if (operator === 'notBlank') {
71
+ return !isBlank(cellValue)
72
+ }
73
+
74
+ // A condition without a value filters nothing (the menu treats it as
75
+ // incomplete rather than matching nothing).
76
+ if (isBlank(condition.value)) {
77
+ return true
78
+ }
79
+
80
+ if (filterType === 'number' || filterType === 'date') {
81
+ const cell = toComparable(cellValue, filterType)
82
+ const bound = toComparable(condition.value, filterType)
83
+ if (cell === null || bound === null) {
84
+ return false
85
+ }
86
+
87
+ switch (operator) {
88
+ case 'equals': {
89
+ return cell === bound
90
+ }
91
+
92
+ case 'notEquals': {
93
+ return cell !== bound
94
+ }
95
+
96
+ case 'greaterThan': {
97
+ return cell > bound
98
+ }
99
+
100
+ case 'greaterThanOrEqual': {
101
+ return cell >= bound
102
+ }
103
+
104
+ case 'lessThan': {
105
+ return cell < bound
106
+ }
107
+
108
+ case 'lessThanOrEqual': {
109
+ return cell <= bound
110
+ }
111
+
112
+ case 'between': {
113
+ const upper = toComparable(condition.value2, filterType)
114
+ return upper === null ? cell >= bound : cell >= bound && cell <= upper
115
+ }
116
+
117
+ default: {
118
+ return false
119
+ }
120
+ }
121
+ }
122
+
123
+ const cell = String(cellValue ?? '').toLowerCase()
124
+ const needle = String(condition.value).toLowerCase()
125
+
126
+ switch (operator) {
127
+ case 'contains': {
128
+ return cell.includes(needle)
129
+ }
130
+
131
+ case 'notContains': {
132
+ return !cell.includes(needle)
133
+ }
134
+
135
+ case 'equals': {
136
+ return cell === needle
137
+ }
138
+
139
+ case 'notEquals': {
140
+ return cell !== needle
141
+ }
142
+
143
+ case 'startsWith': {
144
+ return cell.startsWith(needle)
145
+ }
146
+
147
+ case 'endsWith': {
148
+ return cell.endsWith(needle)
149
+ }
150
+
151
+ default: {
152
+ return false
153
+ }
154
+ }
155
+ }
156
+
157
+ export const evaluateColumnFilter = (
158
+ cellValue: unknown,
159
+ filterValue: DataGridColumnFilterValue,
160
+ filterType: DataGridFilterType = 'text'
161
+ ): boolean => {
162
+ if (typeof filterValue === 'string') {
163
+ return String(cellValue ?? '')
164
+ .toLowerCase()
165
+ .includes(filterValue.toLowerCase())
166
+ }
167
+
168
+ if ('conditions' in filterValue) {
169
+ const results = filterValue.conditions.map(condition =>
170
+ evaluateCondition(cellValue, condition, filterType)
171
+ )
172
+ return filterValue.join === 'or' ? results.some(Boolean) : results.every(Boolean)
173
+ }
174
+
175
+ return filterValue.value.some(candidate => String(candidate) === String(cellValue))
176
+ }
package/src/icons.ts ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid icons.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ // Default icon set. Every icon is an SVG string drawn with `currentColor`, so it
9
+ // inherits the button's text color; each is overridable through the matching
10
+ // `*Icon` option. Sanitized via the SVGAllowlist before insertion.
11
+
12
+ export const DEFAULT_COLUMN_MENU_ICON =
13
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M204 148a52 52 0 1 0 104 0 52 52 0 1 0-104 0m78 0a26 26 0 1 1-26-26 26.03 26.03 0 0 1 26 26M204 264a52 52 0 1 0 104 0 52 52 0 1 0-104 0m78 0a26 26 0 1 1-26-26 26.03 26.03 0 0 1 26 26M204 380a52 52 0 1 0 104 0 52 52 0 1 0-104 0m78 0a26 26 0 1 1-26-26 26.03 26.03 0 0 1 26 26"/></svg>'
14
+
15
+ export const DEFAULT_FILTER_ICON =
16
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M96 197.333h320v32H96zm72 101.334h176v32H168zM216 400h80v32h-80zM48 96h416v32H48z"/></svg>'
17
+
18
+ export const DEFAULT_TOOLBAR_COLUMNS_ICON =
19
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M16 64v384h480V64Zm304 32v320H192V96ZM48 96h112v320H48Zm416 320H352V96h112Z"/></svg>'
20
+
21
+ export const DEFAULT_TOOLBAR_EXPORT_ICON =
22
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M16 464h480v32H16zm379.313-164.687-22.626-22.626L280 369.373V16h-32v353.373l-92.687-92.686-22.626 22.626L264 430.627z"/></svg>'
23
+
24
+ export const DEFAULT_TOOLBAR_UNDO_ICON =
25
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M495.473 197.262c0-73.061-43.651-136.118-106.242-164.462q-2-.9-4.021-1.762-4.046-1.715-8.19-3.235-2.071-.761-4.167-1.47-4.19-1.422-8.468-2.64a180.95 180.95 0 0 0-98.675 0q-4.278 1.218-8.469 2.64-2.094.71-4.166 1.47-4.143 1.519-8.19 3.235-2.023.857-4.021 1.762c-62.592 28.344-106.242 91.4-106.242 164.462v237.483L38.627 338.75 16 361.377 150.623 496l134.623-134.623-22.627-22.627-96 96V197.263c0-72.891 52.814-133.678 122.186-146.1a149.4 149.4 0 0 1 52.479 0c69.371 12.426 122.186 73.213 122.186 146.1h32Z"/></svg>'
26
+
27
+ export const DEFAULT_TOOLBAR_REDO_ICON =
28
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M361.376 495.163 226.753 360.54l22.627-22.627 111.996 111.996 111.997-111.996L496 360.54z"/><path fill="currentColor" d="M377.377 472.52h-32V196.426C345.377 114.584 278.794 48 196.952 48c-83.229 0-148.426 63.106-148.426 143.667h-32c0-48.024 18.85-92.569 53.079-125.429C103.35 33.842 148.576 16 196.952 16c99.487 0 180.425 80.938 180.425 180.426Z"/></svg>'
29
+
30
+ export const DEFAULT_SORT_ASCENDING_ICON =
31
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M390.624 150.625 256 16 121.376 150.625l22.628 22.627 95.997-95.998v417.982h32V77.257l95.995 95.995z"/></svg>'
32
+
33
+ export const DEFAULT_SORT_DESCENDING_ICON =
34
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="m367.997 338.75-95.998 95.997V17.503h-32v417.242l-95.996-95.995-22.627 22.627L256 496l134.624-134.623z"/></svg>'
35
+
36
+ export const DEFAULT_SORT_NEUTRAL_ICON =
37
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M384 433.373V160h-32v274.51l-69.823-69.823-22.627 22.626 107.882 107.883 107.881-107.883-22.626-22.626zM159.432 17.372 51.55 125.255l22.627 22.627L144 78.059V352h32V79.195l68.687 68.687 22.626-22.627z"/></svg>'
38
+
39
+ // Column-menu item icons. Sort actions in the menu reuse the sort header icons.
40
+
41
+ // Pin (pushpin): the needle points to the lower-left, so the unmirrored glyph is
42
+ // "pin left"; a horizontal mirror (scale(-1 1) about the 512 viewBox) is "pin right".
43
+ const PIN_PATH =
44
+ 'm477.8 140.2-106-106a62.132 62.132 0 0 0-93.617 81.24l-4.913 5.533-97.654 42.9-42.611-23.026a24.04 24.04 0 0 0-28.86 4.638L62.6 189.487a23.88 23.88 0 0 0 .479 33.449l101.68 101.679L16 473.373V496h22.627l148.758-148.758L288.6 448.457a23.93 23.93 0 0 0 33.275.642l44.425-41.128a23.98 23.98 0 0 0 4.773-29.092l-23.344-42.858 42.131-90.515 8.6-10.318A62.134 62.134 0 0 0 477.8 140.2m-22.628 65.231a30.125 30.125 0 0 1-42.6 0l-16.885-16.886-33.08 39.678-50.7 108.933 28.087 51.566-34.209 31.669L91.2 205.806l32-33.89 50.969 27.543 118.386-52.008 29.177-32.863-15.158-15.161a30.126 30.126 0 0 1 42.6-42.6l106 106a30.126 30.126 0 0 1 0 42.6Z'
45
+
46
+ const SVG_512 =
47
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false">'
48
+
49
+ export const DEFAULT_PIN_LEFT_ICON =
50
+ `${SVG_512}<path fill="currentColor" d="${PIN_PATH}"/></svg>`
51
+ export const DEFAULT_PIN_RIGHT_ICON =
52
+ `${SVG_512}<g transform="translate(512 0) scale(-1 1)"><path fill="currentColor" d="${PIN_PATH}"/></g></svg>`
53
+ export const DEFAULT_UNPIN_ICON =
54
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="m427.314 107.313-22.628-22.626L256 233.373 107.314 84.687l-22.628 22.626L233.373 256 84.686 404.687l22.628 22.626L256 278.627l148.686 148.686 22.628-22.626L278.627 256z"/></svg>'
55
+ export const DEFAULT_MOVE_LEFT_ICON =
56
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M254.625 56h-38.632L16 256.2 216 456h38.623V336h144V176h-144Zm112 152v96h-144v113.384l-161.37-161.21 161.37-161.535V208Zm96-152h32v400h-32z"/></svg>'
57
+ export const DEFAULT_MOVE_RIGHT_ICON =
58
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="M296.007 56h-38.632v120h-144v160h144v120H296l200-199.8Zm-6.632 361.384V304h-144v-96h144V94.639l161.37 161.535ZM17.375 56h32v400h-32z"/></svg>'
59
+ export const DEFAULT_HIDE_COLUMN_ICON =
60
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" aria-hidden="true" focusable="false"><path fill="currentColor" d="m397.222 131.1-.218-.223c-63.173-63.17-158.534-75.015-233.776-35.531l23.938 23.939c61.571-27.691 136.573-16.327 187.105 34.115L464 246.683v3.107l-71.744 74.585 22.63 22.63L496 262.683V233.79Z"/><path fill="currentColor" d="M352.8 284.33a103.307 103.307 0 0 0-132.893-132.892L246.1 177.63a71.228 71.228 0 0 1 80.507 80.508Zm17.1 62.938-33.831-33.831c.088-.108.179-.212.266-.32l-22.805-22.806q-.126.168-.253.334l-99.681-99.681.334-.253-22.81-22.805c-.108.087-.213.179-.321.266L38.627 16H16v22.627l95.689 95.689L16 233.79v28.893l98.778 102.689.218.222A199.73 199.73 0 0 0 367.372 390l106 106H496v-22.627L392.537 369.911Zm-177.157-131.9 96.128 96.132a71.28 71.28 0 0 1-96.133-96.133Zm-55.014 127.705L48 249.79v-3.107l86.319-89.737 35.065 35.064a103.248 103.248 0 0 0 142.842 142.843l32.007 32.007c-64.51 40.015-150.522 32.095-206.504-23.787"/></svg>'
package/src/index.ts ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid index.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ export { default as DataGrid } from './data-grid'
9
+ export { DEFAULT_LABELS, interpolate } from './labels'
10
+ export { evaluateColumnFilter, FILTER_OPERATORS, VALUELESS_OPERATORS } from './filters'
11
+ export { downloadCsv, exportCsv } from './util/csv'
12
+ export type { CsvDownloadOptions, CsvOptions } from './util/csv'
13
+ export type {
14
+ Column,
15
+ ColumnFiltersState,
16
+ ColumnOrderState,
17
+ ColumnPinningState,
18
+ ColumnSizingState,
19
+ DataGridColumn,
20
+ DataGridColumnFilterContext,
21
+ DataGridColumnFilterFactory,
22
+ DataGridColumnFilterValue,
23
+ DataGridColumnMenuBuilder,
24
+ DataGridColumnMenuContext,
25
+ DataGridColumnSizingOptions,
26
+ DataGridDataRequest,
27
+ DataGridDataResponse,
28
+ DataGridEditableOptions,
29
+ DataGridEditCommitEvent,
30
+ DataGridEditor,
31
+ DataGridEditorContext,
32
+ DataGridEditorFactory,
33
+ DataGridEditorType,
34
+ DataGridFilterCondition,
35
+ DataGridFilterOperator,
36
+ DataGridFilterType,
37
+ DataGridItem,
38
+ DataGridLabels,
39
+ DataGridMenuAction,
40
+ DataGridOptions,
41
+ DataGridPaginationInfoState,
42
+ DataGridPaginationOptions,
43
+ DataGridRowSelectionOptions,
44
+ DataGridSlot,
45
+ DataGridSlotContext,
46
+ DataGridSlotFactory,
47
+ DataGridSlots,
48
+ DataGridSortingOptions,
49
+ DataGridState,
50
+ DataGridToolbarOptions,
51
+ PaginationState,
52
+ RowSelectionState,
53
+ SortingState,
54
+ Table,
55
+ VisibilityState
56
+ } from './types'
package/src/labels.ts ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI PRO data-grid labels.ts
4
+ * License (https://coreui.io/pro/license/)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import type { DataGridLabels } from './types'
9
+
10
+ export const DEFAULT_LABELS: DataGridLabels = {
11
+ addCondition: 'Add condition',
12
+ applyFilter: 'Apply',
13
+ clearFilter: 'Clear filter',
14
+ clearSort: 'Unsort',
15
+ columnMenu: 'Column options for {column}',
16
+ filterAction: 'Filter…',
17
+ filterColumn: 'Filter {column}',
18
+ firstPage: 'First page',
19
+ globalFilterLabel: 'Search',
20
+ globalFilterPlaceholder: 'Search',
21
+ hideColumn: 'Hide column',
22
+ itemsInfo: '{first}–{last} of {total}',
23
+ joinAnd: 'AND',
24
+ joinOr: 'OR',
25
+ lastPage: 'Last page',
26
+ loadError: 'Failed to load data',
27
+ loading: 'Loading…',
28
+ moveLeft: 'Move left',
29
+ moveRight: 'Move right',
30
+ nextPage: 'Next page',
31
+ operatorBetween: 'Between',
32
+ operatorBlank: 'Blank',
33
+ operatorContains: 'Contains',
34
+ operatorEndsWith: 'Ends with',
35
+ operatorEquals: 'Equals',
36
+ operatorGreaterThan: 'Greater than',
37
+ operatorGreaterThanOrEqual: 'Greater than or equal',
38
+ operatorLessThan: 'Less than',
39
+ operatorLessThanOrEqual: 'Less than or equal',
40
+ operatorNotBlank: 'Not blank',
41
+ operatorNotContains: 'Does not contain',
42
+ operatorNotEquals: 'Not equals',
43
+ operatorStartsWith: 'Starts with',
44
+ pageSizeLabel: 'Rows per page',
45
+ paginationLabel: 'Pagination',
46
+ pinLeft: 'Pin left',
47
+ pinRight: 'Pin right',
48
+ previousPage: 'Previous page',
49
+ redoneAnnouncement: 'Change redone',
50
+ resetColumns: 'Reset',
51
+ resultsAnnouncement: '{count} results',
52
+ searchValues: 'Search values',
53
+ selectAllRows: 'Select all rows',
54
+ selectAllValues: 'Select all',
55
+ selectRow: 'Select row',
56
+ showAllColumns: 'Show all',
57
+ sortAscending: 'Sort ascending',
58
+ sortDescending: 'Sort descending',
59
+ toolbarColumns: 'Columns',
60
+ toolbarExport: 'Export',
61
+ toolbarRedo: 'Redo',
62
+ toolbarUndo: 'Undo',
63
+ undoneAnnouncement: 'Change undone',
64
+ unpin: 'Unpin'
65
+ }
66
+
67
+ export const interpolate = (template: string, tokens: Record<string, string | number>): string =>
68
+ template.replace(/\{(\w+)\}/g, (match: string, token: string) =>
69
+ token in tokens ? String(tokens[token]) : match
70
+ )