@tint-ui/data-table 0.3.5

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 (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -0
  3. package/adapters/boolean.d.ts +10 -0
  4. package/adapters/boolean.js +38 -0
  5. package/adapters/index.d.ts +6 -0
  6. package/adapters/index.js +18 -0
  7. package/adapters/number-format.d.ts +1 -0
  8. package/adapters/number-format.js +42 -0
  9. package/adapters/number.d.ts +12 -0
  10. package/adapters/number.js +51 -0
  11. package/adapters/text.d.ts +4 -0
  12. package/adapters/text.js +9 -0
  13. package/cell-adapter-type.d.ts +43 -0
  14. package/cell-adapter-type.js +306 -0
  15. package/cjs/adapters/boolean.js +43 -0
  16. package/cjs/adapters/index.js +21 -0
  17. package/cjs/adapters/number-format.js +46 -0
  18. package/cjs/adapters/number.js +56 -0
  19. package/cjs/adapters/text.js +13 -0
  20. package/cjs/cell-adapter-type.js +312 -0
  21. package/cjs/classes.js +27 -0
  22. package/cjs/context.js +14 -0
  23. package/cjs/data-table-content.js +105 -0
  24. package/cjs/data-table-pagination.js +38 -0
  25. package/cjs/data-table-text-filter.js +83 -0
  26. package/cjs/data-table-toolbar.js +103 -0
  27. package/cjs/data-table-views-options.js +137 -0
  28. package/cjs/data-table.js +63 -0
  29. package/cjs/filter-adapter-type.js +162 -0
  30. package/cjs/filter-adapters/index.js +10 -0
  31. package/cjs/filter-adapters/option.js +152 -0
  32. package/cjs/filter-adapters/use-option-filter.js +195 -0
  33. package/cjs/filter-classes.js +26 -0
  34. package/cjs/filter-fn.js +84 -0
  35. package/cjs/index.js +99 -0
  36. package/cjs/package.json +3 -0
  37. package/cjs/pagination-arrow.js +93 -0
  38. package/cjs/pagination-classes.js +20 -0
  39. package/cjs/pagination-number.js +66 -0
  40. package/cjs/pagination-size-options.js +48 -0
  41. package/cjs/row-button-menu.js +49 -0
  42. package/cjs/row-popover-menu.js +52 -0
  43. package/cjs/toolbar-classes.js +24 -0
  44. package/cjs/types.js +3 -0
  45. package/cjs/use-data-table.js +768 -0
  46. package/cjs/use-lexicon.js +155 -0
  47. package/cjs/use-row-menu.js +60 -0
  48. package/cjs/use-visibility-column.js +105 -0
  49. package/cjs/use-visibility-filter.js +149 -0
  50. package/cjs/utils.js +136 -0
  51. package/classes.d.ts +34 -0
  52. package/classes.js +23 -0
  53. package/context.d.ts +5 -0
  54. package/context.js +9 -0
  55. package/data-table-content.d.ts +9 -0
  56. package/data-table-content.js +98 -0
  57. package/data-table-pagination.d.ts +5 -0
  58. package/data-table-pagination.js +31 -0
  59. package/data-table-text-filter.d.ts +7 -0
  60. package/data-table-text-filter.js +76 -0
  61. package/data-table-toolbar.d.ts +5 -0
  62. package/data-table-toolbar.js +95 -0
  63. package/data-table-views-options.d.ts +2 -0
  64. package/data-table-views-options.js +133 -0
  65. package/data-table.d.ts +18 -0
  66. package/data-table.js +56 -0
  67. package/filter-adapter-type.d.ts +9 -0
  68. package/filter-adapter-type.js +155 -0
  69. package/filter-adapters/index.d.ts +5 -0
  70. package/filter-adapters/index.js +7 -0
  71. package/filter-adapters/option.d.ts +3 -0
  72. package/filter-adapters/option.js +147 -0
  73. package/filter-adapters/use-option-filter.d.ts +27 -0
  74. package/filter-adapters/use-option-filter.js +192 -0
  75. package/filter-classes.d.ts +32 -0
  76. package/filter-classes.js +22 -0
  77. package/filter-fn.d.ts +7 -0
  78. package/filter-fn.js +76 -0
  79. package/index.d.ts +16 -0
  80. package/index.js +16 -0
  81. package/package.json +97 -0
  82. package/pagination-arrow.d.ts +5 -0
  83. package/pagination-arrow.js +86 -0
  84. package/pagination-classes.d.ts +20 -0
  85. package/pagination-classes.js +16 -0
  86. package/pagination-number.d.ts +5 -0
  87. package/pagination-number.js +59 -0
  88. package/pagination-size-options.d.ts +3 -0
  89. package/pagination-size-options.js +44 -0
  90. package/row-button-menu.d.ts +5 -0
  91. package/row-button-menu.js +45 -0
  92. package/row-popover-menu.d.ts +5 -0
  93. package/row-popover-menu.js +48 -0
  94. package/styles-filter.css +1 -0
  95. package/styles-filter.module.css +64 -0
  96. package/styles-filter.module.scss +65 -0
  97. package/styles-pagination.css +1 -0
  98. package/styles-pagination.module.css +28 -0
  99. package/styles-pagination.module.scss +31 -0
  100. package/styles-toolbar.css +1 -0
  101. package/styles-toolbar.module.css +70 -0
  102. package/styles-toolbar.module.scss +67 -0
  103. package/styles.css +1 -0
  104. package/styles.json +8 -0
  105. package/styles.module.css +39 -0
  106. package/styles.module.scss +38 -0
  107. package/toolbar-classes.d.ts +26 -0
  108. package/toolbar-classes.js +20 -0
  109. package/types.d.ts +226 -0
  110. package/types.js +2 -0
  111. package/use-data-table.d.ts +3 -0
  112. package/use-data-table.js +768 -0
  113. package/use-lexicon.d.ts +12 -0
  114. package/use-lexicon.js +151 -0
  115. package/use-row-menu.d.ts +7 -0
  116. package/use-row-menu.js +58 -0
  117. package/use-visibility-column.d.ts +7 -0
  118. package/use-visibility-column.js +101 -0
  119. package/use-visibility-filter.d.ts +7 -0
  120. package/use-visibility-filter.js +145 -0
  121. package/utils.d.ts +14 -0
  122. package/utils.js +128 -0
@@ -0,0 +1,12 @@
1
+ import { DataTableLexicon, LexiconType } from "./types";
2
+ type LexiconReplacementProps = {
3
+ selected: number;
4
+ size: number;
5
+ total: number;
6
+ limit: number;
7
+ offset: number;
8
+ pageNumber: number;
9
+ pageCount: number;
10
+ };
11
+ declare const useLexicon: (customLexicon: Partial<DataTableLexicon>, replacement: LexiconReplacementProps) => LexiconType;
12
+ export { useLexicon };
package/use-lexicon.js ADDED
@@ -0,0 +1,151 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { useApp } from "@tint-ui/app";
5
+ const defaultLexicon = {
6
+ filterClear: "Clear filter",
7
+ filterSelected: "{{ selected }} selected",
8
+ filterNotFound: "Filter options not found",
9
+ filterReset: "Reset filter",
10
+ view: "View",
11
+ viewOptions: "Options",
12
+ viewColumn: "Toggle columns",
13
+ viewSortBy: "Sort By",
14
+ viewFilter: "Filters",
15
+ viewFilterText: "Search...",
16
+ pageFirst: "Go to first page",
17
+ pageLast: "Go to last page",
18
+ pagePrevious: "Go to previous page",
19
+ pageNext: "Go to next page",
20
+ pageOf: "{{ pageNumber }} page of {{ pageCount }}",
21
+ search: "Search...",
22
+ notFound: "Empty data",
23
+ notFoundFiltered: "Records not found",
24
+ title: "{{ size }} row(s) out of {{ total }}",
25
+ onePageTitle: "{{ size }} row(s)",
26
+ selected: "{{ selected }} of {{ size }} row(s) selected"
27
+ };
28
+ const plainKeyList = ["search", "notFound", "notFoundFiltered", "filterClear", "filterReset", "filterNotFound", "view", "viewOptions", "viewFilterText", "viewFilter", "viewSortBy", "viewColumn", "pageFirst", "pageLast", "pagePrevious", "pageNext"];
29
+ const useLexicon = (customLexicon, replacement) => {
30
+ const app = useApp();
31
+ const ref = React.useRef(customLexicon);
32
+ const refReplacement = React.useRef(replacement);
33
+ ref.current = customLexicon;
34
+ refReplacement.current = replacement;
35
+ const lexicon = React.useMemo(() => {
36
+ const defaultText = key => {
37
+ const line = app.line(`dataTable.${key}`);
38
+ if (typeof line === "string") {
39
+ return line;
40
+ }
41
+ return defaultLexicon[key];
42
+ };
43
+ const plain = key => {
44
+ const value = ref.current[key];
45
+ if (!value) {
46
+ return defaultText(key);
47
+ }
48
+ return typeof value === "function" ? value() : value;
49
+ };
50
+ const createPlainFn = key => () => {
51
+ return plain(key);
52
+ };
53
+ const replaceFn = (key, replacement) => {
54
+ const value = ref.current[key] || defaultText(key);
55
+ return typeof value === "function" ? value(replacement) : app.replace(value, replacement);
56
+ };
57
+ const lexicon = {
58
+ filterSearch(label) {
59
+ const value = ref.current.filterSearch;
60
+ if (!value) {
61
+ const line = app.line(`dataTable.filterSearch`);
62
+ if (typeof line === "string") {
63
+ return app.replace(line, {
64
+ label
65
+ });
66
+ }
67
+ return label;
68
+ }
69
+ return typeof value === "function" ? value({
70
+ label
71
+ }) : value;
72
+ },
73
+ filterSelected(selected) {
74
+ return replaceFn("filterSelected", {
75
+ selected
76
+ });
77
+ },
78
+ get pageOf() {
79
+ const {
80
+ pageNumber,
81
+ pageCount
82
+ } = refReplacement.current;
83
+ return replaceFn("pageOf", {
84
+ pageNumber,
85
+ pageCount
86
+ });
87
+ },
88
+ get selected() {
89
+ const {
90
+ size,
91
+ selected
92
+ } = refReplacement.current;
93
+ return replaceFn("selected", {
94
+ size,
95
+ selected
96
+ });
97
+ },
98
+ get onePageTitle() {
99
+ const {
100
+ size
101
+ } = refReplacement.current;
102
+ return replaceFn("onePageTitle", {
103
+ size
104
+ });
105
+ },
106
+ get title() {
107
+ const curr = ref.current;
108
+ const {
109
+ size,
110
+ offset,
111
+ pageCount,
112
+ pageNumber,
113
+ total,
114
+ limit
115
+ } = refReplacement.current;
116
+ if (size === total) {
117
+ let value = curr.onePageTitle;
118
+ if (!value && !curr.title) {
119
+ value = defaultText("onePageTitle");
120
+ }
121
+ if (value) {
122
+ const replacement = {
123
+ size
124
+ };
125
+ return typeof value === "function" ? value(replacement) : app.replace(value, replacement);
126
+ }
127
+ }
128
+ const replacement = {
129
+ size,
130
+ offset,
131
+ total,
132
+ limit,
133
+ pageCount,
134
+ pageNumber
135
+ };
136
+ const value = curr.title || defaultText("title");
137
+ return typeof value === "function" ? value(replacement) : app.replace(value, replacement);
138
+ }
139
+ };
140
+
141
+ // define plain getters
142
+ plainKeyList.forEach(key => {
143
+ Object.defineProperty(lexicon, key, {
144
+ get: createPlainFn(key)
145
+ });
146
+ });
147
+ return lexicon;
148
+ }, [app]);
149
+ return lexicon;
150
+ };
151
+ export { useLexicon };
@@ -0,0 +1,7 @@
1
+ import type { CellContext } from "@tanstack/react-table";
2
+ import type { RowMenuOption } from "./types";
3
+ declare const useRowMenu: <TData>(info: CellContext<TData, unknown>) => (item: Pick<RowMenuOption<TData>, "onClick" | "trigger" | "confirmation" | "enabledKey" | "triggerKey">) => {
4
+ disabled: boolean;
5
+ onClick(): void;
6
+ };
7
+ export { useRowMenu };
@@ -0,0 +1,58 @@
1
+ "use client";
2
+
3
+ import { useTrigger, createTriggerProp } from "@tint-ui/trigger";
4
+ import { useApp } from "@tint-ui/app";
5
+ const useRowMenu = info => {
6
+ const app = useApp();
7
+ const triggerService = useTrigger();
8
+ const data = info.row.original;
9
+ return item => {
10
+ const {
11
+ onClick,
12
+ trigger,
13
+ triggerKey,
14
+ confirmation,
15
+ enabledKey
16
+ } = item;
17
+ const clickHandler = () => {
18
+ if (typeof onClick === "function") {
19
+ onClick(data);
20
+ }
21
+ if (triggerKey) {
22
+ const triggerProp = data[triggerKey];
23
+ if (triggerProp != null) {
24
+ triggerService.emitProp(createTriggerProp(triggerProp));
25
+ }
26
+ }
27
+ if (trigger) {
28
+ const {
29
+ name,
30
+ props
31
+ } = createTriggerProp(trigger);
32
+ triggerService.emit(name, "data" in props ? props : {
33
+ ...props,
34
+ data
35
+ });
36
+ }
37
+ };
38
+ return {
39
+ disabled: enabledKey ? data[enabledKey] === true : false,
40
+ onClick() {
41
+ if (confirmation) {
42
+ const message = app.replace(confirmation, data);
43
+ if (triggerService.registered("dialog:confirm")) {
44
+ triggerService.emit("dialog:confirm", {
45
+ message,
46
+ confirmHandler: clickHandler
47
+ });
48
+ } else if (window.confirm(message)) {
49
+ clickHandler();
50
+ }
51
+ } else {
52
+ clickHandler();
53
+ }
54
+ }
55
+ };
56
+ };
57
+ };
58
+ export { useRowMenu };
@@ -0,0 +1,7 @@
1
+ import type { DataTableDisplayCell } from "./types";
2
+ import type { VisibilityState, OnChangeFn } from "@tanstack/react-table";
3
+ declare const useVisibilityColumn: (name: string, cells: DataTableDisplayCell[], options: {
4
+ storage: string | boolean;
5
+ ssr: boolean;
6
+ }) => [VisibilityState, OnChangeFn<VisibilityState>];
7
+ export { useVisibilityColumn };
@@ -0,0 +1,101 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { onStore } from "./utils.js";
5
+ import { isLocalStorage } from "@tint-ui/tools/browser-support";
6
+ const readState = function (name, storage, readStore, cells) {
7
+ let initialData = {};
8
+ if (readStore) {
9
+ const data = onStore(name, storage, "visibility", (local, name) => {
10
+ const text = local.getItem(name);
11
+ return text && text.startsWith("{") ? JSON.parse(text) : null;
12
+ });
13
+ if (data != null) {
14
+ initialData = data;
15
+ }
16
+ }
17
+ const data = {};
18
+ cells.forEach(item => {
19
+ if (item.invisible) {
20
+ return;
21
+ }
22
+ if (item.required) {
23
+ data[item.name] = true;
24
+ } else {
25
+ const value = initialData[item.name];
26
+ if (value != null) {
27
+ data[item.name] = value;
28
+ } else {
29
+ data[item.name] = !item.hidden;
30
+ }
31
+ }
32
+ });
33
+ return data;
34
+ };
35
+ const useVisibilityColumn = function (name, cells, options) {
36
+ const {
37
+ storage,
38
+ ssr
39
+ } = options;
40
+ const [columnVisibility, setColumnVisibility] = React.useState(() => readState(name, storage, !ssr, cells));
41
+ const ref = React.useRef({
42
+ name,
43
+ storage,
44
+ update(data, fn) {
45
+ const {
46
+ name,
47
+ storage
48
+ } = ref.current;
49
+ onStore(name, storage, "visibility", (local, name) => {
50
+ if (fn) {
51
+ fn(name);
52
+ }
53
+ local.setItem(name, JSON.stringify(data));
54
+ });
55
+ }
56
+ });
57
+ ref.current.name = name;
58
+ ref.current.storage = storage;
59
+ React.useEffect(() => {
60
+ let origin = columnVisibility;
61
+ const data = readState(name, storage, true, cells);
62
+ for (const key in data) {
63
+ if (columnVisibility[key] !== data[key]) {
64
+ origin = data;
65
+ setColumnVisibility(origin);
66
+ break;
67
+ }
68
+ }
69
+ if (!storage || !isLocalStorage()) {
70
+ return;
71
+ }
72
+ let storeKey = "";
73
+ ref.current.update(origin, name => {
74
+ storeKey = name;
75
+ });
76
+ if (storeKey.length) {
77
+ const fn = event => {
78
+ if (event.key === storeKey && event.newValue != null) {
79
+ const data = JSON.parse(event.newValue);
80
+ setColumnVisibility(data);
81
+ ref.current.update(data);
82
+ }
83
+ };
84
+ window.addEventListener("storage", fn);
85
+ return () => {
86
+ window.removeEventListener("storage", fn);
87
+ };
88
+ }
89
+ }, [name, storage, ssr, cells]);
90
+ const columnVisibilityHandler = React.useCallback(data => {
91
+ setColumnVisibility(prevState => {
92
+ if (typeof data === "function") {
93
+ data = data(prevState);
94
+ }
95
+ ref.current.update(data);
96
+ return data;
97
+ });
98
+ }, [setColumnVisibility]);
99
+ return [columnVisibility, columnVisibilityHandler];
100
+ };
101
+ export { useVisibilityColumn };
@@ -0,0 +1,7 @@
1
+ import type { DataTableDisplayFilter, FilterVisibility } from "./types";
2
+ declare const useVisibilityFilter: <TData extends object>(name: string, filters: DataTableDisplayFilter<keyof TData, any>[], filterText: boolean, options: {
3
+ storage: boolean | string;
4
+ ssr: boolean;
5
+ requiredFilterText?: boolean;
6
+ }) => FilterVisibility<TData>;
7
+ export { useVisibilityFilter };
@@ -0,0 +1,145 @@
1
+ import * as React from "react";
2
+ import { onStore } from "./utils.js";
3
+ import { isLocalStorage } from "@tint-ui/tools/browser-support";
4
+ const readState = function (name, storage, readStore, filters, filterText, requiredFilterText) {
5
+ const data = {
6
+ filterText,
7
+ filters: {}
8
+ };
9
+ filters.forEach(filter => {
10
+ data.filters[filter.name] = filter.required || !filter.hidden;
11
+ });
12
+ if (readStore) {
13
+ const localData = onStore(name, storage, "filtering", (local, name) => {
14
+ const text = local.getItem(name);
15
+ return text && text.startsWith("{") ? JSON.parse(text) : null;
16
+ });
17
+ if (localData != null) {
18
+ data.filterText = filterText && localData.filterText;
19
+ const latest = localData.filters || {};
20
+ filters.forEach(({
21
+ required,
22
+ name
23
+ }) => {
24
+ const value = latest[name];
25
+ if (!required && typeof value === "boolean") {
26
+ data.filters[name] = value;
27
+ }
28
+ });
29
+ }
30
+ }
31
+ if (filterText && requiredFilterText) {
32
+ data.filterText = true;
33
+ }
34
+ return data;
35
+ };
36
+ const useVisibilityFilter = function (name, filters, filterText, options) {
37
+ const {
38
+ storage,
39
+ ssr,
40
+ requiredFilterText = false
41
+ } = options;
42
+ const [filteringState, setFilteringState] = React.useState(() => readState(name, storage, !ssr, filters, filterText, requiredFilterText));
43
+ const ref = React.useRef(filteringState);
44
+ ref.current = filteringState;
45
+ const refUpdate = React.useRef((data, fn) => {
46
+ onStore(name, storage, "filtering", (local, name) => {
47
+ if (fn) {
48
+ fn(name);
49
+ }
50
+ local.setItem(name, JSON.stringify(data));
51
+ });
52
+ });
53
+ React.useEffect(() => {
54
+ const data = readState(name, storage, true, filters, filterText, requiredFilterText);
55
+ const compare = () => {
56
+ for (const name in data.filters) {
57
+ if (data.filters[name] !== filteringState.filters[name]) {
58
+ return false;
59
+ }
60
+ }
61
+ return true;
62
+ };
63
+ if (filteringState.filterText !== data.filterText || !compare()) {
64
+ setFilteringState(data);
65
+ }
66
+ if (!storage || !isLocalStorage()) {
67
+ return;
68
+ }
69
+ let storeKey = "";
70
+ refUpdate.current(data, name => {
71
+ storeKey = name;
72
+ });
73
+ if (storeKey.length) {
74
+ const fn = event => {
75
+ if (event.key === storeKey && event.newValue != null) {
76
+ const data = JSON.parse(event.newValue);
77
+ setFilteringState(data);
78
+ refUpdate.current(data);
79
+ }
80
+ };
81
+ window.addEventListener("storage", fn);
82
+ return () => {
83
+ window.removeEventListener("storage", fn);
84
+ };
85
+ }
86
+ }, [name, storage, ssr]);
87
+ const {
88
+ getFilters,
89
+ getVisibleFilters,
90
+ hasFilterVisible,
91
+ onFilterVisibleChange,
92
+ onFilterTextVisibleChange
93
+ } = React.useMemo(() => {
94
+ return {
95
+ getFilters() {
96
+ return filters;
97
+ },
98
+ getVisibleFilters() {
99
+ return filters.filter(item => ref.current.filters[item.name] === true);
100
+ },
101
+ hasFilterVisible(name) {
102
+ return ref.current.filters[name] === true;
103
+ },
104
+ onFilterVisibleChange: (name, visible) => {
105
+ const filter = filters.find(item => item.name === name);
106
+ if (!filter || filter.required || ref.current.filters[name] === visible) {
107
+ return;
108
+ }
109
+ setFilteringState(prev => {
110
+ const state = {
111
+ filterText: prev.filterText,
112
+ filters: {
113
+ ...prev.filters,
114
+ [name]: visible
115
+ }
116
+ };
117
+ refUpdate.current(state);
118
+ return state;
119
+ });
120
+ },
121
+ onFilterTextVisibleChange: visible => {
122
+ if (!filterText || requiredFilterText || ref.current.filterText === visible) {
123
+ return;
124
+ }
125
+ setFilteringState(prev => {
126
+ const state = {
127
+ filterText: !prev.filterText,
128
+ filters: prev.filters
129
+ };
130
+ refUpdate.current(state);
131
+ return state;
132
+ });
133
+ }
134
+ };
135
+ }, [filters, filterText, requiredFilterText]);
136
+ return {
137
+ filterText: filteringState.filterText,
138
+ getVisibleFilters,
139
+ getFilters,
140
+ hasFilterVisible,
141
+ onFilterVisibleChange,
142
+ onFilterTextVisibleChange
143
+ };
144
+ };
145
+ export { useVisibilityFilter };
package/utils.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import type { NavbarConfig, ToolbarConfig } from "./types";
2
+ import type { ColumnFilter } from "@tanstack/react-table";
3
+ declare const onStore: <T = unknown>(name: string, storage: string | boolean, type: string, fn: (storage: Storage, name: string) => T) => T | null;
4
+ declare const getToolbarConfig: (config: null | undefined | Partial<Omit<ToolbarConfig, "onFilterReset">>) => Omit<ToolbarConfig, "onFilterReset">;
5
+ declare const getNavbarConfig: (config: null | undefined | Partial<Omit<NavbarConfig, "onPageSizeChange">>, defaultPageSize: number) => Omit<NavbarConfig, "onPageSizeChange">;
6
+ declare const getPaginationNumber: (pageNumber: number, pageCount: number, left: number) => ({
7
+ divider: true;
8
+ } | {
9
+ divider: false;
10
+ page: number;
11
+ selected: boolean;
12
+ })[];
13
+ declare const diffFilterId: (left: ColumnFilter[], right: ColumnFilter[]) => string;
14
+ export { onStore, getToolbarConfig, getNavbarConfig, getPaginationNumber, diffFilterId };
package/utils.js ADDED
@@ -0,0 +1,128 @@
1
+ import { isLocalStorage } from "@tint-ui/tools/browser-support";
2
+ const onStore = (name, storage, type, fn) => {
3
+ if (!storage || !isLocalStorage()) {
4
+ return null;
5
+ }
6
+ let key = `table:${name}:${type}`;
7
+ if (typeof storage === "string") {
8
+ key += `-${storage}`;
9
+ }
10
+ try {
11
+ return fn(window.localStorage, key);
12
+ } catch (err) {
13
+ console.error("Window storage failure", err);
14
+ }
15
+ return null;
16
+ };
17
+ const defaultSize = "md";
18
+ const getToolbarConfig = config => {
19
+ const {
20
+ size = defaultSize,
21
+ viewIconOnly = false,
22
+ resetIconOnly = false
23
+ } = config || {};
24
+ return {
25
+ size,
26
+ viewIconOnly,
27
+ resetIconOnly
28
+ };
29
+ };
30
+ const getNavbarConfig = (config, defaultPageSize) => {
31
+ const {
32
+ size = defaultSize,
33
+ numberSize = 2,
34
+ pageSize = defaultPageSize,
35
+ pageSizeOptions,
36
+ mode = "arrow"
37
+ } = config || {};
38
+ return {
39
+ size,
40
+ mode,
41
+ pageSize,
42
+ numberSize,
43
+ pageSizeOptions: Array.isArray(pageSizeOptions) && pageSizeOptions.length > 0 ? pageSizeOptions : [pageSize]
44
+ };
45
+ };
46
+ const getPaginationNumber = (pageNumber, pageCount, left) => {
47
+ if (pageCount < 2) {
48
+ return [];
49
+ }
50
+ const items = [];
51
+ const dots = left * 2 + 1 < pageCount;
52
+ const push = pg => {
53
+ if (pg === 0) {
54
+ items.push({
55
+ divider: true
56
+ });
57
+ } else {
58
+ items.push({
59
+ divider: false,
60
+ page: pg,
61
+ selected: pg === pageNumber
62
+ });
63
+ }
64
+ };
65
+ let start = pageNumber - left;
66
+ let end = pageNumber + left;
67
+ if (start < 1) {
68
+ start = 1;
69
+ end = left * 2 + 1;
70
+ }
71
+ if (end > pageCount) {
72
+ end = pageCount;
73
+ start = end - left * 2;
74
+ if (start < 1) {
75
+ start = 1;
76
+ }
77
+ }
78
+ if (start > 1) {
79
+ push(1);
80
+ dots && start > 2 && push(0);
81
+ }
82
+ for (let i = start; i <= end; i++) {
83
+ push(i);
84
+ }
85
+ if (end < pageCount) {
86
+ dots && end + 1 < pageCount && push(0);
87
+ push(pageCount);
88
+ }
89
+ return items;
90
+ };
91
+ const diffCompare = (a, b) => {
92
+ if (Array.isArray(a)) {
93
+ a = a.join(",");
94
+ }
95
+ if (Array.isArray(b)) {
96
+ b = b.join(",");
97
+ }
98
+ return a === b;
99
+ };
100
+ const diffFilterId = (left, right) => {
101
+ const rightData = {};
102
+ for (const {
103
+ id,
104
+ value
105
+ } of right) {
106
+ rightData[id] = value;
107
+ }
108
+ const leftData = {};
109
+ for (const {
110
+ id,
111
+ value
112
+ } of left) {
113
+ if (leftData[id] == null) {
114
+ return id;
115
+ }
116
+ leftData[id] = value;
117
+ }
118
+ for (const {
119
+ id,
120
+ value
121
+ } of right) {
122
+ if (leftData[id] == null || !diffCompare(leftData[id], value)) {
123
+ return id;
124
+ }
125
+ }
126
+ return "*";
127
+ };
128
+ export { onStore, getToolbarConfig, getNavbarConfig, getPaginationNumber, diffFilterId };