native-document 1.0.291 → 1.0.293

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "native-document",
3
- "version": "1.0.291",
3
+ "version": "1.0.293",
4
4
  "description": "A reactive JavaScript framework that preserves native DOM simplicity without sacrificing modern features",
5
5
  "author": "AfroCodeur <https://github.com/afrocodeur>",
6
6
  "license": "MIT",
@@ -75,6 +75,7 @@ BaseComponent.extends(Field);
75
75
  BaseComponent.use(Field, HasEventEmitter);
76
76
  BaseComponent.use(Field, HasValidation);
77
77
 
78
+
78
79
  /**
79
80
  * Registers the render template for Field.
80
81
  * @param {(description: {
@@ -239,6 +239,13 @@ Observable.value = function(data) {
239
239
  if(data?.__$Observable) {
240
240
  return data.val();
241
241
  }
242
+ if(Validator.isJson(data)) {
243
+ const output = {};
244
+ for(const key in data) {
245
+ output[key] = Observable.value(data[key]);
246
+ }
247
+ return output;
248
+ }
242
249
  return data;
243
250
  };
244
251
 
@@ -34,6 +34,7 @@ export const RouteParamPatterns = {
34
34
  * @param {boolean} [$options.shouldRebuild] - Whether to rebuild component on each navigation
35
35
  * @param {Object} [$options.with] - Custom parameter validation patterns
36
36
  * @param {Function} [$options.layout] - Layout component wrapper function
37
+ * @param {Function[]} [$options.layouts] - All prent Layouts component wrapper function
37
38
  */
