@vuu-ui/vuu-utils 2.1.19-beta.1 → 2.1.19-beta.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 (82) hide show
  1. package/package.json +8 -9
  2. package/src/Clock.js +43 -0
  3. package/src/PageVisibilityObserver.js +42 -0
  4. package/src/ScaledDecimal.js +32 -0
  5. package/src/ShellContext.js +5 -0
  6. package/src/ThemeProvider.js +56 -0
  7. package/src/array-utils.js +51 -0
  8. package/src/box-utils.js +51 -0
  9. package/src/broadcast-channel.js +0 -0
  10. package/src/column-utils.js +790 -0
  11. package/src/common-types.js +11 -0
  12. package/src/component-registry.js +83 -0
  13. package/src/context-definitions/DataContext.js +15 -0
  14. package/src/context-definitions/DataProvider.js +13 -0
  15. package/src/context-definitions/DataSourceProvider.js +18 -0
  16. package/src/context-definitions/WorkspaceContext.js +14 -0
  17. package/src/cookie-utils.js +15 -0
  18. package/src/css-utils.js +5 -0
  19. package/src/data-editing/DataEditingProvider.js +13 -0
  20. package/src/data-editing/EditButtons.js +32 -0
  21. package/src/data-editing/EditModeProvider.js +18 -0
  22. package/src/data-editing/EditSession.js +149 -0
  23. package/src/data-editing/edit-utils.js +37 -0
  24. package/src/data-editing/useEditableTable.js +76 -0
  25. package/src/data-utils.js +55 -0
  26. package/src/datasource/BaseDataSource.js +233 -0
  27. package/src/datasource/datasource-action-utils.js +6 -0
  28. package/src/datasource/datasource-filter-utils.js +27 -0
  29. package/src/datasource/datasource-utils.js +148 -0
  30. package/src/date/date-utils.js +80 -0
  31. package/src/date/dateTimePattern.js +17 -0
  32. package/src/date/formatter.js +101 -0
  33. package/src/date/index.js +4 -0
  34. package/src/date/types.js +27 -0
  35. package/src/debug-utils.js +25 -0
  36. package/src/event-emitter.js +78 -0
  37. package/src/feature-utils.js +86 -0
  38. package/src/filters/filter-utils.js +136 -0
  39. package/src/filters/filterAsQuery.js +70 -0
  40. package/src/filters/index.js +2 -0
  41. package/src/form-utils.js +69 -0
  42. package/src/formatting-utils.js +42 -0
  43. package/src/getUniqueId.js +2 -0
  44. package/src/group-utils.js +16 -0
  45. package/src/html-utils.js +108 -0
  46. package/src/index.js +77 -0
  47. package/src/input-utils.js +3 -0
  48. package/src/invariant.js +9 -0
  49. package/src/itemToString.js +9 -0
  50. package/src/json-types.js +0 -0
  51. package/src/json-utils.js +108 -0
  52. package/src/keyboard-utils.js +14 -0
  53. package/src/keyset.js +57 -0
  54. package/src/layout-types.js +0 -0
  55. package/src/list-utils.js +5 -0
  56. package/src/local-storage-utils.js +23 -0
  57. package/src/logging-utils.js +52 -0
  58. package/src/module-utils.js +2 -0
  59. package/src/nanoid/index.js +13 -0
  60. package/src/perf-utils.js +28 -0
  61. package/src/promise-utils.js +26 -0
  62. package/src/protocol-message-utils.js +68 -0
  63. package/src/range-utils.js +109 -0
  64. package/src/react-utils.js +64 -0
  65. package/src/round-decimal.js +83 -0
  66. package/src/row-utils.js +43 -0
  67. package/src/selection-utils.js +25 -0
  68. package/src/shell-layout-types.js +9 -0
  69. package/src/sort-utils.js +75 -0
  70. package/src/table-schema-utils.js +11 -0
  71. package/src/text-utils.js +13 -0
  72. package/src/theme-utils.js +21 -0
  73. package/src/tree-types.js +0 -0
  74. package/src/tree-utils.js +96 -0
  75. package/src/ts-utils.js +6 -0
  76. package/src/typeahead-utils.js +4 -0
  77. package/src/url-utils.js +12 -0
  78. package/src/useId.js +6 -0
  79. package/src/useLayoutEffectSkipFirst.js +9 -0
  80. package/src/useResizeObserver.js +122 -0
  81. package/src/useStateRef.js +21 -0
  82. package/src/user-types.js +0 -0
