neo.mjs 5.1.6 → 5.1.8

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/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/neomjs/pages/master/resources/images/neomjs-logo-250.png">
2
+ <img height="250" width="250" src="https://raw.githubusercontent.com/neomjs/pages/master/resources/images/logo_rounded.svg">
3
3
  </p>
4
4
 
5
5
  <p align="center">
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.1.6'
23
+ * @member {String} version='5.1.8'
24
24
  */
25
- version: '5.1.6'
25
+ version: '5.1.8'
26
26
  }
27
27
 
28
28
  /**
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.1.6'
23
+ * @member {String} version='5.1.8'
24
24
  */
25
- version: '5.1.6'
25
+ version: '5.1.8'
26
26
  }
27
27
 
28
28
  /**
@@ -13,7 +13,6 @@ import TextField from '../../../src/form/field/Text.mjs';
13
13
  class MainContainer extends ConfigurationViewport {
14
14
  static config = {
15
15
  className : 'Neo.examples.button.base.MainContainer',
16
- autoMount : true,
17
16
  configItemLabelWidth: 160,
18
17
  configItemWidth : 280,
19
18
  layout : {ntype: 'hbox', align: 'stretch'}
@@ -1,7 +1,8 @@
1
- import SplitButton from '../../../src/button/Split.mjs';
1
+ import CheckBox from '../../../src/form/field/CheckBox.mjs';
2
2
  import ConfigurationViewport from '../../ConfigurationViewport.mjs';
3
3
  import Radio from '../../../src/form/field/Radio.mjs';
4
4
  import NumberField from '../../../src/form/field/Number.mjs';
5
+ import SplitButton from '../../../src/button/Split.mjs';
5
6
  import TextField from '../../../src/form/field/Text.mjs';
6
7
 
7
8
  /**
@@ -11,9 +12,8 @@ import TextField from '../../../src/form/field/Text.mjs';
11
12
  class MainContainer extends ConfigurationViewport {
12
13
  static config = {
13
14
  className : 'Neo.examples.button.split.MainContainer',
14
- autoMount : true,
15
- configItemLabelWidth: 110,
16
- configItemWidth : 230,
15
+ configItemLabelWidth: 160,
16
+ configItemWidth : 280,
17
17
  layout : {ntype: 'hbox', align: 'stretch'}
18
18
  }
19
19
 
@@ -29,10 +29,17 @@ class MainContainer extends ConfigurationViewport {
29
29
  minValue : 30,
30
30
  stepSize : 5,
31
31
  value : me.exampleComponent.height
32
+ }, {
33
+ module : CheckBox,
34
+ checked : me.exampleComponent.hideTriggerButton,
35
+ labelText: 'hideTriggerButton',
36
+ listeners: {change: me.onConfigChange.bind(me, 'hideTriggerButton')},
37
+ style : {marginTop: '10px'}
32
38
  }, {
33
39
  module : TextField, // todo: selectField with options
34
40
  labelText : 'iconCls',
35
41
  listeners : {change: me.onConfigChange.bind(me, 'iconCls')},
42
+ style : {marginTop: '10px'},
36
43
  value : me.exampleComponent.iconCls
37
44
  }, {
38
45
  module : TextField, // todo: colorPickerField
@@ -7,6 +7,7 @@ import Dialog from '../../src/dialog/Base.mjs';
7
7
  class DemoDialog extends Dialog {
8
8
  static config = {
9
9
  className: 'Neo.examples.dialog.DemoWindow',
10
+ title : 'My Dialog',
10
11
 
11
12
  wrapperStyle: {
12
13
  height: '40%',
@@ -1,6 +1,6 @@
1
- import BreadcrumbToolbar from '../../../../src/toolbar/Breadcrumb.mjs';
2
- import Store from '../../../../src/data/Store.mjs';
3
- import Viewport from '../../../../src/container/Viewport.mjs';
1
+ import BreadcrumbToolbar from '../../../../src/toolbar/Breadcrumb.mjs';
2
+ import MainContainerController from './MainContainerController.mjs';
3
+ import Viewport from '../../../../src/container/Viewport.mjs';
4
4
 
5
5
  /**
6
6
  * @class Neo.examples.toolbar.breadcrumb.view.MainContainer
@@ -13,6 +13,10 @@ class MainContainer extends Viewport {
13
13
  * @protected
14
14
  */
