native-document 1.0.91 → 1.0.93

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 (68) hide show
  1. package/dist/native-document.components.min.js +1168 -138
  2. package/dist/native-document.dev.js +792 -217
  3. package/dist/native-document.dev.js.map +1 -1
  4. package/dist/native-document.devtools.min.js +1 -1
  5. package/dist/native-document.min.js +1 -1
  6. package/docs/advanced-components.md +814 -0
  7. package/docs/anchor.md +71 -11
  8. package/docs/cache.md +888 -0
  9. package/docs/conditional-rendering.md +91 -1
  10. package/docs/core-concepts.md +9 -2
  11. package/docs/elements.md +127 -2
  12. package/docs/extending-native-document-element.md +7 -1
  13. package/docs/filters.md +1216 -0
  14. package/docs/getting-started.md +12 -3
  15. package/docs/lifecycle-events.md +10 -2
  16. package/docs/list-rendering.md +453 -54
  17. package/docs/memory-management.md +9 -7
  18. package/docs/native-document-element.md +30 -9
  19. package/docs/native-fetch.md +744 -0
  20. package/docs/observables.md +135 -6
  21. package/docs/routing.md +7 -1
  22. package/docs/state-management.md +7 -1
  23. package/docs/validation.md +8 -1
  24. package/eslint.config.js +3 -3
  25. package/package.json +3 -2
  26. package/readme.md +53 -14
  27. package/src/components/$traits/HasItems.js +42 -1
  28. package/src/components/BaseComponent.js +4 -1
  29. package/src/components/accordion/Accordion.js +112 -8
  30. package/src/components/accordion/AccordionItem.js +93 -4
  31. package/src/components/alert/Alert.js +164 -4
  32. package/src/components/avatar/Avatar.js +236 -22
  33. package/src/components/menu/index.js +1 -2
  34. package/src/core/data/ObservableArray.js +120 -2
  35. package/src/core/data/ObservableChecker.js +50 -0
  36. package/src/core/data/ObservableItem.js +223 -80
  37. package/src/core/data/ObservableWhen.js +36 -6
  38. package/src/core/data/observable-helpers/array.js +12 -3
  39. package/src/core/data/observable-helpers/computed.js +17 -4
  40. package/src/core/data/observable-helpers/object.js +19 -3
  41. package/src/core/elements/control/for-each-array.js +21 -3
  42. package/src/core/elements/control/for-each.js +17 -5
  43. package/src/core/elements/control/show-if.js +31 -15
  44. package/src/core/elements/control/show-when.js +23 -0
  45. package/src/core/elements/control/switch.js +40 -10
  46. package/src/core/utils/cache.js +5 -0
  47. package/src/core/utils/memoize.js +25 -16
  48. package/src/core/utils/prototypes.js +3 -2
  49. package/src/core/wrappers/AttributesWrapper.js +1 -1
  50. package/src/core/wrappers/NDElement.js +41 -1
  51. package/src/core/wrappers/NdPrototype.js +4 -0
  52. package/src/core/wrappers/TemplateCloner.js +13 -10
  53. package/src/core/wrappers/prototypes/bind-class-extensions.js +1 -1
  54. package/src/core/wrappers/prototypes/nd-element-extensions.js +3 -0
  55. package/src/router/Route.js +9 -4
  56. package/src/router/Router.js +28 -9
  57. package/src/router/errors/RouterError.js +0 -1
  58. package/types/control-flow.d.ts +9 -6
  59. package/types/elements.d.ts +6 -3
  60. package/types/filters/index.d.ts +4 -0
  61. package/types/nd-element.d.ts +5 -238
  62. package/types/observable.d.ts +9 -3
  63. package/types/router.d.ts +5 -1
  64. package/types/template-cloner.ts +1 -0
  65. package/types/validator.ts +11 -1
  66. package/utils.d.ts +2 -1
  67. package/utils.js +4 -4
  68. package/src/core/utils/service.js +0 -6