@@ -0,0 +1,233 @@
1
+ import { parseFilter } from "@vuu-ui/vuu-filter-parser";
2
+ import { EventEmitter } from "../event-emitter.js";
3
+ import { uuid } from "../nanoid/index.js";
4
+ import { isConfigChanged, stripVisualLink, vanillaConfig, withConfigDefaults } from "./datasource-utils.js";
5
+ import { Range } from "../range-utils.js";
6
+ import { filterAsQuery } from "../filters/index.js";
7
+ const defaultSuspenseProps = {
8
+ escalateToDisable: true
9
+ };
10
+ class BaseDataSource extends EventEmitter {
11
+ viewport;
12
+ _clientCallback;
13
+ _configWithVisualLink = vanillaConfig;
14
+ _impendingConfigWithVisualLink = void 0;
15
+ _range = Range(0, 0);
16
+ _size = 0;
17
+ _title;
18
+ _defaultSuspenseProps;
19
+ #freezeTimestamp = void 0;
20
+ #pageCount = 0;
21
+ awaitingConfirmationOfConfigChanges = false;
22
+ constructor({ aggregations, baseFilterSpec, columns, filterSpec, groupBy, sort, suspenseProps = defaultSuspenseProps, title, viewport }){
23
+ super();
24
+ this._configWithVisualLink = {
25
+ ...this._configWithVisualLink,
26
+ aggregations: aggregations || this._configWithVisualLink.aggregations,
27
+ baseFilterSpec: baseFilterSpec || this._configWithVisualLink.baseFilterSpec,
28
+ columns: columns || this._configWithVisualLink.columns,
29
+ filterSpec: filterSpec || this._configWithVisualLink.filterSpec,
30
+ groupBy: groupBy || this._configWithVisualLink.groupBy,
31
+ sort: sort || this._configWithVisualLink.sort
32
+ };
33
+ this._defaultSuspenseProps = suspenseProps;
34
+ this._title = title;
35
+ this.viewport = viewport ?? "";
36
+ }
37
+ subscribe({ baseFilterSpec, columns, aggregations, range, sort, groupBy, filterSpec, viewport = this.viewport || (this.viewport = uuid()) }, callback) {
38
+ this._clientCallback = callback;
39
+ this.viewport = viewport;
40
+ if (aggregations || baseFilterSpec || columns || filterSpec || groupBy || sort) this._configWithVisualLink = {
41
+ ...this._configWithVisualLink,
42
+ aggregations: aggregations || this._configWithVisualLink.aggregations,
43
+ baseFilterSpec: baseFilterSpec || this._configWithVisualLink.baseFilterSpec,
44
+ columns: columns || this._configWithVisualLink.columns,
45
+ filterSpec: filterSpec || this._configWithVisualLink.filterSpec,
46
+ groupBy: groupBy || this._configWithVisualLink.groupBy,
47
+ sort: sort || this._configWithVisualLink.sort
48
+ };
49
+ if (range) {
50
+ this._range = range;
51
+ this.emit("range", range);
52
+ }
53
+ }
54
+ get aggregations() {
55
+ return this._configWithVisualLink.aggregations;
56
+ }
57
+ set aggregations(aggregations) {
58
+ this.config = {
59
+ ...this._configWithVisualLink,
60
+ aggregations
61
+ };
62
+ this.emit("config", this._configWithVisualLink, this.range);
63
+ }
64
+ get baseFilter() {
65
+ return this._configWithVisualLink.baseFilterSpec;
66
+ }
67
+ set baseFilter(baseFilter) {
68
+ this.config = {
69
+ ...this._configWithVisualLink,
70
+ baseFilterSpec: baseFilter
71
+ };
72
+ }
73
+ get columns() {
74
+ return this._configWithVisualLink.columns;
75
+ }
76
+ set columns(columns) {
77
+ this.config = {
78
+ ...this._configWithVisualLink,
79
+ columns
80
+ };
81
+ }
82
+ get filter() {
83
+ return this._configWithVisualLink.filterSpec;
84
+ }
85
+ set filter(filter) {
86
+ this.config = {
87
+ ...this._configWithVisualLink,
88
+ filterSpec: filter
89
+ };
90
+ }
91
+ setFilter(filter) {
92
+ const dataSourceFilter = {
93
+ filter: filterAsQuery(filter),
94
+ filterStruct: filter
95
+ };
96
+ this.filter = dataSourceFilter;
97
+ }
98
+ clearFilter() {
99
+ this.filter = {
100
+ filter: ""
101
+ };
102
+ }
103
+ get isAwaitingConfirmationOfConfigChange() {
104
+ return void 0 !== this._impendingConfigWithVisualLink;
105
+ }
106
+ confirmConfigChange() {
107
+ if (this._impendingConfigWithVisualLink) {
108
+ this._configWithVisualLink = this._impendingConfigWithVisualLink;
109
+ this._impendingConfigWithVisualLink = void 0;
110
+ this.emit("config", this._configWithVisualLink, this.range, true);
111
+ } else throw Error("[BaseDataSource], unexpected call to confirmConfigChange, no changes pending");
112
+ }
113
+ get config() {
114
+ return stripVisualLink(this._impendingConfigWithVisualLink ?? this._configWithVisualLink);
115
+ }
116
+ set config(config) {
117
+ const confirmed = this.awaitingConfirmationOfConfigChanges ? true : void 0;
118
+ this.awaitingConfirmationOfConfigChanges = false;
119
+ const configChanges = this.applyConfig(config);
120
+ if (configChanges) requestAnimationFrame(()=>{
121
+ this.emit("config", this._configWithVisualLink, this.range, confirmed, configChanges);
122
+ });
123
+ }
124
+ get impendingConfig() {
125
+ return this._impendingConfigWithVisualLink;
126
+ }
127
+ set impendingConfig(config) {
128
+ if (config) {
129
+ this.awaitingConfirmationOfConfigChanges = true;
130
+ const configChanges = this.applyConfig(config);
131
+ if (configChanges) this.emit("config", this.config, this.range, false, configChanges);
132
+ } else throw Error("[BaseDataSource] ''unsetting impendingConfig is not currently supported");
133
+ }
134
+ get pageCount() {
135
+ return this.#pageCount;
136
+ }
137
+ set pageCount(pageCount) {
138
+ if (pageCount !== this.#pageCount) {
139
+ this.#pageCount = pageCount;
140
+ this.emit("page-count", pageCount);
141
+ }
142
+ }
143
+ get range() {
144
+ return this._range;
145
+ }
146
+ set range(range) {
147
+ if (range.from !== this._range.from || range.to !== this._range.to) {
148
+ this._range = range;
149
+ this.pageCount = Math.ceil(this._size / (range.to - range.from));
150
+ this.rangeRequest(range.withBuffer);
151
+ requestAnimationFrame(()=>{
152
+ this.emit("range", range);
153
+ });
154
+ }
155
+ }
156
+ get size() {
157
+ return this._size;
158
+ }
159
+ set size(size) {
160
+ this._size = size;
161
+ if (0 !== this.range.to) {
162
+ const pageCount = Math.ceil(size / (this.range.to - this.range.from));
163
+ this.pageCount = pageCount;
164
+ }
165
+ }
166
+ get sort() {
167
+ return this._configWithVisualLink.sort;
168
+ }
169
+ set sort(sort) {
170
+ this.config = {
171
+ ...this._configWithVisualLink,
172
+ sort
173
+ };
174
+ this.emit("config", this._configWithVisualLink, this.range);
175
+ }
176
+ get title() {
177
+ return this._title ?? "";
178
+ }
179
+ set title(title) {
180
+ this._title = title;
181
+ this.emit("title-changed", this.viewport ?? "", title);
182
+ }
183
+ applyConfig(config, preserveExistingConfigAttributes = false) {
184
+ const { noChanges, ...otherChanges } = isConfigChanged(this._configWithVisualLink, config);
185
+ if (true !== noChanges) {
186
+ if (config) {
187
+ const newConfig = config?.filterSpec?.filter && config?.filterSpec.filterStruct === void 0 ? {
188
+ ...config,
189
+ filterSpec: {
190
+ filter: config.filterSpec.filter,
191
+ filterStruct: parseFilter(config.filterSpec.filter)
192
+ }
193
+ } : config;
194
+ if (preserveExistingConfigAttributes) if (this.awaitingConfirmationOfConfigChanges) this._impendingConfigWithVisualLink = {
195
+ ...this._configWithVisualLink,
196
+ ...config
197
+ };
198
+ else {
199
+ this._impendingConfigWithVisualLink = void 0;
200
+ this._configWithVisualLink = {
201
+ ...this._configWithVisualLink,
202
+ ...config
203
+ };
204
+ }
205
+ else if (this.awaitingConfirmationOfConfigChanges) this._impendingConfigWithVisualLink = withConfigDefaults(newConfig);
206
+ else {
207
+ this._impendingConfigWithVisualLink = void 0;
208
+ this._configWithVisualLink = withConfigDefaults(newConfig);
209
+ }
210
+ return otherChanges;
211
+ }
212
+ }
213
+ }
214
+ freeze() {
215
+ if (this.isFrozen) throw Error("[BaseDataSource] cannot freeze, dataSource is already frozen");
216
+ this.#freezeTimestamp = new Date().getTime();
217
+ this.emit("freeze", true, this.#freezeTimestamp);
218
+ }
219
+ unfreeze() {
220
+ if (this.isFrozen) {
221
+ const freezeTimestamp = this.#freezeTimestamp;
222
+ this.#freezeTimestamp = void 0;
223
+ this.emit("freeze", false, freezeTimestamp);
224
+ } else throw Error("[BaseDataSource] cannot freeze, dataSource is already frozen");
225
+ }
226
+ get freezeTimestamp() {
227
+ return this.#freezeTimestamp;
228
+ }
229
+ get isFrozen() {
230
+ return "number" == typeof this.#freezeTimestamp;
231
+ }
232
+ }
233
+ export { BaseDataSource, defaultSuspenseProps };
@@ -0,0 +1,6 @@
1
+ const isVisualLinksAction = (action)=>"vuu-links" === action.type;
2
+ const isVisualLinkCreatedAction = (action)=>"vuu-link-created" === action.type;
3
+ const isVisualLinkRemovedAction = (action)=>"vuu-link-removed" === action.type;
4
+ const isViewportMenusAction = (action)=>"vuu-menu" === action.type;
5
+ const isVuuFeatureAction = (action)=>isViewportMenusAction(action) || isVisualLinksAction(action);
6
+ export { isViewportMenusAction, isVisualLinkCreatedAction, isVisualLinkRemovedAction, isVisualLinksAction, isVuuFeatureAction };
@@ -0,0 +1,27 @@
1
+ import { parseFilter } from "@vuu-ui/vuu-filter-parser";
2
+ const combineFilters = ({ baseFilterSpec, filterSpec, ...config })=>{
3
+ if (void 0 === baseFilterSpec || "" === baseFilterSpec.filter) if (filterSpec.filterStruct || "" === filterSpec.filter) return {
4
+ ...config,
5
+ filterSpec
6
+ };
7
+ else return {
8
+ ...config,
9
+ filterSpec: {
10
+ filter: filterSpec.filter,
11
+ filterStruct: parseFilter(filterSpec.filter)
12
+ }
13
+ };
14
+ {
15
+ const baseFilterQuery = baseFilterSpec.filter;
16
+ const combinedFilter = filterSpec.filter.length > 0 && baseFilterQuery.length > 0 ? `${filterSpec.filter} and ${baseFilterQuery}` : filterSpec.filter || baseFilterQuery;
17
+ const newConfig = {
18
+ ...config,
19
+ filterSpec: {
20
+ filter: combinedFilter,
21
+ filterStruct: combinedFilter.length > 0 ? parseFilter(combinedFilter) : void 0
22
+ }
23
+ };
24
+ return newConfig;
25
+ }
26
+ };
27
+ export { combineFilters };
@@ -0,0 +1,148 @@
1
+ const NoFilter = {
2
+ filter: ""
3
+ };
4
+ const NoSort = {
5
+ sortDefs: []
6
+ };
7
+ const vanillaConfig = {
8
+ aggregations: [],
9
+ columns: [],
10
+ filterSpec: NoFilter,
11
+ groupBy: [],
12
+ sort: NoSort
13
+ };
14
+ const stripVisualLink = (configWithVisualLink)=>{
15
+ if (!configWithVisualLink.visualLink) return configWithVisualLink;
16
+ {
17
+ const { visualLink, ...config } = configWithVisualLink;
18
+ return config;
19
+ }
20
+ };
21
+ const equivalentAggregations = ({ aggregations: agg1 }, { aggregations: agg2 })=>void 0 === agg1 && agg2?.length === 0 || void 0 === agg2 && agg1?.length === 0;
22
+ const equivalentColumns = ({ columns: cols1 }, { columns: cols2 })=>void 0 === cols1 && cols2?.length === 0 || void 0 === cols2 && cols1?.length === 0;
23
+ const equivalentFilter = ({ filterSpec: f1 }, { filterSpec: f2 })=>void 0 === f1 && f2?.filter === "" || void 0 === f2 && f1?.filter === "";
24
+ const equivalentGroupBy = ({ groupBy: val1 }, { groupBy: val2 })=>void 0 === val1 && val2?.length === 0 || void 0 === val2 && val1?.length === 0;
25
+ const equivalentSort = ({ sort: s1 }, { sort: s2 })=>void 0 === s1 && s2?.sortDefs.length === 0 || void 0 === s2 && s1?.sortDefs.length === 0;
26
+ const exactlyTheSame = (a, b)=>{
27
+ if (a === b) return true;
28
+ if (void 0 === a && void 0 === b) return true;
29
+ return false;
30
+ };
31
+ const isAggregationsChanged = (config, newConfig)=>{
32
+ const { aggregations: agg1 } = config;
33
+ const { aggregations: agg2 } = newConfig;
34
+ if (exactlyTheSame(agg1, agg2) || equivalentAggregations(config, newConfig)) return false;
35
+ if (void 0 === agg1 || void 0 === agg2) return true;
36
+ if (agg1.length !== agg2.length) return true;
37
+ return agg1.some(({ column, aggType }, i)=>column !== agg2[i].column || aggType !== agg2[i].aggType);
38
+ };
39
+ const isColumnsChanged = (config, newConfig)=>{
40
+ const { columns: cols1 } = config;
41
+ const { columns: cols2 } = newConfig;
42
+ if (exactlyTheSame(cols1, cols2) || equivalentColumns(config, newConfig)) return false;
43
+ if (void 0 === cols1 || void 0 === cols2) return true;
44
+ if (cols1?.length !== cols2?.length) return true;
45
+ return cols1.some((column, i)=>column !== cols2?.[i]);
46
+ };
47
+ const isBaseFilterChanged = (c1, c2)=>{
48
+ if (equivalentFilter(c1, c2)) return false;
49
+ return c1.baseFilterSpec?.filter !== c2.baseFilterSpec?.filter;
50
+ };
51
+ const isFilterChanged = (c1, c2)=>{
52
+ if (equivalentFilter(c1, c2)) return false;
53
+ return c1.filterSpec?.filter !== c2.filterSpec?.filter;
54
+ };
55
+ const isGroupByChanged = (config, newConfig)=>{
56
+ const { groupBy: g1 } = config;
57
+ const { groupBy: g2 } = newConfig;
58
+ if (exactlyTheSame(g1, g2) || equivalentGroupBy(config, newConfig)) return false;
59
+ if (void 0 === g1 || void 0 === g2) return true;
60
+ if (g1?.length !== g2?.length) return true;
61
+ return g1.some((column, i)=>column !== g2?.[i]);
62
+ };
63
+ const isSortChanged = (config, newConfig)=>{
64
+ const { sort: s1 } = config;
65
+ const { sort: s2 } = newConfig;
66
+ if (exactlyTheSame(s1, s2) || equivalentSort(config, newConfig)) return false;
67
+ if (void 0 === s1 || void 0 === s2) return true;
68
+ if (s1?.sortDefs.length !== s2?.sortDefs.length) return true;
69
+ return s1.sortDefs.some(({ column, sortType }, i)=>column !== s2.sortDefs[i].column || sortType !== s2.sortDefs[i].sortType);
70
+ };
71
+ const isVisualLinkChanged = ({ visualLink: v1 }, { visualLink: v2 })=>{
72
+ if (exactlyTheSame(v1, v2)) return false;
73
+ if (void 0 === v1 || void 0 === v2) return true;
74
+ return v1.label !== v2.label || v2.parentVpId !== v2.parentVpId;
75
+ };
76
+ const NO_CONFIG_CHANGES = {
77
+ aggregationsChanged: false,
78
+ baseFilterChanged: false,
79
+ columnsChanged: false,
80
+ filterChanged: false,
81
+ groupByChanged: false,
82
+ noChanges: true,
83
+ sortChanged: false,
84
+ visualLinkChanged: false
85
+ };
86
+ const isConfigChanged = (config, newConfig)=>{
87
+ if (exactlyTheSame(config, newConfig)) return NO_CONFIG_CHANGES;
88
+ if (void 0 === config && void 0 == newConfig) return NO_CONFIG_CHANGES;
89
+ if (void 0 === config) return isConfigChanged({}, newConfig);
90
+ if (void 0 === newConfig) return isConfigChanged(config, {});
91
+ const aggregationsChanged = isAggregationsChanged(config, newConfig);
92
+ const baseFilterChanged = isBaseFilterChanged(config, newConfig);
93
+ const columnsChanged = isColumnsChanged(config, newConfig);
94
+ const filterChanged = isFilterChanged(config, newConfig);
95
+ const groupByChanged = isGroupByChanged(config, newConfig);
96
+ const sortChanged = isSortChanged(config, newConfig);
97
+ const visualLinkChanged = isVisualLinkChanged(config, newConfig);
98
+ const noChanges = !(aggregationsChanged || baseFilterChanged || columnsChanged || filterChanged || groupByChanged || sortChanged || visualLinkChanged);
99
+ return {
100
+ aggregationsChanged,
101
+ baseFilterChanged,
102
+ columnsChanged,
103
+ filterChanged,
104
+ groupByChanged,
105
+ noChanges,
106
+ sortChanged,
107
+ visualLinkChanged
108
+ };
109
+ };
110
+ const hasGroupBy = (config)=>void 0 !== config && void 0 !== config.groupBy && config.groupBy.length > 0;
111
+ const hasBaseFilter = (config)=>config?.baseFilterSpec !== void 0 && config.baseFilterSpec.filter.length > 0;
112
+ const hasFilter = (config)=>config?.filterSpec !== void 0 && config.filterSpec.filter.length > 0;
113
+ const hasSort = (config)=>config?.sort !== void 0 && Array.isArray(config.sort?.sortDefs) && config.sort.sortDefs.length > 0;
114
+ const isTypeaheadSuggestionProvider = (source)=>"function" == typeof source["getTypeaheadSuggestions"];
115
+ const isTableSchemaMessage = (message)=>"TABLE_META_RESP" === message.type;
116
+ const isConnectionQualityMetrics = (msg)=>"connection-metrics" === msg.type;
117
+ const messageHasResult = (msg)=>void 0 !== msg.result;
118
+ const isVisualLinkMessage = (msg)=>msg.type.endsWith("_VISUAL_LINK");
119
+ const isVisualLinksMessage = (msg)=>"vuu-links" === msg.type;
120
+ const isViewportMessage = (msg)=>"viewport" in msg;
121
+ const messageHasDataRows = (message)=>"viewport-update" === message.type && Array.isArray(message.rows);
122
+ const messageHasSize = (message)=>"viewport-update" === message.type && "number" == typeof message.size;
123
+ const withConfigDefaults = (config)=>{
124
+ if (config.aggregations && config.baseFilterSpec && config.columns && config.filterSpec && config.groupBy && config.sort) return config;
125
+ {
126
+ const { aggregations = [], baseFilterSpec: baseFilter = {
127
+ filter: ""
128
+ }, columns = [], filterSpec: filter = {
129
+ filter: ""
130
+ }, groupBy = [], sort = {
131
+ sortDefs: []
132
+ }, visualLink } = config;
133
+ return {
134
+ aggregations,
135
+ baseFilterSpec: baseFilter,
136
+ columns,
137
+ filterSpec: filter,
138
+ groupBy,
139
+ sort,
140
+ visualLink
141
+ };
142
+ }
143
+ };
144
+ const dataSourceRowToEntity = (row, columnMap)=>Object.entries(columnMap).reduce((entity, [name, index])=>({
145
+ ...entity,
146
+ [name]: row[index]
147
+ }), {});
148
+ export { NO_CONFIG_CHANGES, NoFilter, NoSort, dataSourceRowToEntity, hasBaseFilter, hasFilter, hasGroupBy, hasSort, isBaseFilterChanged, isConfigChanged, isConnectionQualityMetrics, isFilterChanged, isGroupByChanged, isTableSchemaMessage, isTypeaheadSuggestionProvider, isViewportMessage, isVisualLinkMessage, isVisualLinksMessage, messageHasDataRows, messageHasResult, messageHasSize, stripVisualLink, vanillaConfig, withConfigDefaults };
@@ -0,0 +1,80 @@
1
+ import { CalendarDate } from "@internationalized/date";
2
+ function toCalendarDate(d) {
3
+ return new CalendarDate(d.getFullYear(), d.getMonth() + 1, d.getDate());
4
+ }
5
+ const zeroTime = "00:00:00";
6
+ const zeroTimeUnit = "00";
7
+ function incrementTimeUnitValue(unit, value) {
8
+ const num = parseInt(value);
9
+ if ("hours" === unit && num < 23) return `${num + 1}`.padStart(2, "0").slice(-2);
10
+ if ("hours" === unit && 23 === num) return "00";
11
+ if (num < 59) return `${num + 1}`.padStart(2, "0").slice(-2);
12
+ if (59 === num) return "00";
13
+ return value;
14
+ }
15
+ function decrementTimeUnitValue(unit, value) {
16
+ const num = parseInt(value);
17
+ if ("hours" === unit && num > 0) return `${num - 1}`.padStart(2, "0").slice(-2);
18
+ if ("hours" === unit && 0 === num) return "23";
19
+ if (num > 0) return `${num - 1}`.padStart(2, "0").slice(-2);
20
+ if (0 === num) return "59";
21
+ return value;
22
+ }
23
+ function updateTimeString(timeString, unit, value) {
24
+ const newTimeString = "hours" === unit ? value.concat(timeString.slice(2)) : "minutes" === unit ? timeString.slice(0, 3).concat(value).concat(timeString.slice(5)) : timeString.slice(0, 6).concat(value);
25
+ if (isValidTimeString(newTimeString)) return newTimeString;
26
+ throw Error(`[date-utils] udateTimeSting invalid result ${newTimeString}`);
27
+ }
28
+ const validTimePattern = /(?:[0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/;
29
+ const isValidTimeString = (value)=>"string" == typeof value && validTimePattern.test(value);
30
+ function asTimeString(value, allowUndefined = false) {
31
+ if (void 0 === value) if (allowUndefined) return value;
32
+ else throw Error("[date-utils] asTimeString, value cannot be undefined");
33
+ if (isValidTimeString(value)) return value;
34
+ if ("number" == typeof value) return Time.millisToTimeString(value);
35
+ if ("string" == typeof value) {
36
+ const valueAsInt = parseInt(value);
37
+ if (!isNaN(valueAsInt)) return Time.millisToTimeString(valueAsInt);
38
+ } else throw Error(`[date-utils] asTimeString, value ${value} is not valid TimeString`);
39
+ }
40
+ const padZero = (val)=>`${val}`.padStart(2, "0");
41
+ class TimeImpl {
42
+ #hours;
43
+ #minutes;
44
+ #seconds;
45
+ constructor(timeString){
46
+ const [hours, minutes, seconds] = timeString.split(":");
47
+ this.#hours = parseInt(hours);
48
+ this.#minutes = parseInt(minutes);
49
+ this.#seconds = parseInt(seconds);
50
+ }
51
+ get hours() {
52
+ return this.#hours;
53
+ }
54
+ get minutes() {
55
+ return this.#minutes;
56
+ }
57
+ get seconds() {
58
+ return this.#seconds;
59
+ }
60
+ asDate(date) {
61
+ const dt = void 0 === date ? new Date() : "string" == typeof date ? new Date(date) : date;
62
+ dt.setHours(this.#hours);
63
+ dt.setMinutes(this.#minutes);
64
+ dt.setSeconds(this.seconds);
65
+ dt.setMilliseconds(0);
66
+ return dt;
67
+ }
68
+ toString() {
69
+ return Time.toString(this.#hours, this.#minutes, this.#seconds);
70
+ }
71
+ }
72
+ const Time = (timeString)=>new TimeImpl(timeString);
73
+ Time.millisToTimeString = (timestamp)=>new Date(timestamp).toTimeString().slice(0, 8);
74
+ Time.toString = (hours, minutes, seconds)=>`${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`;
75
+ Time.isDateInMillis = (dtInMillis)=>{
76
+ const n = "number" == typeof dtInMillis ? dtInMillis : Number(dtInMillis);
77
+ if (!Number.isFinite(n) || !Number.isInteger(n)) return false;
78
+ return new Date(n).getTime() === n;
79
+ };
80
+ export { Time, asTimeString, decrementTimeUnitValue, incrementTimeUnitValue, isValidTimeString, toCalendarDate, updateTimeString, zeroTime, zeroTimeUnit };
@@ -0,0 +1,17 @@
1
+ import { isTypeDescriptor } from "../column-utils.js";
2
+ import { isDateTimePattern } from "./types.js";
3
+ const defaultPatternsByType = {
4
+ time: "hh:mm:ss",
5
+ date: "dd.mm.yyyy"
6
+ };
7
+ const fallbackDateTimePattern = {
8
+ date: defaultPatternsByType["date"],
9
+ time: defaultPatternsByType["time"]
10
+ };
11
+ function dateTimePattern(type) {
12
+ if (isTypeDescriptor(type)) {
13
+ if (type.formatting && isDateTimePattern(type.formatting.pattern)) return type.formatting.pattern;
14
+ }
15
+ return fallbackDateTimePattern;
16
+ }
17
+ export { dateTimePattern, defaultPatternsByType, fallbackDateTimePattern };
@@ -0,0 +1,101 @@
1
+ import { DateFormatter } from "@internationalized/date";
2
+ const baseTimeFormatOptions = {
3
+ hour: "2-digit",
4
+ minute: "2-digit",
5
+ second: "2-digit"
6
+ };
7
+ const formatConfigByTimePatterns = {
8
+ "hh:mm:ss": {
9
+ locale: "en-GB",
10
+ options: {
11
+ ...baseTimeFormatOptions,
12
+ hour12: false
13
+ }
14
+ },
15
+ "hh:mm:ss a": {
16
+ locale: "en-GB",
17
+ options: {
18
+ ...baseTimeFormatOptions,
19
+ hour12: true
20
+ }
21
+ },
22
+ "hh:mm:ss.ms": {
23
+ locale: "en-GB",
24
+ options: {
25
+ ...baseTimeFormatOptions,
26
+ hour12: false,
27
+ fractionalSecondDigits: 3
28
+ }
29
+ }
30
+ };
31
+ const baseDateFormatOptions = {
32
+ day: "2-digit",
33
+ month: "2-digit",
34
+ year: "numeric"
35
+ };
36
+ const formatConfigByDatePatterns = {
37
+ "dd.mm.yyyy": {
38
+ locale: "de-De",
39
+ options: {
40
+ ...baseDateFormatOptions
41
+ }
42
+ },
43
+ "dd/mm/yyyy": {
44
+ locale: "en-GB",
45
+ options: {
46
+ ...baseDateFormatOptions
47
+ }
48
+ },
49
+ "dd MMM yyyy": {
50
+ locale: "en-GB",
51
+ options: {
52
+ ...baseDateFormatOptions,
53
+ month: "short"
54
+ }
55
+ },
56
+ "dd MMMM yyyy": {
57
+ locale: "en-GB",
58
+ options: {
59
+ ...baseDateFormatOptions,
60
+ month: "long"
61
+ }
62
+ },
63
+ "mm/dd/yyyy": {
64
+ locale: "en-US",
65
+ options: {
66
+ ...baseDateFormatOptions
67
+ }
68
+ },
69
+ "MMM dd, yyyy": {
70
+ locale: "en-US",
71
+ options: {
72
+ ...baseDateFormatOptions,
73
+ month: "short"
74
+ }
75
+ },
76
+ "MMMM dd, yyyy": {
77
+ locale: "en-US",
78
+ options: {
79
+ ...baseDateFormatOptions,
80
+ month: "long"
81
+ }
82
+ }
83
+ };
84
+ const dateFormatterISO = {
85
+ format: (date)=>new Date(date - 60000 * date.getTimezoneOffset()).toISOString().replace(/T.*/, "")
86
+ };
87
+ function getDateFormatter({ locale, options }) {
88
+ return new DateFormatter(locale, options);
89
+ }
90
+ function getDateAndTimeFormatters({ date, time }) {
91
+ const out = [];
92
+ if ("yyyy-mm-dd" === date) out.push(dateFormatterISO);
93
+ else if (date) out.push(getDateFormatter(formatConfigByDatePatterns[date]));
94
+ if (time) out.push(getDateFormatter(formatConfigByTimePatterns[time]));
95
+ return out;
96
+ }
97
+ function formatDate(pattern) {
98
+ const formatters = getDateAndTimeFormatters(pattern);
99
+ return (d)=>formatters.map((f)=>f.format(d)).join(" ");
100
+ }
101
+ export { formatDate, getDateFormatter };
@@ -0,0 +1,4 @@
1
+ export * from "./formatter.js";
2
+ export { Time, asTimeString, decrementTimeUnitValue, incrementTimeUnitValue, isValidTimeString, toCalendarDate, updateTimeString, zeroTime, zeroTimeUnit } from "./date-utils.js";
3
+ export { dateTimePattern, defaultPatternsByType, fallbackDateTimePattern } from "./dateTimePattern.js";
4
+ export { dateTimeLabelByType, isDatePattern, isTimePattern, supportedDateTimePatterns } from "./types.js";
@@ -0,0 +1,27 @@
1
+ const supportedDatePatterns = [
2
+ "yyyy-mm-dd",
3
+ "dd.mm.yyyy",
4
+ "dd/mm/yyyy",
5
+ "dd MMM yyyy",
6
+ "dd MMMM yyyy",
7
+ "mm/dd/yyyy",
8
+ "MMM dd, yyyy",
9
+ "MMMM dd, yyyy"
10
+ ];
11
+ const supportedTimePatterns = [
12
+ "hh:mm:ss",
13
+ "hh:mm:ss a",
14
+ "hh:mm:ss.ms"
15
+ ];
16
+ const supportedDateTimePatterns = {
17
+ date: supportedDatePatterns,
18
+ time: supportedTimePatterns
19
+ };
20
+ const dateTimeLabelByType = {
21
+ date: "Date",
22
+ time: "Time"
23
+ };
24
+ const isDatePattern = (pattern)=>supportedDatePatterns.includes(pattern);
25
+ const isTimePattern = (pattern)=>supportedTimePatterns.includes(pattern);
26
+ const isDateTimePattern = (pattern)=>isDatePattern(pattern?.date) || isTimePattern(pattern?.time);
27
+ export { dateTimeLabelByType, isDatePattern, isDateTimePattern, isTimePattern, supportedDateTimePatterns };
@@ -0,0 +1,25 @@
1
+ import { logger } from "./logging-utils.js";
2
+ const { debug: debug, debugEnabled: debugEnabled } = logger("range-monitor");
3
+ class RangeMonitor {
4
+ source;
5
+ range = {
6
+ from: 0,
7
+ to: 0
8
+ };
9
+ timestamp = 0;
10
+ constructor(source){
11
+ this.source = source;
12
+ }
13
+ isSet() {
14
+ return 0 !== this.timestamp;
15
+ }
16
+ set({ from, to }) {
17
+ const { timestamp } = this;
18
+ this.range.from = from;
19
+ this.range.to = to;
20
+ this.timestamp = performance.now();
21
+ if (!timestamp) return 0;
22
+ debugEnabled && debug(`<${this.source}> [${from}-${to}], ${(this.timestamp - timestamp).toFixed(0)} ms elapsed`);
23
+ }
24
+ }
25
+ export { RangeMonitor };