38
39
  export function Route($path, $component, $options = {}) {
39
40
 
@@ -46,6 +47,7 @@ export function Route($path, $component, $options = {}) {
46
47
  const $shouldRebuild = $options.shouldRebuild || false;
47
48
  const $paramsValidators = $options.with || {};
48
49
  const $layout = $options.layout || null;
50
+ const $layouts = $options.layouts || null;
49
51
 
50
52
  const $params = {};
51
53
  const $paramsNames = [];
@@ -91,6 +93,7 @@ export function Route($path, $component, $options = {}) {
91
93
  this.shouldRebuild = () => $shouldRebuild;
92
94
  this.path = () => $path;
93
95
  this.layout = () => $layout;
96
+ this.layouts = () => $layouts;
94
97
 
95
98
  /**
96
99
  *
@@ -57,4 +57,9 @@ export const RouteGroupHelper = {
57
57
  }
58
58
  return null;
59
59
  },
60
+ layouts($groupTree) {
61
+ return $groupTree
62
+ .map(g => g.options?.layout)
63
+ .filter(Boolean);
64
+ },
60
65
  };
@@ -63,6 +63,10 @@ export default function Router($options = {}) {
63
63
  middlewares: RouteGroupHelper.fullMiddlewares($groupTree, options?.middlewares || []),
64
64
  name: options?.name ? RouteGroupHelper.fullName($groupTree, options.name) : null,
65
65
  layout: options?.layout || RouteGroupHelper.layout($groupTree),
66
+ layouts: [
67
+ ...RouteGroupHelper.layouts($groupTree),
68
+ ...(options?.layout ? [options.layout] : []),
69
+ ],
66
70
  });
67
71
  $routes.push(route);
68
72
  if(route.name()) {
@@ -205,8 +209,6 @@ export default function Router($options = {}) {
205
209
  $currentState.query = query;
206
210
  $currentState.path = path;
207
211
 
208
- console.log({ builded: true })
209
-
210
212
  const middlewares = [...route.middlewares(), trigger];
211
213
  let currentIndex = 0;
212
214
  const request = { ...$currentState };
@@ -223,7 +225,7 @@ export default function Router($options = {}) {
223
225
 
224
226
  this.currentRouteName = function() {
225
227
  return $currentState.route.name();
226
- }
228
+ };
227
229
 
228
230
  }
229
231
 
@@ -287,16 +289,24 @@ Router.get = function(name) {
287
289
 
288
290
  Router.currentRoute = function(name = null) {
289
291
  return Router.get(name).currentState().route;
290
- }
292
+ };
291
293
 
292
294
  Router.push = function(target, name = null) {
293
295
  return Router.get(name).push(target);
294
296
  };
295
297
 
298
+ Router.pushToo = function(routeName, params = {}, routerName = null) {
299
+ return Router.get(routerName).push({ name: routeName, params });
300
+ };
301
+
296
302
  Router.replace = function(target, name = null) {
297
303
  return Router.get(name).replace(target);
298
304
  };
299
305
 
306
+ Router.replaceTo = function(routeName, params = {}, routerName = null) {
307
+ return Router.get(routerName).replace({ name: routeName, params });
308
+ };
309
+
300
310
  Router.forward = function(name = null) {
301
311
  return Router.get(name).forward();
302
312
  };
@@ -18,6 +18,7 @@ export function RouterComponent(router, container) {
18
18
 
19
19
  const $lifecycles = new Map();
20
20
  let $currentPath = null;
21
+ let $mountedChain = [];
21
22
 
22
23
  const getNodeAnchorForLayout = (node, path) => {
23
24
  const existingAnchor = $routeInstanceAnchors.get(node);
@@ -55,39 +56,65 @@ export function RouterComponent(router, container) {
55
56
  return nodeToInsert;
56
57
  };
57
58
 
58
- const updateContainerByLayout = (layout, node, route, path) => {
59
+ const updateContainerByLayout = (layouts, node, route, path) => {
60
+
59
61
  const nodeToInsert = getNodeToInsert(node);
62
+ let matchDepth = 0;
60
63
 
61
- const cachedLayout = $layoutCache.get(nodeToInsert);
62
- if(cachedLayout) {
63
- if(cachedLayout === $currentLayout) {
64
- const layoutAnchor = getNodeAnchorForLayout(nodeToInsert, path);
65
- removeLastNodeInserted();
66
- $lastNodeInserted = nodeToInsert;
67
- layoutAnchor.replaceContent(nodeToInsert);
68
- return;
69
- }
70
- cleanContainer();
64
+ while (matchDepth < $mountedChain.length && matchDepth < layouts.length && $mountedChain[matchDepth].layoutFn === layouts[matchDepth]) {
65
+ matchDepth++;
66
+ }
67
+
68
+ if (matchDepth === layouts.length && matchDepth === $mountedChain.length) {
69
+ removeLastNodeInserted();
71
70
  $lastNodeInserted = nodeToInsert;
72
- $currentLayout = cachedLayout;
73
- const layoutAnchor = getNodeAnchorForLayout(nodeToInsert, path);
74
- layoutAnchor.replaceContent(nodeToInsert);
75
- container.appendChild($currentLayout);
71
+ $mountedChain[matchDepth - 1]?.anchor?.replaceContent(nodeToInsert);
76
72
  return;
77
73
  }
78
- cleanContainer();
74
+
75
+
76
+ if ($mountedChain[matchDepth]) {
77
+ $mountedChain[matchDepth].element.remove();
78
+ }
79
+
80
+ const $mountedChainKeep = $mountedChain.slice(0, matchDepth);
81
+ const newLayers = [];
82
+ let slot = nodeToInsert;
79
83
  $lastNodeInserted = nodeToInsert;
80
- const anchor = getNodeAnchorForLayout(nodeToInsert, path);
81
84
 
82
- $currentLayout = ElementCreator.getChild(layout(anchor));
83
- $layoutCache.set(nodeToInsert, $currentLayout);
84
- container.appendChild($currentLayout);
85
+ for(let i = layouts.length - 1; i >= matchDepth; i -= 1) {
86
+ const layout = layouts[i];
87
+ let cached = $layoutCache.get(layout);
88
+ if(!cached) {
89
+ const anchor = getNodeAnchorForLayout(slot, `${path}:layout:${i}`);
90
+ const element = ElementCreator.getChild(layout(anchor));
91
+ cached = { element, anchor };
92
+ $layoutCache.set(layout, cached);
93
+ }
94
+ else {
95
+ cached.anchor.replaceContent(slot);
96
+ }
97
+
98
+ newLayers.unshift({ layoutFn: layout, anchor: cached.anchor, element: cached.element });
99
+ slot = cached.element;
100
+ }
101
+
102
+ $mountedChain = [...$mountedChainKeep, ...newLayers];
103
+
104
+ if (matchDepth === 0) {
105
+ container.appendChild(newLayers[0].element);
106
+ } else {
107
+ $mountedChainKeep[matchDepth - 1].anchor.replaceContent(newLayers[0]?.element || slot);
108
+ }
109
+
85
110
  };
86
111
 
87
112
  const updateContainer = function(node, route, path) {
88
- const layout = route.layout();
89
- if(layout) {
90
- updateContainerByLayout(layout, node, route, path);
113
+ const layouts = route.layouts();
114
+
115
+
116
+ if(layouts.length) {
117
+ updateContainerByLayout(layouts, node, route, path);
91
118
  return;
92
119
  }
93
120
  const nodeToInsert = getNodeToInsert(node);
@@ -1,4 +1,5 @@
1
1
  import DebugManager from '../../core/utils/debug-manager.js';
2
+ import {Observable} from '../../core/data/Observable';
2
3
 
3
4
  export default function HistoryRouter() {
4
5
 
@@ -12,8 +13,9 @@ export default function HistoryRouter() {
12
13
  if(window.history.state && window.history.state.path === path) {
13
14
  return;
14
15
  }
15
- window.history.pushState({ name: route.name(), params, path}, route.name() || path , path);
16
- this.handleRouteChange(route, params, query, path);
16
+ const resolvedParams = Observable.value(params);
17
+ window.history.pushState({ name: route.name(), params: resolvedParams, path}, route.name() || path , path);
18
+ this.handleRouteChange(route, resolvedParams, query, path);
17
19
  } catch (e) {
18
20
  DebugManager.error('HistoryRouter', 'Error in pushState', e);
19
21
  }
@@ -8,6 +8,6 @@ export default function CopyButtonRender($desc, instance) {
8
8
  return;
9
9
  }
10
10
 
11
- navigator.clipboard.writeText($desc.target.val());
11
+ navigator.clipboard.writeText($desc.target.valueOf());
12
12
  });
13
13
  }
@@ -39,7 +39,7 @@
39
39
  box-sizing: border-box;
40
40
  margin: 0;
41
41
  padding: var(--space-cozy) 0;
42
- inset: unset;
42
+ /*inset: unset;*/
43
43
  overflow: hidden;
44
44
 
45
45
  &:popover-open {
@@ -29,6 +29,7 @@ export default function FormControlRender($desc, instance) {
29
29
  fields: fieldsObject,
30
30
  errors: errorsSummary,
31
31
  form: instance,
32
+ data: dataProxy(fieldsObject),
32
33
  }, instance);
33
34
 
34
35
  if(!((form instanceof HTMLFormElement) || form?.$element instanceof HTMLFormElement)) {
@@ -44,6 +45,17 @@ export default function FormControlRender($desc, instance) {
44
45
  return form;
45
46
  }
46
47
 
48
+ const dataProxy = (fieldsObject) => {
49
+ const data = {};
50
+ for(const name in fieldsObject) {
51
+ if(!fieldsObject[name]?.$model) {
52
+ continue;
53
+ }
54
+ data[name] = fieldsObject[name].$model();
55
+ }
56
+ return data;
57
+ };
58
+
47
59
  const buildDefaultLayout = ({ fields, errors, form }) => {
48
60
  return Form({ class: 'form-control-default', ...form.resolveProps() }, [
49
61
  ...Object.values(fields),
@@ -35,9 +35,9 @@ export default function PopoverRender($desc, instance, classPrefix = 'popover')
35
35
  : $desc.trigger).toNdElement();
36
36
 
37
37
  const editableProps = instance.getEditableProps();
38
- const toUnit = v => v + 'px';
39
38
 
40
39
  const popoverId = classPrefix+'-nd-' + (++$popoverId);
40
+ const toUnit = v => v + 'px';
41
41
  const $x = Observable(10).intercept(toUnit);
42
42
  const $y = Observable(0).intercept(toUnit);
43
43
 
@@ -48,7 +48,7 @@ export default function PopoverRender($desc, instance, classPrefix = 'popover')
48
48
  editableProps.class.add(classPrefix);
49
49
  }
50
50
  editableProps.class.add('is-'+$desc.variant);
51
- editableProps.style.add({left: $x, top: $y});
51
+ editableProps.style.add({ '--popover-left-position': $x, '--popover-top-position': $y});
52
52
 
53
53
  const popover = Div({
54
54
  popover: 'manual',
@@ -134,8 +134,8 @@ export default function PopoverRender($desc, instance, classPrefix = 'popover')
134
134
  }[side];
135
135
 
136
136
  Object.assign(popoverArrow.style, {
137
- left: arrowData.x != null ? 'calc('+arrowData.x + 'px - var(--popover-left-offset))' : '',
138
- top: arrowData.y != null ? 'calc('+arrowData.y + 'px - var(--popover-top-offset))' : '',
137
+ left: arrowData.x != null ? arrowData.x + 'px' : '',
138
+ top: arrowData.y != null ? arrowData.y + 'px' : '',
139
139
  [staticSide]: '-4px',
140
140
  });
141
141
 
@@ -14,8 +14,11 @@
14
14
  --popover-arrow-size: 8px;
15
15
  --popover-animation-duration: 0.15s;
16
16
 
17
- --popover-left-offset: 0;
18
- --popover-top-offset: 0;
17
+ --popover-left-offset: 0px;
18
+ --popover-top-offset: 0px;
19
+
20
+ --popover-top-position: 0px;
21
+ --popover-left-position: 0px;
19
22
  }
20
23
 
21
24
 
@@ -45,6 +48,8 @@
45
48
  padding: 0;
46
49
  inset: unset;
47
50
  overflow: initial;
51
+ top: calc(var(--popover-top-position) + var(--popover-top-offset));
52
+ left: calc(var(--popover-left-position) + var(--popover-left-offset));
48
53
 
49
54
  &.is-primary {
50
55
  --popover-bg: var(--color-primary);
@@ -27,7 +27,6 @@
27
27
  padding: var(--tooltip-padding);
28
28
  box-sizing: border-box;
29
29
  margin: 0;
30
- inset: unset;
31
30
  overflow: initial;
32
31
  line-height: 1.5;
33
32
  pointer-events: none;
package/types/router.d.ts CHANGED
@@ -73,7 +73,9 @@ export interface RouterStatic {
73
73
  create(options: { mode: 'memory' | 'history' | 'hash'; name?: string; entry?: string }, callback: (router: Router) => void): Router;
74
74
  get(name?: string): Router;
75
75
  push(target: string | { name: string; params?: RouteParams; query?: QueryParams }, name?: string): void;
76
+ pushTo(routeName: string, params?: RouteParams, routerName?: string): void;
76
77
  replace(target: string | { name: string; params?: RouteParams; query?: QueryParams }, name?: string): void;
78
+ replaceTo(routeName: string, params?: RouteParams, routerName?: string): void;
77
79
  forward(name?: string): void;
78
80
  back(name?: string): void;
79
81
  }