@furystack/shades-common-components 3.0.4 → 3.1.2

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 (62) hide show
  1. package/dist/components/app-bar-link.js +39 -0
  2. package/dist/components/app-bar-link.js.map +1 -0
  3. package/dist/components/app-bar.js +1 -2
  4. package/dist/components/app-bar.js.map +1 -1
  5. package/dist/components/data-grid/body.js +6 -26
  6. package/dist/components/data-grid/body.js.map +1 -1
  7. package/dist/components/data-grid/data-grid-row.js +62 -0
  8. package/dist/components/data-grid/data-grid-row.js.map +1 -0
  9. package/dist/components/data-grid/data-grid.js +16 -17
  10. package/dist/components/data-grid/data-grid.js.map +1 -1
  11. package/dist/components/data-grid/footer.js +8 -6
  12. package/dist/components/data-grid/footer.js.map +1 -1
  13. package/dist/components/data-grid/header.js +1 -1
  14. package/dist/components/data-grid/header.js.map +1 -1
  15. package/dist/components/data-grid/index.js +1 -0
  16. package/dist/components/data-grid/index.js.map +1 -1
  17. package/dist/components/data-grid/selection-cell.js +32 -0
  18. package/dist/components/data-grid/selection-cell.js.map +1 -0
  19. package/dist/components/grid.js +1 -3
  20. package/dist/components/grid.js.map +1 -1
  21. package/dist/components/index.js +1 -0
  22. package/dist/components/index.js.map +1 -1
  23. package/dist/components/paper.js +1 -1
  24. package/dist/components/paper.js.map +1 -1
  25. package/dist/services/collection-service.js +80 -2
  26. package/dist/services/collection-service.js.map +1 -1
  27. package/package.json +7 -6
  28. package/src/components/app-bar-link.tsx +44 -0
  29. package/src/components/app-bar.tsx +1 -2
  30. package/src/components/data-grid/body.tsx +15 -40
  31. package/src/components/data-grid/data-grid-row.tsx +88 -0
  32. package/src/components/data-grid/data-grid.tsx +27 -32
  33. package/src/components/data-grid/footer.tsx +22 -20
  34. package/src/components/data-grid/header.tsx +1 -1
  35. package/src/components/data-grid/index.tsx +1 -0
  36. package/src/components/data-grid/selection-cell.tsx +32 -0
  37. package/src/components/grid.tsx +1 -1
  38. package/src/components/index.ts +1 -0
  39. package/src/components/paper.tsx +1 -1
  40. package/src/services/collection-service.ts +88 -2
  41. package/tsconfig.json +2 -1
  42. package/tsconfig.tsbuildinfo +1 -1
  43. package/types/components/animations.d.ts +2 -2
  44. package/types/components/animations.d.ts.map +1 -1
  45. package/types/components/app-bar-link.d.ts +3 -0
  46. package/types/components/app-bar-link.d.ts.map +1 -0
  47. package/types/components/app-bar.d.ts.map +1 -1
  48. package/types/components/data-grid/body.d.ts +0 -2
  49. package/types/components/data-grid/body.d.ts.map +1 -1
  50. package/types/components/data-grid/data-grid-row.d.ts +15 -0
  51. package/types/components/data-grid/data-grid-row.d.ts.map +1 -0
  52. package/types/components/data-grid/data-grid.d.ts +4 -9
  53. package/types/components/data-grid/data-grid.d.ts.map +1 -1
  54. package/types/components/data-grid/footer.d.ts.map +1 -1
  55. package/types/components/data-grid/index.d.ts +1 -0
  56. package/types/components/data-grid/index.d.ts.map +1 -1
  57. package/types/components/data-grid/selection-cell.d.ts +6 -0
  58. package/types/components/data-grid/selection-cell.d.ts.map +1 -0
  59. package/types/components/index.d.ts +1 -0
  60. package/types/components/index.d.ts.map +1 -1
  61. package/types/services/collection-service.d.ts +4 -1
  62. package/types/services/collection-service.d.ts.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"collection-service.js","sourceRoot":"","sources":["../../src/services/collection-service.ts"],"names":[],"mappings":";;;;AACA,0FAA6C;AAC7C,4CAAwE;AAWxE,MAAa,iBAAiB;IAwB5B,YAAY,KAAqB,EAAE,eAA+C;QAhBjE,aAAQ,GAAG,IAAI,+BAAS,CAAC,CAAC,CAAC,CAAA;QAIrC,SAAI,GAAG,IAAI,uBAAe,CAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAA;QAExE,UAAK,GAAG,IAAI,uBAAe,CAAsB,SAAS,CAAC,CAAA;QAE3D,cAAS,GAAG,IAAI,uBAAe,CAAU,KAAK,CAAC,CAAA;QAI/C,UAAK,GAAG,IAAI,uBAAe,EAAiB,CAAA;QAE5C,cAAS,GAAG,IAAI,uBAAe,CAAM,EAAE,CAAC,CAAA;QAG7C,IAAI,CAAC,aAAa,GAAG,IAAI,uBAAe,CAAiC,eAAe,CAAC,CAAA;QACzF,IAAI,CAAC,UAAU,GAAG,IAAA,gBAAQ,EAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC3C,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;YAC7B,IAAI;gBACF,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAC7B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAA;gBACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;gBAC1B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;gBAC9B,OAAO,MAAM,CAAA;aACd;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;gBAC1B,MAAM,KAAK,CAAA;aACZ;oBAAS;gBACR,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;gBACvB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;aAC/B;QACH,CAAC,EAAE,GAAG,CAAC,CAAA;QACP,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAA;IACnE,CAAC;IA1CM,OAAO;QACZ,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAA;QAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA;QACnB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAA;QACpB,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;CAsCF;AA5CD,8CA4CC"}