15
15
  className: 'Neo.examples.toolbar.breadcrumb.view.MainContainer',
16
+ /**
17
+ * @member {Neo.controller.Component} controller=MainContainerController
18
+ */
19
+ controller: MainContainerController,
16
20
  /**
17
21
  * @member {Object[]} items
18
22
  */
@@ -20,38 +24,86 @@ class MainContainer extends Viewport {
20
24
  module : BreadcrumbToolbar,
21
25
  activeKey: 2,
22
26
  flex : 'none',
27
+ reference: 'breadcrumb-toolbar',
23
28
 
24
29
  store: {
25
- module: Store,
26
-
27
- model: {
28
- fields: [{
29
- name: 'id',
30
- type: 'Integer'
31
- }, {
32
- name: 'name',
33
- type: 'String'
34
- }, {
35
- name: 'parentId',
36
- type: 'Integer'
37
- }, {
38
- name: 'route',
39
- type: 'String'
40
- }]
41
- },
42
-
43
30
  data: [
44
- {id: 1, name: 'Home', parentId: null, route: '/home/'},
45
- {id: 2, name: 'Accessibility', parentId: 1, route: '/home/accessibility/'},
46
- {id: 3, name: 'Imprint', parentId: 1, route: '/home/imprint/'},
47
- {id: 4, name: 'News', parentId: 1, route: '/home/news/'},
31
+ {id: 1, name: 'Home', parentId: null, route: '/home/'},
32
+ {id: 2, name: 'Accessibility', parentId: 1, route: '/home/accessibility/'},
33
+ {id: 3, name: 'Imprint', parentId: 1, route: '/home/imprint/'},
34
+ {id: 4, name: 'News', parentId: 1, route: '/home/news/'},
35
+ {id: 5, name: 'Forms', parentId: null, route: '/forms/'},
36
+ {id: 6, name: 'Form 1', parentId: 5, route: '/forms/form1/'},
37
+ {id: 7, name: 'Page 1', parentId: 6, route: '/forms/form1/page1/'},
38
+ {id: 8, name: 'Page 2', parentId: 6, route: '/forms/form1/page2/'},
39
+ {id: 9, name: 'Form 2', parentId: 5, route: '/forms/form2/'},
40
+ {id: 10, name: 'Page 1', parentId: 9, route: '/forms/form2/page1/'},
41
+ {id: 11, name: 'Page 2', parentId: 9, route: '/forms/form2/page2/'}
48
42
  ]
49
43
  }
44
+ }, {
45
+ ntype: 'label',
46
+ style: {marginTop: '40px'},
47
+ text : 'Navigate to'
48
+ }, {
49
+ ntype : 'toolbar',
50
+ flex : 'none',
51
+ layout: {ntype: 'vbox', align: 'start'},
52
+
53
+ itemDefaults: {
54
+ ntype : 'button',
55
+ handler: 'onActiveKeyButtonClick',
56
+ style : {marginTop: '10px'}
57
+ },
58
+
59
+ items: [{
60
+ activeKey: 1,
61
+ text : 'Home'
62
+ }, {
63
+ activeKey: 2,
64
+ style : {marginLeft: '20px', marginTop: '10px'},
65
+ text : 'Accessibility'
66
+ }, {
67
+ activeKey: 3,
68
+ style : {marginLeft: '20px', marginTop: '10px'},
69
+ text : 'Imprint'
70
+ }, {
71
+ activeKey: 4,
72
+ style : {marginLeft: '20px', marginTop: '10px'},
73
+ text : 'News'
74
+ }, {
75
+ activeKey: 5,
76
+ text : 'Forms'
77
+ }, {
78
+ activeKey: 6,
79
+ style : {marginLeft: '20px', marginTop: '10px'},
80
+ text : 'Form 1'
81
+ }, {
82
+ activeKey: 7,
83
+ style : {marginLeft: '40px', marginTop: '10px'},
84
+ text : 'Page 1'
85
+ }, {
86
+ activeKey: 8,
87
+ style : {marginLeft: '40px', marginTop: '10px'},
88
+ text : 'Page 2'
89
+ }, {
90
+ activeKey: 9,
91
+ style : {marginLeft: '20px', marginTop: '10px'},
92
+ text : 'Form 2'
93
+ }, {
94
+ activeKey: 10,
95
+ style : {marginLeft: '40px', marginTop: '10px'},
96
+ text : 'Page 1'
97
+ }, {
98
+ activeKey: 11,
99
+ style : {marginLeft: '40px', marginTop: '10px'},
100
+ text : 'Page 2'
101
+ }]
50
102
  }],
