@brandup/ui-app 1.0.44 → 2.0.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 (39) hide show
  1. package/README.md +7 -4
  2. package/dist/cjs/app.js +397 -0
  3. package/dist/cjs/app.js.map +1 -0
  4. package/dist/cjs/builder.js +53 -0
  5. package/dist/cjs/builder.js.map +1 -0
  6. package/dist/cjs/constants.js +21 -0
  7. package/dist/cjs/constants.js.map +1 -0
  8. package/dist/cjs/ext.js +39 -0
  9. package/dist/cjs/ext.js.map +1 -0
  10. package/dist/cjs/helpers/url.js +206 -0
  11. package/dist/cjs/helpers/url.js.map +1 -0
  12. package/dist/cjs/index.js +11 -760
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/middlewares/hyperlink.js +75 -0
  15. package/dist/cjs/middlewares/hyperlink.js.map +1 -0
  16. package/dist/cjs/middlewares/invoker.js +55 -0
  17. package/dist/cjs/middlewares/invoker.js.map +1 -0
  18. package/dist/cjs/middlewares/state.js +86 -0
  19. package/dist/cjs/middlewares/state.js.map +1 -0
  20. package/dist/mjs/app.js +393 -0
  21. package/dist/mjs/app.js.map +1 -0
  22. package/dist/mjs/builder.js +51 -0
  23. package/dist/mjs/builder.js.map +1 -0
  24. package/dist/mjs/constants.js +17 -0
  25. package/dist/mjs/constants.js.map +1 -0
  26. package/dist/mjs/ext.js +37 -0
  27. package/dist/mjs/ext.js.map +1 -0
  28. package/dist/mjs/helpers/url.js +202 -0
  29. package/dist/mjs/helpers/url.js.map +1 -0
  30. package/dist/mjs/index.js +7 -759
  31. package/dist/mjs/index.js.map +1 -1
  32. package/dist/mjs/middlewares/hyperlink.js +70 -0
  33. package/dist/mjs/middlewares/hyperlink.js.map +1 -0
  34. package/dist/mjs/middlewares/invoker.js +53 -0
  35. package/dist/mjs/middlewares/invoker.js.map +1 -0
  36. package/dist/mjs/middlewares/state.js +81 -0
  37. package/dist/mjs/middlewares/state.js.map +1 -0
  38. package/dist/types.d.ts +155 -7
  39. package/package.json +11 -4
package/dist/cjs/index.js CHANGED
@@ -1,767 +1,18 @@
1
1
  'use strict';
2
2
 
3
- var ui = require('@brandup/ui');
4
- var uiHelpers = require('@brandup/ui-helpers');
3
+ var builder = require('./builder.js');
4
+ var app = require('./app.js');
5
+ var ext = require('./ext.js');
6
+ var url = require('./helpers/url.js');
7
+ var constants = require('./constants.js');
5
8
 
6
- class MiddlewareInvoker {
7
- middleware;
8
- __next;
9
- constructor(middleware) {
10
- this.middleware = middleware;
11
- }
12
- next(middleware) {
13
- if (this.__next)
14
- this.__next.next(middleware);
15
- else
16
- this.__next = new MiddlewareInvoker(middleware);
17
- }
18
- invoke(method, context) {
19
- return this.__exec(method, context);
20
- }
21
- async __exec(method, context) {
22
- const nextFunc = () => this.__next ? this.__next.__exec(method, context) : Promise.resolve();
23
- context.abort.throwIfAborted();
24
- const methodFunc = this.middleware[method];
25
- if (typeof methodFunc === "function") {
26
- const methodResult = methodFunc.call(this.middleware, context, nextFunc);
27
- if (!methodResult || !(methodResult instanceof Promise))
28
- throw new Error(`Middleware "${this.middleware.name}" method "${method}" is not async.`);
29
- await methodResult;
30
- }
31
- else
32
- await nextFunc();
33
- }
34
- }
35
9
 
36
- const result = {
37
- LoadingElementClass: "loading",
38
- NavUrlClassName: "applink",
39
- FormClassName: "appform",
40
- NavUrlAttributeName: "data-nav-url",
41
- NavUrlReplaceAttributeName: "data-nav-replace",
42
- NavUrlScopeAttributeName: "data-nav-scope",
43
- NavIgnoreAttributeName: "data-nav-ignore",
44
- STATE_CLASS: {
45
- LOADING: "bp-state-loading",
46
- LOADED: "bp-state-loaded",
47
- READY: "bp-state-ready"
48
- }
49
- };
50
10
 
