@furystack/shades-common-components 10.0.35 → 11.0.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/CHANGELOG.md +66 -0
- package/esm/components/animations.spec.d.ts +2 -0
- package/esm/components/animations.spec.d.ts.map +1 -0
- package/esm/components/animations.spec.js +201 -0
- package/esm/components/animations.spec.js.map +1 -0
- package/esm/components/app-bar-link.js +21 -20
- package/esm/components/app-bar-link.js.map +1 -1
- package/esm/components/app-bar-link.spec.d.ts +2 -0
- package/esm/components/app-bar-link.spec.d.ts.map +1 -0
- package/esm/components/app-bar-link.spec.js +252 -0
- package/esm/components/app-bar-link.spec.js.map +1 -0
- package/esm/components/app-bar.js +21 -21
- package/esm/components/app-bar.js.map +1 -1
- package/esm/components/app-bar.spec.d.ts +2 -0
- package/esm/components/app-bar.spec.d.ts.map +1 -0
- package/esm/components/app-bar.spec.js +117 -0
- package/esm/components/app-bar.spec.js.map +1 -0
- package/esm/components/avatar.d.ts.map +1 -1
- package/esm/components/avatar.js +15 -19
- package/esm/components/avatar.js.map +1 -1
- package/esm/components/avatar.spec.d.ts +2 -0
- package/esm/components/avatar.spec.d.ts.map +1 -0
- package/esm/components/avatar.spec.js +114 -0
- package/esm/components/avatar.spec.js.map +1 -0
- package/esm/components/button.d.ts.map +1 -1
- package/esm/components/button.js +145 -156
- package/esm/components/button.js.map +1 -1
- package/esm/components/button.spec.d.ts +2 -0
- package/esm/components/button.spec.d.ts.map +1 -0
- package/esm/components/button.spec.js +155 -0
- package/esm/components/button.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-input.d.ts.map +1 -1
- package/esm/components/command-palette/command-palette-input.js +18 -16
- package/esm/components/command-palette/command-palette-input.js.map +1 -1
- package/esm/components/command-palette/command-palette-input.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-input.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-input.spec.js +233 -0
- package/esm/components/command-palette/command-palette-input.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-manager.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-manager.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-manager.spec.js +362 -0
- package/esm/components/command-palette/command-palette-manager.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-suggestion-list.d.ts.map +1 -1
- package/esm/components/command-palette/command-palette-suggestion-list.js +42 -46
- package/esm/components/command-palette/command-palette-suggestion-list.js.map +1 -1
- package/esm/components/command-palette/command-palette-suggestion-list.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js +376 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -0
- package/esm/components/command-palette/index.d.ts.map +1 -1
- package/esm/components/command-palette/index.js +100 -110
- package/esm/components/command-palette/index.js.map +1 -1
- package/esm/components/command-palette/index.spec.d.ts +2 -0
- package/esm/components/command-palette/index.spec.d.ts.map +1 -0
- package/esm/components/command-palette/index.spec.js +509 -0
- package/esm/components/command-palette/index.spec.js.map +1 -0
- package/esm/components/data-grid/body.js +1 -1
- package/esm/components/data-grid/body.js.map +1 -1
- package/esm/components/data-grid/body.spec.d.ts +2 -0
- package/esm/components/data-grid/body.spec.d.ts.map +1 -0
- package/esm/components/data-grid/body.spec.js +228 -0
- package/esm/components/data-grid/body.spec.js.map +1 -0
- package/esm/components/data-grid/data-grid-row.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid-row.js +49 -73
- package/esm/components/data-grid/data-grid-row.js.map +1 -1
- package/esm/components/data-grid/data-grid-row.spec.d.ts +2 -0
- package/esm/components/data-grid/data-grid-row.spec.d.ts.map +1 -0
- package/esm/components/data-grid/data-grid-row.spec.js +296 -0
- package/esm/components/data-grid/data-grid-row.spec.js.map +1 -0
- package/esm/components/data-grid/data-grid.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid.js +35 -28
- package/esm/components/data-grid/data-grid.js.map +1 -1
- package/esm/components/data-grid/data-grid.spec.d.ts +2 -0
- package/esm/components/data-grid/data-grid.spec.d.ts.map +1 -0
- package/esm/components/data-grid/data-grid.spec.js +544 -0
- package/esm/components/data-grid/data-grid.spec.js.map +1 -0
- package/esm/components/data-grid/footer.js +21 -15
- package/esm/components/data-grid/footer.js.map +1 -1
- package/esm/components/data-grid/footer.spec.d.ts +2 -0
- package/esm/components/data-grid/footer.spec.d.ts.map +1 -0
- package/esm/components/data-grid/footer.spec.js +264 -0
- package/esm/components/data-grid/footer.spec.js.map +1 -0
- package/esm/components/data-grid/header.d.ts.map +1 -1
- package/esm/components/data-grid/header.js +55 -33
- package/esm/components/data-grid/header.js.map +1 -1
- package/esm/components/data-grid/header.spec.d.ts +2 -0
- package/esm/components/data-grid/header.spec.d.ts.map +1 -0
- package/esm/components/data-grid/header.spec.js +421 -0
- package/esm/components/data-grid/header.spec.js.map +1 -0
- package/esm/components/data-grid/selection-cell.d.ts.map +1 -1
- package/esm/components/data-grid/selection-cell.js +13 -6
- package/esm/components/data-grid/selection-cell.js.map +1 -1
- package/esm/components/data-grid/selection-cell.spec.d.ts +2 -0
- package/esm/components/data-grid/selection-cell.spec.d.ts.map +1 -0
- package/esm/components/data-grid/selection-cell.spec.js +118 -0
- package/esm/components/data-grid/selection-cell.spec.js.map +1 -0
- package/esm/components/fab.d.ts.map +1 -1
- package/esm/components/fab.js +10 -1
- package/esm/components/fab.js.map +1 -1
- package/esm/components/fab.spec.d.ts +2 -0
- package/esm/components/fab.spec.d.ts.map +1 -0
- package/esm/components/fab.spec.js +95 -0
- package/esm/components/fab.spec.js.map +1 -0
- package/esm/components/form.spec.d.ts +2 -0
- package/esm/components/form.spec.d.ts.map +1 -0
- package/esm/components/form.spec.js +314 -0
- package/esm/components/form.spec.js.map +1 -0
- package/esm/components/grid.d.ts.map +1 -1
- package/esm/components/grid.js +40 -37
- package/esm/components/grid.js.map +1 -1
- package/esm/components/grid.spec.d.ts +2 -0
- package/esm/components/grid.spec.d.ts.map +1 -0
- package/esm/components/grid.spec.js +316 -0
- package/esm/components/grid.spec.js.map +1 -0
- package/esm/components/inputs/autocomplete.spec.d.ts +2 -0
- package/esm/components/inputs/autocomplete.spec.d.ts.map +1 -0
- package/esm/components/inputs/autocomplete.spec.js +194 -0
- package/esm/components/inputs/autocomplete.spec.js.map +1 -0
- package/esm/components/inputs/input.d.ts.map +1 -1
- package/esm/components/inputs/input.js +141 -109
- package/esm/components/inputs/input.js.map +1 -1
- package/esm/components/inputs/input.spec.d.ts +2 -0
- package/esm/components/inputs/input.spec.d.ts.map +1 -0
- package/esm/components/inputs/input.spec.js +577 -0
- package/esm/components/inputs/input.spec.js.map +1 -0
- package/esm/components/inputs/text-area.d.ts.map +1 -1
- package/esm/components/inputs/text-area.js +54 -58
- package/esm/components/inputs/text-area.js.map +1 -1
- package/esm/components/inputs/text-area.spec.d.ts +2 -0
- package/esm/components/inputs/text-area.spec.d.ts.map +1 -0
- package/esm/components/inputs/text-area.spec.js +214 -0
- package/esm/components/inputs/text-area.spec.js.map +1 -0
- package/esm/components/loader.js +1 -1
- package/esm/components/loader.js.map +1 -1
- package/esm/components/loader.spec.d.ts +2 -0
- package/esm/components/loader.spec.d.ts.map +1 -0
- package/esm/components/loader.spec.js +251 -0
- package/esm/components/loader.spec.js.map +1 -0
- package/esm/components/modal.d.ts.map +1 -1
- package/esm/components/modal.js +11 -9
- package/esm/components/modal.js.map +1 -1
- package/esm/components/modal.spec.d.ts +2 -0
- package/esm/components/modal.spec.d.ts.map +1 -0
- package/esm/components/modal.spec.js +227 -0
- package/esm/components/modal.spec.js.map +1 -0
- package/esm/components/noty-list.d.ts.map +1 -1
- package/esm/components/noty-list.js +39 -40
- package/esm/components/noty-list.js.map +1 -1
- package/esm/components/noty-list.spec.d.ts +2 -0
- package/esm/components/noty-list.spec.d.ts.map +1 -0
- package/esm/components/noty-list.spec.js +486 -0
- package/esm/components/noty-list.spec.js.map +1 -0
- package/esm/components/paper.d.ts.map +1 -1
- package/esm/components/paper.js +15 -12
- package/esm/components/paper.js.map +1 -1
- package/esm/components/paper.spec.d.ts +2 -0
- package/esm/components/paper.spec.d.ts.map +1 -0
- package/esm/components/paper.spec.js +63 -0
- package/esm/components/paper.spec.js.map +1 -0
- package/esm/components/skeleton.js +1 -1
- package/esm/components/skeleton.js.map +1 -1
- package/esm/components/skeleton.spec.d.ts +2 -0
- package/esm/components/skeleton.spec.d.ts.map +1 -0
- package/esm/components/skeleton.spec.js +159 -0
- package/esm/components/skeleton.spec.js.map +1 -0
- package/esm/components/styles.spec.d.ts +2 -0
- package/esm/components/styles.spec.d.ts.map +1 -0
- package/esm/components/styles.spec.js +56 -0
- package/esm/components/styles.spec.js.map +1 -0
- package/esm/components/suggest/index.d.ts.map +1 -1
- package/esm/components/suggest/index.js +74 -83
- package/esm/components/suggest/index.js.map +1 -1
- package/esm/components/suggest/index.spec.d.ts +2 -0
- package/esm/components/suggest/index.spec.d.ts.map +1 -0
- package/esm/components/suggest/index.spec.js +515 -0
- package/esm/components/suggest/index.spec.js.map +1 -0
- package/esm/components/suggest/suggest-input.d.ts.map +1 -1
- package/esm/components/suggest/suggest-input.js +16 -17
- package/esm/components/suggest/suggest-input.js.map +1 -1
- package/esm/components/suggest/suggest-input.spec.d.ts +2 -0
- package/esm/components/suggest/suggest-input.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggest-input.spec.js +138 -0
- package/esm/components/suggest/suggest-input.spec.js.map +1 -0
- package/esm/components/suggest/suggest-manager.spec.d.ts +2 -0
- package/esm/components/suggest/suggest-manager.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggest-manager.spec.js +308 -0
- package/esm/components/suggest/suggest-manager.spec.js.map +1 -0
- package/esm/components/suggest/suggestion-list.d.ts.map +1 -1
- package/esm/components/suggest/suggestion-list.js +43 -48
- package/esm/components/suggest/suggestion-list.js.map +1 -1
- package/esm/components/suggest/suggestion-list.spec.d.ts +2 -0
- package/esm/components/suggest/suggestion-list.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggestion-list.spec.js +252 -0
- package/esm/components/suggest/suggestion-list.spec.js.map +1 -0
- package/esm/components/tabs.d.ts.map +1 -1
- package/esm/components/tabs.js +32 -18
- package/esm/components/tabs.js.map +1 -1
- package/esm/components/tabs.spec.d.ts +2 -0
- package/esm/components/tabs.spec.d.ts.map +1 -0
- package/esm/components/tabs.spec.js +187 -0
- package/esm/components/tabs.spec.js.map +1 -0
- package/esm/components/wizard/index.d.ts.map +1 -1
- package/esm/components/wizard/index.js +10 -7
- package/esm/components/wizard/index.js.map +1 -1
- package/esm/components/wizard/index.spec.d.ts +2 -0
- package/esm/components/wizard/index.spec.d.ts.map +1 -0
- package/esm/components/wizard/index.spec.js +171 -0
- package/esm/components/wizard/index.spec.js.map +1 -0
- package/esm/services/collection-service.spec.js +391 -2
- package/esm/services/collection-service.spec.js.map +1 -1
- package/esm/services/css-variable-theme.d.ts.map +1 -1
- package/esm/services/css-variable-theme.js +21 -1
- package/esm/services/css-variable-theme.js.map +1 -1
- package/esm/services/css-variable-theme.spec.d.ts +2 -0
- package/esm/services/css-variable-theme.spec.d.ts.map +1 -0
- package/esm/services/css-variable-theme.spec.js +169 -0
- package/esm/services/css-variable-theme.spec.js.map +1 -0
- package/esm/services/default-palette.d.ts +4 -0
- package/esm/services/default-palette.d.ts.map +1 -1
- package/esm/services/default-palette.js +22 -0
- package/esm/services/default-palette.js.map +1 -1
- package/esm/services/theme-provider-service.d.ts +59 -1
- package/esm/services/theme-provider-service.d.ts.map +1 -1
- package/esm/services/theme-provider-service.js.map +1 -1
- package/esm/services/theme-provider-service.spec.d.ts +2 -0
- package/esm/services/theme-provider-service.spec.d.ts.map +1 -0
- package/esm/services/theme-provider-service.spec.js +166 -0
- package/esm/services/theme-provider-service.spec.js.map +1 -0
- package/package.json +2 -2
- package/src/components/animations.spec.ts +299 -0
- package/src/components/app-bar-link.spec.tsx +341 -0
- package/src/components/app-bar-link.tsx +21 -21
- package/src/components/app-bar.spec.tsx +142 -0
- package/src/components/app-bar.tsx +22 -22
- package/src/components/avatar.spec.tsx +146 -0
- package/src/components/avatar.tsx +17 -20
- package/src/components/button.spec.tsx +193 -0
- package/src/components/button.tsx +162 -197
- package/src/components/command-palette/command-palette-input.spec.tsx +320 -0
- package/src/components/command-palette/command-palette-input.tsx +19 -22
- package/src/components/command-palette/command-palette-manager.spec.ts +470 -0
- package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +499 -0
- package/src/components/command-palette/command-palette-suggestion-list.tsx +42 -46
- package/src/components/command-palette/index.spec.tsx +684 -0
- package/src/components/command-palette/index.tsx +107 -136
- package/src/components/data-grid/body.spec.tsx +340 -0
- package/src/components/data-grid/body.tsx +1 -1
- package/src/components/data-grid/data-grid-row.spec.tsx +382 -0
- package/src/components/data-grid/data-grid-row.tsx +50 -82
- package/src/components/data-grid/data-grid.spec.tsx +939 -0
- package/src/components/data-grid/data-grid.tsx +38 -35
- package/src/components/data-grid/footer.spec.tsx +344 -0
- package/src/components/data-grid/footer.tsx +19 -19
- package/src/components/data-grid/header.spec.tsx +563 -0
- package/src/components/data-grid/header.tsx +53 -44
- package/src/components/data-grid/selection-cell.spec.tsx +150 -0
- package/src/components/data-grid/selection-cell.tsx +12 -6
- package/src/components/fab.spec.tsx +108 -0
- package/src/components/fab.tsx +10 -1
- package/src/components/form.spec.tsx +481 -0
- package/src/components/grid.spec.tsx +334 -0
- package/src/components/grid.tsx +57 -63
- package/src/components/inputs/autocomplete.spec.tsx +258 -0
- package/src/components/inputs/input.spec.tsx +808 -0
- package/src/components/inputs/input.tsx +153 -139
- package/src/components/inputs/text-area.spec.tsx +285 -0
- package/src/components/inputs/text-area.tsx +53 -79
- package/src/components/loader.spec.tsx +346 -0
- package/src/components/loader.tsx +1 -1
- package/src/components/modal.spec.tsx +304 -0
- package/src/components/modal.tsx +11 -9
- package/src/components/noty-list.spec.tsx +631 -0
- package/src/components/noty-list.tsx +39 -50
- package/src/components/paper.spec.tsx +72 -0
- package/src/components/paper.tsx +15 -13
- package/src/components/skeleton.spec.tsx +219 -0
- package/src/components/skeleton.tsx +1 -1
- package/src/components/styles.spec.ts +70 -0
- package/src/components/suggest/index.spec.tsx +861 -0
- package/src/components/suggest/index.tsx +74 -101
- package/src/components/suggest/suggest-input.spec.tsx +181 -0
- package/src/components/suggest/suggest-input.tsx +16 -24
- package/src/components/suggest/suggest-manager.spec.ts +409 -0
- package/src/components/suggest/suggestion-list.spec.tsx +334 -0
- package/src/components/suggest/suggestion-list.tsx +43 -48
- package/src/components/tabs.spec.tsx +236 -0
- package/src/components/tabs.tsx +33 -21
- package/src/components/wizard/index.spec.tsx +224 -0
- package/src/components/wizard/index.tsx +10 -9
- package/src/services/collection-service.spec.ts +492 -3
- package/src/services/css-variable-theme.spec.ts +204 -0
- package/src/services/css-variable-theme.ts +21 -1
- package/src/services/default-palette.ts +22 -0
- package/src/services/theme-provider-service.spec.ts +195 -0
- package/src/services/theme-provider-service.ts +60 -2
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { FindOptions } from '@furystack/core'
|
|
2
2
|
import type { ChildrenList } from '@furystack/shades'
|
|
3
|
-
import { createComponent, Shade } from '@furystack/shades'
|
|
3
|
+
import { attachStyles, createComponent, Shade } from '@furystack/shades'
|
|
4
4
|
import type { ObservableValue } from '@furystack/utils'
|
|
5
5
|
import { ClickAwayService } from '../../services/click-away-service.js'
|
|
6
6
|
import type { CollectionService } from '../../services/collection-service.js'
|
|
7
|
-
import {
|
|
7
|
+
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
8
8
|
import type { GridProps } from '../grid.js'
|
|
9
9
|
import { DataGridBody } from './body.js'
|
|
10
10
|
import { DataGridFooter } from './footer.js'
|
|
@@ -80,27 +80,22 @@ export const DataGrid: <T, Column extends string>(
|
|
|
80
80
|
children: ChildrenList,
|
|
81
81
|
) => JSX.Element<any> = Shade({
|
|
82
82
|
shadowDomName: 'shade-data-grid',
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
'
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
props.collectionService.hasFocus.setValue(false)
|
|
97
|
-
}),
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
const headerStyle: Partial<CSSStyleDeclaration> = {
|
|
83
|
+
css: {
|
|
84
|
+
display: 'block',
|
|
85
|
+
width: '100%',
|
|
86
|
+
height: '100%',
|
|
87
|
+
overflow: 'auto',
|
|
88
|
+
zIndex: '1',
|
|
89
|
+
'& table': {
|
|
90
|
+
width: '100%',
|
|
91
|
+
maxHeight: 'calc(100% - 4em)',
|
|
92
|
+
position: 'relative',
|
|
93
|
+
borderCollapse: 'collapse',
|
|
94
|
+
},
|
|
95
|
+
'& th': {
|
|
101
96
|
backdropFilter: 'blur(12px) saturate(180%)',
|
|
102
97
|
background: 'rgba(128,128,128,0.3)',
|
|
103
|
-
color:
|
|
98
|
+
color: cssVariableTheme.text.secondary,
|
|
104
99
|
height: '48px',
|
|
105
100
|
padding: '0 1.2em',
|
|
106
101
|
alignItems: 'center',
|
|
@@ -114,34 +109,42 @@ export const DataGrid: <T, Column extends string>(
|
|
|
114
109
|
textAlign: 'left',
|
|
115
110
|
zIndex: '1',
|
|
116
111
|
boxShadow: 'rgba(0, 0, 0, 0.2) 1px 1px 1px 2px',
|
|
117
|
-
borderBottom:
|
|
118
|
-
borderRight:
|
|
119
|
-
|
|
112
|
+
borderBottom: '2px solid rgba(128, 128, 128, 0.2)',
|
|
113
|
+
borderRight: '1px solid rgba(128, 128, 128, 0.2)',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
constructed: ({ props }) => {
|
|
117
|
+
const listener = (ev: KeyboardEvent) => props.collectionService.handleKeyDown(ev)
|
|
118
|
+
window.addEventListener('keydown', listener)
|
|
119
|
+
return () => window.removeEventListener('keydown', listener)
|
|
120
|
+
},
|
|
121
|
+
render: ({ props, useDisposable, element }) => {
|
|
122
|
+
useDisposable(
|
|
123
|
+
'clickAway',
|
|
124
|
+
() =>
|
|
125
|
+
new ClickAwayService(element, () => {
|
|
126
|
+
props.collectionService.hasFocus.setValue(false)
|
|
127
|
+
}),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if (props.styles?.wrapper) {
|
|
131
|
+
attachStyles(element, { style: props.styles.wrapper })
|
|
120
132
|
}
|
|
121
133
|
|
|
122
134
|
return (
|
|
123
135
|
<div
|
|
124
136
|
className="shade-grid-wrapper"
|
|
125
|
-
style={{
|
|
126
|
-
...props.styles?.wrapper,
|
|
127
|
-
width: '100%',
|
|
128
|
-
height: '100%',
|
|
129
|
-
overflow: 'auto',
|
|
130
|
-
zIndex: '1',
|
|
131
|
-
}}
|
|
132
137
|
onclick={() => {
|
|
133
138
|
props.collectionService.hasFocus.setValue(true)
|
|
134
139
|
}}
|
|
135
140
|
ariaMultiSelectable="true"
|
|
136
141
|
>
|
|
137
|
-
<table
|
|
138
|
-
style={{ width: '100%', maxHeight: 'calc(100% - 4em)', position: 'relative', borderCollapse: 'collapse' }}
|
|
139
|
-
>
|
|
142
|
+
<table>
|
|
140
143
|
<thead>
|
|
141
144
|
<tr>
|
|
142
145
|
{props.columns.map((column) => {
|
|
143
146
|
return (
|
|
144
|
-
<th style={
|
|
147
|
+
<th style={props.styles?.header}>
|
|
145
148
|
{props.headerComponents?.[column]?.(column) || props.headerComponents?.default?.(column) || (
|
|
146
149
|
<DataGridHeader<
|
|
147
150
|
ReturnType<typeof props.collectionService.data.getValue>['entries'][number],
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import type { FindOptions } from '@furystack/core'
|
|
2
|
+
import { Injector } from '@furystack/inject'
|
|
3
|
+
import { createComponent, initializeShadeRoot } from '@furystack/shades'
|
|
4
|
+
import { ObservableValue, sleepAsync } from '@furystack/utils'
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
6
|
+
import { CollectionService } from '../../services/collection-service.js'
|
|
7
|
+
import { DataGridFooter, dataGridItemsPerPage } from './footer.js'
|
|
8
|
+
|
|
9
|
+
type TestItem = { id: number; name: string }
|
|
10
|
+
|
|
11
|
+
describe('DataGridFooter', () => {
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
document.body.innerHTML = '<div id="root"></div>'
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
document.body.innerHTML = ''
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const createService = (entries: TestItem[] = [], count?: number) => {
|
|
21
|
+
const service = new CollectionService<TestItem>()
|
|
22
|
+
service.data.setValue({ entries, count: count ?? entries.length })
|
|
23
|
+
return service
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const createFindOptions = (
|
|
27
|
+
top: number = 10,
|
|
28
|
+
skip: number = 0,
|
|
29
|
+
): ObservableValue<FindOptions<TestItem, Array<keyof TestItem>>> => {
|
|
30
|
+
return new ObservableValue<FindOptions<TestItem, Array<keyof TestItem>>>({ top, skip })
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
it('should render with custom element', async () => {
|
|
34
|
+
const injector = new Injector()
|
|
35
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
36
|
+
const service = createService()
|
|
37
|
+
const findOptions = createFindOptions()
|
|
38
|
+
|
|
39
|
+
initializeShadeRoot({
|
|
40
|
+
injector,
|
|
41
|
+
rootElement,
|
|
42
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
await sleepAsync(50)
|
|
46
|
+
|
|
47
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
48
|
+
expect(footer).not.toBeNull()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('should render items per page select', async () => {
|
|
52
|
+
const injector = new Injector()
|
|
53
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
54
|
+
const service = createService()
|
|
55
|
+
const findOptions = createFindOptions()
|
|
56
|
+
|
|
57
|
+
initializeShadeRoot({
|
|
58
|
+
injector,
|
|
59
|
+
rootElement,
|
|
60
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
await sleepAsync(50)
|
|
64
|
+
|
|
65
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
66
|
+
const selects = footer?.querySelectorAll('select')
|
|
67
|
+
|
|
68
|
+
expect(selects?.length).toBeGreaterThan(0)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('should render all items per page options', async () => {
|
|
72
|
+
const injector = new Injector()
|
|
73
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
74
|
+
const service = createService()
|
|
75
|
+
const findOptions = createFindOptions()
|
|
76
|
+
|
|
77
|
+
initializeShadeRoot({
|
|
78
|
+
injector,
|
|
79
|
+
rootElement,
|
|
80
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
await sleepAsync(50)
|
|
84
|
+
|
|
85
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
86
|
+
const selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
87
|
+
const itemsPerPageSelect = selects.find((s) => {
|
|
88
|
+
const parent = s.parentElement
|
|
89
|
+
return parent?.textContent?.includes('items per page')
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
expect(itemsPerPageSelect).toBeDefined()
|
|
93
|
+
const options = itemsPerPageSelect?.querySelectorAll('option')
|
|
94
|
+
expect(options?.length).toBe(dataGridItemsPerPage.length)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('should show page selector when pagination is enabled', async () => {
|
|
98
|
+
const injector = new Injector()
|
|
99
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
100
|
+
const service = createService([], 100)
|
|
101
|
+
const findOptions = createFindOptions(10, 0)
|
|
102
|
+
|
|
103
|
+
initializeShadeRoot({
|
|
104
|
+
injector,
|
|
105
|
+
rootElement,
|
|
106
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
await sleepAsync(50)
|
|
110
|
+
|
|
111
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
112
|
+
const pager = footer?.querySelector('.pager')
|
|
113
|
+
expect(pager?.textContent).toContain('Goto page')
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('should hide page selector when showing all items (Infinity)', async () => {
|
|
117
|
+
const injector = new Injector()
|
|
118
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
119
|
+
const service = createService([], 50)
|
|
120
|
+
const findOptions = createFindOptions(Infinity, 0)
|
|
121
|
+
|
|
122
|
+
initializeShadeRoot({
|
|
123
|
+
injector,
|
|
124
|
+
rootElement,
|
|
125
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
await sleepAsync(50)
|
|
129
|
+
|
|
130
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
131
|
+
const pager = footer?.querySelector('.pager')
|
|
132
|
+
expect(pager?.textContent).not.toContain('Goto page')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('should render correct number of page options based on data count and items per page', async () => {
|
|
136
|
+
const injector = new Injector()
|
|
137
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
138
|
+
const service = createService([], 100)
|
|
139
|
+
const findOptions = createFindOptions(25, 0)
|
|
140
|
+
|
|
141
|
+
initializeShadeRoot({
|
|
142
|
+
injector,
|
|
143
|
+
rootElement,
|
|
144
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
await sleepAsync(50)
|
|
148
|
+
|
|
149
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
150
|
+
const selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
151
|
+
const pageSelect = selects.find((s) => {
|
|
152
|
+
const parent = s.parentElement
|
|
153
|
+
return parent?.textContent?.includes('Goto page')
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
expect(pageSelect).toBeDefined()
|
|
157
|
+
const options = pageSelect?.querySelectorAll('option')
|
|
158
|
+
expect(options?.length).toBe(4)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
it('should update findOptions when page is changed', async () => {
|
|
162
|
+
const injector = new Injector()
|
|
163
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
164
|
+
const service = createService([], 100)
|
|
165
|
+
const findOptions = createFindOptions(10, 0)
|
|
166
|
+
|
|
167
|
+
initializeShadeRoot({
|
|
168
|
+
injector,
|
|
169
|
+
rootElement,
|
|
170
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
await sleepAsync(50)
|
|
174
|
+
|
|
175
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
176
|
+
const selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
177
|
+
const pageSelect = selects.find((s) => {
|
|
178
|
+
const parent = s.parentElement
|
|
179
|
+
return parent?.textContent?.includes('Goto page')
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
expect(pageSelect).toBeDefined()
|
|
183
|
+
|
|
184
|
+
pageSelect!.value = '2'
|
|
185
|
+
pageSelect!.dispatchEvent(new Event('change', { bubbles: true }))
|
|
186
|
+
|
|
187
|
+
await sleepAsync(50)
|
|
188
|
+
|
|
189
|
+
const updatedOptions = findOptions.getValue()
|
|
190
|
+
expect(updatedOptions.skip).toBe(20)
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('should update findOptions when items per page is changed', async () => {
|
|
194
|
+
const injector = new Injector()
|
|
195
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
196
|
+
const service = createService([], 100)
|
|
197
|
+
const findOptions = createFindOptions(10, 0)
|
|
198
|
+
|
|
199
|
+
initializeShadeRoot({
|
|
200
|
+
injector,
|
|
201
|
+
rootElement,
|
|
202
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
await sleepAsync(50)
|
|
206
|
+
|
|
207
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
208
|
+
const selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
209
|
+
const itemsPerPageSelect = selects.find((s) => {
|
|
210
|
+
const parent = s.parentElement
|
|
211
|
+
return parent?.textContent?.includes('items per page')
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
expect(itemsPerPageSelect).toBeDefined()
|
|
215
|
+
|
|
216
|
+
itemsPerPageSelect!.value = '25'
|
|
217
|
+
itemsPerPageSelect!.dispatchEvent(new Event('change', { bubbles: true }))
|
|
218
|
+
|
|
219
|
+
await sleepAsync(50)
|
|
220
|
+
|
|
221
|
+
const updatedOptions = findOptions.getValue()
|
|
222
|
+
expect(updatedOptions.top).toBe(25)
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
it('should preserve current page position when changing items per page', async () => {
|
|
226
|
+
const injector = new Injector()
|
|
227
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
228
|
+
const service = createService([], 100)
|
|
229
|
+
const findOptions = createFindOptions(10, 20)
|
|
230
|
+
|
|
231
|
+
initializeShadeRoot({
|
|
232
|
+
injector,
|
|
233
|
+
rootElement,
|
|
234
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
await sleepAsync(50)
|
|
238
|
+
|
|
239
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
240
|
+
const selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
241
|
+
const itemsPerPageSelect = selects.find((s) => {
|
|
242
|
+
const parent = s.parentElement
|
|
243
|
+
return parent?.textContent?.includes('items per page')
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
expect(itemsPerPageSelect).toBeDefined()
|
|
247
|
+
|
|
248
|
+
itemsPerPageSelect!.value = '25'
|
|
249
|
+
itemsPerPageSelect!.dispatchEvent(new Event('change', { bubbles: true }))
|
|
250
|
+
|
|
251
|
+
await sleepAsync(50)
|
|
252
|
+
|
|
253
|
+
const updatedOptions = findOptions.getValue()
|
|
254
|
+
expect(updatedOptions.top).toBe(25)
|
|
255
|
+
expect(updatedOptions.skip).toBe(50)
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
it('should select the correct current page in the page selector', async () => {
|
|
259
|
+
const injector = new Injector()
|
|
260
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
261
|
+
const service = createService([], 100)
|
|
262
|
+
const findOptions = createFindOptions(10, 30)
|
|
263
|
+
|
|
264
|
+
initializeShadeRoot({
|
|
265
|
+
injector,
|
|
266
|
+
rootElement,
|
|
267
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
await sleepAsync(50)
|
|
271
|
+
|
|
272
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
273
|
+
const selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
274
|
+
const pageSelect = selects.find((s) => {
|
|
275
|
+
const parent = s.parentElement
|
|
276
|
+
return parent?.textContent?.includes('Goto page')
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
expect(pageSelect).toBeDefined()
|
|
280
|
+
expect(pageSelect?.value).toBe('3')
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
it('should select the correct items per page option', async () => {
|
|
284
|
+
const injector = new Injector()
|
|
285
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
286
|
+
const service = createService([], 100)
|
|
287
|
+
const findOptions = createFindOptions(25, 0)
|
|
288
|
+
|
|
289
|
+
initializeShadeRoot({
|
|
290
|
+
injector,
|
|
291
|
+
rootElement,
|
|
292
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
await sleepAsync(50)
|
|
296
|
+
|
|
297
|
+
const footer = document.querySelector('shade-data-grid-footer')
|
|
298
|
+
const selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
299
|
+
const itemsPerPageSelect = selects.find((s) => {
|
|
300
|
+
const parent = s.parentElement
|
|
301
|
+
return parent?.textContent?.includes('items per page')
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
expect(itemsPerPageSelect).toBeDefined()
|
|
305
|
+
expect(itemsPerPageSelect?.value).toBe('25')
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
it('should react to data count changes', async () => {
|
|
309
|
+
const injector = new Injector()
|
|
310
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
311
|
+
const service = createService([], 50)
|
|
312
|
+
const findOptions = createFindOptions(10, 0)
|
|
313
|
+
|
|
314
|
+
initializeShadeRoot({
|
|
315
|
+
injector,
|
|
316
|
+
rootElement,
|
|
317
|
+
jsxElement: <DataGridFooter service={service} findOptions={findOptions} />,
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
await sleepAsync(50)
|
|
321
|
+
|
|
322
|
+
let footer = document.querySelector('shade-data-grid-footer')
|
|
323
|
+
let selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
324
|
+
let pageSelect = selects.find((s) => s.parentElement?.textContent?.includes('Goto page'))
|
|
325
|
+
let pageOptions = pageSelect?.querySelectorAll('option')
|
|
326
|
+
|
|
327
|
+
expect(pageOptions?.length).toBe(5)
|
|
328
|
+
|
|
329
|
+
service.data.setValue({ entries: [], count: 100 })
|
|
330
|
+
|
|
331
|
+
await sleepAsync(50)
|
|
332
|
+
|
|
333
|
+
footer = document.querySelector('shade-data-grid-footer')
|
|
334
|
+
selects = Array.from(footer?.querySelectorAll('select') ?? [])
|
|
335
|
+
pageSelect = selects.find((s) => s.parentElement?.textContent?.includes('Goto page'))
|
|
336
|
+
pageOptions = pageSelect?.querySelectorAll('option')
|
|
337
|
+
|
|
338
|
+
expect(pageOptions?.length).toBe(10)
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
it('should export dataGridItemsPerPage constant', () => {
|
|
342
|
+
expect(dataGridItemsPerPage).toEqual([10, 20, 25, 50, 100, Infinity])
|
|
343
|
+
})
|
|
344
|
+
})
|
|
@@ -2,7 +2,7 @@ import type { FindOptions } from '@furystack/core'
|
|
|
2
2
|
import { Shade, createComponent } from '@furystack/shades'
|
|
3
3
|
import type { ObservableValue } from '@furystack/utils'
|
|
4
4
|
import type { CollectionService } from '../../services/collection-service.js'
|
|
5
|
-
import {
|
|
5
|
+
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
6
6
|
|
|
7
7
|
export const dataGridItemsPerPage = [10, 20, 25, 50, 100, Infinity]
|
|
8
8
|
|
|
@@ -11,9 +11,23 @@ export const DataGridFooter: <T>(props: {
|
|
|
11
11
|
findOptions: ObservableValue<FindOptions<T, Array<keyof T>>>
|
|
12
12
|
}) => JSX.Element = Shade({
|
|
13
13
|
shadowDomName: 'shade-data-grid-footer',
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
css: {
|
|
15
|
+
display: 'block',
|
|
16
|
+
'& .pager': {
|
|
17
|
+
backdropFilter: 'blur(10px)',
|
|
18
|
+
color: cssVariableTheme.text.secondary,
|
|
19
|
+
position: 'sticky',
|
|
20
|
+
bottom: '0',
|
|
21
|
+
display: 'flex',
|
|
22
|
+
justifyContent: 'flex-end',
|
|
23
|
+
padding: '1em',
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
},
|
|
26
|
+
'& select': {
|
|
27
|
+
margin: '0 1em',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
render: ({ props, useObservable }) => {
|
|
17
31
|
const { service, findOptions } = props
|
|
18
32
|
const [currentData] = useObservable('dataUpdater', service.data)
|
|
19
33
|
const [currentOptions, setCurrentOptions] = useObservable('optionsUpdater', findOptions, {
|
|
@@ -32,24 +46,11 @@ export const DataGridFooter: <T>(props: {
|
|
|
32
46
|
.map((_, index) => index)
|
|
33
47
|
|
|
34
48
|
return (
|
|
35
|
-
<div
|
|
36
|
-
className="pager"
|
|
37
|
-
style={{
|
|
38
|
-
backdropFilter: 'blur(10px)',
|
|
39
|
-
color: theme.text.secondary,
|
|
40
|
-
position: 'sticky',
|
|
41
|
-
bottom: '0',
|
|
42
|
-
display: 'flex',
|
|
43
|
-
justifyContent: 'flex-end',
|
|
44
|
-
padding: '1em',
|
|
45
|
-
alignItems: 'center',
|
|
46
|
-
}}
|
|
47
|
-
>
|
|
49
|
+
<div className="pager">
|
|
48
50
|
{currentEntriesPerPage !== Infinity && (
|
|
49
51
|
<div>
|
|
50
52
|
Goto page
|
|
51
53
|
<select
|
|
52
|
-
style={{ margin: '0 1em' }}
|
|
53
54
|
onchange={(ev) => {
|
|
54
55
|
const value = parseInt((ev.target as HTMLInputElement).value, 10)
|
|
55
56
|
setCurrentOptions({ ...currentOptions, skip: (currentOptions.top || 0) * value })
|
|
@@ -66,7 +67,6 @@ export const DataGridFooter: <T>(props: {
|
|
|
66
67
|
<div>
|
|
67
68
|
Show
|
|
68
69
|
<select
|
|
69
|
-
style={{ margin: '0 1em' }}
|
|
70
70
|
onchange={(ev) => {
|
|
71
71
|
const value = parseInt((ev.currentTarget as HTMLInputElement).value, 10)
|
|
72
72
|
setCurrentOptions({
|