51
103
  /**
52
104
  * @member {Object} layout={ntype:'vbox',align:'stretch'}
53
105
  */
54
- layout: {ntype: 'vbox', align: 'stretch'},
106
+ layout: {ntype: 'vbox', align: 'start'},
55
107
  /**
56
108
  * @member {Object} style={padding:'20px'}
57
109
  */
@@ -0,0 +1,26 @@
1
+ import Controller from '../../../../src/controller/Component.mjs';
2
+
3
+ /**
4
+ * @class Neo.examples.toolbar.breadcrumb.view.MainContainerController
5
+ * @extends Neo.controller.Component
6
+ */
7
+ class MainContainerController extends Controller {
8
+ static config = {
9
+ /**
10
+ * @member {String} className='Neo.examples.toolbar.breadcrumb.view.MainContainerController'
11
+ * @protected
12
+ */
13
+ className: 'Neo.examples.toolbar.breadcrumb.view.MainContainerController'
14
+ }
15
+
16
+ /**
17
+ * @param {Object} data
18
+ */
19
+ onActiveKeyButtonClick(data) {
20
+ this.getReference('breadcrumb-toolbar').activeKey = data.component.activeKey;
21
+ }
22
+ }
23
+
24
+ Neo.applyClassConfig(MainContainerController);
25
+
26
+ export default MainContainerController;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.1.6",
3
+ "version": "5.1.8",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -8,9 +8,9 @@
8
8
  border : none;
9
9
  margin : 0;
10
10
  padding: .5em;
11
+ }
11
12
 
12
- &:last-child {
13
- border-left: v(button-border-width) solid v(button-border-color);
14
- }
13
+ .neo-trigger-button {
14
+ border-left: v(button-border-width) solid v(button-border-color);
15
15
  }
16
16
  }
@@ -60,10 +60,6 @@
60
60
  border : none;
61
61
  border-bottom: 1px solid v(dialog-border-color);
62
62
 
63
- &.neo-draggable {
64
- cursor: move;
65
- }
66
-
67
63
  .neo-button {
68
64
  border : 0;
69
65
  margin-right: 0.3em;
@@ -81,12 +77,18 @@
81
77
 
82
78
  .neo-panel-header-text {
83
79
  color : v(dialog-header-color);
80
+ overflow : hidden;
84
81
  pointer-events: none;
82
+ text-overflow : ellipsis;
85
83
  user-drag : none; // not supported yet
86
84
  user-select : none;
87
85
 
88
86
  -webkit-user-drag: none;
89
87
  }
88
+
89
+ &.neo-draggable {
90
+ cursor: move;
91
+ }
90
92
  }
91
93
  }
92
94
  }
@@ -4,6 +4,7 @@
4
4
  color : v(trigger-color);
5
5
  cursor : pointer;
6
6
  display : flex;
7
+ flex-shrink : 0;
7
8
  font-size : 14px;
8
9
  height : v(textfield-input-height); // has to be 1px smaller to not overlap the bottom border on hover
