@pushwoosh/smart-components-kit 1.0.53 → 1.0.55

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.
@@ -13,11 +13,14 @@ export function DataTable(props) {
13
13
  const {
14
14
  columns,
15
15
  width,
16
+ bgColor,
16
17
  isBordered = true,
17
18
  paginationPadding,
18
19
  context,
20
+ allLimits,
19
21
  renderTableTop,
20
22
  renderAfter,
23
+ onClearRequest,
21
24
  hidePagination,
22
25
  hidePageSizeSelector
23
26
  } = props;
@@ -26,16 +29,27 @@ export function DataTable(props) {
26
29
  params
27
30
  } = context;
28
31
  const isFiltered = ((_data$value = data.value) === null || _data$value === void 0 ? void 0 : _data$value.isFiltered) || params.search;
32
+ const onClearRequestDefault = () => {
33
+ const keys = ['perPage', 'order', 'direction'];
34
+ context.onChangeParams(keys.reduce((acc, key) => ({
35
+ ...acc,
36
+ [key]: context.params[key]
37
+ }), {
38
+ page: 1,
39
+ search: ''
40
+ }));
41
+ };
29
42
  return React.createElement(DataTableContext.Provider, {
30
43
  value: context
31
44
  }, React.createElement(Table, {
32
45
  columns: columns,
33
46
  width: width,
34
- isBordered: isBordered
47
+ isBordered: isBordered,
48
+ "$bgColor": bgColor
35
49
  }, renderTableTop === null || renderTableTop === void 0 ? void 0 : renderTableTop(context), 'renderHead' in props && props.renderHead(), 'renderList' in props ? props.renderList(context) : React.createElement(DataTableList, {
36
50
  renderItem: props.renderItem
37
51
  }), !hidePagination && React.createElement(DataTablePagination, {
38
- allLimits: [10, 20, 50, 100],
52
+ allLimits: allLimits ?? [10, 20, 50, 100],
39
53
  padding: paginationPadding,
40
54
  hidePageSizeSelector: hidePageSizeSelector
41
55
  }, data.loading && React.createElement(Horizontal, {
@@ -58,23 +72,14 @@ export function DataTable(props) {
58
72
  "$gap": 4
59
73
  }, "Result:", React.createElement(LockedText, null, `${(_data$value3 = data.value) === null || _data$value3 === void 0 ? void 0 : _data$value3.total} item${(((_data$value4 = data.value) === null || _data$value4 === void 0 ? void 0 : _data$value4.total) ?? 0) > 1 ? 's' : ''}`)), !data.loading && !data.error && (((_data$value5 = data.value) === null || _data$value5 === void 0 ? void 0 : _data$value5.total) ?? 0) === 0 && !isFiltered && React.createElement(Horizontal, {
60
74
  "$placeItems": "center"
61
- }, React.createElement(LockedText, null, "No items yet")), !data.loading && (((_data$value6 = data.value) === null || _data$value6 === void 0 || (_data$value6 = _data$value6.items) === null || _data$value6 === void 0 ? void 0 : _data$value6.length) ?? 0) === 0 && isFiltered && React.createElement(Horizontal, {
75
+ }, React.createElement(LockedText, null, "No items yet")), !data.loading && isFiltered && React.createElement(Horizontal, {
62
76
  "$gap": 16
63
- }, !data.error && React.createElement(Horizontal, {
77
+ }, !data.error && (((_data$value6 = data.value) === null || _data$value6 === void 0 || (_data$value6 = _data$value6.items) === null || _data$value6 === void 0 ? void 0 : _data$value6.length) ?? 0) === 0 && React.createElement(Horizontal, {
64
78
  "$placeItems": "center",
65
79
  "$gap": 4
66
80
  }, "Result:", React.createElement(LockedText, null, "No match found")), React.createElement(Button, {
67
81
  color: "primary",
68
82
  view: "ghost",
69
- onClick: () => {
70
- const keys = ['perPage', 'order', 'direction'];
71
- context.onChangeParams(keys.reduce((acc, key) => ({
72
- ...acc,
73
- [key]: context.params[key]
74
- }), {
75
- page: 1,
76
- search: ''
77
- }));
78
- }
83
+ onClick: onClearRequest ?? onClearRequestDefault
79
84
  }, "Clear request")))), renderAfter === null || renderAfter === void 0 ? void 0 : renderAfter(context));
80
85
  }
@@ -4,25 +4,31 @@ export type DataTableListProps<I, P extends DataTableParams> = {
4
4
  columns: string;
5
5
  width?: string | number;
6
6
  isBordered?: boolean;
7
+ bgColor?: string;
7
8
  context: DataTableContextType<I, P>;
8
9
  hidePagination?: boolean;
9
10
  hidePageSizeSelector?: boolean;
10
11
  paginationPadding?: string;
12
+ allLimits?: number[];
11
13
  renderTableTop?: (ctxValue: DataTableContextType<I, P>) => ReactNode;
12
14
  renderList: (ctxValue: DataTableContextType<I, P>) => ReactNode;
13
15
  renderAfter?: (ctxValue: DataTableContextType<I, P>) => ReactNode;
16
+ onClearRequest?: () => void;
14
17
  };
15
18
  export type DataTableItemProps<I, P extends DataTableParams> = {
16
19
  columns: string;
17
20
  width?: string | number;
18
21
  isBordered?: boolean;
22
+ bgColor?: string;
19
23
  context: DataTableContextType<I, P>;
20
24
  hidePagination?: boolean;
21
25
  hidePageSizeSelector?: boolean;
22
26
  paginationPadding?: string;
27
+ allLimits?: number[];
23
28
  renderTableTop?: (ctxValue: DataTableContextType<I, P>) => ReactNode;
24
29
  renderHead: () => ReactNode;
25
30
  renderItem: (item: I) => ReactNode;
26
31
  renderAfter?: (ctxValue: DataTableContextType<I, P>) => ReactNode;
32
+ onClearRequest?: () => void;
27
33
  };
28
34
  export type DataTableProps<I, P extends DataTableParams> = DataTableListProps<I, P> | DataTableItemProps<I, P>;
@@ -39,7 +39,7 @@ export function useDataTableGetParams({
39
39
  const searchParams = new URLSearchParams(locationSearch);
40
40
  const paramsWithPrefix = mapKeys(params, key => `${prefix}${key}`);
41
41
  for (const [key, value] of Object.entries(paramsWithPrefix)) {
42
- if (value === undefined || value === null || value === '') {
42
+ if (value === undefined || value === null || value === '' || Array.isArray(value) && value.length === 0) {
43
43
  searchParams.delete(key);
44
44
  } else {
45
45
  searchParams.set(key, String(value));
package/Table/styles.d.ts CHANGED
@@ -3,6 +3,7 @@ export type TableProps = {
3
3
  columns: string;
4
4
  width?: string | number;
5
5
  isBordered?: boolean;
6
+ $bgColor?: string;
6
7
  };
7
8
  export declare const Table: import("styled-components").StyledComponent<"div", any, {
8
9
  $alignContent?: "end" | "start" | "center" | "space-between" | "space-around" | "space-evenly" | "stretch" | undefined;
package/Table/styles.js CHANGED
@@ -8,7 +8,9 @@ export const Table = styled(Vertical).withConfig({
8
8
  columns
9
9
  }) => columns, ({
10
10
  isBordered
11
- }) => isBordered ? `1px solid ${Color.DIVIDER}` : 'none', ShapeRadius.SECTION, Color.CLEAR, ({
11
+ }) => isBordered ? `1px solid ${Color.DIVIDER}` : 'none', ShapeRadius.SECTION, ({
12
+ $bgColor
13
+ }) => $bgColor ?? Color.CLEAR, ({
12
14
  width
13
15
  }) => width ? `width: ${toCssValue(width)};` : '', Color.DIVIDER);
14
16
  export const Td = styled(GridContainer).attrs({
@@ -0,0 +1,32 @@
1
+ export type ChangeType = 'init' | 'set' | 'remove';
2
+ export interface KeyValueChange<K extends IDBValidKey = IDBValidKey, V = unknown> {
3
+ key: K;
4
+ value: V | undefined;
5
+ inMemory: boolean;
6
+ type: ChangeType;
7
+ }
8
+ export interface UniversalKeyValueStoreOptions<K extends IDBValidKey = IDBValidKey> {
9
+ memoryKeys?: K[];
10
+ }
11
+ export declare class UniversalKeyValueStore<K extends IDBValidKey = IDBValidKey, V = unknown> {
12
+ private readonly store;
13
+ private readonly memoryKeySet;
14
+ private readonly memory;
15
+ private readonly emitter;
16
+ private constructor();
17
+ static initialize<K extends IDBValidKey = IDBValidKey, V = unknown>(dbName: string, tableName: string, options: UniversalKeyValueStoreOptions<K>): Promise<UniversalKeyValueStore<K, V>>;
18
+ private init;
19
+ static makeEventName(key: IDBValidKey): string;
20
+ private toStorageKey;
21
+ private isMemoryKey;
22
+ private emitEvent;
23
+ get(key: K): Promise<V | undefined>;
24
+ getMemory(key: K): V | undefined;
25
+ set(key: K, value: V): Promise<void>;
26
+ remove(key: K): Promise<void>;
27
+ getAll(): Promise<Record<string, V>>;
28
+ getAllMemory(): Record<string, V>;
29
+ subscribe(key: K, listener: (change: KeyValueChange<K, V>) => void, options?: {
30
+ callImmediately?: boolean;
31
+ }): () => void;
32
+ }
@@ -0,0 +1,140 @@
1
+ import { createStore, get as idbGet, set as idbSet, del as idbDel, entries as idbEntries } from 'idb-keyval';
2
+ import { SimpleEventEmitter } from './SimpleEventEmitter';
3
+ export class UniversalKeyValueStore {
4
+ store;
5
+ memoryKeySet;
6
+ memory;
7
+ emitter;
8
+ constructor(dbName, tableName, options) {
9
+ const {
10
+ memoryKeys = []
11
+ } = options;
12
+ this.store = createStore(dbName, tableName);
13
+ this.memoryKeySet = new Set(memoryKeys);
14
+ this.memory = new Map();
15
+ this.emitter = new SimpleEventEmitter();
16
+ }
17
+ static async initialize(dbName, tableName, options) {
18
+ const instance = new UniversalKeyValueStore(dbName, tableName, options);
19
+ await instance.init();
20
+ return instance;
21
+ }
22
+ async init() {
23
+ if (this.memoryKeySet.size > 0) {
24
+ for (const key of this.memoryKeySet) {
25
+ try {
26
+ const value = await idbGet(this.toStorageKey(key), this.store);
27
+ if (value !== undefined) {
28
+ this.memory.set(key, value);
29
+ }
30
+ } catch (e) {
31
+ console.error('Failed to init memory key from IndexedDB', {
32
+ key,
33
+ error: e
34
+ });
35
+ }
36
+ }
37
+ }
38
+ }
39
+ static makeEventName(key) {
40
+ return `key:${String(key)}`;
41
+ }
42
+ toStorageKey(key) {
43
+ return key;
44
+ }
45
+ isMemoryKey(key) {
46
+ return this.memoryKeySet.has(key);
47
+ }
48
+ emitEvent(eventName, payload) {
49
+ try {
50
+ this.emitter.emit(eventName, payload);
51
+ } catch (e) {
52
+ console.error('Failed to emit event', {
53
+ eventName,
54
+ payload,
55
+ error: e
56
+ });
57
+ }
58
+ }
59
+ async get(key) {
60
+ if (this.isMemoryKey(key) && this.memory.has(key)) {
61
+ return this.memory.get(key);
62
+ }
63
+ const value = await idbGet(this.toStorageKey(key), this.store);
64
+ if (this.isMemoryKey(key) && value !== undefined) {
65
+ this.memory.set(key, value);
66
+ }
67
+ return value;
68
+ }
69
+ getMemory(key) {
70
+ if (this.isMemoryKey(key)) {
71
+ return this.memory.get(key);
72
+ }
73
+ return undefined;
74
+ }
75
+ async set(key, value) {
76
+ const inMemory = this.isMemoryKey(key);
77
+ if (inMemory) {
78
+ this.memory.set(key, value);
79
+ }
80
+ const payload = {
81
+ key,
82
+ value,
83
+ inMemory,
84
+ type: 'set'
85
+ };
86
+ this.emitEvent(UniversalKeyValueStore.makeEventName(key), payload);
87
+ await idbSet(this.toStorageKey(key), value, this.store);
88
+ }
89
+ async remove(key) {
90
+ const inMemory = this.isMemoryKey(key);
91
+ if (inMemory) {
92
+ this.memory.delete(key);
93
+ }
94
+ const payload = {
95
+ key,
96
+ value: undefined,
97
+ inMemory,
98
+ type: 'remove'
99
+ };
100
+ this.emitEvent(UniversalKeyValueStore.makeEventName(key), payload);
101
+ await idbDel(this.toStorageKey(key), this.store);
102
+ }
103
+ async getAll() {
104
+ const persistentRaw = await idbEntries(this.store);
105
+ const persistent = {};
106
+ for (const [storageKey, value] of Object.entries(persistentRaw)) {
107
+ persistent[storageKey] = value;
108
+ }
109
+ const result = {
110
+ ...persistent
111
+ };
112
+ for (const [key, value] of this.memory.entries()) {
113
+ result[String(key)] = value;
114
+ }
115
+ return result;
116
+ }
117
+ getAllMemory() {
118
+ return Array.from(this.memory.entries()).reduce((acc, [key, value]) => {
119
+ acc[String(key)] = value;
120
+ return acc;
121
+ }, {});
122
+ }
123
+ subscribe(key, listener, options) {
124
+ const eventName = UniversalKeyValueStore.makeEventName(key);
125
+ const unsubscribe = this.emitter.on(eventName, listener, false);
126
+ if (options !== null && options !== void 0 && options.callImmediately) {
127
+ this.get(key).then(value => {
128
+ if (value !== undefined) {
129
+ listener({
130
+ key,
131
+ value,
132
+ inMemory: this.isMemoryKey(key),
133
+ type: 'init'
134
+ });
135
+ }
136
+ });
137
+ }
138
+ return unsubscribe;
139
+ }
140
+ }
@@ -1,6 +1,7 @@
1
1
  import { SimpleEventEmitter } from './SimpleEventEmitter';
2
2
  import type { SPAContextType } from './types';
3
+ import { UniversalKeyValueStore } from './UniversalKeyValueStore';
3
4
  import { useSPAContext } from './useSPAContext';
4
5
  export type { SPAContextType };
5
- export { useSPAContext, SimpleEventEmitter };
6
+ export { useSPAContext, SimpleEventEmitter, UniversalKeyValueStore };
6
7
  export declare const SPAContextProvider: import("react").Provider<SPAContextType | undefined>;
package/context/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { SPAContext } from './context';
2
2
  import { SimpleEventEmitter } from './SimpleEventEmitter';
3
+ import { UniversalKeyValueStore } from './UniversalKeyValueStore';
3
4
  import { useSPAContext } from './useSPAContext';
4
- export { useSPAContext, SimpleEventEmitter };
5
+ export { useSPAContext, SimpleEventEmitter, UniversalKeyValueStore };
5
6
  export const SPAContextProvider = SPAContext.Provider;
@@ -5,6 +5,7 @@ import type { API as RpcGatewayPaymentAPI } from '@pushwoosh/rpc-gateway-payment
5
5
  import type { API as RpcGatewayAPI } from '@pushwoosh/rpc-v2-http-api-data';
6
6
  import type { SessionStore } from '@pushwoosh/session-store';
7
7
  import type { SimpleEventEmitter } from './SimpleEventEmitter';
8
+ import type { UniversalKeyValueStore } from './UniversalKeyValueStore';
8
9
  export type Environment = {
9
10
  isPWI: boolean;
10
11
  isPushwoosh: boolean;
@@ -32,5 +33,6 @@ export type SPAContextType = {
32
33
  };
33
34
  readonly eventBus: SimpleEventEmitter;
34
35
  readonly environment: Environment;
36
+ readonly keyValueStorage: UniversalKeyValueStore;
35
37
  readonly __smartComponentsCache: Record<string, any>;
36
38
  };
package/package.json CHANGED
@@ -26,6 +26,7 @@
26
26
  "@pushwoosh/kit-helpers": "^4.8.1",
27
27
  "@pushwoosh/kit-icons": "^2.1.6",
28
28
  "@pushwoosh/kit-typography": "^1.7.3",
29
+ "idb-keyval": "^6.2.2",
29
30
  "react-router-dom": "^5.3.4"
30
31
  },
31
32
  "devDependencies": {
@@ -51,5 +52,5 @@
51
52
  "react": "^16.14.0 || ^18.0.0",
52
53
  "react-dom": "^16.14.0 || ^18.0.0"
53
54
  },
54
- "version": "1.0.53"
55
+ "version": "1.0.55"
55
56
  }