@lexriver/dome 2.0.2 → 2.0.4

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 (43) hide show
  1. package/out/index.cjs +994 -0
  2. package/out/index.mjs +2164 -0
  3. package/out/src/AnimatedArray.d.ts +29 -0
  4. package/out/src/AnimatedTable.d.mts +2 -1
  5. package/out/src/AnimatedTable.d.ts +39 -0
  6. package/out/src/AnimatedTable.mjs +2 -1
  7. package/out/src/AnimatedText.d.mts +1 -1
  8. package/out/src/AnimatedText.d.ts +13 -0
  9. package/out/src/AnimatedText.mjs +1 -1
  10. package/out/src/Animation.d.ts +4 -0
  11. package/out/src/Dome.d.ts +9 -0
  12. package/out/src/Dome.mjs +1 -1
  13. package/out/src/DomeComponent.d.ts +25 -0
  14. package/out/src/DomeManipulator.d.ts +52 -0
  15. package/out/src/DomeRouter.d.ts +32 -0
  16. package/out/src/LongestCommonSubsequence.d.ts +15 -0
  17. package/out/src/index.d.mts +5 -1
  18. package/out/src/index.d.ts +15 -0
  19. package/out/src/index.mjs +5 -1
  20. package/package.json +21 -3
  21. package/out/src/DomeRouter.console-test.d.mts +0 -1
  22. package/out/src/DomeRouter.console-test.mjs +0 -44
  23. package/out/src/concurrent-updates.test.d.mts +0 -1
  24. package/out/src/concurrent-updates.test.mjs +0 -203
  25. package/out/src/temp-test.d.mts +0 -1
  26. package/out/src/temp-test.mjs +0 -20
  27. package/out/vitest.config.d.ts +0 -2
  28. package/out/vitest.config.js +0 -9
  29. package/src/AnimatedArray.mts +0 -74
  30. package/src/AnimatedTable.mts +0 -120
  31. package/src/AnimatedText.mts +0 -30
  32. package/src/Animation.mts +0 -4
  33. package/src/Dome.mts +0 -346
  34. package/src/DomeComponent.mts +0 -84
  35. package/src/DomeManipulator.mts +0 -391
  36. package/src/DomeRouter.console-test.mts +0 -52
  37. package/src/DomeRouter.mts +0 -287
  38. package/src/LongestCommonSubsequence.mts +0 -201
  39. package/src/concurrent-updates.test.mts +0 -252
  40. package/src/index.mts +0 -12
  41. package/src/temp-test.mts +0 -23
  42. package/tsconfig.json +0 -59
  43. package/vitest.config.ts +0 -10