1
+ {"version":3,"file":"collection-service.js","sourceRoot":"","sources":["../../src/services/collection-service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furystack/shades-common-components",
3
- "version": "3.0.4",
3
+ "version": "3.1.2",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "FuryStack",
@@ -17,13 +17,14 @@
17
17
  "author": "gallay.lajos@gmail.com",
18
18
  "license": "GPL-2.0",
19
19
  "devDependencies": {
20
- "typescript": "^4.6.4"
20
+ "typescript": "4.7.4"
21
21
  },
22
22
  "dependencies": {
23
- "@furystack/core": "^11.0.3",
24
- "@furystack/inject": "^6.0.3",
25
- "@furystack/shades": "^5.0.4",
26
- "@furystack/utils": "^3.0.3",
23
+ "@furystack/core": "^11.0.5",
24
+ "@furystack/inject": "^7.0.1",
25
+ "@furystack/shades": "^6.0.1",
26
+ "@furystack/utils": "^3.0.5",
27
+ "path-to-regexp": "^6.2.1",
27
28
  "semaphore-async-await": "^1.5.1",
28
29
  "tslib": "^2.4.0"
29
30
  },
@@ -0,0 +1,44 @@
1
+ import { createComponent, LocationService, RouteLink, RouteLinkProps, Shade } from '@furystack/shades'
2
+ import { match } from 'path-to-regexp'
3
+ import { ThemeProviderService } from '../services'
4
+
5
+ export const AppBarLink = Shade<RouteLinkProps, { isActive: boolean }>({
6
+ getInitialState: () => ({ isActive: false }),
7
+ resources: ({ injector, props, updateState, element, getState }) => {
8
+ const updateColor = () => {
9
+ const { isActive } = getState()
10
+ const themeProviderService = injector.getInstance(ThemeProviderService)
11
+ const theme = themeProviderService.theme.getValue()
12
+ const el = element.querySelector('a') as HTMLElement
13
+ const backgroundColor = isActive ? theme.button.active : 'rgba(128, 128, 128, 0.05)'
14
+
15
+ el.style.backgroundColor = backgroundColor
16
+ el.style.color = themeProviderService.getTextColor(backgroundColor)
17
+ }
18
+ return [
19
+ injector.getInstance(LocationService).onLocationChanged.subscribe(async (currentUrl) => {
20
+ const isActive = !!match(props.href as string)(currentUrl)
21
+ updateState({ isActive }, false)
22
+ updateColor()
23
+ }, true),
24
+ ]
25
+ },
26
+ shadowDomName: 'shade-app-bar-link',
27
+ render: ({ children, props }) => {
28
+ return (
29
+ <RouteLink
30
+ style={{
31
+ display: 'flex',
32
+ height: '100%',
33
+ textDecoration: 'none',
34
+ alignItems: 'center',
35
+ padding: '0 8px',
36
+ ...props.style,
37
+ }}
38
+ {...props}
39
+ >
40
+ {children}
41
+ </RouteLink>
42
+ )
43
+ },
44
+ })
@@ -11,7 +11,7 @@ export const AppBar = Shade({
11
11
  constructed: ({ element }) => {
12
12
  const container = element.children[0] as HTMLElement
13
13
  requestAnimationFrame(() => {
14
- container.style.padding = '8px 8px'
14
+ // container.style.padding = '8px 8px'
15
15
  container.style.opacity = '1'
16
16
  })
17
17
  },
@@ -28,7 +28,6 @@ export const AppBar = Shade({
28
28
  boxShadow: '0 0 12px rgba(0,0,0,0.6)',
29
29
  transition:
30
30
  'opacity .35s cubic-bezier(0.550, 0.085, 0.680, 0.530), padding .2s cubic-bezier(0.550, 0.085, 0.680, 0.530)',
31
- padding: '6px 16px',
32
31
  opacity: '0',
33
32
  position: 'fixed',
34
33
  zIndex: '1',
@@ -1,7 +1,8 @@
1
1
  import { CollectionService } from '../../services/collection-service'
2
- import { ChildrenList, Shade, createComponent } from '@furystack/shades'
2
+ import { ChildrenList, Shade, createComponent, createFragment } from '@furystack/shades'
3
3
  import { DataRowCells } from './data-grid'
4
4
  import { Loader } from '../loader'
5
+ import { DataGridRow } from './data-grid-row'
5
6
 
6
7
  export interface DataGridBodyProps<T> {
7
8
  service: CollectionService<T>
@@ -13,8 +14,6 @@ export interface DataGridBodyProps<T> {
13
14
 
14
15
  export interface DataGridBodyState<T> {
15
16
  data: T[]
16
- selection: T[]
17
- focus: T | undefined
18
17
  isLoading: boolean
19
18
  }
20
19
 
@@ -24,19 +23,12 @@ export const DataGridBody: <T>(props: DataGridBodyProps<T>, children: ChildrenLi
24
23
  >({
25
24
  getInitialState: ({ props }) => ({
26
25
  data: props.service.data.getValue().entries,
27
- selection: props.service.selection.getValue(),
28
- focus: props.service.focus.getValue(),
29
26
  isLoading: props.service.isLoading.getValue(),
30
27
  }),
31
- constructed: ({ props, updateState }) => {
32
- const disposables = [
33
- props.service.data.subscribe((data) => updateState({ data: data.entries })),
34
- props.service.focus.subscribe((focus) => updateState({ focus })),
35
- props.service.selection.subscribe((selection) => updateState({ selection })),
36
- props.service.isLoading.subscribe((isLoading) => updateState({ isLoading })),
37
- ]
38
- return () => disposables.map((d) => d.dispose())
39
- },
28
+ resources: ({ props, updateState }) => [
29
+ props.service.data.subscribe((data) => updateState({ data: data.entries })),
30
+ props.service.isLoading.subscribe((isLoading) => updateState({ isLoading })),
31
+ ],
40
32
  shadowDomName: 'shade-data-grid-body',
41
33
  render: ({ getState, props, element }) => {
42
34
  element.style.display = 'table-row-group'
@@ -45,6 +37,7 @@ export const DataGridBody: <T>(props: DataGridBodyProps<T>, children: ChildrenLi
45
37
  if (state.isLoading) {
46
38
  return (
47
39
  <div style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center', width: '100%' }}>
40
+ {/* TODO: Skeleton */}
48
41
  <Loader style={{ height: '128px', width: '128px' }} />
49
42
  </div>
50
43
  )
@@ -55,34 +48,16 @@ export const DataGridBody: <T>(props: DataGridBodyProps<T>, children: ChildrenLi
55
48
  }
56
49
 
57
50
  return (
58
- <div style={{ display: 'contents' }}>
51
+ <>
59
52
  {state.data.map((entry) => (
60
- <tr
61
- style={{
62
- background: state.selection.includes(entry) ? 'rgba(128,128,128,0.3)' : 'transparent',
63
- filter: state.focus === entry ? 'brightness(1.5)' : 'brightness(1)',
64
- cursor: 'default',
65
- boxShadow: '2px 1px 0px rgba(255,255,255,0.07)',
66
- fontSize: '0.8em',
67
- }}
68
- onclick={() => {
69
- if (getState().focus !== entry) {
70
- props.service.focus.setValue(entry)
71
- props.service.selection.setValue([entry])
72
- }
73
- }}
74
- ondblclick={() => props.onDoubleClick?.(entry)}
75
- >
76
- {props.columns.map((column: any) => (
77
- <td style={{ padding: '0.5em', ...props.style }}>
78
- {props.rowComponents?.[column]?.(entry, state) || props.rowComponents?.default?.(entry, state) || (
79
- <span>{entry[column]}</span>
80
- )}
81
- </td>
82
- ))}
83
- </tr>
53
+ <DataGridRow<any>
54
+ columns={props.columns}
55
+ entry={entry}
56
+ service={props.service}
57
+ rowComponents={props.rowComponents}
58
+ ></DataGridRow>
84
59
  ))}
85
- </div>
60
+ </>
86
61
  )
87
62
  },
88
63
  })
@@ -0,0 +1,88 @@
1
+ import { ChildrenList, createComponent, createFragment, Shade } from '@furystack/shades'
2
+ import { CollectionService } from '../../services/collection-service'
3
+ import { DataRowCells } from './data-grid'
4
+
5
+ export interface DataGridRowProps<T> {
6
+ entry: T
7
+ columns: Array<keyof T>
8
+ service: CollectionService<T>
9
+ rowComponents?: DataRowCells<T>
10
+ }
11
+
12
+ export interface DataGridRowState<T> {
13
+ selection?: T[]
14
+ focus?: T
15
+ }
16
+
17
+ export const DataGridRow: <T>(props: DataGridRowProps<T>, children: ChildrenList) => JSX.Element<any, any> = Shade<
18
+ DataGridRowProps<any>,
19
+ DataGridRowState<any>
20
+ >({
21
+ getInitialState: ({ props }) => ({
22
+ focus: props.service.focusedEntry.getValue(),
23
+ selection: props.service.selection.getValue(),
24
+ }),
25
+ shadowDomName: 'shades-data-grid-row',
26
+ resources: ({ props, element }) => [
27
+ props.service.focusedEntry.subscribe((newEntry) => {
28
+ if (newEntry === props.entry) {
29
+ element.style.filter = 'brightness(1.5)'
30
+ element.style.fontWeight = 'bolder'
31
+
32
+ const headerHeight = element.closest('table')?.querySelector('th')?.getBoundingClientRect().height || 42
33
+
34
+ const parent = element.closest('.shade-grid-wrapper') as HTMLElement
35
+ const maxTop = element.offsetTop - headerHeight
36
+ const currentTop = parent.scrollTop
37
+ if (maxTop < currentTop) {
38
+ parent.scrollTo({ top: maxTop, behavior: 'smooth' })
39
+ }
40
+
41
+ const footerHeight =
42
+ element.closest('shade-data-grid')?.querySelector('shade-data-grid-footer')?.getBoundingClientRect().height ||
43
+ 42
44
+ const visibleMaxTop = parent.clientHeight - footerHeight // parent.getBoundingClientRect().height - footerHeight - headerHeight
45
+ const desiredMaxTop = element.offsetTop + element.clientHeight
46
+ if (desiredMaxTop > visibleMaxTop) {
47
+ parent.scrollTo({ top: desiredMaxTop - visibleMaxTop, behavior: 'smooth' })
48
+ }
49
+
50
+ // ;(element as any).scrollIntoView({ inline: 'nearest', block: 'nearest', behavior: 'smooth' })
51
+ } else {
52
+ element.style.filter = 'brightness(1)'
53
+ element.style.fontWeight = 'inherit'
54
+ }
55
+ }),
56
+ props.service.selection.subscribe((selection) => {
57
+ if (selection.includes(props.entry)) {
58
+ element.style.background = 'rgba(128,128,128,0.1)'
59
+ } else {
60
+ element.style.background = 'none'
61
+ }
62
+ }),
63
+ ],
64
+
65
+ render: ({ getState, props, element }) => {
66
+ const state = getState()
67
+ const { entry, rowComponents, columns } = props
68
+
69
+ element.style.display = 'table-row'
70
+ element.style.cursor = 'default'
71
+ element.style.userSelect = 'none'
72
+
73
+ element.onclick = () => {
74
+ props.service.focusedEntry.setValue(props.entry)
75
+ }
76
+ return (
77
+ <>
78
+ {columns.map((column) => (
79
+ <td style={{ padding: '0.5em' }}>
80
+ {rowComponents?.[column]?.(entry, state) || rowComponents?.default?.(entry, state) || (
81
+ <span>{entry[column]}</span>
82
+ )}
83
+ </td>
84
+ ))}
85
+ </>
86
+ )
87
+ },
88
+ })
@@ -1,17 +1,17 @@
1
1
  import { ChildrenList, createComponent, Shade } from '@furystack/shades'
2
2
  import { CollectionService } from '../../services/collection-service'
3
3
  import { GridProps } from '../grid'
4
- import { colors } from '../styles'
5
4
  import { DataGridHeader } from './header'
6
- import { DataGridBody, DataGridBodyState } from './body'
5
+ import { DataGridBody } from './body'
7
6
  import { DataGridFooter } from './footer'
8
- import { ThemeProviderService } from '../../services'
7
+ import { ClickAwayService, ThemeProviderService } from '../../services'
8
+ import { DataGridRowState } from './data-grid-row'
9
9
 
10
10
  export type DataHeaderCells<T> = {
11
- [TKey in keyof T | 'default']?: (name: keyof T, state: DataGridState) => JSX.Element
11
+ [TKey in keyof T | 'default']?: (name: keyof T) => JSX.Element
12
12
  }
13
13
  export type DataRowCells<T> = {
14
- [TKey in keyof T | 'default']?: (element: T, state: DataGridBodyState<T>) => JSX.Element
14
+ [TKey in keyof T | 'default']?: (element: T, state: DataGridRowState<T>) => JSX.Element
15
15
  }
16
16
 
17
17
  export interface DataGridProps<T> {
@@ -20,25 +20,16 @@ export interface DataGridProps<T> {
20
20
  service: CollectionService<T>
21
21
  headerComponents: DataHeaderCells<T>
22
22
  rowComponents: DataRowCells<T>
23
- onFocusChange?: (entry?: T) => void
24
- onSelectionChange?: (selection: T[]) => void
25
- onDoubleClick?: (entry: T) => void
26
- }
27
-
28
- export interface DataGridState {
29
- error?: unknown
23
+ autofocus?: boolean
30
24
  }
31
25
 
32
26
  export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => JSX.Element<any, any> = Shade<
33
- DataGridProps<any>,
34
- DataGridState
27
+ DataGridProps<any>
35
28
  >({
36
29
  shadowDomName: 'shade-data-grid',
37
- getInitialState: () => ({}),
38
- constructed: ({ props, updateState, injector, element }) => {
30
+ resources: ({ injector, element, props }) => {
39
31
  const tp = injector.getInstance(ThemeProviderService)
40
- const subscriptions = [
41
- props.service.error.subscribe((error) => updateState({ error })),
32
+ return [
42
33
  tp.theme.subscribe((t) => {
43
34
  const headers = element.querySelectorAll('th')
44
35
  const { r, g, b } = tp.getRgbFromColorString(t.background.paper)
@@ -47,18 +38,21 @@ export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => J
47
38
  header.style.backgroundColor = `rgba(${r}, ${g}, ${b}, 0.3)`
48
39
  })
49
40
  }),
50
- props.service.focus.subscribe((f) => props.onFocusChange?.(f)),
51
- props.service.selection.subscribe((f) => props.onSelectionChange?.(f)),
41
+ new ClickAwayService(element, () => {
42
+ props.service.hasFocus.setValue(false)
43
+ }),
52
44
  ]
53
- return () => Promise.all(subscriptions.map((s) => s.dispose()))
54
45
  },
55
- render: ({ props, getState, injector }) => {
46
+ constructed: ({ props }) => {
47
+ const listener = (ev: KeyboardEvent) => props.service.handleKeyDown(ev)
48
+
49
+ window.addEventListener('keydown', listener)
50
+
51
+ return () => window.removeEventListener('keydown', listener)
52
+ },
53
+ render: ({ props, injector }) => {
56
54
  const tp = injector.getInstance(ThemeProviderService)
57
55
  const theme = tp.theme.getValue()
58
- const state = getState()
59
- if (state.error) {
60
- return <div style={{ color: colors.error.main }}>{JSON.stringify(state.error)}</div>
61
- }
62
56
 
63
57
  const { r, g, b } = tp.getRgbFromColorString(theme.background.paper)
64
58
  const headerStyle: Partial<CSSStyleDeclaration> = {
@@ -86,17 +80,19 @@ export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => J
86
80
  overflow: 'auto',
87
81
  zIndex: '1',
88
82
  }}
83
+ onclick={() => {
84
+ props.service.hasFocus.setValue(true)
85
+ }}
89
86
  >
90
- <table style={{ width: '100%', height: 'calc(100% - 4em)', position: 'relative' }}>
87
+ <table style={{ width: '100%', maxHeight: 'calc(100% - 4em)', position: 'relative' }}>
91
88
  <thead>
92
89
  <tr>
93
90
  {props.columns.map((column: any) => {
94
91
  return (
95
92
  <th style={headerStyle}>
96
- {props.headerComponents?.[column]?.(column, state) ||
97
- props.headerComponents?.default?.(column, state) || (
98
- <DataGridHeader<any, typeof column> field={column} collectionService={props.service} />
99
- )}
93
+ {props.headerComponents?.[column]?.(column) || props.headerComponents?.default?.(column) || (
94
+ <DataGridHeader<any, typeof column> field={column} collectionService={props.service} />
95
+ )}
100
96
  </th>
101
97
  )
102
98
  })}
@@ -107,7 +103,6 @@ export const DataGrid: <T>(props: DataGridProps<T>, children: ChildrenList) => J
107
103
  service={props.service}
108
104
  rowComponents={props.rowComponents}
109
105
  style={props.styles?.cell}
110
- onDoubleClick={props.onDoubleClick}
111
106
  />
112
107
  </table>
113
108
  <DataGridFooter service={props.service} />
@@ -2,7 +2,7 @@ import { Shade, createComponent } from '@furystack/shades'
2
2
  import { ThemeProviderService } from '../../services'
3
3
  import { CollectionService, CollectionData } from '../../services/collection-service'
4
4
 
5
- export const dataGridItemsPerPage = [10, 20, 25, 50, 100]
5
+ export const dataGridItemsPerPage = [10, 20, 25, 50, 100, Infinity]
6
6
 
7
7
  export const DataGridFooter = Shade<{ service: CollectionService<any> }, { data: CollectionData<any> }>({
8
8
  shadowDomName: 'shade-data-grid-footer',
@@ -26,13 +26,14 @@ export const DataGridFooter = Shade<{ service: CollectionService<any> }, { data:
26
26
  const state = getState()
27
27
  const currentQuerySettings = props.service.querySettings.getValue()
28
28
  const currentPage = Math.ceil(currentQuerySettings.skip || 0) / (currentQuerySettings.top || 1)
29
+ const currentEntriesPerPage = currentQuerySettings.top || Infinity
29
30
  const theme = injector.getInstance(ThemeProviderService).theme.getValue()
30
31
 
31
32
  return (
32
33
  <div
33
34
  className="pager"
34
35
  style={{
35
- background: theme.background.paper,
36
+ backdropFilter: 'blur(10px)',
36
37
  color: theme.text.secondary,
37
38
  position: 'sticky',
38
39
  bottom: '0',
@@ -42,27 +43,28 @@ export const DataGridFooter = Shade<{ service: CollectionService<any> }, { data:
42
43
  alignItems: 'center',
43
44
  }}
44
45
  >
45
- <div>
46
- Goto page
47
- <select
48
- style={{ margin: '0 1em' }}
49
- onchange={(ev) => {
50
- const value = parseInt((ev.target as any).value, 10)
51
- const currentQuery = props.service.querySettings.getValue()
52
- props.service.querySettings.setValue({ ...currentQuery, skip: (currentQuery.top || 0) * value })
53
- }}
54
- >
55
- {[...new Array(Math.ceil(state.data.count / (props.service.querySettings.getValue().top || Infinity)))].map(
56
- (_val, index) => (
46
+ {currentEntriesPerPage !== Infinity && (
47
+ <div>
48
+ Goto page
49
+ <select
50
+ style={{ margin: '0 1em' }}
51
+ onchange={(ev) => {
52
+ const value = parseInt((ev.target as any).value, 10)
53
+ const currentQuery = props.service.querySettings.getValue()
54
+ props.service.querySettings.setValue({ ...currentQuery, skip: (currentQuery.top || 0) * value })
55
+ }}
56
+ >
57
+ {[
58
+ ...new Array(Math.ceil(state.data.count / (props.service.querySettings.getValue().top || Infinity))),
59
+ ].map((_val, index) => (
57
60
  <option value={index.toString()} selected={currentPage === index}>
58
61
  {(index + 1).toString()}
59
62
  </option>
60
- ),
61
- )}
62
- </select>
63
- </div>
63
+ ))}
64
+ </select>
65
+ </div>
66
+ )}
64
67
  <div>
65
- {' '}
66
68
  Show
67
69
  <select
68
70
  style={{ margin: '0 1em' }}
@@ -76,7 +78,7 @@ export const DataGridFooter = Shade<{ service: CollectionService<any> }, { data:
76
78
  }}
77
79
  >
78
80
  {dataGridItemsPerPage.map((no) => (
79
- <option value={no.toString()} selected={no === currentQuerySettings.top}>
81
+ <option value={no.toString()} selected={no === currentEntriesPerPage}>
80
82
  {no.toString()}
81
83
  </option>
82
84
  ))}
@@ -29,7 +29,7 @@ export const DataGridHeader: <T, K extends keyof T>(
29
29
  ...currentSettings,
30
30
  filter: {
31
31
  ...currentSettings.filter,
32
- [props.field]: value ? { $regex: value } : undefined,
32
+ [props.field]: { $regex: value },
33
33
  },
34
34
  }
35
35
  props.collectionService.querySettings.setValue(newSettings)
@@ -1 +1,2 @@
1
1
  export * from './data-grid'
2
+ export * from './selection-cell'
@@ -0,0 +1,32 @@
1
+ import { createComponent, Shade } from '@furystack/shades'
2
+ import { CollectionService } from '../../services'
3
+
4
+ export const SelectionCell = Shade<{ entry: any; service: CollectionService<any> }>({
5
+ shadowDomName: 'shades-data-grid-selection-cell',
6
+ resources: ({ props, element }) => [
7
+ props.service.selection.subscribe((selection) => {
8
+ if (selection.includes(props.entry)) {
9
+ ;(element.firstChild as HTMLInputElement).checked = true
10
+ } else {
11
+ ;(element.firstChild as HTMLInputElement).checked = false
12
+ }
13
+ }),
14
+ ],
15
+ render: ({ props }) => {
16
+ return (
17
+ <input
18
+ onchange={(ev) => {
19
+ if ((ev.target as HTMLInputElement).checked) {
20
+ props.service.selection.setValue([...props.service.selection.getValue(), props.entry])
21
+ } else {
22
+ props.service.selection.setValue([
23
+ ...props.service.selection.getValue().filter((entry) => entry !== props.entry),
24
+ ])
25
+ }
26
+ }}
27
+ type="checkbox"
28
+ checked={props.service.selection.getValue().includes(props.entry) ? true : false}
29
+ />
30
+ )
31
+ },
32
+ })
@@ -64,7 +64,7 @@ export const Grid: <T>(props: GridProps<T>, children: ChildrenList) => JSX.Eleme
64
64
  <th style={headerStyle}>
65
65
  {props.headerComponents?.[column]?.(column) || props.headerComponents?.default?.(column) || (
66
66
  <span>{column}</span>
67
- )}{' '}
67
+ )}
68
68
  </th>
69
69
  )
70
70
  })}
@@ -1,5 +1,6 @@
1
1
  export * from './animations'
2
2
  export * from './app-bar'
3
+ export * from './app-bar-link'
3
4
  export * from './autocomplete'
4
5
  export * from './avatar'
5
6
  export * from './button'
@@ -24,7 +24,7 @@ export const Paper = Shade<PartialElement<HTMLDivElement> & { elevation?: 1 | 2
24
24
  color: themeProvider.theme.getValue().text.secondary,
25
25
  margin: '8px',
26
26
  padding: '6px 16px',
27
- ...(props ? props.style : {}),
27
+ ...props?.style,
28
28
  }}
29
29
  >
30
30
  {children}