9
10
  justify-content: center;
@@ -16,4 +16,4 @@
16
16
  border-left-color: transparent;
17
17
  width : 0;
18
18
  }
19
- }
19
+ }
@@ -30,7 +30,7 @@ $neoMap: map-merge($neoMap, (
30
30
  'button-text-color' : #1c60a0,
31
31
  'button-text-color-active' : #1c60a0,
32
32
  'button-text-color-disabled' : #1c60a0,
33
- 'button-text-color-hover' : #bbb,
33
+ 'button-text-color-hover' : #1c60a0,
34
34
  'button-text-font-family' : #{neo(neo-font-family)},
35
35
  'button-text-font-size' : 11px,
36
36
  'button-text-font-weight' : 600,
@@ -237,12 +237,12 @@ const DefaultConfig = {
237
237
  useVdomWorker: true,
238
238
  /**
239
239
  * buildScripts/injectPackageVersion.mjs will update this value
240
- * @default '5.1.6'
240
+ * @default '5.1.8'
241
241
  * @memberOf! module:Neo
242
242
  * @name config.version
243
243
  * @type String
244
244
  */
245
- version: '5.1.6'
245
+ version: '5.1.8'
246
246
  };
247
247
 
248
248
  Object.assign(DefaultConfig, {
@@ -18,6 +18,10 @@ class Split extends Button {
18
18
  * @protected
19
19
  */
20
20
  ntype: 'split-button',
21
+ /**
22
+ * @member {Boolean} hideTriggerButton_=false
23
+ */
24
+ hideTriggerButton_: false,
21
25
  /**
22
26
  * Read only, it will get created inside the ctor.
23
27
  * Use triggerButtonConfig to pass initial config for it.
@@ -63,11 +67,14 @@ class Split extends Button {
63
67
  me.triggerButton = Neo.create({
64
68
  module : Button,
65
69
  appName : me.appName,
70
+ cls : ['neo-trigger-button'],
66
71
  disabled: me.disabled,
67
72
  handler : me.splitButtonHandler,
73
+ hidden : me.hideTriggerButton,
68
74
  iconCls : me.triggerButtonIconCls,
69
- parentId: me.id,
75
+ parentId: me.vdom.id, // wrapper id
70
76
  pressed : me.pressed,
77
+ ui : me.ui,
71
78
  ...me.triggerButtonConfig
72
79
  });
73
80
 
@@ -75,6 +82,20 @@ class Split extends Button {
75
82
  me.update();
76
83
  }
77
84
 
85
+ /**
86
+ * Triggered after the appName config got changed
87
+ * @param {String|null} value
88
+ * @param {String|null} oldValue
89
+ * @protected
90
+ */
91
+ afterSetAppName(value, oldValue) {
92
+ if (this.triggerButton) {
93
+ this.triggerButton.appName = value;
94
+ }
95
+
96
+ super.afterSetAppName(value, oldValue);
97
+ }
98
+
78
99
  /**
79
100
  * Triggered after the disabled config got changed
80
101
  * @param {Boolean} value
@@ -82,15 +103,42 @@ class Split extends Button {
82
103
  * @protected
83
104
  */
84
105
  afterSetDisabled(value, oldValue) {
85
- let me = this;
106
+ let triggerButton = this.triggerButton;
86
107
 
87
- if (me.triggerButton) {
88
- me.triggerButton.disabled = value;
108
+ if (triggerButton) {
109
+ triggerButton.disabled = value;
89
110
  }
90
111
 
91
112
  super.afterSetDisabled(value, oldValue);
92
113
  }
93
114
 
115
+ /**
116
+ * Triggered after the id config got changed
117
+ * @param {String} value
118
+ * @param {String} oldValue
119
+ * @protected
120
+ */
121
+ afterSetId(value, oldValue) {
122
+ this.vdom.id = value + '__wrapper';
123
+
124
+ // silent vdom update, the super call will trigger the engine
125
+ super.afterSetId(value, oldValue);
126
+ }
127
+
128
+ /**
129
+ * Triggered after the hideTriggerButton config got changed
130
+ * @param {Boolean} value
131
+ * @param {Boolean} oldValue
132
+ * @protected
133
+ */
134
+ afterSetHideTriggerButton(value, oldValue) {
135
+ let triggerButton = this.triggerButton;
136
+
137
+ if (triggerButton) {
138
+ triggerButton.hidden = value;
139
+ }
140
+ }
141
+
94
142
  /**
95
143
  * Triggered after the pressed config got changed
96
144
  * @param {Boolean} value
@@ -98,10 +146,10 @@ class Split extends Button {
98
146
  * @protected
99
147
  */
100
148
  afterSetPressed(value, oldValue) {
101
- let me = this;
149
+ let triggerButton = this.triggerButton;
102
150
 
103
- if (me.triggerButton) {
104
- me.triggerButton.pressed = value;
151
+ if (triggerButton) {
152
+ triggerButton.pressed = value;
105
153
  }
106
154
 
107
155
  super.afterSetPressed(value, oldValue);
@@ -114,11 +162,27 @@ class Split extends Button {
114
162
  * @protected
115
163
  */
116
164
  afterSetTriggerButtonIconCls(value, oldValue) {
117
- if (this.triggerButton) {
118
- this.triggerButton.iconCls = value;
165
+ let triggerButton = this.triggerButton;
166
+
167
+ if (triggerButton) {
168
+ triggerButton.iconCls = value;
119
169
  }
120
170
  }
121
171
 
172
+ /**
173
+ * @param {String|null} value
174
+ * @param {String|null} oldValue
175
+ */
176
+ afterSetUi(value, oldValue) {
177
+ let triggerButton = this.triggerButton;
178
+
179
+ if (triggerButton) {
180
+ triggerButton.ui = value;
181
+ }
182
+
183
+ super.afterSetUi(value, oldValue);
184
+ }
185
+
122
186
  /**
123
187
  * @param {Boolean} [updateParentVdom=false]
124
188
  * @param {Boolean} [silent=false]
@@ -1659,11 +1659,11 @@ class Base extends CoreBase {
1659
1659
  let me = this;
1660
1660
 
1661
1661
  if (me.hideMode !== 'visibility') {
1662
- me.vdom.removeDom = false;
1663
- me.update();
1662
+ delete me.vdom.removeDom;
1663
+ !me.silentVdomUpdate && me.render(true);
1664
1664
  } else {
1665
1665
  let style = me.style;
1666
- style.visibility = 'visible';
1666
+ delete style.visibility;
1667
1667
  me.style = style;
1668
1668
  }
1669
1669
 
@@ -113,9 +113,9 @@ class Base extends Panel {
113
113
  */
114
114
  resizablePluginConfig: null,
115
115
  /**
116
- * @member {String} title='Dialog Title'
116
+ * @member {String|null} title_=null
117
117
  */
118
- title: 'Dialog Title',
118
+ title_: null,
119
119
  /**
120
120
  * @member {Object} _vdom
121
121
  */
@@ -268,6 +268,18 @@ class Base extends Panel {
268
268
  });
269
269
  }
270
270
 
271
+ /**
272
+ * Triggered after the title config got changed
273
+ * @param {String|null} value
274
+ * @param {String|null} oldValue
275
+ * @protected
276
+ */
277
+ afterSetTitle(value, oldValue) {
278
+ if (this.headerToolbar) {
279
+ this.headerToolbar.title = value;
280
+ }
281
+ }
282
+
271
283
  /**
272
284
  *
273
285
  */
@@ -419,7 +431,12 @@ class Base extends Panel {
419
431
  maximize: me.maximize
420
432
  };
421
433
 
422
- map[data.action].call(me, data);
434
+ map[data.action]?.call(me, data);
435
+
436
+ me.fire('headerAction', {
437
+ dialog: me,
438
+ ...data
439
+ })
423
440
  }
424
441
 
425
442
  /**
@@ -47,7 +47,7 @@ class Toolbar extends Base {
47
47
  * @protected
48
48
  */
49
49
  afterSetTitle(value, oldValue) {
50
- oldValue && this.down({flag: 'title-label'})?.set({
50
+ this.down({flag: 'title-label'})?.set({
51
51
  removeDom: !value,
52
52
  text : value
53
53
  })
package/src/list/Base.mjs CHANGED
@@ -554,7 +554,7 @@ class Base extends Component {
554
554
  let itemId = vnodeId.split('__')[1],
555
555
  model = this.store.model,
556
556
  keyField = model?.getField(model.keyProperty),
557
- keyType = keyField?.type.toLowerCase();
557
+ keyType = keyField?.type?.toLowerCase();
558
558
 
559
559
  if (keyType === 'integer' || keyType === 'number') {
560
560
  itemId = parseInt(itemId);
@@ -11,10 +11,10 @@ import NeoArray from '../util/Array.mjs';
11
11
  class Base extends Container {
12
12
  /**
13
13
  * Valid values for dock
14
- * @member {String[]} dockPositions=['top','right','bottom','left']
14
+ * @member {String[]} dockPositions=['top','right','bottom','left', null]
15
15
  * @static
16
16
  */
17
- static dockPositions = ['top', 'right', 'bottom', 'left']
17
+ static dockPositions = ['top', 'right', 'bottom', 'left', null]
18
18
 
19
19
  static config = {
20
20
  /**
@@ -32,9 +32,9 @@ class Base extends Container {
32
32
  */
33
33
  baseCls: ['neo-toolbar'],
34
34
  /**
35
- * @member {String} dock_='top'
35
+ * @member {String|null} dock_=null
36
36
  */
37
- dock_: 'top',
37
+ dock_: null,
38
38
  /**
39
39
  * @member {Object} itemDefaults={ntype:'button'}
40
40
  */
@@ -42,9 +42,9 @@ class Base extends Container {
42
42
  ntype: 'button'
43
43
  },
44
44
  /**
45
- * @member {Object} _layout={ntype: 'hbox', align: 'center', pack : 'start'}
45
+ * @member {Object} layout={ntype: 'hbox', align: 'center', pack : 'start'}
46
46
  */
47
- _layout: {
47
+ layout: {
48
48
  ntype: 'hbox',
49
49
  align: 'center',
50
50
  pack : 'start'
@@ -89,7 +89,7 @@ class Base extends Container {
89
89
  dockPositions = me.getStaticConfig('dockPositions');
90
90
 
91
91
  dockPositions.forEach(key => {
92
- NeoArray[key === value ? 'add' : 'remove'](cls, 'neo-dock-' + key);
92
+ key !== null && NeoArray[key === value ? 'add' : 'remove'](cls, 'neo-dock-' + key);
93
93
  });
94
94
 
95
95
  me.cls = cls;
@@ -154,36 +154,39 @@ class Base extends Container {
154
154
  * @returns {Object} layoutConfig
155
155
  */
156
156
  getLayoutConfig() {
157
- let layoutConfig;
158
-
159
- switch(this.dock) {
160
- case 'bottom':
161
- case 'top':
162
- layoutConfig = {
163
- ntype: 'hbox',
164
- align: 'center',
165
- pack : 'start'
166
- };
167
- break;
168
- case 'left':
169
- layoutConfig = {
170
- ntype : 'vbox',
171
- align : 'center',
172
- direction: 'column-reverse',
173
- pack : 'start'
174
- };
175
- break;
176
- case 'right':
177
- layoutConfig = {
178
- ntype : 'vbox',
179
- align : 'center',
180
- direction: 'column',
181
- pack : 'start'
182
- };
183
- break;
157
+ let me = this,
158
+ layoutConfig;
159
+
160
+ if (me.dock) {
161
+ switch(me.dock) {
162
+ case 'bottom':
163
+ case 'top':
164
+ layoutConfig = {
165
+ ntype: 'hbox',
166
+ align: 'center',
167
+ pack : 'start'
168
+ };
169
+ break;
170
+ case 'left':
171
+ layoutConfig = {
172
+ ntype : 'vbox',
173
+ align : 'center',
174
+ direction: 'column-reverse',
175
+ pack : 'start'
176
+ };
177
+ break;
178
+ case 'right':
179
+ layoutConfig = {
180
+ ntype : 'vbox',
181
+ align : 'center',
182
+ direction: 'column',
183
+ pack : 'start'
184
+ };
185
+ break;
186
+ }
184
187
  }
185
188
 
186
- return layoutConfig;
189
+ return layoutConfig || me.layout;
187
190
  }
188
191
  }
189
192
 
@@ -1,4 +1,5 @@
1
1
  import ClassSystemUtil from '../util/ClassSystem.mjs';
2
+ import HashHistory from '../util/HashHistory.mjs';
2
3
  import Store from '../data/Store.mjs';
3
4
  import Toolbar from '../toolbar/Base.mjs';
4
5
 
@@ -18,24 +19,58 @@ class Breadcrumb extends Toolbar {
18
19
  * @protected
19
20
  */
20
21
  ntype: 'breadcrumb-toolbar',
21
- /**
22
- * @member {String[]} baseCls=['neo-breadcrumb-toolbar','neo-toolbar']
23
- */
24
- baseCls: ['neo-breadcrumb-toolbar', 'neo-toolbar'],
25
22
  /**
26
23
  * @member {Number|String|null} activeKey_=null
27
24
  */
28
25
  activeKey_: null,
29
26
  /**
30
- * @member {Object[]} items
27
+ * @member {String[]} baseCls=['neo-breadcrumb-toolbar','neo-toolbar']
31
28
  */
32
- items: [],
29
+ baseCls: ['neo-breadcrumb-toolbar', 'neo-toolbar'],
33
30
  /**
34
31
  * @member {Neo.data.Store|Object} store_=null
35
32
  */
36
33
  store_: null
37
34
  }
38
35
 
36
+ /**
37
+ * @member {Object} defaultStoreConfig
38
+ */
39
+ defaultStoreConfig = {
40
+ module: Store,
41
+
42
+ model: {
43
+ fields: [{
44
+ name: 'id',
45
+ type: 'Integer'
46
+ }, {
47
+ name: 'name',
48
+ type: 'String'
49
+ }, {
50
+ name: 'parentId',
51
+ type: 'Integer'
52
+ }, {
53
+ name: 'route', // Each route has to end with a '/'. E.g.: '/home/accessibility/'
54
+ type: 'String'
55
+ }]
56
+ }
57
+ }
58
+ /**
59
+ * @member {Boolean} updateOnHashChange=true
60
+ */
61
+ updateOnHashChange = true
62
+
63
+ /**
64
+ * @param {Object} config
65
+ */
66
+ construct(config) {
67
+ super.construct(config);
68
+
69
+ let me = this;
70
+
71
+ me.updateOnHashChange && HashHistory.on('change', me.onHashChange, me);
72
+ }
73
+
39
74
  /**
40
75
  * Triggered after the activeKey config got changed
41
76
  * @param {Number|String|null} value
@@ -43,7 +78,16 @@ class Breadcrumb extends Toolbar {
43
78
  * @protected
44
79
  */
45
80
  afterSetActiveKey(value, oldValue) {
46
- this.store.getCount?.() > 0 && this.updateItems()
81
+ let me = this,
82
+ route;
83
+
84
+ if (value !== null && me.store.getCount?.() > 0) {
85
+ me.updateItems();
86
+
87
+ route = me.store.get(value)?.route;
88
+
89
+ route && Neo.Main.setRoute({value: route})
90
+ }
47
91
  }
48
92
 
49
93
  /**
@@ -53,14 +97,10 @@ class Breadcrumb extends Toolbar {
53
97
  * @protected
54
98
  */
55
99
  afterSetStore(value, oldValue) {
56
- let me = this;
57
-
58
100
  value.on({
59
- load: this.onStoreLoad,
60
- scope: me
61
- });
62
-
63
- value?.getCount() > 0 && me.onStoreLoad(value.items)
101
+ load : this.onStoreLoad,
102
+ scope: this
103
+ })
64
104
  }
65
105
 
66
106
  /**
@@ -72,7 +112,18 @@ class Breadcrumb extends Toolbar {
72
112
  */
73
113
  beforeSetStore(value, oldValue) {
74
114
  oldValue?.destroy();
75
- return ClassSystemUtil.beforeSetInstance(value, Store);
115
+ return ClassSystemUtil.beforeSetInstance(value, null, this.defaultStoreConfig);
116
+ }
117
+
118
+ /**
119
+ *
120
+ */
121
+ destroy(...args) {
122
+ let me = this;
123
+
124
+ me.updateOnHashChange && HashHistory.un('change', me.onHashChange, me);
125
+
126
+ super.destroy(...args);
76
127
  }
77
128
 
78
129
  /**
@@ -95,11 +146,31 @@ class Breadcrumb extends Toolbar {
95
146
  return items;
96
147
  }
97
148
 
149
+ /**
150
+ * @param {Object} value
151
+ * @param {Object} oldValue
152
+ */
153
+ onHashChange(value, oldValue) {
154
+ let hashString = value?.hashString,
155
+ store = this.store,
156
+ activeKey;
157
+
158
+ if (hashString && !hashString.endsWith('/')) {
159
+ hashString += '/';
160
+ }
161
+
162
+ activeKey = hashString && store.findFirst({route: hashString})?.[store.keyProperty] || null;
163
+
164
+ if (activeKey !== null) {
165
+ this.activeKey = activeKey;
166
+ }
167
+ }
168
+
98
169
  /**
99
170
  * @param {Object[]} items
100
171
  */
101
172
  onStoreLoad(items) {
102
- this.activeKey !== null && this.updateItems()
173
+ this.afterSetActiveKey(this.activeKey, null);
103
174
  }
104
175
 
105
176
  /**
@@ -114,23 +185,39 @@ class Breadcrumb extends Toolbar {
114
185
  newItems = [],
115
186
  config, item
116
187
 
188
+ me.silentVdomUpdate = true;
189
+
117
190
  for (; i < len; i++) {
118
191
  item = pathItems[i];
119
192
 
120
193
  config = {
194
+ disabled : i === len - 1,
121
195
  editRoute: false,
196
+ hidden : false,
122
197
  route : item.route,
123
198
  text : item.name
124
199
  };
125
200
 
126
201
  if (items[i]) {
127
- items[i].set(config);
202
+ items[i].setSilent(config)
128
203
  } else {
129
- newItems.push(config);
204
+ newItems.push(config)
130
205
  }
131
206
  }
132
207
 
208
+ len = items.length;
209
+
210
+ for (; i < len; i++) {
211
+ items[i].setSilent({
212
+ hidden: true
213
+ })
214
+ }
215
+
133
216
  newItems.length > 0 && me.add(newItems);
217
+
218
+ me.silentVdomUpdate = false;
219
+
220
+ me.update()
134
221
  }
135
222
  }
136
223
 
@@ -61,13 +61,15 @@ class HashHistory extends Base {
61
61
  let me = this,
62
62
  stack = me.stack;
63
63
 
64
- stack.unshift(data);
64
+ if (stack[0]?.hashString !== data.hashString) {
65
+ stack.unshift(data);
65
66
 
66
- if (stack.length > me.maxItems) {
67
- stack.pop();
68
- }
67
+ if (stack.length > me.maxItems) {
68
+ stack.pop();
69
+ }
69
70
 
70
- me.fire('change', data, stack[1] || null);
71
+ me.fire('change', data, stack[1] || null)
72
+ }
71
73
  }
72
74
  }
73
75