@furystack/shades-common-components 7.0.0 → 8.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/esm/components/data-grid/body.d.ts.map +1 -1
- package/esm/components/data-grid/body.js +0 -5
- package/esm/components/data-grid/body.js.map +1 -1
- package/esm/components/data-grid/data-grid-row.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid-row.js +40 -37
- package/esm/components/data-grid/data-grid-row.js.map +1 -1
- package/esm/components/data-grid/data-grid.d.ts +7 -1
- package/esm/components/data-grid/data-grid.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid.js +7 -6
- package/esm/components/data-grid/data-grid.js.map +1 -1
- package/esm/components/data-grid/footer.d.ts +3 -0
- package/esm/components/data-grid/footer.d.ts.map +1 -1
- package/esm/components/data-grid/footer.js +13 -11
- package/esm/components/data-grid/footer.js.map +1 -1
- package/esm/components/data-grid/header.d.ts +6 -6
- package/esm/components/data-grid/header.d.ts.map +1 -1
- package/esm/components/data-grid/header.js +39 -33
- package/esm/components/data-grid/header.js.map +1 -1
- package/esm/services/collection-service.d.ts +2 -21
- package/esm/services/collection-service.d.ts.map +1 -1
- package/esm/services/collection-service.js +7 -36
- package/esm/services/collection-service.js.map +1 -1
- package/esm/services/collection-service.spec.js +2 -5
- package/esm/services/collection-service.spec.js.map +1 -1
- package/package.json +1 -1
- package/src/components/data-grid/body.tsx +0 -11
- package/src/components/data-grid/data-grid-row.tsx +42 -39
- package/src/components/data-grid/data-grid.tsx +25 -13
- package/src/components/data-grid/footer.tsx +19 -13
- package/src/components/data-grid/header.tsx +59 -45
- package/src/services/collection-service.spec.ts +14 -20
- package/src/services/collection-service.ts +7 -62
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-service.d.ts","sourceRoot":"","sources":["../../src/services/collection-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"collection-service.d.ts","sourceRoot":"","sources":["../../src/services/collection-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;IAE/B;;;OAGG;IAEH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;CACtC;AAED,qBAAa,iBAAiB,CAAC,CAAC,CAAE,YAAW,UAAU;IA2IzC,OAAO,CAAC,OAAO;IA1IpB,OAAO;IAQP,UAAU,UAAW,CAAC,aAA8C;IAEpE,cAAc,UAAW,CAAC,UAEhC;IAEM,mBAAmB,UAAW,CAAC,UAErC;IAEM,eAAe,UAAW,CAAC,UAEjC;IAEM,IAAI,qCAAoE;IAExE,YAAY,iCAAgD;IAE5D,SAAS,uBAA+B;IAExC,UAAU,0BAA0B;IAEpC,QAAQ,2BAA6B;IAErC,aAAa,CAAC,EAAE,EAAE,aAAa;IA6E/B,cAAc,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,UAAU;gBA6B1B,OAAO,GAAE,wBAAwB,CAAC,CAAC,CAAM;IAEtD,oBAAoB,CAAC,KAAK,EAAE,CAAC;CAGrC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { debounce, ObservableValue } from '@furystack/utils';
|
|
1
|
+
import { ObservableValue } from '@furystack/utils';
|
|
3
2
|
export class CollectionService {
|
|
4
3
|
options;
|
|
5
4
|
dispose() {
|
|
6
|
-
this.querySettings.dispose();
|
|
7
5
|
this.data.dispose();
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
6
|
+
this.selection.dispose();
|
|
7
|
+
this.searchTerm.dispose();
|
|
8
|
+
this.hasFocus.dispose();
|
|
9
|
+
this.focusedEntry.dispose();
|
|
10
10
|
}
|
|
11
11
|
isSelected = (entry) => this.selection.getValue().includes(entry);
|
|
12
12
|
addToSelection = (entry) => {
|
|
@@ -18,12 +18,7 @@ export class CollectionService {
|
|
|
18
18
|
toggleSelection = (entry) => {
|
|
19
19
|
this.isSelected(entry) ? this.removeFromSelection(entry) : this.addToSelection(entry);
|
|
20
20
|
};
|
|
21
|
-
loadLock = new Lock();
|
|
22
|
-
getEntries;
|
|
23
21
|
data = new ObservableValue({ count: 0, entries: [] });
|
|
24
|
-
error = new ObservableValue(undefined);
|
|
25
|
-
isLoading = new ObservableValue(false);
|
|
26
|
-
querySettings;
|
|
27
22
|
focusedEntry = new ObservableValue(undefined);
|
|
28
23
|
selection = new ObservableValue([]);
|
|
29
24
|
searchTerm = new ObservableValue('');
|
|
@@ -125,34 +120,10 @@ export class CollectionService {
|
|
|
125
120
|
}
|
|
126
121
|
this.focusedEntry.setValue(entry);
|
|
127
122
|
}
|
|
128
|
-
constructor(options) {
|
|
123
|
+
constructor(options = {}) {
|
|
129
124
|
this.options = options;
|
|
130
|
-
this.querySettings = new ObservableValue(this.options.defaultSettings);
|
|
131
|
-
const loader = this.options.debounceMs
|
|
132
|
-
? debounce(this.options.loader, this.options.debounceMs)
|
|
133
|
-
: this.options.loader;
|
|
134
|
-
this.getEntries = async (opt) => {
|
|
135
|
-
await this.loadLock.acquire();
|
|
136
|
-
try {
|
|
137
|
-
this.error.setValue(undefined);
|
|
138
|
-
this.isLoading.setValue(true);
|
|
139
|
-
const result = await loader(opt);
|
|
140
|
-
this.data.setValue(result);
|
|
141
|
-
return result;
|
|
142
|
-
}
|
|
143
|
-
catch (error) {
|
|
144
|
-
this.error.setValue(error);
|
|
145
|
-
throw error;
|
|
146
|
-
}
|
|
147
|
-
finally {
|
|
148
|
-
this.loadLock.release();
|
|
149
|
-
this.isLoading.setValue(false);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
this.querySettings.subscribe((val) => this.getEntries(val));
|
|
153
|
-
this.getEntries(this.querySettings.getValue());
|
|
154
125
|
}
|
|
155
|
-
|
|
126
|
+
handleRowDoubleClick(entry) {
|
|
156
127
|
this.options.onRowDoubleClick?.(entry);
|
|
157
128
|
}
|
|
158
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-service.js","sourceRoot":"","sources":["../../src/services/collection-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"collection-service.js","sourceRoot":"","sources":["../../src/services/collection-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,11 +5,8 @@ const testEntries = [{ foo: 1 }, { foo: 2 }, { foo: 3 }];
|
|
|
5
5
|
describe('CollectionService', () => {
|
|
6
6
|
describe('Selection', () => {
|
|
7
7
|
it('Should add and remove selection', async () => {
|
|
8
|
-
await usingAsync(new CollectionService({
|
|
9
|
-
|
|
10
|
-
loader: async () => ({ count: 3, entries: testEntries }),
|
|
11
|
-
}), async (collectionService) => {
|
|
12
|
-
await collectionService.getEntries({});
|
|
8
|
+
await usingAsync(new CollectionService({}), async (collectionService) => {
|
|
9
|
+
collectionService.data.setValue({ count: 3, entries: testEntries });
|
|
13
10
|
testEntries.forEach((entry) => {
|
|
14
11
|
expect(collectionService.isSelected(entry)).toBe(false);
|
|
15
12
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-service.spec.js","sourceRoot":"","sources":["../../src/services/collection-service.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAE3D,MAAM,WAAW,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"collection-service.spec.js","sourceRoot":"","sources":["../../src/services/collection-service.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAE3D,MAAM,WAAW,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,UAAU,CAAC,IAAI,iBAAiB,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE;gBACtE,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAA;gBACnE,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;oBAC5B,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBACzD,CAAC,CAAC,CAAA;gBAEF,iBAAiB,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;gBAEhD,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAC/D,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAChE,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAEhE,iBAAiB,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;gBAErD,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAEhE,iBAAiB,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;gBACjD,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjE,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,6 @@ import type { CollectionService } from '../../services/collection-service.js'
|
|
|
2
2
|
import type { ChildrenList } from '@furystack/shades'
|
|
3
3
|
import { Shade, createComponent } from '@furystack/shades'
|
|
4
4
|
import type { DataRowCells } from './data-grid.js'
|
|
5
|
-
import { Loader } from '../loader.js'
|
|
6
5
|
import { DataGridRow } from './data-grid-row.js'
|
|
7
6
|
|
|
8
7
|
export interface DataGridBodyProps<T> {
|
|
@@ -29,16 +28,6 @@ export const DataGridBody: <T>(props: DataGridBodyProps<T>, children: ChildrenLi
|
|
|
29
28
|
},
|
|
30
29
|
render: ({ props, useObservable }) => {
|
|
31
30
|
const [data] = useObservable('data', props.service.data)
|
|
32
|
-
const [isLoading] = useObservable('isLoading', props.service.isLoading)
|
|
33
|
-
|
|
34
|
-
if (isLoading) {
|
|
35
|
-
return (
|
|
36
|
-
<div style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center', width: '100%' }}>
|
|
37
|
-
{/* TODO: Skeleton */}
|
|
38
|
-
{props.loaderComponent || <Loader style={{ height: '128px', width: '128px' }} />}
|
|
39
|
-
</div>
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
31
|
|
|
43
32
|
if (!data?.entries?.length) {
|
|
44
33
|
return props.emptyComponent || <div> - No Data - </div>
|
|
@@ -39,52 +39,55 @@ export const DataGridRow: <T>(props: DataGridRowProps<T>, children: ChildrenList
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const attachFocusedStyle = (newEntry?: any) => {
|
|
43
|
+
if (newEntry === props.entry) {
|
|
44
|
+
attachStyles(element, {
|
|
45
|
+
style: props.focusedRowStyle || {
|
|
46
|
+
boxShadow: `0 0 50px 1px rgba(255,255,255,0.2) inset, 0 0 35px 1px var(--shades-theme-palette-primary-main) inset, 2px 0px 5px 0px rgba(0,0,0,0.3)`,
|
|
47
|
+
transition: 'box-shadow 0.1s ease-in-out',
|
|
48
|
+
fontWeight: 'bolder',
|
|
49
|
+
},
|
|
50
|
+
})
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
element.classList.add('focused')
|
|
46
53
|
|
|
47
|
-
|
|
48
|
-
const [focus] = useObservable('focus', service.focusedEntry, {
|
|
49
|
-
onChange: (newEntry) => {
|
|
50
|
-
if (newEntry === props.entry) {
|
|
51
|
-
attachStyles(element, {
|
|
52
|
-
style: props.focusedRowStyle || {
|
|
53
|
-
boxShadow: `0 0 0 1px ${theme.palette.primary.main}`,
|
|
54
|
-
fontWeight: 'bolder',
|
|
55
|
-
},
|
|
56
|
-
})
|
|
54
|
+
const headerHeight = element.closest('table')?.querySelector('th')?.getBoundingClientRect().height || 42
|
|
57
55
|
|
|
58
|
-
|
|
56
|
+
const parent = element.closest('.shade-grid-wrapper') as HTMLElement
|
|
57
|
+
const maxTop = element.offsetTop - headerHeight
|
|
58
|
+
const currentTop = parent.scrollTop
|
|
59
|
+
if (maxTop < currentTop) {
|
|
60
|
+
parent.scrollTo({ top: maxTop, behavior: 'smooth' })
|
|
61
|
+
}
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
const footerHeight =
|
|
64
|
+
element.closest('shade-data-grid')?.querySelector('shade-data-grid-footer')?.getBoundingClientRect().height ||
|
|
65
|
+
42
|
|
66
|
+
const visibleMaxTop = parent.clientHeight - footerHeight
|
|
67
|
+
const desiredMaxTop = element.offsetTop + element.clientHeight
|
|
68
|
+
if (desiredMaxTop > visibleMaxTop) {
|
|
69
|
+
parent.scrollTo({ top: desiredMaxTop - visibleMaxTop, behavior: 'smooth' })
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
element.classList.remove('focused')
|
|
73
|
+
attachStyles(element, {
|
|
74
|
+
style: props.unfocusedRowStyle || {
|
|
75
|
+
boxShadow: 'none',
|
|
76
|
+
fontWeight: 'inherit',
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
}
|
|
61
81
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
parent.scrollTo({ top: maxTop, behavior: 'smooth' })
|
|
67
|
-
}
|
|
82
|
+
const [selection] = useObservable('isSelected', service.selection, {
|
|
83
|
+
onChange: attachSelectedStyles,
|
|
84
|
+
})
|
|
85
|
+
attachSelectedStyles(selection)
|
|
68
86
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
.height || 42
|
|
72
|
-
const visibleMaxTop = parent.clientHeight - footerHeight
|
|
73
|
-
const desiredMaxTop = element.offsetTop + element.clientHeight
|
|
74
|
-
if (desiredMaxTop > visibleMaxTop) {
|
|
75
|
-
parent.scrollTo({ top: desiredMaxTop - visibleMaxTop, behavior: 'smooth' })
|
|
76
|
-
}
|
|
77
|
-
} else {
|
|
78
|
-
element.classList.remove('focused')
|
|
79
|
-
attachStyles(element, {
|
|
80
|
-
style: props.unfocusedRowStyle || {
|
|
81
|
-
boxShadow: 'none',
|
|
82
|
-
fontWeight: 'inherit',
|
|
83
|
-
},
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
+
const [focus] = useObservable('focus', service.focusedEntry, {
|
|
88
|
+
onChange: attachFocusedStyle,
|
|
87
89
|
})
|
|
90
|
+
attachFocusedStyle(focus)
|
|
88
91
|
|
|
89
92
|
element.style.display = 'table-row'
|
|
90
93
|
element.style.cursor = 'default'
|
|
@@ -7,6 +7,8 @@ import { DataGridBody } from './body.js'
|
|
|
7
7
|
import { DataGridFooter } from './footer.js'
|
|
8
8
|
import { ThemeProviderService } from '../../services/theme-provider-service.js'
|
|
9
9
|
import { ClickAwayService } from '../../services/click-away-service.js'
|
|
10
|
+
import type { FindOptions } from '@furystack/core'
|
|
11
|
+
import type { ObservableValue } from '@furystack/utils'
|
|
10
12
|
|
|
11
13
|
export type DataHeaderCells<T> = {
|
|
12
14
|
[TKey in keyof T | 'default']?: (name: keyof T) => JSX.Element
|
|
@@ -27,7 +29,12 @@ export interface DataGridProps<T> {
|
|
|
27
29
|
/**
|
|
28
30
|
* A collection service to use for data source
|
|
29
31
|
*/
|
|
30
|
-
|
|
32
|
+
collectionService: CollectionService<T>
|
|
33
|
+
/**
|
|
34
|
+
* The query settings to use for the data source
|
|
35
|
+
*/
|
|
36
|
+
findOptions: ObservableValue<FindOptions<T, Array<keyof T>>>
|
|
37
|
+
|
|
31
38
|
/**
|
|
32
39
|
* A list of custom header components to use
|
|
33
40
|
*/
|
|
@@ -68,12 +75,10 @@ export interface DataGridProps<T> {
|
|
|
68
75
|
loaderComponent?: JSX.Element
|
|
69
76
|
}
|
|
70
77
|
|
|
71
|
-
export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => JSX.Element<any> = Shade
|
|
72
|
-
DataGridProps<any>
|
|
73
|
-
>({
|
|
78
|
+
export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => JSX.Element<any> = Shade({
|
|
74
79
|
shadowDomName: 'shade-data-grid',
|
|
75
80
|
constructed: ({ props }) => {
|
|
76
|
-
const listener = (ev: KeyboardEvent) => props.
|
|
81
|
+
const listener = (ev: KeyboardEvent) => props.collectionService.handleKeyDown(ev)
|
|
77
82
|
window.addEventListener('keydown', listener)
|
|
78
83
|
return () => window.removeEventListener('keydown', listener)
|
|
79
84
|
},
|
|
@@ -85,12 +90,13 @@ export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => J
|
|
|
85
90
|
'clickAway',
|
|
86
91
|
() =>
|
|
87
92
|
new ClickAwayService(element, () => {
|
|
88
|
-
props.
|
|
93
|
+
props.collectionService.hasFocus.setValue(false)
|
|
89
94
|
}),
|
|
90
95
|
)
|
|
91
96
|
|
|
92
97
|
const headerStyle: Partial<CSSStyleDeclaration> = {
|
|
93
98
|
backdropFilter: 'blur(12px) saturate(180%)',
|
|
99
|
+
background: 'rgba(128,128,128,0.3)',
|
|
94
100
|
color: theme.text.secondary,
|
|
95
101
|
height: '38px',
|
|
96
102
|
alignItems: 'center',
|
|
@@ -114,18 +120,24 @@ export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => J
|
|
|
114
120
|
zIndex: '1',
|
|
115
121
|
}}
|
|
116
122
|
onclick={() => {
|
|
117
|
-
props.
|
|
123
|
+
props.collectionService.hasFocus.setValue(true)
|
|
118
124
|
}}
|
|
119
125
|
ariaMultiSelectable="true"
|
|
120
126
|
>
|
|
121
127
|
<table style={{ width: '100%', maxHeight: 'calc(100% - 4em)', position: 'relative' }}>
|
|
122
128
|
<thead>
|
|
123
129
|
<tr>
|
|
124
|
-
{props.columns.map((column
|
|
130
|
+
{props.columns.map((column) => {
|
|
125
131
|
return (
|
|
126
132
|
<th style={headerStyle}>
|
|
127
133
|
{props.headerComponents?.[column]?.(column) || props.headerComponents?.default?.(column) || (
|
|
128
|
-
<DataGridHeader<
|
|
134
|
+
<DataGridHeader<
|
|
135
|
+
ReturnType<typeof props.collectionService.data.getValue>['entries'][number],
|
|
136
|
+
typeof column
|
|
137
|
+
>
|
|
138
|
+
field={column}
|
|
139
|
+
findOptions={props.findOptions}
|
|
140
|
+
/>
|
|
129
141
|
)}
|
|
130
142
|
</th>
|
|
131
143
|
)
|
|
@@ -134,10 +146,10 @@ export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => J
|
|
|
134
146
|
</thead>
|
|
135
147
|
<DataGridBody
|
|
136
148
|
columns={props.columns}
|
|
137
|
-
service={props.
|
|
149
|
+
service={props.collectionService}
|
|
138
150
|
rowComponents={props.rowComponents}
|
|
139
|
-
onRowClick={(entry, ev) => props.
|
|
140
|
-
onRowDoubleClick={(entry) => props.
|
|
151
|
+
onRowClick={(entry, ev) => props.collectionService.handleRowClick(entry, ev)}
|
|
152
|
+
onRowDoubleClick={(entry) => props.collectionService.handleRowDoubleClick(entry)}
|
|
141
153
|
style={props.styles?.cell}
|
|
142
154
|
focusedRowStyle={props.focusedRowStyle}
|
|
143
155
|
selectedRowStyle={props.selectedRowStyle}
|
|
@@ -147,7 +159,7 @@ export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => J
|
|
|
147
159
|
loaderComponent={props.loaderComponent}
|
|
148
160
|
/>
|
|
149
161
|
</table>
|
|
150
|
-
<DataGridFooter service={props.
|
|
162
|
+
<DataGridFooter service={props.collectionService} findOptions={props.findOptions} />
|
|
151
163
|
</div>
|
|
152
164
|
)
|
|
153
165
|
},
|
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import { Shade, createComponent } from '@furystack/shades'
|
|
2
2
|
import { ThemeProviderService } from '../../services/theme-provider-service.js'
|
|
3
3
|
import type { CollectionService } from '../../services/collection-service.js'
|
|
4
|
+
import type { FindOptions } from '@furystack/core'
|
|
5
|
+
import type { ObservableValue } from '@furystack/utils'
|
|
4
6
|
|
|
5
7
|
export const dataGridItemsPerPage = [10, 20, 25, 50, 100, Infinity]
|
|
6
8
|
|
|
7
|
-
export const DataGridFooter = Shade<{
|
|
9
|
+
export const DataGridFooter = Shade<{
|
|
10
|
+
service: CollectionService<any>
|
|
11
|
+
findOptions: ObservableValue<FindOptions<any, any[]>>
|
|
12
|
+
}>({
|
|
8
13
|
shadowDomName: 'shade-data-grid-footer',
|
|
9
14
|
render: ({ props, injector, useObservable }) => {
|
|
10
15
|
const { theme } = injector.getInstance(ThemeProviderService)
|
|
11
16
|
|
|
12
|
-
const
|
|
17
|
+
const { service, findOptions } = props
|
|
18
|
+
const [currentData] = useObservable('dataUpdater', service.data)
|
|
19
|
+
const [currentOptions, setCurrentOptions] = useObservable('optionsUpdater', findOptions, {
|
|
20
|
+
filter: (newValue, oldValue) => {
|
|
21
|
+
return newValue.top !== oldValue.top || newValue.skip !== oldValue.skip
|
|
22
|
+
},
|
|
23
|
+
})
|
|
13
24
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const top = currentQuerySettings.top || Infinity
|
|
17
|
-
const skip = currentQuerySettings.skip || 0
|
|
25
|
+
const top = currentOptions.top || Infinity
|
|
26
|
+
const skip = currentOptions.skip || 0
|
|
18
27
|
const currentPage = Math.ceil(skip) / (top || 1)
|
|
19
28
|
const currentEntriesPerPage = top
|
|
20
29
|
|
|
@@ -39,13 +48,10 @@ export const DataGridFooter = Shade<{ service: CollectionService<any> }>({
|
|
|
39
48
|
style={{ margin: '0 1em' }}
|
|
40
49
|
onchange={(ev) => {
|
|
41
50
|
const value = parseInt((ev.target as any).value, 10)
|
|
42
|
-
|
|
43
|
-
props.service.querySettings.setValue({ ...currentQuery, skip: (currentQuery.top || 0) * value })
|
|
51
|
+
setCurrentOptions({ ...currentOptions, skip: (currentOptions.top || 0) * value })
|
|
44
52
|
}}
|
|
45
53
|
>
|
|
46
|
-
{[
|
|
47
|
-
...new Array(Math.ceil(currentData.count / (props.service.querySettings.getValue().top || Infinity))),
|
|
48
|
-
].map((_val, index) => (
|
|
54
|
+
{[...new Array(Math.ceil(currentData.count / (currentOptions.top || Infinity)))].map((_val, index) => (
|
|
49
55
|
<option value={index.toString()} selected={currentPage === index}>
|
|
50
56
|
{(index + 1).toString()}
|
|
51
57
|
</option>
|
|
@@ -59,8 +65,8 @@ export const DataGridFooter = Shade<{ service: CollectionService<any> }>({
|
|
|
59
65
|
style={{ margin: '0 1em' }}
|
|
60
66
|
onchange={(ev) => {
|
|
61
67
|
const value = parseInt((ev.currentTarget as any).value as string, 10)
|
|
62
|
-
|
|
63
|
-
...
|
|
68
|
+
setCurrentOptions({
|
|
69
|
+
...currentOptions,
|
|
64
70
|
top: value,
|
|
65
71
|
skip: currentPage * value,
|
|
66
72
|
})
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import type { FindOptions } from '@furystack/core'
|
|
1
|
+
import type { FilterType, FindOptions } from '@furystack/core'
|
|
2
2
|
import type { ChildrenList } from '@furystack/shades'
|
|
3
3
|
import { Shade, createComponent } from '@furystack/shades'
|
|
4
|
-
import type { CollectionService } from '../../services/collection-service.js'
|
|
5
4
|
import { Input } from '../inputs/input.js'
|
|
6
5
|
import { Form } from '../form.js'
|
|
7
6
|
import { Button } from '../button.js'
|
|
8
|
-
import { ObservableValue } from '@furystack/utils'
|
|
7
|
+
import { ObservableValue, sleepAsync } from '@furystack/utils'
|
|
9
8
|
import { collapse, expand } from '../animations.js'
|
|
10
9
|
|
|
11
10
|
export interface DataGridHeaderProps<T, K extends keyof T> {
|
|
12
|
-
collectionService: CollectionService<T>
|
|
13
11
|
field: K
|
|
12
|
+
findOptions: ObservableValue<FindOptions<T, K[]>>
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
export interface DataGridHeaderState<T> {
|
|
17
|
-
|
|
15
|
+
export interface DataGridHeaderState<T, K extends keyof T> {
|
|
16
|
+
findOptions: FindOptions<T, K[]>
|
|
18
17
|
isSearchOpened: boolean
|
|
19
18
|
updateSearchValue: (value: string) => void
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
export const OrderButton = Shade<{
|
|
21
|
+
export const OrderButton = Shade<{
|
|
22
|
+
field: string
|
|
23
|
+
findOptions: ObservableValue<FindOptions<any, any[]>>
|
|
24
|
+
}>({
|
|
23
25
|
shadowDomName: 'data-grid-order-button',
|
|
24
26
|
render: ({ props, useObservable }) => {
|
|
25
|
-
const [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
const currentOrder = Object.keys(currentQuerySettings.order || {})[0]
|
|
30
|
-
const currentOrderDirection = Object.values(currentQuerySettings.order || {})[0]
|
|
27
|
+
const [findOptions, onFindOptionsChange] = useObservable('findOptions', props.findOptions, {})
|
|
28
|
+
|
|
29
|
+
const currentOrder = Object.keys(findOptions.order || {})[0]
|
|
30
|
+
const currentOrderDirection = Object.values(findOptions.order || {})[0]
|
|
31
31
|
return (
|
|
32
32
|
<Button
|
|
33
33
|
title="Change order"
|
|
@@ -46,8 +46,8 @@ export const OrderButton = Shade<{ collectionService: CollectionService<any>; fi
|
|
|
46
46
|
newDirection = currentOrderDirection === 'ASC' ? 'DESC' : 'ASC'
|
|
47
47
|
}
|
|
48
48
|
newOrder[props.field] = newDirection
|
|
49
|
-
|
|
50
|
-
...
|
|
49
|
+
onFindOptionsChange({
|
|
50
|
+
...findOptions,
|
|
51
51
|
order: newOrder,
|
|
52
52
|
})
|
|
53
53
|
}}
|
|
@@ -58,22 +58,21 @@ export const OrderButton = Shade<{ collectionService: CollectionService<any>; fi
|
|
|
58
58
|
},
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
const SearchButton = Shade<{
|
|
61
|
+
const SearchButton = Shade<{
|
|
62
|
+
fieldName: string
|
|
63
|
+
onclick: () => void
|
|
64
|
+
findOptions: ObservableValue<FindOptions<any, any[]>>
|
|
65
|
+
}>({
|
|
62
66
|
shadowDomName: 'data-grid-search-button',
|
|
63
|
-
render: ({ props, useObservable
|
|
64
|
-
const [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const button = element.querySelector('button') as HTMLInputElement
|
|
69
|
-
button.innerHTML = currentValue ? '🔍' : '🔎'
|
|
70
|
-
button.style.textShadow = currentValue
|
|
71
|
-
? '1px 1px 20px rgba(235,225,45,0.9), 1px 1px 12px rgba(235,225,45,0.9), 0px 0px 3px rgba(255,200,145,0.6)'
|
|
72
|
-
: 'none'
|
|
67
|
+
render: ({ props, useObservable }) => {
|
|
68
|
+
const [findOptions] = useObservable('currentValue', props.findOptions, {
|
|
69
|
+
filter: (newValue) => {
|
|
70
|
+
return !!newValue.filter?.[props.fieldName]
|
|
73
71
|
},
|
|
74
72
|
})
|
|
75
73
|
|
|
76
|
-
const filterValue =
|
|
74
|
+
const filterValue =
|
|
75
|
+
(findOptions.filter?.[props.fieldName] as FilterType<{ [K in typeof props.fieldName]: string }>)?.$regex || ''
|
|
77
76
|
|
|
78
77
|
return (
|
|
79
78
|
<Button
|
|
@@ -95,20 +94,23 @@ const SearchButton = Shade<{ service: CollectionService<any>; fieldName: string;
|
|
|
95
94
|
const SearchForm = Shade<{
|
|
96
95
|
onSubmit: (newValue: string) => void
|
|
97
96
|
onClear: () => void
|
|
98
|
-
service: CollectionService<any>
|
|
99
97
|
fieldName: string
|
|
98
|
+
findOptions: ObservableValue<FindOptions<any, any[]>>
|
|
100
99
|
}>({
|
|
101
100
|
shadowDomName: 'data-grid-search-form',
|
|
102
|
-
render: ({ props, useObservable
|
|
101
|
+
render: ({ props, useObservable }) => {
|
|
103
102
|
type SearchSubmitType = { searchValue: string }
|
|
104
103
|
|
|
105
|
-
const [
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
104
|
+
const [findOptions] = useObservable('currentValue', props.findOptions, {
|
|
105
|
+
filter: (newValue, lastValue) => {
|
|
106
|
+
const newFilter = newValue.filter?.[props.fieldName] as FilterType<{ [K in typeof props.fieldName]: string }>
|
|
107
|
+
const lastFilter = lastValue.filter?.[props.fieldName] as FilterType<{ [K in typeof props.fieldName]: string }>
|
|
108
|
+
return newFilter?.$regex !== lastFilter?.$regex
|
|
109
109
|
},
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
+
const currentValue = (findOptions.filter?.[props.fieldName] as any)?.$regex || ''
|
|
113
|
+
|
|
112
114
|
return (
|
|
113
115
|
<Form<SearchSubmitType>
|
|
114
116
|
className="search-form"
|
|
@@ -131,7 +133,7 @@ const SearchForm = Shade<{
|
|
|
131
133
|
autofocus
|
|
132
134
|
labelTitle={`${props.fieldName}`}
|
|
133
135
|
name="searchValue"
|
|
134
|
-
value={
|
|
136
|
+
value={currentValue}
|
|
135
137
|
labelProps={{
|
|
136
138
|
style: { padding: '0px 2em' },
|
|
137
139
|
}}
|
|
@@ -140,7 +142,9 @@ const SearchForm = Shade<{
|
|
|
140
142
|
<Button
|
|
141
143
|
type="reset"
|
|
142
144
|
style={{ padding: '4px', margin: '0' }}
|
|
143
|
-
onclick={() => {
|
|
145
|
+
onclick={(ev) => {
|
|
146
|
+
ev.preventDefault()
|
|
147
|
+
ev.stopPropagation()
|
|
144
148
|
props.onClear()
|
|
145
149
|
}}
|
|
146
150
|
>
|
|
@@ -158,6 +162,7 @@ const SearchForm = Shade<{
|
|
|
158
162
|
export const DataGridHeader: <T, K extends keyof T>(
|
|
159
163
|
props: DataGridHeaderProps<T, K>,
|
|
160
164
|
children: ChildrenList,
|
|
165
|
+
findOptions: ObservableValue<FindOptions<T, Array<keyof T>>>,
|
|
161
166
|
) => JSX.Element<any> = Shade<DataGridHeaderProps<any, any>>({
|
|
162
167
|
shadowDomName: 'data-grid-header',
|
|
163
168
|
render: ({ props, element, useObservable }) => {
|
|
@@ -170,25 +175,34 @@ export const DataGridHeader: <T, K extends keyof T>(
|
|
|
170
175
|
expand(headerContent)
|
|
171
176
|
} else {
|
|
172
177
|
searchForm.style.display = 'flex'
|
|
173
|
-
expand(searchForm).then(() =>
|
|
178
|
+
expand(searchForm).then(async () => {
|
|
179
|
+
await sleepAsync(100)
|
|
180
|
+
searchForm.querySelector('input')?.focus()
|
|
181
|
+
})
|
|
174
182
|
collapse(headerContent)
|
|
175
183
|
}
|
|
176
184
|
},
|
|
177
185
|
})
|
|
186
|
+
|
|
187
|
+
const [findOptions, setFindOptions] = useObservable('findOptions', props.findOptions, {
|
|
188
|
+
filter: (newValue, oldValue) => {
|
|
189
|
+
return newValue.filter?.[props.field] !== oldValue.filter?.[props.field]
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
|
|
178
193
|
const updateSearchValue = (value?: string) => {
|
|
179
|
-
const currentSettings = props.collectionService.querySettings.getValue()
|
|
180
194
|
if (value) {
|
|
181
195
|
const newSettings: FindOptions<unknown, any> = {
|
|
182
|
-
...
|
|
196
|
+
...findOptions,
|
|
183
197
|
filter: {
|
|
184
|
-
...
|
|
198
|
+
...findOptions.filter,
|
|
185
199
|
[props.field]: { $regex: value },
|
|
186
200
|
},
|
|
187
201
|
}
|
|
188
|
-
|
|
202
|
+
setFindOptions(newSettings)
|
|
189
203
|
} else {
|
|
190
|
-
const { [props.field]: _, ...newFilter } =
|
|
191
|
-
|
|
204
|
+
const { [props.field]: _, ...newFilter } = findOptions.filter || {}
|
|
205
|
+
setFindOptions({ ...findOptions, filter: newFilter })
|
|
192
206
|
}
|
|
193
207
|
|
|
194
208
|
setIsSearchOpened(false)
|
|
@@ -199,8 +213,8 @@ export const DataGridHeader: <T, K extends keyof T>(
|
|
|
199
213
|
<SearchForm
|
|
200
214
|
onSubmit={updateSearchValue}
|
|
201
215
|
onClear={updateSearchValue}
|
|
202
|
-
service={props.collectionService}
|
|
203
216
|
fieldName={props.field}
|
|
217
|
+
findOptions={props.findOptions}
|
|
204
218
|
/>
|
|
205
219
|
<div
|
|
206
220
|
className="header-content"
|
|
@@ -223,11 +237,11 @@ export const DataGridHeader: <T, K extends keyof T>(
|
|
|
223
237
|
onclick={() => {
|
|
224
238
|
setIsSearchOpened(true)
|
|
225
239
|
}}
|
|
226
|
-
|
|
240
|
+
findOptions={props.findOptions}
|
|
227
241
|
fieldName={props.field}
|
|
228
242
|
/>
|
|
229
243
|
|
|
230
|
-
<OrderButton
|
|
244
|
+
<OrderButton field={props.field} findOptions={props.findOptions} />
|
|
231
245
|
</div>
|
|
232
246
|
</div>
|
|
233
247
|
</>
|