simplyview 3.1.4 → 3.3.0
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.
- package/dist/simply.app.js +105 -41
- package/dist/simply.app.min.js +1 -1
- package/dist/simply.app.min.js.map +3 -3
- package/dist/simply.everything.js +128 -43
- package/dist/simply.everything.min.js +1 -1
- package/dist/simply.everything.min.js.map +3 -3
- package/package.json +1 -1
- package/src/action.mjs +52 -19
- package/src/activate.mjs +24 -2
- package/src/app.mjs +47 -9
- package/src/route.mjs +20 -20
package/package.json
CHANGED
package/src/action.mjs
CHANGED
|
@@ -1,17 +1,66 @@
|
|
|
1
|
-
export function actions(options, optionsCompat)
|
|
1
|
+
export function actions(options, optionsCompat)
|
|
2
|
+
{
|
|
2
3
|
if (optionsCompat) {
|
|
3
4
|
let app = options
|
|
4
5
|
options = optionsCompat
|
|
5
6
|
options.app = app
|
|
6
7
|
}
|
|
8
|
+
|
|
7
9
|
if (options.app) {
|
|
10
|
+
const waitHandler = {
|
|
11
|
+
apply(target, thisArg, argumentsList)
|
|
12
|
+
{
|
|
13
|
+
try {
|
|
14
|
+
const result = target(...argumentsList)
|
|
15
|
+
if (result instanceof Promise) {
|
|
16
|
+
options.app.hooks.wait(true)
|
|
17
|
+
return result.finally(() => {
|
|
18
|
+
options.app.hooks.wait(false, target)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
return result
|
|
22
|
+
} catch(err) {
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const functionHandler = {
|
|
28
|
+
apply(target, thisArg, argumentsList)
|
|
29
|
+
{
|
|
30
|
+
try {
|
|
31
|
+
const result = target(...argumentsList)
|
|
32
|
+
if (result instanceof Promise) {
|
|
33
|
+
if (options.app.hooks.wait) {
|
|
34
|
+
options.app.hooks.wait(true, target)
|
|
35
|
+
return result.catch(err => {
|
|
36
|
+
return options.app.hooks.error(err, target)
|
|
37
|
+
})
|
|
38
|
+
.finally(() => {
|
|
39
|
+
options.app.hooks.wait(false, target)
|
|
40
|
+
})
|
|
41
|
+
} else {
|
|
42
|
+
return result.catch(err => {
|
|
43
|
+
return options.app.hooks.error(err, target)
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result
|
|
48
|
+
} catch(err) {
|
|
49
|
+
return options.app.hooks.error(err, target)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
8
54
|
const actionHandler = {
|
|
9
|
-
get(target, property)
|
|
55
|
+
get(target, property)
|
|
56
|
+
{
|
|
10
57
|
if (!target[property]) {
|
|
11
58
|
return undefined
|
|
12
59
|
}
|
|
13
|
-
if (
|
|
60
|
+
if (options.app.hooks?.error) {
|
|
14
61
|
return new Proxy(target[property].bind(options.app), functionHandler)
|
|
62
|
+
} else if (options.app.hooks?.wait) {
|
|
63
|
+
return new Proxy(target[property].bind(options.app), waitHandler)
|
|
15
64
|
} else {
|
|
16
65
|
return target[property].bind(options.app)
|
|
17
66
|
}
|
|
@@ -21,20 +70,4 @@ export function actions(options, optionsCompat) {
|
|
|
21
70
|
} else {
|
|
22
71
|
return options
|
|
23
72
|
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const functionHandler = {
|
|
27
|
-
apply(target, thisArg, argumentsList) {
|
|
28
|
-
try {
|
|
29
|
-
const result = target(...argumentsList)
|
|
30
|
-
if (result instanceof Promise) {
|
|
31
|
-
return result.catch(err => {
|
|
32
|
-
return thisArg.catch(err)
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
return result
|
|
36
|
-
} catch(err) {
|
|
37
|
-
return thisArg.catch(err)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
73
|
}
|
package/src/activate.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
if (!Symbol.onDestroy) {
|
|
2
|
+
Symbol.onDestroy = Symbol('onDestroy')
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
const listeners = new Map()
|
|
2
6
|
|
|
3
7
|
export const activate = {
|
|
@@ -31,7 +35,12 @@ function callListeners(node) {
|
|
|
31
35
|
const activate = node?.dataset?.simplyActivate
|
|
32
36
|
if (activate && listeners.has(activate)) {
|
|
33
37
|
for (let callback of listeners.get(activate)) {
|
|
34
|
-
callback.call(node)
|
|
38
|
+
const onDestroy = callback.call(node)
|
|
39
|
+
if (typeof onDestroy == 'function') {
|
|
40
|
+
node[Symbol.onDestroy] = onDestroy
|
|
41
|
+
} else if (typeof onDestroy != 'undefined') {
|
|
42
|
+
console.warn('activate listener may only return a de-activate function, instead got', onDestroy)
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
}
|
|
@@ -42,13 +51,26 @@ function handleChanges(changes) {
|
|
|
42
51
|
if (change.type == 'childList') {
|
|
43
52
|
for (let node of change.addedNodes) {
|
|
44
53
|
if (node.querySelectorAll) {
|
|
45
|
-
|
|
54
|
+
let toActivate = Array.from(node.querySelectorAll('[data-simply-activate]'))
|
|
46
55
|
if (node.matches('[data-simply-activate]')) {
|
|
47
56
|
toActivate.push(node)
|
|
48
57
|
}
|
|
49
58
|
activateNodes = activateNodes.concat(toActivate)
|
|
50
59
|
}
|
|
51
60
|
}
|
|
61
|
+
for (let node of change.removedNodes) {
|
|
62
|
+
if (node.querySelectorAll) {
|
|
63
|
+
let toDestroy = Array.from(node.querySelectorAll('[data-simply-activate]'))
|
|
64
|
+
if (node.matches['[data-simply-activate']) {
|
|
65
|
+
toDestroy.push(node)
|
|
66
|
+
}
|
|
67
|
+
for (let child of toDestroy) {
|
|
68
|
+
if (child[Symbol.onDestroy]) {
|
|
69
|
+
child[Symbol.onDestroy].call(child)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
52
74
|
}
|
|
53
75
|
}
|
|
54
76
|
for (let node of activateNodes) {
|
package/src/app.mjs
CHANGED
|
@@ -16,16 +16,12 @@ class SimplyApp {
|
|
|
16
16
|
case 'keyboard': // backwards compatible
|
|
17
17
|
this.keys = keys({ app: this, keys: options.keys })
|
|
18
18
|
break
|
|
19
|
+
case 'root': // backwards compatibility
|
|
20
|
+
case 'baseURL':
|
|
21
|
+
this.baseURL = options[key]
|
|
22
|
+
break
|
|
19
23
|
case 'routes':
|
|
20
24
|
this.routes = routes({ app: this, routes: options.routes})
|
|
21
|
-
this.routes.handleEvents();
|
|
22
|
-
globalThis.setTimeout(() => {
|
|
23
|
-
if (this.routes.has(globalThis.location?.hash)) {
|
|
24
|
-
this.routes.match(globalThis.location.hash)
|
|
25
|
-
} else {
|
|
26
|
-
this.routes.match(globalThis.location?.pathname+globalThis.location?.hash)
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
25
|
break
|
|
30
26
|
case 'actions':
|
|
31
27
|
this.actions = actions({app: this, actions: options.actions})
|
|
@@ -39,8 +35,32 @@ class SimplyApp {
|
|
|
39
35
|
case 'view':
|
|
40
36
|
this.view = view({app: this, view: options.view})
|
|
41
37
|
break
|
|
38
|
+
case 'hooks':
|
|
39
|
+
const moduleHandler = {
|
|
40
|
+
get: (target, property) => {
|
|
41
|
+
if (!target[property]) {
|
|
42
|
+
return undefined
|
|
43
|
+
}
|
|
44
|
+
if (typeof target[property]=='function') {
|
|
45
|
+
return new Proxy(target[property], functionHandler)
|
|
46
|
+
} else if (target[property] && typeof target[property]=='object') {
|
|
47
|
+
return new Proxy(target[property], moduleHandler)
|
|
48
|
+
} else {
|
|
49
|
+
return target[property]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const functionHandler = {
|
|
54
|
+
apply: (target, thisArg, argumentsList) => {
|
|
55
|
+
// note: must use short function syntax so this is set to the app
|
|
56
|
+
return target.apply(this, argumentsList)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
this[key] = new Proxy(options[key], moduleHandler)
|
|
60
|
+
break
|
|
42
61
|
default:
|
|
43
|
-
|
|
62
|
+
console.log('simply.app: unknown initialization option "'+key+'", added as-is')
|
|
63
|
+
this[key] = options[key]
|
|
44
64
|
break
|
|
45
65
|
}
|
|
46
66
|
}
|
|
@@ -48,6 +68,24 @@ class SimplyApp {
|
|
|
48
68
|
get app() {
|
|
49
69
|
return this
|
|
50
70
|
}
|
|
71
|
+
async start() {
|
|
72
|
+
if (this.hooks?.start) {
|
|
73
|
+
await this.hooks.start()
|
|
74
|
+
}
|
|
75
|
+
if (this.routes) {
|
|
76
|
+
if (this.baseURL) {
|
|
77
|
+
this.routes.init({ baseURL: this.baseURL })
|
|
78
|
+
}
|
|
79
|
+
this.routes.handleEvents();
|
|
80
|
+
globalThis.setTimeout(() => {
|
|
81
|
+
if (this.routes.has(globalThis.location?.hash)) {
|
|
82
|
+
this.routes.match(globalThis.location.hash)
|
|
83
|
+
} else {
|
|
84
|
+
this.routes.match(globalThis.location?.pathname+globalThis.location?.hash)
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
51
89
|
}
|
|
52
90
|
|
|
53
91
|
export function app(options={}) {
|
package/src/route.mjs
CHANGED
|
@@ -12,7 +12,7 @@ class SimplyRoute
|
|
|
12
12
|
{
|
|
13
13
|
constructor(options={})
|
|
14
14
|
{
|
|
15
|
-
this.
|
|
15
|
+
this.baseURL = options.baseURL || '/'
|
|
16
16
|
this.app = options.app || {}
|
|
17
17
|
this.addMissingSlash = !!options.addMissingSlash
|
|
18
18
|
this.matchExact = !!options.matchExact
|
|
@@ -63,7 +63,7 @@ class SimplyRoute
|
|
|
63
63
|
matches = route.match.exec(path+'/')
|
|
64
64
|
if (matches) {
|
|
65
65
|
path+='/'
|
|
66
|
-
history.replaceState({}, '', getURL(path, this.
|
|
66
|
+
history.replaceState({}, '', getURL(path, this.baseURL))
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -91,7 +91,7 @@ class SimplyRoute
|
|
|
91
91
|
|
|
92
92
|
runListeners(action, params)
|
|
93
93
|
{
|
|
94
|
-
if (!Object.keys(this.listeners[action])) {
|
|
94
|
+
if (!this.listeners[action] || !Object.keys(this.listeners[action])) {
|
|
95
95
|
return
|
|
96
96
|
}
|
|
97
97
|
Object.keys(this.listeners[action]).forEach((route) => {
|
|
@@ -112,8 +112,8 @@ class SimplyRoute
|
|
|
112
112
|
handleEvents()
|
|
113
113
|
{
|
|
114
114
|
globalThis.addEventListener('popstate', () => {
|
|
115
|
-
if (this.match(getPath(document.location.pathname + document.location.hash, this.
|
|
116
|
-
this.match(getPath(document.location.pathname, this.
|
|
115
|
+
if (this.match(getPath(document.location.pathname + document.location.hash, this.baseURL)) === false) {
|
|
116
|
+
this.match(getPath(document.location.pathname, this.baseURL))
|
|
117
117
|
}
|
|
118
118
|
})
|
|
119
119
|
this.app.container.addEventListener('click', (evt) => {
|
|
@@ -136,7 +136,7 @@ class SimplyRoute
|
|
|
136
136
|
let check = [link.hash, link.pathname+link.hash, link.pathname]
|
|
137
137
|
let path
|
|
138
138
|
do {
|
|
139
|
-
path = getPath(check.shift(), this.
|
|
139
|
+
path = getPath(check.shift(), this.baseURL);
|
|
140
140
|
} while(check.length && !this.has(path))
|
|
141
141
|
if ( this.has(path) ) {
|
|
142
142
|
let params = this.runListeners('goto', { path: path});
|
|
@@ -154,13 +154,13 @@ class SimplyRoute
|
|
|
154
154
|
|
|
155
155
|
goto(path)
|
|
156
156
|
{
|
|
157
|
-
history.pushState({},'',getURL(path, this.
|
|
157
|
+
history.pushState({},'',getURL(path, this.baseURL))
|
|
158
158
|
return this.match(path)
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
has(path)
|
|
162
162
|
{
|
|
163
|
-
path = getPath(path, this.
|
|
163
|
+
path = getPath(path, this.baseURL)
|
|
164
164
|
for (let route of this.routeInfo) {
|
|
165
165
|
var matches = route.match.exec(path)
|
|
166
166
|
if (matches && matches.length) {
|
|
@@ -196,22 +196,22 @@ class SimplyRoute
|
|
|
196
196
|
|
|
197
197
|
init(options)
|
|
198
198
|
{
|
|
199
|
-
if (options.
|
|
200
|
-
this.
|
|
199
|
+
if (options.baseURL) {
|
|
200
|
+
this.baseURL = options.baseURL
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
function getPath(path,
|
|
205
|
+
function getPath(path, baseURL='/')
|
|
206
206
|
{
|
|
207
|
-
if (path.substring(0,
|
|
207
|
+
if (path.substring(0,baseURL.length)==baseURL
|
|
208
208
|
||
|
|
209
|
-
(
|
|
210
|
-
&& path.length==(
|
|
211
|
-
&& path ==
|
|
209
|
+
( baseURL[baseURL.length-1]=='/'
|
|
210
|
+
&& path.length==(baseURL.length-1)
|
|
211
|
+
&& path == baseURL.substring(0,path.length)
|
|
212
212
|
)
|
|
213
213
|
) {
|
|
214
|
-
path = path.substring(
|
|
214
|
+
path = path.substring(baseURL.length)
|
|
215
215
|
}
|
|
216
216
|
if (path[0]!='/' && path[0]!='#') {
|
|
217
217
|
path = '/'+path
|
|
@@ -219,16 +219,16 @@ function getPath(path, root='/')
|
|
|
219
219
|
return path
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
function getURL(path,
|
|
222
|
+
function getURL(path, baseURL)
|
|
223
223
|
{
|
|
224
|
-
path = getPath(path,
|
|
225
|
-
if (
|
|
224
|
+
path = getPath(path, baseURL)
|
|
225
|
+
if (baseURL[baseURL.length-1]==='/' && path[0]==='/') {
|
|
226
226
|
path = path.substring(1)
|
|
227
227
|
}
|
|
228
228
|
if (path[0]=='#') {
|
|
229
229
|
return path
|
|
230
230
|
}
|
|
231
|
-
return
|
|
231
|
+
return baseURL + path
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
function getRegexpFromRoute(route, exact=false)
|