@@ -5,12 +5,18 @@ import Anchor from "../../elements/anchor";
5
5
  import {ElementCreator} from "../../wrappers/ElementCreator";
6
6
 
7
7
  /**
8
- * Show the element if the condition is true
8
+ * Conditionally shows an element based on an observable condition.
9
+ * The element is mounted/unmounted from the DOM as the condition changes.
9
10
  *
10
- * @param {ObservableItem|ObservableChecker} condition
11
- * @param {*} child
12
- * @param {{comment?: string|null, shouldKeepInCache?: Boolean}} configs
13
- * @returns {DocumentFragment}
11
+ * @param {ObservableItem<boolean>|ObservableChecker<boolean>|ObservableWhen} condition - Observable condition to watch
12
+ * @param {ValidChild} child - Element or content to show/hide
13
+ * @param {Object} [options={}] - Configuration options
14
+ * @param {string|null} [options.comment=null] - Comment for debugging
15
+ * @param {boolean} [options.shouldKeepInCache=true] - Whether to cache the element when hidden
16
+ * @returns {AnchorDocumentFragment} Anchor fragment managing the conditional content
17
+ * @example
18
+ * const isVisible = Observable(false);
19
+ * ShowIf(isVisible, Div({}, 'Hello World'));
14
20
  */