51
- var constants = /*#__PURE__*/Object.freeze({
52
- __proto__: null,
53
- default: result
54
- });
55
-
56
- const STATE_MIDDLEWARE_NAME = "app-state";
57
- const StateMiddlewareFactory = () => {
58
- let counter = 0;
59
- const begin = (context) => {
60
- const prev = counter++;
61
- if (prev === 0) {
62
- context.app.element?.classList.remove(result.STATE_CLASS.LOADED);
63
- context.app.element?.classList.add(result.STATE_CLASS.LOADING);
64
- }
65
- };
66
- const end = (context) => {
67
- counter--;
68
- if (counter <= 0) {
69
- counter = 0;
70
- context.app.element?.classList.add(result.STATE_CLASS.LOADED);
71
- context.app.element?.classList.remove(result.STATE_CLASS.LOADING);
72
- }
73
- };
74
- return {
75
- name: STATE_MIDDLEWARE_NAME,
76
- start: async (context, next) => {
77
- begin(context);
78
- try {
79
- await next();
80
- // on success the begin() is left open on purpose: the loading state
81
- // must persist through "loaded" and the first navigation, which closes
82
- // it (see the "first" branch in navigate). On error we close it here.
83
- }
84
- catch (reason) {
85
- end(context);
86
- throw reason;
87
- }
88
- },
89
- loaded: async (context, next) => {
90
- try {
91
- await next();
92
- context.app.element?.classList.add(result.STATE_CLASS.READY);
93
- }
94
- catch (reason) {
95
- end(context);
96
- throw reason;
97
- }
98
- },
99
- navigate: async (context, next) => {
100
- begin(context);
101
- try {
102
- await next();
103
- }
104
- finally {
105
- end(context); // close the begin() of this navigation
106
- // the first navigation also closes the loading opened by start(),
107
- // which intentionally leaves its begin() open until the page is rendered
108
- if (context.source == "first")
109
- end(context);
110
- }
111
- },
112
- submit: async (context, next) => {
113
- begin(context);
114
- try {
115
- await next();
116
- }
117
- finally {
118
- end(context);
119
- }
120
- },
121
- stop: async (_context, next) => {
122
- await next();
123
- }
124
- };
125
- };
126
-
127
- const HYPERLINK_MIDDLEWARE_NAME = "app-hyperlink";
128
- const HyperLinkMiddlewareFactory = () => {
129
- let onClick;
130
- return {
131
- name: HYPERLINK_MIDDLEWARE_NAME,
132
- start: async (context, next) => {
133
- await next();
134
- window.addEventListener("click", onClick = (e) => {
135
- let elem = e.target;
136
- let ignore = false;
137
- while (elem) {
138
- if (elem instanceof HTMLElement) {
139
- if (elem.hasAttribute(result.NavIgnoreAttributeName)) {
140
- ignore = true;
141
- break;
142
- }
143
- if (elem.classList.contains(result.NavUrlClassName) || elem.hasAttribute(result.NavUrlAttributeName))
144
- break;
145
- }
146
- if (elem === e.currentTarget)
147
- return;
148
- elem = elem.parentElement;
149
- }
150
- if (!elem || e.ctrlKey || e.metaKey || elem.getAttribute("target") === "_blank")
151
- return;
152
- e.preventDefault();
153
- e.stopPropagation();
154
- if (ignore)
155
- return;
156
- let url;
157
- if (elem.tagName === "A")
158
- url = elem.getAttribute("href");
159
- else if (elem.hasAttribute(result.NavUrlAttributeName))
160
- url = elem.getAttribute(result.NavUrlAttributeName);
161
- else
162
- throw "Not found url for navigation.";
163
- if (elem.classList.contains(result.LoadingElementClass))
164
- return;
165
- elem.classList.add(result.LoadingElementClass);
166
- context.app
167
- .nav({
168
- url,
169
- replace: elem.hasAttribute(result.NavUrlReplaceAttributeName),
170
- scope: elem.getAttribute(result.NavUrlScopeAttributeName),
171
- data: { clickElem: elem }
172
- })
173
- .catch(() => { })
174
- .finally(() => elem.classList.remove(result.LoadingElementClass));
175
- }, false);
176
- },
177
- stop: (_context, next) => {
178
- window.removeEventListener("click", onClick, false);
179
- return next();
180
- }
181
- };
182
- };
183
-
184
- const parseUrl = (basePath, url) => {
185
- const loc = window.location;
186
- let origin = loc.origin;
187
- let path;
188
- let query = null;
189
- let hash = null;
190
- let isExternal = false;
191
- if (basePath === '/')
192
- basePath = '';
193
- if (!url) {
194
- path = loc.pathname;
195
- if (loc.search)
196
- query = new URLSearchParams(loc.search);
197
- if (loc.hash)
198
- hash = loc.hash;
199
- }
200
- else {
201
- if (url.startsWith("#")) {
202
- path = loc.pathname;
203
- query = new URLSearchParams(loc.search);
204
- hash = url;
205
- }
206
- else if (url.startsWith("?")) {
207
- const hastIndex = url.lastIndexOf("#");
208
- if (hastIndex !== -1) {
209
- hash = url.substring(hastIndex);
210
- url = url.substring(0, hastIndex);
211
- }
212
- path = loc.pathname;
213
- query = new URLSearchParams(url);
214
- }
215
- else if (url.startsWith("http")) {
216
- const u = new URL(url);
217
- if (u.origin != origin) {
218
- origin = u.origin;
219
- isExternal = true;
220
- }
221
- path = u.pathname;
222
- query = u.searchParams;
223
- hash = u.hash || null;
224
- }
225
- else {
226
- const hastIndex = url.lastIndexOf("#");
227
- if (hastIndex !== -1) {
228
- hash = url.substring(hastIndex);
229
- url = url.substring(0, hastIndex);
230
- }
231
- const queryIndex = url.lastIndexOf("?");
232
- if (queryIndex !== -1) {
233
- query = new URLSearchParams(url.substring(queryIndex));
234
- url = url.substring(0, queryIndex);
235
- }
236
- path = url;
237
- if (!path.startsWith("/")) {
238
- let curPath = loc.pathname;
239
- if (curPath.endsWith("/"))
240
- curPath = curPath.substring(0, curPath.length - 1);
241
- path = curPath + "/" + path;
242
- }
243
- }
244
- }
245
- if (!path)
246
- path = '/';
247
- else if (path.length > 1 && path.endsWith('/'))
248
- path = path.substring(0, path.length - 1);
249
- path = path.toLowerCase();
250
- if (basePath) {
251
- if (path.startsWith(basePath.toLowerCase())) {
252
- path = path.substring(basePath.length);
253
- if (!path)
254
- path = '/';
255
- }
256
- else
257
- basePath = '';
258
- }
259
- if (!query)
260
- query = new URLSearchParams();
261
- if (hash === '#')
262
- hash = null;
263
- else if (hash)
264
- hash = hash.substring(1);
265
- var result = {
266
- full: '',
267
- url: '',
268
- relative: '',
269
- origin,
270
- basePath,
271
- path,
272
- query,
273
- hash,
274
- external: isExternal
275
- };
276
- rebuildUrl(result);
277
- return result;
278
- };
279
- /**
280
- * Add or replace query parameters.
281
- * @param url Source url for extending query.
282
- * @param query New or update parameters.
283
- */
284
- const extendQuery = (url, query) => {
285
- if (query instanceof URLSearchParams) {
286
- query.forEach((_v, k) => url.query.delete(k));
287
- query.forEach((v, k) => url.query.append(k, v));
288
- }
289
- else if (query instanceof FormData) {
290
- query.forEach((_v, k) => url.query.delete(k));
291
- query.forEach((v, k) => url.query.append(k, v.toString()));
292
- }
293
- else {
294
- for (const key in query) {
295
- const value = query[key];
296
- if (!Array.isArray(value)) {
297
- url.query.set(key, value);
298
- }
299
- else {
300
- url.query.delete(key);
301
- value.forEach(val => url.query.append(key, val));
302
- }
303
- }
304
- }
305
- rebuildUrl(url);
306
- };
307
- const rebuildUrl = (parsedUrl) => {
308
- let relativeUrl = parsedUrl.basePath + parsedUrl.path;
309
- if (relativeUrl.length > 1 && relativeUrl.endsWith('/'))
310
- relativeUrl = relativeUrl.substring(0, relativeUrl.length - 1);
311
- if (parsedUrl.query.size)
312
- relativeUrl += "?" + parsedUrl.query.toString();
313
- parsedUrl.url = parsedUrl.origin + relativeUrl;
314
- parsedUrl.relative = relativeUrl;
315
- parsedUrl.full = parsedUrl.hash ? `${parsedUrl.url}#${parsedUrl.hash}` : parsedUrl.url;
316
- };
317
- const buildUrl = (basePath, path, query, hash) => {
318
- let url = basePath;
319
- if (url == '/')
320
- url = '';
321
- if (path) {
322
- if (!path.startsWith("/"))
323
- path = '/' + path;
324
- url += path;
325
- }
326
- if (!url)
327
- url = '/';
328
- else if (url.endsWith('/'))
329
- url = url.substring(0, url.length - 1);
330
- if (query) {
331
- let params;
332
- if (query instanceof URLSearchParams)
333
- params = query;
334
- else if (query instanceof FormData) {
335
- params = new URLSearchParams();
336
- query.forEach((value, key) => params.append(key, value.toString()));
337
- }
338
- else {
339
- params = new URLSearchParams();
340
- for (const key in query) {
341
- const value = query[key];
342
- if (value === null || typeof value === "undefined")
343
- continue;
344
- if (Array.isArray(value))
345
- value.forEach(v => params.append(key, v));
346
- else
347
- params.append(key, value);
348
- }
349
- }
350
- if (params.size)
351
- url += "?" + params.toString();
352
- }
353
- if (hash) {
354
- if (!hash.startsWith("#"))
355
- hash = "#" + hash;
356
- if (hash != "#")
357
- url += hash;
358
- }
359
- return url;
360
- };
361
- var urlHelper = {
362
- parseUrl,
363
- extendQuery,
364
- buildUrl
365
- };
366
-
367
- var url = /*#__PURE__*/Object.freeze({
368
- __proto__: null,
369
- default: urlHelper
370
- });
371
-
372
- const APP_TYPENAME = "brandup-ui-app";
373
- const NAV_OVERIDE_ERROR = "NavigationOveride";
374
- /**
375
- * Base application class.
376
- */
377
- class Application extends ui.UIElement {
378
- /** Application environment. */
379
- env;
380
- /** Application model. */
381
- model;
382
- /** Application middleware invoker. */
383
- invoker;
384
- __abort;
385
- __isInited;
386
- __isRuned;
387
- __middlewares = {};
388
- __globalSubmit;
389
- __execNav; // current navigation invoking
390
- __lastNav; // last success navigation
391
- constructor(env, model, ..._args) {
392
- super();
393
- this.env = env;
394
- this.model = model;
395
- const core = { name: "app-root" };
396
- this.invoker = new MiddlewareInvoker(core);
397
- this.__abort = new AbortController();
398
- }
399
- get typeName() { return APP_TYPENAME; }
400
- /** Current navigation context. */
401
- get current() { return this.__lastNav?.context; }
402
- /** Application destroy signal. */
403
- get abort() { return this.__abort.signal; }
404
- /** @internal */
405
- initialize(middlewares) {
406
- if (this.__isInited)
407
- throw new Error('Application already initialized.');
408
- this.__isInited = true;
409
- this.onInitialize();
410
- middlewares.forEach(middleware => {
411
- const name = middleware.name;
412
- if (this.__middlewares.hasOwnProperty(name))
413
- throw new Error(`Middleware "${name}" already registered.`);
414
- this.__middlewares[name] = middleware;
415
- this.invoker.next(middleware);
416
- });
417
- }
418
- /** Initialize application instance. */
419
- onInitialize() {
420
- this.invoker.next(StateMiddlewareFactory());
421
- this.invoker.next(HyperLinkMiddlewareFactory());
422
- }
423
- /** Begin run application. */
424
- onStarting() { return Promise.resolve(); }
425
- /** Complate run application. */
426
- onStared() { return Promise.resolve(); }
427
- /**
428
- * Get middleware by type.
429
- * @param type Type of middleware.
430
- * @returns Middleware instance.
431
- */
432
- middleware(name) {
433
- this.__abort.signal.throwIfAborted();
434
- const middleware = this.__middlewares[name];
435
- if (!middleware)
436
- throw new Error(`Middleware ${name} is not registered.`);
437
- return middleware;
438
- }
439
- /**
440
- * Run application.
441
- * @param contextData Run context data.
442
- * @param element HTMLElement of application. Default is document.body.
443
- * @returns Promise of runned result.
444
- */
445
- async run(contextData, element) {
446
- if (this.__abort.signal.aborted)
447
- throw new Error('Application is destroyed.');
448
- if (this.__isRuned)
449
- throw new Error('Application already run.');
450
- this.__isRuned = true;
451
- if (!contextData)
452
- contextData = {};
453
- element = element || document.body;
454
- this.setElement(element);
455
- const context = {
456
- abort: this.__abort.signal,
457
- app: this,
458
- data: contextData
459
- };
460
- try {
461
- await this.onStarting();
462
- await this.invoker.invoke("start", context);
463
- console.info("app start success");
464
- this.__abort.signal.throwIfAborted();
465
- await this.invoker.invoke("loaded", context);
466
- console.info("app load success");
467
- this.__abort.signal.throwIfAborted();
468
- window.addEventListener("popstate", (e) => this.__onPopState(context, e));
469
- element.addEventListener("submit", this.__globalSubmit = (e) => {
470
- const form = e.target;
471
- if (!form.classList.contains(result.FormClassName))
472
- return;
473
- e.preventDefault();
474
- this.__onSubmit({ form, button: e.submitter instanceof HTMLButtonElement ? e.submitter : null })
475
- .catch(() => { });
476
- }, false);
477
- await this.onStared();
478
- console.info("app runned");
479
- }
480
- catch (reason) {
481
- console.error(`app run error: ${reason}`);
482
- throw reason;
483
- }
484
- try {
485
- await this.nav({ data: context.data, abort: this.__abort.signal });
486
- }
487
- catch (reason) {
488
- if (reason === NAV_OVERIDE_ERROR) {
489
- console.info(`app run nav overided`);
490
- return context;
491
- }
492
- throw reason;
493
- }
494
- return context;
495
- }
496
- /**
497
- * Navigate application to url.
498
- * @param options Navigate options.
499
- * @returns Promise of navigated result.
500
- */
501
- async nav(options) {
502
- const opt = (!options || typeof options === "string") ? { url: options } : options;
503
- let { url = null, query, replace = false, scope = null, data = {}, abort } = opt;
504
- const navUrl = urlHelper.parseUrl(this.env.basePath, url);
505
- if (query)
506
- urlHelper.extendQuery(navUrl, query);
507
- let isFirst = !this.__lastNav && !this.__execNav;
508
- let action;
509
- if (isFirst)
510
- action = "first";
511
- else {
512
- const isChangedUrl = this.__lastNav?.context.url.toLowerCase() !== navUrl.url.toLowerCase();
513
- const hasHash = !!this.__lastNav?.context.hash || !!navUrl.hash;
514
- if (isChangedUrl)
515
- action = "url-change"; // если изменился url
516
- else
517
- action = hasHash ? "hash" : "url-no-change";
518
- }
519
- const base = this.__beginNav(abort);
520
- const context = {
521
- ...this.__createContext(base, navUrl, isFirst ? "first" : "nav", action, data, replace),
522
- scope
523
- };
524
- const currentNav = { method: "navigate", context, abort: base.navAbort, status: "work" };
525
- return await this.__execNavigate(currentNav, base.parentNav);
526
- }
527
- /**
528
- * Reload page with nav.
529
- */
530
- reload() {
531
- this.__abort.signal.throwIfAborted();
532
- return this.nav({ replace: true });
533
- }
534
- /**
535
- * Global reload page in browser.
536
- */
537
- restart() {
538
- this.__abort.signal.throwIfAborted();
539
- window.location.reload();
540
- }
541
- async destroy(contextData) {
542
- if (this.__abort.signal.aborted)
543
- return Promise.reject('Application already destroyed.');
544
- this.__abort.abort();
545
- console.info("app destroy begin");
546
- if (this.__execNav)
547
- this.__execNav.abort.abort();
548
- if (this.__lastNav)
549
- this.__lastNav.abort.abort();
550
- if (this.__globalSubmit)
551
- this.element?.removeEventListener("submit", this.__globalSubmit);
552
- const destroyAbort = new AbortController();
553
- const context = {
554
- abort: destroyAbort.signal,
555
- app: this,
556
- data: contextData || {}
557
- };
558
- try {
559
- await this.invoker.invoke("stop", context);
560
- console.info("app destroy success");
561
- return context;
562
- }
563
- catch (reason) {
564
- console.error(`app destroy error: ${reason}`);
565
- throw reason;
566
- }
567
- finally {
568
- super.destroy();
569
- }
570
- }
571
- /**
572
- * Generate url of application base url.
573
- * @param path Add optional path of base url.
574
- * @param query Add optional query params.
575
- * @param hash Add optional hash.
576
- * @returns Relative url with base path.
577
- */
578
- buildUrl(path, query, hash) {
579
- this.__abort.signal.throwIfAborted();
580
- return urlHelper.buildUrl(this.env.basePath, path, query, hash);
581
- }
582
- async __onSubmit(options) {
583
- const opt = options instanceof HTMLFormElement ? { form: options } : options;
584
- const { form, button = null, query, data = {} } = opt;
585
- if ((!button || !button.formNoValidate) && !form.checkValidity())
586
- throw new Error('Form is invalid.');
587
- let replace = form.hasAttribute(result.NavUrlReplaceAttributeName);
588
- let method = form.method;
589
- let enctype = form.enctype;
590
- let url = form.action;
591
- if (button) {
592
- if (button.hasAttribute("formmethod"))
593
- method = button.formMethod;
594
- if (button.hasAttribute("formenctype"))
595
- enctype = button.formEnctype;
596
- if (button.hasAttribute("formaction"))
597
- url = button.formAction;
598
- button.classList.add(result.LoadingElementClass);
599
- if (button.hasAttribute(result.NavUrlReplaceAttributeName))
600
- replace = true;
601
- }
602
- if (form.classList.contains(result.LoadingElementClass))
603
- throw new Error('Form already submitting.');
604
- form.classList.add(result.LoadingElementClass);
605
- method = method.toUpperCase();
606
- try {
607
- if (method === "GET")
608
- await this.nav({ url, query: new FormData(form), data: data, replace, abort: opt.abort });
609
- else {
610
- const navUrl = urlHelper.parseUrl(this.env.basePath, url);
611
- if (query)
612
- urlHelper.extendQuery(navUrl, query);
613
- const base = this.__beginNav(opt.abort);
614
- const context = {
615
- ...this.__createContext(base, navUrl, "submit", "submit", data, replace),
616
- form,
617
- button,
618
- method,
619
- enctype
620
- };
621
- const currentNav = { method: "submit", context, abort: base.navAbort, status: "work" };
622
- await this.__execNavigate(currentNav);
623
- }
624
- }
625
- finally {
626
- form.classList.remove(result.LoadingElementClass);
627
- if (button)
628
- button.classList.remove(result.LoadingElementClass);
629
- }
630
- }
631
- __onPopState(_context, event) {
632
- const popUrl = location.href;
633
- console.log(`popstate: ${popUrl}`, event.state);
634
- this.nav({ url: popUrl, data: { popstate: event.state } });
635
- }
636
- /** Detect parent (overriding) navigation and compose the abort signal shared by a new navigation. */
637
- __beginNav(abort) {
638
- let parentNav;
639
- if (this.__execNav && this.__execNav.status === "work") {
640
- parentNav = this.__execNav;
641
- parentNav.abort.abort(NAV_OVERIDE_ERROR);
642
- parentNav.context.overided = true;
643
- }
644
- const navAbort = new AbortController();
645
- const aborts = [this.__abort.signal, navAbort.signal];
646
- if (abort)
647
- aborts.push(abort);
648
- return { parentNav, navAbort, abort: AbortSignal.any(aborts) };
649
- }
650
- /** Build the navigation context fields shared by nav and submit. */
651
- __createContext(base, navUrl, source, action, data, replace) {
652
- const { parentNav, abort } = base;
653
- return {
654
- index: parentNav ? parentNav.context.index + 1 : 1,
655
- id: uiHelpers.Guid.createGuid(),
656
- source,
657
- app: this,
658
- abort,
659
- current: this.__lastNav?.context,
660
- parent: parentNav?.context,
661
- overided: false,
662
- action,
663
- data,
664
- url: navUrl.url,
665
- origin: navUrl.origin,
666
- pathAndQuery: navUrl.relative,
667
- basePath: navUrl.basePath,
668
- path: navUrl.path,
669
- query: navUrl.query,
670
- hash: navUrl.hash,
671
- external: navUrl.external,
672
- replace,
673
- redirect: async (options) => {
674
- abort.throwIfAborted();
675
- const result = await this.nav(options);
676
- abort.throwIfAborted();
677
- return result;
678
- }
679
- };
680
- }
681
- async __execNavigate(nav, parent) {
682
- if (parent)
683
- parent.overide = nav;
684
- try {
685
- console.info(`${nav.method} begin`, nav.context);
686
- nav.context.abort.throwIfAborted();
687
- this.__execNav = nav;
688
- await this.invoker.invoke(nav.method, nav.context);
689
- this.__lastNav = nav;
690
- nav.status = "success";
691
- console.info(`${nav.method} ${nav.status} ${nav.context.url}`);
692
- return nav.context;
693
- }
694
- catch (reason) {
695
- if (reason?.name === "AbortError") {
696
- nav.status = "cancelled";
697
- console.warn(`${nav.method} ${nav.status} ${nav.context.url}`);
698
- }
699
- else if (reason === NAV_OVERIDE_ERROR) {
700
- if (!nav.context.overided || !nav.overide)
701
- throw new Error("Nav is not overided.");
702
- nav.status = "overided";
703
- console.warn(`${nav.method} ${nav.status} ${nav.context.url}`);
704
- return nav.overide.context; // return redirected navigation
705
- }
706
- else {
707
- nav.status = "error";
708
- console.error(`${nav.method} ${nav.status} ${nav.context.url}: ${reason}`);
709
- }
710
- throw reason;
711
- }
712
- }
713
- }
714
-
715
- class ApplicationBuilder {
716
- __model;
717
- __appType = (Application);
718
- __middlewares = [];
719
- constructor(model) {
720
- this.__model = model;
721
- }
722
- useApp(appType) {
723
- this.__appType = appType;
724
- return this;
725
- }
726
- useMiddleware(createFunc, ...params) {
727
- let midl = createFunc(...params);
728
- this.__middlewares.push(midl);
729
- return this;
730
- }
731
- build(env, ...args) {
732
- if (!env.basePath || env.basePath == '/')
733
- env.basePath = '';
734
- const app = new this.__appType(env, this.__model, ...args);
735
- app.initialize(this.__middlewares);
736
- return app;
737
- }
738
- }
739
-
740
- HTMLElement.prototype.navUrl = function (url) {
741
- if (this instanceof HTMLAnchorElement)
742
- this.href = url;
743
- else
744
- this.dataset.navUrl = url;
745
- this.classList.add(result.NavUrlClassName);
746
- return this;
747
- };
748
- HTMLElement.prototype.nav = function (app, path, query, hash) {
749
- const url = app.buildUrl(path, query, hash);
750
- return this.navUrl(url);
751
- };
752
- HTMLElement.prototype.navReplace = function () {
753
- this.setAttribute(result.NavUrlReplaceAttributeName, "");
754
- return this;
755
- };
756
- HTMLElement.prototype.navScope = function (scope) {
757
- this.setAttribute(result.NavUrlScopeAttributeName, scope);
758
- return this;
759
- };
760
-
761
- exports.APP_TYPENAME = APP_TYPENAME;
762
- exports.Application = Application;
763
- exports.ApplicationBuilder = ApplicationBuilder;
764
- exports.CONSTANTS = constants;
765
- exports.NAV_OVERIDE_ERROR = NAV_OVERIDE_ERROR;
11
+ exports.ApplicationBuilder = builder.ApplicationBuilder;
12
+ exports.APP_TYPENAME = app.APP_TYPENAME;
13
+ exports.Application = app.Application;
14
+ exports.NAV_OVERIDE_ERROR = app.NAV_OVERIDE_ERROR;
15
+ exports.enableNavExtensions = ext.enableNavExtensions;
766
16
  exports.UrlHelper = url;
17
+ exports.CONSTANTS = constants;
767
18
  //# sourceMappingURL=index.js.map