@@ -1,287 +0,0 @@
1
- import { DomeManipulator } from "./DomeManipulator.mjs"
2
-
3
- // const filename = '[DomeRouter]'
4
-
5
- export type RouteAction = (
6
- params:{[key:string]:string|number},
7
- url:string,
8
- scrollToPreviousPositionAsync:()=>Promise<void>,
9
- query:{[key:string]:string}
10
- ) => void|Promise<void>
11
-
12
- interface Route{
13
- routeSlices:string[]
14
- exactMatch:boolean
15
- action:RouteAction
16
- }
17
-
18
- interface HistoryUrl{
19
- url:string
20
- scroll:number
21
- }
22
-
23
- export namespace DomeRouter {
24
- const historyUrls:HistoryUrl[] = []
25
- const scrollPositionByUrl = new Map<string, number>()
26
- export let maxHistoryUrlsCount:number = 20
27
- const allRoutes:Route[] = []
28
- let onNotFoundAction:(()=>void)|undefined = undefined
29
-
30
- window.addEventListener('popstate', async (e) => {
31
- // on go back/forward
32
- //console.log(filename, 'window.popstate event', e, 'historyUrls=', historyUrls)
33
- const url = window.location.pathname
34
- await executeAsync(url, getScrollPositionForUrl(url) )
35
-
36
- await DomeManipulator.scrollToAsync({
37
- pxFromTop: getScrollPositionForUrl(window.location.pathname)
38
- })
39
- })
40
-
41
- function getScrollPositionForUrl(url:string){
42
- return scrollPositionByUrl.get(url) ?? 0
43
- }
44
-
45
- function saveScrollPositionForUrl(url:string){
46
- scrollPositionByUrl.set(url, DomeManipulator.getCurrentScrollPosition())
47
- }
48
-
49
- function saveScrollPositionForCurrentUrl(){
50
- scrollPositionByUrl.set(getCurrentUrl(), DomeManipulator.getCurrentScrollPosition())
51
- }
52
-
53
- export function navigate(url:string){
54
- addUrlToHistory(getCurrentUrl())
55
- saveScrollPositionForCurrentUrl()
56
- window.history.pushState(null, '', url)
57
- executeAsync(url, 0)
58
- DomeManipulator.scrollToTop()
59
- // historyUrls.push()
60
- }
61
-
62
- export function goBack(){
63
- window.history.go(-1)
64
- }
65
-
66
- export function goForward(){
67
- window.history.go(+1)
68
- }
69
-
70
- export function changeUrl(url:string){
71
- window.history.replaceState(null, '', url)
72
- // if(historyUrls.length>0){
73
- // historyUrls[historyUrls.length-1].url = url
74
- // }
75
- }
76
-
77
- function addUrlToHistory(url:string){
78
- historyUrls.push({url, scroll: 0})
79
- while(historyUrls.length>maxHistoryUrlsCount){
80
- historyUrls.shift()
81
- }
82
-
83
- // save scroll position to previous url
84
- if(historyUrls.length>1){
85
- historyUrls[historyUrls.length-2].scroll = DomeManipulator.getCurrentScrollPosition()
86
- }
87
-
88
- // console.log('adding url to history', url)
89
- // console.log('historyUrls=', historyUrls)
90
- }
91
-
92
-
93
-
94
- export function getCurrentUrl(){
95
- return window.location.pathname
96
- // return historyUrls.length>0?historyUrls[historyUrls.length-1]:window.location.pathname
97
- }
98
-
99
- /**
100
- * get previous page url navigated by router
101
- * @param previousPageIndex 0=previousPage, 1=previousPage-1, etc
102
- */
103
- export function getPreviousPageUrl(previousPageIndex:number=0):string|undefined{
104
- //if(historyUrls.length==0) return undefined
105
- let index = historyUrls.length-2-previousPageIndex
106
- if(index >= 0 && index < historyUrls.length) return historyUrls[index].url
107
- return undefined
108
- }
109
-
110
- // export function reloadCurrentPage(addToHistory:boolean = false){
111
- // const url = window.location.pathname
112
- // if(addToHistory) addUrlToHistory(url)
113
- // executeAsync(url, getScrollPositionForUrl(url)) // TODO: check
114
- // }
115
-
116
- export function resolveUrl(url:string = window.location.pathname, addToHistory = true){
117
- if(addToHistory) addUrlToHistory(window.location.pathname)
118
- executeAsync(url, getScrollPositionForUrl(url))
119
- }
120
-
121
- export function onRoute(route:string, exactMatch:boolean, action:RouteAction){
122
- if(route[0] !== '/') throw new Error('Please provide correct route. route='+route)
123
- let routeSlices = getRouteSlices(route)
124
- allRoutes.push({routeSlices, exactMatch, action})
125
- }
126
-
127
- function getRouteSlices(route:string){
128
- //return route.split('/').filter(x => x.length>0).map(x => decodeURIComponent(x))
129
- return route.split('/').map(x => decodeURIComponent(x))
130
- }
131
-
132
- export function onNotFound(action:()=>void){
133
- onNotFoundAction = action
134
- }
135
-
136
- /**
137
- * Check if url matched route.
138
- * example: /get-product/445345, /get-product/:productId, true ==> Map([productId:445345])
139
- * example: /get-product/123, /another-route, true ==> undefined
140
- * example: /articles, /articles, true ==> Map()
141
- * example: /articles/some-article, /articles, false ==> Map()
142
- * @param url
143
- * @param route
144
- * @param exactMatch
145
- */
146
- export function checkUrlMatchRouteAndGetParameters(url:string, route:string, exactMatch:boolean = true):Object|undefined{
147
- // this function is purely for export
148
-
149
- const urlSlices = getRouteSlices(url)
150
- const routeSlices = getRouteSlices(route)
151
- if(exactMatch && routeSlices.length !== urlSlices.length) return undefined
152
- // all routeSlices must match for !exactMatch
153
- //const extractedParameters = new Map<string,string>()
154
- const extractedParameters = {}
155
- for(let i=0;i<routeSlices.length;i++){
156
- let cRouteSlice = routeSlices[i]
157
- let cUrlSlice = urlSlices[i] // could be undefined
158
- //console.info('\t\t cRouteSlice=', cRouteSlice, 'cUrlSlice=', cUrlSlice)
159
-
160
- if(cRouteSlice.startsWith(':')){
161
- // we have a param name
162
- if(cUrlSlice === undefined){
163
- return undefined
164
- }
165
-
166
- const [name, value] = parseToNameAndValue(cRouteSlice, cUrlSlice)
167
- extractedParameters[name] = value
168
-
169
-
170
- } else {
171
- // no param name
172
- if(cRouteSlice !== cUrlSlice){
173
- return undefined
174
- }
175
- }
176
- }
177
- return extractedParameters
178
- }
179
-
180
- /**
181
- * parse name with type or without type
182
- * :quantity
183
- * :quantity<number>
184
- * :quantity<float>
185
- * :quantity<int>
186
- *
187
- * @param name string that starts with `:`
188
- * @param value string that contains value
189
- */
190
- function parseToNameAndValue(name:string, value:string):[string,string|number]{
191
- if(!name) throw new Error('no name')
192
-
193
- // parse name with type
194
- // :quantity<number>
195
- // :lat<float>
196
- // :count<int>
197
- const haveMatch = name.match(/:(.+)<(.+)>/)
198
- if(haveMatch){
199
- const paramName = haveMatch[1]
200
- const paramType = haveMatch[2].toLowerCase()
201
- if(paramType == 'int'){
202
- return [paramName, parseInt(value)]
203
-
204
- } else if(paramType == 'float'){
205
- return [paramName, parseFloat(value)]
206
-
207
- } else if(paramType == 'number'){
208
- return [paramName, Number(value)]
209
-
210
- } else {
211
- return [paramName, value]
212
- }
213
- } else {
214
- return [name.substring(1), value]
215
- }
216
-
217
- }
218
-
219
- function parseQueryString(search:string):{[key:string]:string}{
220
- const query:{[key:string]:string} = {}
221
- if(!search || search[0] !== '?') return query
222
- const params = new URLSearchParams(search.substring(1))
223
- for(const [key, value] of params.entries()){
224
- query[key] = value
225
- }
226
- return query
227
- }
228
-
229
- async function executeAsync(url:string = window.location.pathname, scrollToPosition:number){
230
- const queryString = window.location.search
231
- const query = parseQueryString(queryString)
232
- url = url.split('?')[0] // Strip query params
233
- //const url = window.location.pathname
234
- const urlSlices = getRouteSlices(url)
235
- // urlSlices = show, category, 345
236
- let countOfFoundRoutes = 0
237
- for(let route of allRoutes){
238
- //console.info('\t route=', route.routeSlices, route.exactMatch)
239
- // route.routeSlices = show, category, :categoryId
240
- if(route.exactMatch && route.routeSlices.length != urlSlices.length) continue
241
-
242
- // all routeSlices must match for !exactMatch
243
- let matched:boolean = true
244
- //let extractedParameters = new Map<string,string>()
245
- const extractedParameters = {}
246
- for(let i=0;i<route.routeSlices.length;i++){
247
- let cRouteSlice = route.routeSlices[i]
248
- let cUrlSlice = urlSlices[i] // could be undefined
249
- //console.info('\t\t cRouteSlice=', cRouteSlice, 'cUrlSlice=', cUrlSlice)
250
-
251
- if(cRouteSlice && typeof cRouteSlice === 'string' && cRouteSlice.startsWith(':')){
252
- // we have a param name
253
- if(cUrlSlice === undefined){
254
- matched = false
255
- continue
256
- }
257
- // we have some variable, save it
258
- const [name, value] = parseToNameAndValue(cRouteSlice, cUrlSlice)
259
- extractedParameters[name] = value
260
-
261
- } else {
262
- // no param name
263
- if(cRouteSlice !== cUrlSlice){
264
- matched = false
265
- continue
266
- }
267
- }
268
- }
269
- if(matched){
270
- countOfFoundRoutes++
271
- //console.log('DomeRouter', 'executeAsync', url, route, extractedParameters)
272
- await route.action(extractedParameters, url, async () => {
273
- await DomeManipulator.scrollToAsync({
274
- pxFromTop: scrollToPosition
275
- })
276
- }, query)
277
- }
278
- }
279
- if(countOfFoundRoutes==0 && onNotFoundAction){
280
- //console.log('DomeRouter', 'onNotFoundAction()')
281
- onNotFoundAction()
282
- }
283
- }
284
- }
285
-
286
-
287
-
@@ -1,201 +0,0 @@
1
- export module LongestCommonSubsequence {
2
- // https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequence
3
- export function getLongestCommonSubsequence(set1: string[], set2: string[]) {
4
- // Init LCS matrix.
5
- const lcsMatrix = Array(set2.length + 1).fill(null).map(() => Array(set1.length + 1).fill(null));
6
-
7
- // Fill first row with zeros.
8
- for (let columnIndex = 0; columnIndex <= set1.length; columnIndex += 1) {
9
- lcsMatrix[0][columnIndex] = 0;
10
- }
11
-
12
- // Fill first column with zeros.
13
- for (let rowIndex = 0; rowIndex <= set2.length; rowIndex += 1) {
14
- lcsMatrix[rowIndex][0] = 0;
15
- }
16
-
17
- // Fill rest of the column that correspond to each of two strings.
18
- for (let rowIndex = 1; rowIndex <= set2.length; rowIndex += 1) {
19
- for (let columnIndex = 1; columnIndex <= set1.length; columnIndex += 1) {
20
- if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
21
- lcsMatrix[rowIndex][columnIndex] = lcsMatrix[rowIndex - 1][columnIndex - 1] + 1;
22
- } else {
23
- lcsMatrix[rowIndex][columnIndex] = Math.max(
24
- lcsMatrix[rowIndex - 1][columnIndex],
25
- lcsMatrix[rowIndex][columnIndex - 1],
26
- );
27
- }
28
- }
29
- }
30
-
31
- // Calculate LCS based on LCS matrix.
32
- if (!lcsMatrix[set2.length][set1.length]) {
33
- // If the length of largest common string is zero then return empty string.
34
- return [''];
35
- }
36
-
37
- const longestSequence:string[] = [];
38
- let columnIndex = set1.length;
39
- let rowIndex = set2.length;
40
-
41
- while (columnIndex > 0 || rowIndex > 0) {
42
- if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
43
- // Move by diagonal left-top.
44
- longestSequence.unshift(set1[columnIndex - 1]);
45
- columnIndex -= 1;
46
- rowIndex -= 1;
47
- } else if (lcsMatrix[rowIndex][columnIndex] === lcsMatrix[rowIndex][columnIndex - 1]) {
48
- // Move left.
49
- columnIndex -= 1;
50
- } else {
51
- // Move up.
52
- rowIndex -= 1;
53
- }
54
- }
55
-
56
- return longestSequence;
57
- }
58
-
59
- export function getPatch({ oldArray, newArray, onRemove, onAdd }: {
60
- oldArray: string[]
61
- newArray: string[]
62
- onRemove: (index: number, item: string) => void
63
- onAdd: (index: number, item: string) => void
64
- }){
65
- const lcsArray = getLongestCommonSubsequence(oldArray, newArray)
66
-
67
- let countOfOperations = 0
68
-
69
- // console.log('oldArray=', oldArray.join(' '))
70
- // console.log('newArray=', newArray.join(' '))
71
- // console.log('lcsArray=', lcsArray.join(' '))
72
-
73
- // old: A B B B C
74
- // new: X X B B B B C
75
- // lcs: B B B C
76
-
77
- //let lcsStartIndexForOld = 0
78
- //let lcsStartIndexForNew = 0
79
- let lcsIndex = 0
80
- //let newIndex = 0
81
-
82
-
83
- for(let oldIndex = 0; oldIndex < oldArray.length; oldIndex++){
84
- let oldItem = oldArray[oldIndex]
85
- //let oldItemInLcs = itemInArray(oldItem, lcsArray, lcsStartIndexForOld)
86
- let oldItemInLcs = lcsArray[lcsIndex] == oldItem
87
- //console.log('oldIndex=', oldIndex, 'oldItem=', oldItem, 'in LCS=', oldItemInLcs)
88
- if(oldItemInLcs){
89
- //lcsStartIndexForOld++
90
- lcsIndex++
91
- // so we must keep this element
92
- //continue
93
- } else {
94
- onRemove(oldIndex-countOfOperations, oldItem)
95
- //indexForOperation++
96
- countOfOperations++
97
- }
98
- }
99
-
100
- lcsIndex = 0
101
-
102
- for(let newIndex = 0; newIndex < newArray.length; newIndex++){
103
- let newItem = newArray[newIndex]
104
- //let newItemInLcs = itemInArray(newItem, lcsArray, lcsStartIndexForNew)
105
- let newItemInLcs = lcsArray[lcsIndex] == newItem
106
- if(newItemInLcs){
107
- lcsIndex++
108
- //lcsStartIndexForNew++
109
- //keep
110
- } else {
111
- onAdd(newIndex, newItem)
112
- countOfOperations++
113
- }
114
- }
115
-
116
-
117
- return countOfOperations
118
-
119
-
120
- }
121
-
122
- export function getPatchOrdered({ oldArray, newArray, onRemove, onAdd }: {
123
- oldArray: string[]
124
- newArray: string[]
125
- onRemove: (index: number, item: string) => void
126
- onAdd: (index: number, item: string) => void
127
- }){
128
-
129
- const lcsArray = getLongestCommonSubsequence(oldArray, newArray)
130
-
131
-
132
-
133
- //let countOfOperations = 0
134
-
135
- // console.log('oldArray=', oldArray.join(' '))
136
- // console.log('newArray=', newArray.join(' '))
137
- // console.log('lcsArray=', lcsArray.join(' '))
138
-
139
- // old: A B B B C
140
- // new: X X B B B B C
141
- // lcs: B B B C
142
-
143
- let lcsIndexForOld = 0
144
- let lcsIndexForNew = 0
145
- //let lcsIndex = 0
146
- let oldIndex = 0
147
- let newIndex = 0
148
- let countOfRemoveOperations = 0
149
- let countOfAddOperations = 0
150
- let indexForOperation = 0
151
-
152
- while(oldIndex < oldArray.length || newIndex < newArray.length){
153
- while(oldIndex < oldArray.length){
154
- let oldItem = oldArray[oldIndex]
155
- //let oldItemInLcs = itemInArray(oldItem, lcsArray, lcsStartIndexForOld)
156
- let oldItemInLcs = lcsArray[lcsIndexForOld] == oldItem
157
- //console.log('oldItem', oldIndex, oldItem, oldItemInLcs)
158
- if(oldItemInLcs){
159
-
160
- //lcsStartIndexForNew++
161
- //lcsStartIndexForOld++
162
- lcsIndexForOld++
163
- //indexForOperation++
164
- oldIndex++
165
- break
166
- } else {
167
- //onRemove(oldIndex-countOfRemoveOperations, oldItem)
168
- onRemove(indexForOperation, oldItem)
169
- countOfRemoveOperations++
170
- oldIndex++
171
- }
172
-
173
- }
174
- while(newIndex < newArray.length){
175
- let newItem = newArray[newIndex]
176
- //let newItemInLcs = itemInArray(newItem, lcsArray, lcsStartIndexForNew)
177
- let newItemInLcs = lcsArray[lcsIndexForNew] == newItem
178
- //console.log('newItem', oldIndex, newItem, newItemInLcs)
179
- if(newItemInLcs){
180
- //lcsStartIndexForNew++
181
- lcsIndexForNew++
182
- indexForOperation++
183
- newIndex++
184
- break
185
- } else {
186
- onAdd(indexForOperation, newItem)
187
- indexForOperation++
188
- countOfAddOperations++
189
- newIndex++
190
- }
191
-
192
- }
193
- }
194
-
195
- // console.log('countOf(+)operations', countOfAddOperations)
196
- // console.log('countOf(-)operations', countOfRemoveOperations)
197
- return countOfAddOperations+countOfRemoveOperations
198
-
199
- }
200
-
201
- }