15
21
  export const ShowIf = function(condition, child, { comment = null, shouldKeepInCache = true} = {}) {
16
22
  if(!(Validator.isObservable(condition)) && !Validator.isObservableWhenResult(condition)) {
@@ -47,11 +53,18 @@ export const ShowIf = function(condition, child, { comment = null, shouldKeepInC
47
53
  }
48
54
 
49
55
  /**
50
- * Hide the element if the condition is true
51
- * @param {ObservableItem|ObservableChecker} condition
52
- * @param child
53
- * @param {{comment?: string|null, shouldKeepInCache?: Boolean}} configs
54
- * @returns {DocumentFragment}
56
+ * Conditionally hides an element when the observable condition is true.
57
+ * Inverse of ShowIf - element is shown when condition is false.
58
+ *
59
+ * @param {ObservableItem<boolean>|ObservableChecker<boolean>} condition - Observable condition to watch
60
+ * @param {ValidChild} child - Element or content to show/hide
61
+ * @param {Object} [configs] - Configuration options
62
+ * @param {string|null} [configs.comment] - Comment for debugging
63
+ * @param {boolean} [configs.shouldKeepInCache] - Whether to cache element when hidden
64
+ * @returns {AnchorDocumentFragment} Anchor fragment managing the conditional content
65
+ * @example
66
+ * const hasError = Observable(false);
67
+ * HideIf(hasError, Div({}, 'Content'));
55
68
  */
56
69
  export const HideIf = function(condition, child, configs) {
57
70
  const hideCondition = Observable(!condition.val());
@@ -61,12 +74,15 @@ export const HideIf = function(condition, child, configs) {
61
74
  }
62
75
 
63
76
  /**
64
- * Hide the element if the condition is false
77
+ * Conditionally hides an element when the observable condition is false.
78
+ * Same as ShowIf - element is shown when condition is true.
65
79
  *
66
- * @param {ObservableItem|ObservableChecker} condition
67
- * @param {*} child
68
- * @param {{comment?: string|null, shouldKeepInCache?: Boolean}} configs
69
- * @returns {DocumentFragment}
80
+ * @param {ObservableItem<boolean>|ObservableChecker<boolean>|ObservableWhen} condition - Observable condition to watch
81
+ * @param {ValidChild} child - Element or content to show/hide
82
+ * @param {Object} [configs] - Configuration options
83
+ * @param {string|null} [configs.comment] - Comment for debugging
84
+ * @param {boolean} [configs.shouldKeepInCache] - Whether to cache element when hidden
85
+ * @returns {AnchorDocumentFragment} Anchor fragment managing the conditional content
70
86
  */
71
87
  export const HideIfNot = function(condition, child, configs) {
72
88
  return ShowIf(condition, child, configs);
@@ -2,6 +2,29 @@ import Validator from "../../utils/validator.js";
2
2
  import NativeDocumentError from "../../errors/NativeDocumentError.js";
3
3
  import {ShowIf} from "./show-if.js";
4
4
 
5
+ /**
6
+ * Shows content when an observable equals a specific value.
7
+ * Can be called with 2 or 3 arguments.
8
+ *
9
+ * @overload
10
+ * @param {ObservableWhen} observerWhenResult - Result from observable.when(value)
11
+ * @param {ValidChild} view - Content to show when condition matches
12
+ * @returns {AnchorDocumentFragment}
13
+ *
14
+ * @overload
15
+ * @param {ObservableItem} observer - Observable to watch
16
+ * @param {*} target - Value to match
17
+ * @param {ValidChild} view - Content to show when observable equals target
18
+ * @returns {AnchorDocumentFragment}
19
+ *
20
+ * @example
21
+ * // 2 arguments
22
+ * const status = Observable('idle');
23
+ * ShowWhen(status.when('loading'), LoadingSpinner());
24
+ *
25
+ * // 3 arguments
26
+ * ShowWhen(status, 'loading', LoadingSpinner());
27
+ */
5
28
  export const ShowWhen = function() {
6
29
  if(arguments.length === 2) {
7
30
  const [observer, target] = arguments;
@@ -6,11 +6,24 @@ import {ElementCreator} from "../../wrappers/ElementCreator";
6
6
 
7
7
 
8
8
  /**
9
+ * Displays different content based on the current value of an observable.
10
+ * Like a switch statement for UI - shows the content corresponding to current value.
9
11
  *
10
- * @param {ObservableItem|ObservableChecker} $condition
11
- * @param {{[key]: *}} values
12
- * @param {Boolean} shouldKeepInCache
13
- * @returns {DocumentFragment}
12
+ * @param {ObservableItem|ObservableChecker} $condition - Observable to watch
13
+ * @param {Object<string|number, ValidChild>} values - Map of values to their corresponding content
14
+ * @param {boolean} [shouldKeepInCache=true] - Whether to cache rendered views
15
+ * @returns {AnchorDocumentFragment & {add: Function, remove: Function}} Fragment with dynamic methods
16
+ * @example
17
+ * const status = Observable('idle');
18
+ * const view = Match(status, {
19
+ * idle: Div({}, 'Ready'),
20
+ * loading: Div({}, 'Loading...'),
21
+ * error: Div({}, 'Error occurred')
22
+ * });
23
+ *
24
+ * // Dynamic addition
25
+ * view.add('success', Div({}, 'Success!'));
26
+ * view.remove('idle');
14
27
  */
15
28
  export const Match = function($condition, values, shouldKeepInCache = true) {
16
29
 
@@ -67,11 +80,19 @@ export const Match = function($condition, values, shouldKeepInCache = true) {
67
80
 
68
81
 
69
82
  /**
83
+ * Displays one of two views based on a boolean observable condition.
84
+ * Simplified version of Match for true/false cases.
70
85
  *
71
- * @param {ObservableItem|ObservableChecker} $condition
72
- * @param {*} onTrue
73
- * @param {*} onFalse
74
- * @returns {DocumentFragment}
86
+ * @param {ObservableItem<boolean>|ObservableChecker<boolean>} $condition - Boolean observable to watch
87
+ * @param {ValidChild} onTrue - Content to show when condition is true
88
+ * @param {ValidChild} onFalse - Content to show when condition is false
89
+ * @returns {AnchorDocumentFragment} Fragment managing the conditional content
90
+ * @example
91
+ * const isLoggedIn = Observable(false);
92
+ * Switch(isLoggedIn,
93
+ * Div({}, 'Welcome back!'),
94
+ * Div({}, 'Please login')
95
+ * );
75
96
  */
76
97
  export const Switch = function ($condition, onTrue, onFalse) {
77
98
  if(!Validator.isObservable($condition)) {
@@ -85,9 +106,15 @@ export const Switch = function ($condition, onTrue, onFalse) {
85
106
  }
86
107
 
87
108
  /**
109
+ * Provides a fluent API for conditional rendering with show/otherwise pattern.
88
110
  *
89
- * @param {ObservableItem|ObservableChecker} $condition
90
- * @returns {{show: Function, otherwise: (((*) => {}):DocumentFragment)}
111
+ * @param {ObservableItem<boolean>|ObservableChecker<boolean>} $condition - Boolean observable to watch
112
+ * @returns {{show: Function, otherwise: Function}} Object with fluent methods
113
+ * @example
114
+ * const isLoading = Observable(false);
115
+ * When(isLoading)
116
+ * .show(LoadingSpinner())
117
+ * .otherwise(Content());
91
118
  */
92
119
  export const When = function($condition) {
93
120
  if(!Validator.isObservable($condition)) {
@@ -105,6 +132,9 @@ export const When = function($condition) {
105
132
  otherwise(onFalse) {
106
133
  $onFalse = onFalse;
107
134
  return Switch($condition, $onTrue, $onFalse);
135
+ },
136
+ toNdElement() {
137
+ return Switch($condition, $onTrue, $onFalse);
108
138
  }
109
139
  }
110
140
  }
@@ -0,0 +1,5 @@
1
+ import { once as _once, autoMemoize, autoOnce } from "./memoize.js";
2
+
3
+ export const once = fn => autoOnce(fn);
4
+ export const singleton = fn => _once(fn);
5
+ export const memoize = fn => autoMemoize(fn);
@@ -3,9 +3,10 @@
3
3
  export const once = (fn) => {
4
4
  let result = null;
5
5
  return (...args) => {
6
- if(result === null) {
7
- result = fn(...args);
6
+ if(result) {
7
+ return result;
8
8
  }
9
+ result = fn(...args);
9
10
  return result;
10
11
  };
11
12
  };
@@ -14,9 +15,10 @@ export const autoOnce = (fn) => {
14
15
  let target = null;
15
16
  return new Proxy({}, {
16
17
  get: (_, key) => {
17
- if(target === null) {
18
- target = fn();
18
+ if(target) {
19
+ return target[key];
19
20
  }
21
+ target = fn();
20
22
  return target[key];
21
23
  }
22
24
  });
@@ -26,10 +28,13 @@ export const memoize = (fn) => {
26
28
  const cache = new Map();
27
29
  return (...args) => {
28
30
  const [key, ...rest] = args;
29
- if(!cache.has(key)) {
30
- cache.set(key, fn(...rest));
31
+ const cached = cache.get(key);
32
+ if(cached) {
33
+ return cached;
31
34
  }
32
- return cache.get(key);
35
+ const result = fn(...rest);
36
+ cache.set(key, result);
37
+ return result;
33
38
  };
34
39
  };
35
40
 
@@ -37,17 +42,21 @@ export const autoMemoize = (fn) => {
37
42
  const cache = new Map();
38
43
  return new Proxy({}, {
39
44
  get: (_, key) => {
40
- if(!cache.has(key)) {
41
- if(fn.length > 0) {
42
- return (...args) => {
43
- const result = fn(...args);
44
- cache.set(key, result);
45
- return result;
46
- }
45
+ const cached = cache.get(key);
46
+ if(cached) {
47
+ return cached;
48
+ }
49
+
50
+ if(fn.length > 0) {
51
+ return (...args) => {
52
+ const result = fn(...args, key);
53
+ cache.set(key, result);
54
+ return result;
47
55
  }
48
- cache.set(key, fn());
49
56
  }
50
- return cache.get(key);
57
+ const result = fn(key);
58
+ cache.set(key, result);
59
+ return result;
51
60
  }
52
61
  });
53
62
  };
@@ -27,13 +27,14 @@ Function.prototype.cached = function(...args) {
27
27
  };
28
28
 
29
29
  Function.prototype.errorBoundary = function(callback) {
30
- return (...args) => {
30
+ const handler = (...args) => {
31
31
  try {
32
32
  return this.apply(this, args);
33
33
  } catch(e) {
34
- return callback(e);
34
+ return callback(e, {caller: handler, args: args });
35
35
  }
36
36
  };
37
+ return handler;
37
38
  };
38
39
 
39
40
  String.prototype.use = function(args) {
@@ -17,7 +17,7 @@ export function bindClassAttribute(element, data) {
17
17
  continue;
18
18
  }
19
19
  if(value.__$isObservableWhen) {
20
- element.classes.toggle(className, value.isMath());
20
+ element.classes.toggle(className, value.isActive());
21
21
  value.subscribe((shouldAdd) => element.classes.toggle(className, shouldAdd));
22
22
  continue;
23
23
  }
@@ -103,12 +103,35 @@ NDElement.prototype.closedShadow = function(style = null) {
103
103
  return this.shadow('closed', style);
104
104
  };
105
105
 
106
+ /**
107
+ * Attaches a template binding to the element by hydrating it with the specified method.
108
+ *
109
+ * @param {string} methodName - Name of the hydration method to call
110
+ * @param {BindingHydrator} bindingHydrator - Template binding with $hydrate method
111
+ * @returns {HTMLElement} The underlying HTML element
112
+ * @example
113
+ * const onClick = $binder.attach((event, data) => console.log(data));
114
+ * element.nd.attach('onClick', onClick);
115
+ */
106
116
  NDElement.prototype.attach = function(methodName, bindingHydrator) {
107
117
  bindingHydrator.$hydrate(this.$element, methodName);
108
118
  return this.$element;
109
119
  };
110
120
 
111
-
121
+ /**
122
+ * Extends the current NDElement instance with custom methods.
123
+ * Methods are bound to the instance and available for chaining.
124
+ *
125
+ * @param {Object} methods - Object containing method definitions
126
+ * @returns {this} The NDElement instance with added methods for chaining
127
+ * @example
128
+ * element.nd.with({
129
+ * highlight() {
130
+ * this.$element.style.background = 'yellow';
131
+ * return this;
132
+ * }
133
+ * }).highlight().onClick(() => console.log('Clicked'));
134
+ */
112
135
  NDElement.prototype.with = function(methods) {
113
136
  if (!methods || typeof methods !== 'object') {
114
137
  throw new NativeDocumentError('extend() requires an object of methods');
@@ -139,6 +162,23 @@ NDElement.prototype.with = function(methods) {
139
162
  return this;
140
163
  }
141
164
 
165
+ /**
166
+ * Extends the NDElement prototype with new methods available to all NDElement instances.
167
+ * Use this to add global methods to all NDElements.
168
+ *
169
+ * @param {Object} methods - Object containing method definitions to add to prototype
170
+ * @returns {typeof NDElement} The NDElement constructor
171
+ * @throws {NativeDocumentError} If methods is not an object or contains non-function values
172
+ * @example
173
+ * NDElement.extend({
174
+ * fadeIn() {
175
+ * this.$element.style.opacity = '1';
176
+ * return this;
177
+ * }
178
+ * });
179
+ * // Now all NDElements have .fadeIn() method
180
+ * Div().nd.fadeIn();
181
+ */
142
182
  NDElement.extend = function(methods) {
143
183
  if (!methods || typeof methods !== 'object') {
144
184
  throw new NativeDocumentError('NDElement.extend() requires an object of methods');
@@ -38,6 +38,10 @@ EVENTS_WITH_STOP.forEach(eventSourceName => {
38
38
  _stop(this.$element, eventName, callback);
39
39
  return this;
40
40
  };
41
+ NDElement.prototype['onPreventStop'+eventSourceName] = function(callback = null) {
42
+ _preventStop(this.$element, eventName, callback);
43
+ return this;
44
+ };
41
45
  });
42
46
 
43
47
  EVENTS_WITH_PREVENT.forEach(eventSourceName => {
@@ -65,7 +65,12 @@ const bindAttachMethods = function(node, bindDingData, data) {
65
65
 
66
66
  const applyBindingTreePath = (root, target, data, path) => {
67
67
  if(path.fn) {
68
- path.fn(data, target, root);
68
+ if(typeof path.fn === 'string') {
69
+ ElementCreator.bindTextNode(target, data[0][path.fn]);
70
+ }
71
+ else {
72
+ path.fn(data, target, root);
73
+ }
69
74
  }
70
75
  if(path.children) {
71
76
  for(let i = 0, length = path.children.length; i < length; i++) {
@@ -91,15 +96,16 @@ export function TemplateCloner($fn) {
91
96
  if(bindDingData && bindDingData.value) {
92
97
  currentPath.fn = bindDingData.value;
93
98
  const textNode = node.cloneNode();
99
+ if(typeof bindDingData.value === 'string') {
100
+ ElementCreator.bindTextNode(textNode, data[0][bindDingData.value]);
101
+ return textNode;
102
+ }
94
103
  bindDingData.value(data, textNode);
95
104
  return textNode;
96
105
  }
97
106
  return node.cloneNode(true);
98
107
  }
99
- const nodeCloned = node.cloneNode(node.fullCloneNode);
100
- if(node.fullCloneNode) {
101
- return nodeCloned;
102
- }
108
+ const nodeCloned = node.cloneNode();
103
109
  if(bindDingData) {
104
110
  bindAttributes(nodeCloned, bindDingData, data);
105
111
  bindAttachMethods(nodeCloned, bindDingData, data);
@@ -164,12 +170,9 @@ export function TemplateCloner($fn) {
164
170
  }
165
171
  this.value = (callbackOrProperty) => {
166
172
  if(typeof callbackOrProperty !== 'function') {
167
- return createBinding(function(data, textNode) {
168
- const firstArgument = data[0];
169
- ElementCreator.bindTextNode(textNode, firstArgument[callbackOrProperty]);
170
- }, 'value');
173
+ return createBinding(callbackOrProperty, 'value');
171
174
  }
172
- return createBinding(function(data, textNode) {
175
+ return createBinding((data, textNode) => {
173
176
  ElementCreator.bindTextNode(textNode, callbackOrProperty(...data));
174
177
  }, 'value');
175
178
  };
@@ -9,7 +9,7 @@ ObservableItem.prototype.bindNdClass = function(element, className) {
9
9
  };
10
10
 
11
11
  ObservableWhen.prototype.bindNdClass = function(element, className) {
12
- element.classes.toggle(className, this.isMath());
12
+ element.classes.toggle(className, this.isMatch());
13
13
  this.subscribe((shouldAdd) => element.classes.toggle(className, shouldAdd));
14
14
  };
15
15
 
@@ -4,6 +4,7 @@ import TemplateBinding from "../TemplateBinding";
4
4
  import {ElementCreator} from "../ElementCreator";
5
5
  import PluginsManager from "../../utils/plugins-manager";
6
6
  import Validator from "../../utils/validator";
7
+ import ObservableChecker from "../../data/ObservableChecker";
7
8
 
8
9
  String.prototype.toNdElement = function () {
9
10
  const formattedChild = this.resolveObservableTemplate ? this.resolveObservableTemplate() : this;
@@ -33,6 +34,8 @@ ObservableItem.prototype.toNdElement = function () {
33
34
  return ElementCreator.createObservableNode(null, this);
34
35
  };
35
36
 
37
+ ObservableChecker.prototype.toNdElement = ObservableItem.prototype.toNdElement;
38
+
36
39
  NDElement.prototype.toNdElement = function () {
37
40
  return this.$element ?? this.$build?.() ?? this.build?.() ?? null;
38
41
  };
@@ -5,11 +5,16 @@ export const RouteParamPatterns = {
5
5
  };
6
6
 
7
7
  /**
8
+ * Creates a new Route instance.
8
9
  *
9
- * @param {string} $path
10
- * @param {Function} $component
11
- * @param {{name:?string, middlewares:Function[], shouldRebuild:Boolean, with: Object }}$options
12
- * @class
10
+ * @param {string} $path - URL pattern with optional parameters (e.g., '/user/{id:number}')
11
+ * @param {Function} $component - Component function that returns HTMLElement or DocumentFragment
12
+ * @param {Object} [$options={}] - Route configuration options
13
+ * @param {string} [$options.name] - Unique name for the route (used for navigation)
14
+ * @param {Function[]} [$options.middlewares] - Array of middleware functions
15
+ * @param {boolean} [$options.shouldRebuild] - Whether to rebuild component on each navigation
16
+ * @param {Object} [$options.with] - Custom parameter validation patterns
17
+ * @param {Function} [$options.layout] - Layout component wrapper function
13
18
  */
14
19
  export function Route($path, $component, $options = {}) {
15
20
 
@@ -14,7 +14,7 @@ export const DEFAULT_ROUTER_NAME = 'default';
14
14
  /**
15
15
  *
16
16
  * @param {{mode: 'memory'|'history'|'hash'}} $options
17
- * @constructor
17
+ * @class
18
18
  */
19
19
  export default function Router($options = {}) {
20
20
 
@@ -72,11 +72,20 @@ export default function Router($options = {}) {
72
72
  };
73
73
 
74
74
  /**
75
+ * Groups routes under a common path prefix with shared options.
75
76
  *
76
- * @param {string} suffix
77
- * @param {{ middlewares: Function[], name: string}} options
78
- * @param {Function} callback
79
- * @returns {this}
77
+ * @param {string} suffix - Path prefix to prepend to all routes in the group
78
+ * @param {Object} options - Group configuration options
79
+ * @param {Function[]} [options.middlewares] - Middlewares applied to all routes in group
80
+ * @param {string} [options.name] - Name prefix for all routes in group
81
+ * @param {Function} [options.layout] - Layout component for all routes in group
82
+ * @param {Function} callback - Function that defines routes within the group
83
+ * @returns {this} Router instance for chaining
84
+ * @example
85
+ * router.group('/admin', { middlewares: [authMiddleware], layout: AdminLayout }, () => {
86
+ * router.add('/users', UsersPage, { name: 'users' });
87
+ * router.add('/settings', SettingsPage, { name: 'settings' });
88
+ * });
80
89
  */
81
90
  this.group = function(suffix, options, callback) {
82
91
  if(!Validator.isFunction(callback)) {
@@ -194,14 +203,24 @@ export default function Router($options = {}) {
194
203
  Router.routers = {};
195
204
 
196
205
  /**
206
+ * Creates and initializes a new router instance.
197
207
  *
198
- * @param {{mode: 'memory'|'history'|'hash', name?:string, entry?: string}} options
199
- * @param {Function} callback
200
- * @param {Element} container
208
+ * @param {Object} options - Router configuration
209
+ * @param {'memory'|'history'|'hash'} options.mode - Routing mode
210
+ * @param {string} [options.name] - Router name for multi-router apps
211
+ * @param {string} [options.entry] - Initial route path
212
+ * @param {Function} callback - Setup function that receives the router instance
213
+ * @returns {Router} The configured router instance with mount() method
214
+ * @example
215
+ * const router = Router.create({ mode: 'history' }, (r) => {
216
+ * r.add('/home', HomePage, { name: 'home' });
217
+ * r.add('/about', AboutPage, { name: 'about' });
218
+ * });
219
+ * router.mount('#app');
201
220
  */
202
221
  Router.create = function(options, callback) {
203
222
  if(!Validator.isFunction(callback)) {
204
- DebugManager.error('Router', 'Callback must be a function', e);
223
+ DebugManager.error('Router', 'Callback must be a function');
205
224
  throw new RouterError('Callback must be a function');
206
225
  }
207
226
  const router = new Router(options);
@@ -5,5 +5,4 @@ export default class RouterError extends Error {
5
5
  super(message);
6
6
  this.context = context;
7
7
  }
8
-
9
8
  }
@@ -12,7 +12,10 @@ export interface HideIfFunction {
12
12
  }
13
13
 
14
14
  export interface MatchFunction {
15
- <T extends string | number>(condition: ObservableItem<T> | ObservableChecker<T>, values: Record<T, ValidChild>, shouldKeepInCache?: boolean): DocumentFragment;
15
+ <T extends string | number>(condition: ObservableItem<T> | ObservableChecker<T>, values: Record<T, ValidChild>, shouldKeepInCache?: boolean): DocumentFragment & {
16
+ add(key: T, child: ValidChild, shouldFocusOn?: boolean): void;
17
+ remove(key: T): void;
18
+ };
16
19
  }
17
20
 
18
21
  export interface SwitchFunction {
@@ -30,14 +33,14 @@ export interface WhenFunction {
30
33
  export interface ForEachFunction {
31
34
  <T>(data: T[] | Record<string, T> | ObservableItem<T[]> | ObservableItem<Record<string, T>>,
32
35
  callback: (item: T, index?: ObservableItem<number>) => ValidChild,
33
- key?: string | ((item: T, defaultKey: string | number) => string),
34
- configs?: { shouldKeepItemsInCache: boolean, isParentUniqueChild: boolean, }): DocumentFragment,
36
+ key?: string | ((item: T, defaultKey: string | number) => string | number),
37
+ options?: { shouldKeepItemsInCache: boolean, isParentUniqueChild: boolean, }): DocumentFragment,
35
38
  }
36
39
 
37
40
  export interface ForEachArrayFunction {
38
41
  <T>(data: ObservableArray<T>,
39
42
  callback: (item: T, index?: ObservableItem<number>) => ValidChild,
40
- configs?: { pushDelay?: (items: T[]) => number, isParentUniqueChild: boolean, shouldKeepItemsInCache?: boolean }): DocumentFragment;
43
+ configs?: { isParentUniqueChild: boolean, shouldKeepItemsInCache?: boolean }): DocumentFragment;
41
44
  }
42
45
 
43
46
  export interface HideIfNotFunction {
@@ -45,8 +48,8 @@ export interface HideIfNotFunction {
45
48
  }
46
49
 
47
50
 
48
- export function ShowWhen(observer: ObservableWhen, target: any): ReturnType<typeof ShowIf>;
49
- export function ShowWhen(observer: ObservableWhen, target: any, view: any): ReturnType<typeof ShowIf>;
51
+ export function ShowWhen(observerWhenResult: ObservableWhen, view: ValidChild): ReturnType<typeof ShowIf>;
52
+ export function ShowWhen(observer: ObservableItem, target: any, view: ValidChild): ReturnType<typeof ShowIf>;
50
53
 
51
54
  // Control Flow Components
52
55
  export declare const ShowIf: ShowIfFunction;
@@ -130,12 +130,15 @@ export declare type AnchorDocumentFragment = DocumentFragment & {
130
130
  clear: () => void;
131
131
  remove: () => void;
132
132
  removeChildren: () => void;
133
- insertBefore: (child: ValidChild, before: HTMLElement|Comment) => void;
133
+ insertBefore: (child: ValidChild, before: HTMLElement|Comment|null) => void;
134
134
  replaceContent: (child: ValidChild) => void;
135
- appendElement: (child: ValidChild, before: HTMLElement) => void;
136
- getByIndex: (index: number) => HTMLElement;
135
+ setContent: (child: ValidChild) => void;
136
+ appendElement: (child: ValidChild, before: HTMLElement|Comment|null) => void;
137
+ append: (...args: ValidChild[]) => void;
138
+ getByIndex: (index: number) => HTMLElement|null;
137
139
  endElement: () => Comment;
138
140
  startElement: () => Comment;
141
+ removeWithAnchors: () => void;
139
142
  };
140
143
 
141
144
  // Anchor
@@ -0,0 +1,4 @@
1
+ export * from './types';
2
+ export * from './dates';
3
+ export * from './standard';
4
+ export * from './strings';