neo.mjs 6.15.2 → 6.15.4
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/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/view/Viewport.mjs +73 -10
- package/apps/portal/view/ViewportModel.mjs +29 -0
- package/apps/portal/view/learn/MainContainer.mjs +7 -8
- package/apps/portal/view/learn/MainContainerController.mjs +1 -1
- package/apps/portal/view/learn/PageSectionsContainer.mjs +51 -0
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +2 -2
- package/resources/data/deck/learnneo/pages/2023-10-14T19-25-08-153Z.md +0 -2
- package/resources/data/deck/learnneo/pages/ComponentsAndContainers.md +44 -11
- package/resources/data/deck/learnneo/pages/Config.md +0 -2
- package/resources/data/deck/learnneo/pages/CustomComponents.md +45 -0
- package/resources/data/deck/learnneo/pages/DescribingTheUI.md +0 -2
- package/resources/data/deck/learnneo/pages/Earthquakes.md +0 -2
- package/resources/data/deck/learnneo/pages/Events.md +0 -2
- package/resources/data/deck/learnneo/pages/Extending.md +0 -1
- package/resources/data/deck/learnneo/pages/References.md +0 -2
- package/resources/data/deck/learnneo/pages/Setup.md +0 -2
- package/resources/data/deck/learnneo/tree.json +2 -2
- package/resources/scss/src/apps/portal/learn/ContentView.scss +25 -20
- package/resources/scss/src/apps/portal/learn/LivePreview.scss +27 -6
- package/resources/scss/src/apps/portal/learn/MainContainer.scss +3 -33
- package/resources/scss/src/apps/portal/learn/PageContainer.scss +8 -3
- package/resources/scss/src/apps/portal/learn/PageSectionsContainer.scss +14 -0
- package/resources/scss/src/apps/portal/learn/PageSectionsList.scss +14 -4
- package/resources/scss/src/component/wrapper/MonacoEditor.scss +3 -0
- package/resources/scss/theme-neo-light/Global.scss +9 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Base.mjs +0 -1
- package/src/component/wrapper/MonacoEditor.mjs +5 -0
- package/src/core/Base.mjs +24 -4
- package/src/form/field/ComboBox.mjs +7 -7
- package/src/list/Base.mjs +12 -5
- package/src/main/addon/IntersectionObserver.mjs +29 -5
- package/src/main/addon/Navigator.mjs +207 -155
- package/apps/portal/view/learn/PageSectionsPanel.mjs +0 -53
- package/resources/scss/src/apps/portal/learn/PageSectionsPanel.scss +0 -24
@@ -37,81 +37,42 @@ class Navigator extends Base {
|
|
37
37
|
}
|
38
38
|
|
39
39
|
/**
|
40
|
-
*
|
41
|
-
*
|
42
|
-
* When navigation occurs from one navigable element to another, the `navigate` event
|
43
|
-
* will be fired.
|
44
|
-
*
|
45
|
-
* Note that if focus is expected to enter the subject, the navigable elements
|
46
|
-
* designated by the `selector` must be focusable in some way. So if not using natively
|
47
|
-
* focusable elements, they must have `tabIndex="-1"`.
|
48
|
-
*
|
49
|
-
* Upon navigation, the `aria-activedescendant` property is automatically updated
|
50
|
-
* on the `eventSource` element (which defaults to the subject element, but may be external)
|
51
|
-
*
|
52
|
-
* Pressing `Enter` when an item is active clicks that item.
|
53
|
-
*
|
54
|
-
* if `autoClick` is set to `true` in the data, simply navigating to an element will click it.
|
55
|
-
* @param {*} data
|
56
|
-
* @param {String} data.id The element id to navigate in.
|
57
|
-
* @param {String} [data.eventSource] Optional - the element id to read keystrokes from.
|
58
|
-
* defaults to the main element id. Select field uses this. Focus remains in the field's
|
59
|
-
* `<input>` element while navigating its dropdown.
|
60
|
-
* @param {String} data.selector A CSS selector which identifies the navigable elements.
|
61
|
-
* @param {String} data.activeCls A CSS class to add to the currently active navigable element.
|
62
|
-
* @param {Boolean} data.wrap Pass as `true` to have navigation wrap from first to last and vice versa.
|
63
|
-
* @param {Boolean} [data.autoClick=false] Pass as `true` to have navigation click the target navigated to.
|
64
|
-
* TabPanels will use this on their tab toolbar.
|
40
|
+
* @param {HTMLElement} el
|
65
41
|
*/
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
eventSource = data.eventSource = data.eventSource ? DomAccess.getElement(data.eventSource) : subject;
|
71
|
-
|
72
|
-
subject.$navigator = data;
|
73
|
-
|
74
|
-
if (!data.activeCls) {
|
75
|
-
data.activeCls = 'neo-navigator-active-item'
|
42
|
+
clickItem(el) {
|
43
|
+
// The element knows how to click itself.
|
44
|
+
if (typeof el.click === 'function') {
|
45
|
+
el.click();
|
76
46
|
}
|
47
|
+
// It operates through a listener, so needs an event firing into it.
|
48
|
+
else {
|
49
|
+
const
|
50
|
+
rect = el.getBoundingClientRect(),
|
51
|
+
clientX = rect.x + (rect.width / 2),
|
52
|
+
clientY = rect.y + (rect.height / 2);
|
77
53
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
// And within an element that matches our selector
|
89
|
-
el.closest(data.selector)
|
90
|
-
);
|
91
|
-
|
92
|
-
// TreeWalker so that we can easily move between navigable elements within the target.
|
93
|
-
data.treeWalker = document.createTreeWalker(subject, NodeFilter.SHOW_ELEMENT, node => me.navigateNodeFilter(node, data));
|
94
|
-
|
95
|
-
// We have to know when the DOM mutates in case the active item is removed.
|
96
|
-
(data.targetMutationMonitor = new MutationObserver(e => me.navigateTargetChildListChange(e, data))).observe(subject, {
|
97
|
-
childList : true,
|
98
|
-
subtree : true
|
99
|
-
});
|
100
|
-
|
101
|
-
eventSource.addEventListener('keydown', data.l1 = e => me.navigateKeyDownHandler(e, data));
|
102
|
-
subject.addEventListener('mousedown', data.l2 = e => me.navigateMouseDownHandler(e, data));
|
103
|
-
subject.addEventListener('click', data.l3 = e => me.navigateClickHandler(e, data));
|
104
|
-
subject.addEventListener('focusin', data.l4 = e => me.navigateFocusInHandler(e, data));
|
105
|
-
subject.addEventListener('focusout', data.l5 = e => me.navigateFocusOutHandler(e, data));
|
54
|
+
el.dispatchEvent(new MouseEvent('click', {
|
55
|
+
bubbles : true,
|
56
|
+
altKey : Neo.altKeyDown,
|
57
|
+
ctrlKey : Neo.controlKeyDown,
|
58
|
+
metaKey : Neo.metaKeyDown,
|
59
|
+
shiftKey : Neo.shiftKeyDown,
|
60
|
+
clientX,
|
61
|
+
clientY
|
62
|
+
}))
|
63
|
+
}
|
106
64
|
}
|
107
65
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
66
|
+
/**
|
67
|
+
* The navigables we are dealing with, if they are focusable must *not* be tabbable.
|
68
|
+
* Only *one* must be tabbable, so that tabbing into the subject element goes to the
|
69
|
+
* one active element.
|
70
|
+
*
|
71
|
+
* Tabbing *from* that must exit the subject element.
|
72
|
+
*
|
73
|
+
* So we must ensure that all the focusable elements except the first are not tabbable.
|
74
|
+
* @param {Object} data
|
75
|
+
*/
|
115
76
|
fixItemFocusability(data) {
|
116
77
|
// If the key events are being read from an external element, then that will always contain
|
117
78
|
// focus, so we have nothing to do here. The navigable items wil be inert and not
|
@@ -141,35 +102,25 @@ class Navigator extends Base {
|
|
141
102
|
}
|
142
103
|
}
|
143
104
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
data.targetMutationMonitor.disconnect(target);
|
151
|
-
data.eventSource.removeEventListener('keydown', data.l1);
|
152
|
-
target.removeEventListener('mousedown', data.l2);
|
153
|
-
target.removeEventListener('click', data.l3);
|
154
|
-
target.removeEventListener('focusin', data.l4);
|
155
|
-
target.removeEventListener('focusout', data.l5);
|
156
|
-
}
|
157
|
-
}
|
158
|
-
|
159
|
-
// This is called if mutations take place within the subject element.
|
160
|
-
// We have to keep things in order if the list items change.
|
161
|
-
navigateTargetChildListChange(mutations, data) {
|
162
|
-
this.fixItemFocusability(data);
|
163
|
-
|
164
|
-
// Active item gone.
|
165
|
-
// Try to activate the item at the same index;
|
166
|
-
if (data.activeItem && !data.subject.contains(data.activeItem)) {
|
167
|
-
const allItems = data.subject.querySelectorAll(data.selector);
|
105
|
+
/**
|
106
|
+
* @param {MouseEvent} e
|
107
|
+
* @param {Object} data
|
108
|
+
*/
|
109
|
+
navigateClickHandler(e, data) {
|
110
|
+
const target = e.target.closest(data.selector);
|
168
111
|
|
169
|
-
|
112
|
+
// If there was a focusable under the mouse, mousedown will have focused it and and we
|
113
|
+
// will have respond to that in navigateFocusInHandler.
|
114
|
+
// If not, we navigate programmatically.
|
115
|
+
if (target && !data.findFocusable(target)) {
|
116
|
+
this.navigateTo(target, data);
|
170
117
|
}
|
171
118
|
}
|
172
119
|
|
120
|
+
/**
|
121
|
+
* @param {FocusEvent} e
|
122
|
+
* @param {Object} data
|
123
|
+
*/
|
173
124
|
navigateFocusInHandler(e, data) {
|
174
125
|
const
|
175
126
|
target = e.target.closest(data.selector),
|
@@ -189,6 +140,10 @@ class Navigator extends Base {
|
|
189
140
|
}
|
190
141
|
}
|
191
142
|
|
143
|
+
/**
|
144
|
+
* @param {FocusEvent} e
|
145
|
+
* @param {Object} data
|
146
|
+
*/
|
192
147
|
navigateFocusOutHandler(e, data) {
|
193
148
|
const { target } = e;
|
194
149
|
|
@@ -201,28 +156,35 @@ class Navigator extends Base {
|
|
201
156
|
}
|
202
157
|
}
|
203
158
|
|
204
|
-
|
205
|
-
|
159
|
+
/**
|
160
|
+
* @param {Number} direction
|
161
|
+
* @param {Object} data
|
162
|
+
*/
|
163
|
+
navigateGetAdjacent(direction=1, data) {
|
164
|
+
const { treeWalker } = data;
|
206
165
|
|
207
|
-
//
|
208
|
-
|
209
|
-
|
210
|
-
if (target && !data.findFocusable(target)) {
|
211
|
-
this.navigateTo(target, data);
|
212
|
-
}
|
213
|
-
}
|
166
|
+
// Walk forwards or backwards to the next or previous node which matches our selector
|
167
|
+
treeWalker.currentNode = this.navigatorGetActiveItem(data) || data.subject;
|
168
|
+
treeWalker[direction < 0 ? 'previousNode' : 'nextNode']();
|
214
169
|
|
215
|
-
|
216
|
-
|
170
|
+
// Found a target in the requested direction
|
171
|
+
if (treeWalker.currentNode) {
|
172
|
+
if (treeWalker.currentNode !== data.activeItem) {
|
173
|
+
return treeWalker.currentNode;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
// Could not find target in requested direction, then wrap if configured to do so
|
177
|
+
else if (data.wrap !== false) {
|
178
|
+
const allItems = data.subject.querySelector(data.selector);
|
217
179
|
|
218
|
-
|
219
|
-
// If not, we have to programmatically activate on click, but we must not draw focus away from
|
220
|
-
// where it is, so preventDefault
|
221
|
-
if (target && !data.findFocusable(target)) {
|
222
|
-
e.preventDefault();
|
180
|
+
return allItems[direction === 1 ? 0 : allItems.length - 1];
|
223
181
|
}
|
224
182
|
}
|
225
183
|
|
184
|
+
/**
|
185
|
+
* @param {KeyboardEvent} keyEvent
|
186
|
+
* @param {Object} data
|
187
|
+
*/
|
226
188
|
navigateKeyDownHandler(keyEvent, data) {
|
227
189
|
const
|
228
190
|
me = this,
|
@@ -290,27 +252,46 @@ class Navigator extends Base {
|
|
290
252
|
}
|
291
253
|
}
|
292
254
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
255
|
+
/**
|
256
|
+
* @param {MouseEvent} e
|
257
|
+
* @param {Object} data
|
258
|
+
*/
|
259
|
+
navigateMouseDownHandler(e, data) {
|
260
|
+
const target = e.target.closest(data.selector);
|
261
|
+
|
262
|
+
// If there is a focusable under the mouse, it will take focus, and we respond to that in navigateFocusInHandler.
|
263
|
+
// If not, we have to programmatically activate on click, but we must not draw focus away from
|
264
|
+
// where it is, so preventDefault
|
265
|
+
if (target && !data.findFocusable(target)) {
|
266
|
+
e.preventDefault();
|
297
267
|
}
|
298
|
-
|
299
|
-
else {
|
300
|
-
const
|
301
|
-
rect = el.getBoundingClientRect(),
|
302
|
-
clientX = rect.x + (rect.width / 2),
|
303
|
-
clientY = rect.y + (rect.height / 2);
|
268
|
+
}
|
304
269
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
270
|
+
/**
|
271
|
+
* @param {HTMLElement} node
|
272
|
+
* @param {Object} data
|
273
|
+
*/
|
274
|
+
navigateNodeFilter(node, data) {
|
275
|
+
return node.offsetParent && node.matches?.(data.selector) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
276
|
+
}
|
277
|
+
|
278
|
+
/**
|
279
|
+
* This is called if mutations take place within the subject element.
|
280
|
+
* We have to keep things in order if the list items change.
|
281
|
+
* @param {MutationRecord[]} mutations
|
282
|
+
* @param {Object} data
|
283
|
+
*/
|
284
|
+
navigateTargetChildListChange(mutations, data) {
|
285
|
+
this.fixItemFocusability(data);
|
286
|
+
|
287
|
+
if (data.keepFocusIndex) {
|
288
|
+
// Active item gone.
|
289
|
+
// Try to activate the item at the same index;
|
290
|
+
if (data.activeItem && !data.subject.contains(data.activeItem)) {
|
291
|
+
const allItems = data.subject.querySelectorAll(data.selector);
|
292
|
+
|
293
|
+
allItems.length && this.navigateTo(allItems[Math.max(Math.min(data.activeIndex, allItems.length - 1), 0)], data);
|
294
|
+
}
|
314
295
|
}
|
315
296
|
}
|
316
297
|
|
@@ -362,6 +343,25 @@ class Navigator extends Base {
|
|
362
343
|
}
|
363
344
|
}
|
364
345
|
|
346
|
+
/**
|
347
|
+
* @param {Object} data
|
348
|
+
* @returns {HTMLElement|null}
|
349
|
+
*/
|
350
|
+
navigatorGetActiveItem(data) {
|
351
|
+
let activeItem = data.activeItem && DomAccess.getElement(data.activeItem.id) || null;
|
352
|
+
|
353
|
+
if (!activeItem && ('activeIndex' in data)) {
|
354
|
+
const allItems = data.subject.querySelectorAll(data.selector);
|
355
|
+
|
356
|
+
activeItem = allItems[Math.max(Math.min(data.activeIndex, allItems.length - 1), 0)];
|
357
|
+
}
|
358
|
+
return activeItem;
|
359
|
+
}
|
360
|
+
|
361
|
+
/**
|
362
|
+
* @param {HTMLElement} newActiveElement
|
363
|
+
* @param {Object} data
|
364
|
+
*/
|
365
365
|
setActiveItem(newActiveElement, data) {
|
366
366
|
const allItems = Array.from(data.subject.querySelectorAll(data.selector));
|
367
367
|
|
@@ -411,40 +411,92 @@ class Navigator extends Base {
|
|
411
411
|
}
|
412
412
|
}
|
413
413
|
|
414
|
-
|
415
|
-
|
414
|
+
/**
|
415
|
+
* Sets up keyboard based navigation within the passed element id.
|
416
|
+
*
|
417
|
+
* When navigation occurs from one navigable element to another, the `navigate` event
|
418
|
+
* will be fired.
|
419
|
+
*
|
420
|
+
* Note that if focus is expected to enter the subject, the navigable elements
|
421
|
+
* designated by the `selector` must be focusable in some way. So if not using natively
|
422
|
+
* focusable elements, they must have `tabIndex="-1"`.
|
423
|
+
*
|
424
|
+
* Upon navigation, the `aria-activedescendant` property is automatically updated
|
425
|
+
* on the `eventSource` element (which defaults to the subject element, but may be external)
|
426
|
+
*
|
427
|
+
* Pressing `Enter` when an item is active clicks that item.
|
428
|
+
*
|
429
|
+
* if `autoClick` is set to `true` in the data, simply navigating to an element will click it.
|
430
|
+
* @param {*} data
|
431
|
+
* @param {String} data.id The element id to navigate in.
|
432
|
+
* @param {String} [data.eventSource] Optional - the element id to read keystrokes from.
|
433
|
+
* defaults to the main element id. Select field uses this. Focus remains in the field's
|
434
|
+
* `<input>` element while navigating its dropdown.
|
435
|
+
* @param {String} data.selector A CSS selector which identifies the navigable elements.
|
436
|
+
* @param {String} data.activeCls A CSS class to add to the currently active navigable element.
|
437
|
+
* @param {Boolean} data.wrap Pass as `true` to have navigation wrap from first to last and vice versa.
|
438
|
+
* @param {Boolean} [data.autoClick=false] Pass as `true` to have navigation click the target navigated to.
|
439
|
+
* TabPanels will use this on their tab toolbar.
|
440
|
+
*/
|
441
|
+
subscribe(data) {
|
442
|
+
const
|
443
|
+
me = this,
|
444
|
+
subject = data.subject = DomAccess.getElement(data.id),
|
445
|
+
eventSource = data.eventSource = data.eventSource ? DomAccess.getElement(data.eventSource) : subject;
|
416
446
|
|
417
|
-
|
418
|
-
treeWalker.currentNode = this.navigatorGetActiveItem(data) || data.subject;
|
419
|
-
treeWalker[direction < 0 ? 'previousNode' : 'nextNode']();
|
447
|
+
subject.$navigator = data;
|
420
448
|
|
421
|
-
|
422
|
-
|
423
|
-
if (treeWalker.currentNode !== data.activeItem) {
|
424
|
-
return treeWalker.currentNode;
|
425
|
-
}
|
449
|
+
if (!data.activeCls) {
|
450
|
+
data.activeCls = 'neo-navigator-active-item'
|
426
451
|
}
|
427
|
-
// Could not find target in requested direction, then wrap if configured to do so
|
428
|
-
else if (data.wrap !== false) {
|
429
|
-
const allItems = data.subject.querySelector(data.selector);
|
430
452
|
|
431
|
-
|
432
|
-
|
433
|
-
|
453
|
+
// Ensure that only *one* of the child focusables is actually tabbable.
|
454
|
+
// We use arrow keys for internal navigation. TAB must move out.
|
455
|
+
me.fixItemFocusability(data);
|
434
456
|
|
435
|
-
|
436
|
-
|
457
|
+
// Finds a focusable item starting from a descendant el within one of our selector items
|
458
|
+
data.findFocusable = el => DomUtils.closest(el, el =>
|
459
|
+
// We're looking for an element that is focusable
|
460
|
+
DomUtils.isFocusable(el) &&
|
461
|
+
// And within our subject element
|
462
|
+
(subject.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_CONTAINED_BY) &&
|
463
|
+
// And within an element that matches our selector
|
464
|
+
el.closest(data.selector)
|
465
|
+
);
|
437
466
|
|
438
|
-
|
439
|
-
|
467
|
+
// TreeWalker so that we can easily move between navigable elements within the target.
|
468
|
+
data.treeWalker = document.createTreeWalker(subject, NodeFilter.SHOW_ELEMENT, node => me.navigateNodeFilter(node, data));
|
440
469
|
|
441
|
-
|
442
|
-
|
443
|
-
|
470
|
+
// We have to know when the DOM mutates in case the active item is removed.
|
471
|
+
(data.targetMutationMonitor = new MutationObserver(e => me.navigateTargetChildListChange(e, data))).observe(subject, {
|
472
|
+
childList : true,
|
473
|
+
subtree : true
|
474
|
+
});
|
475
|
+
|
476
|
+
eventSource.addEventListener('keydown', data.l1 = e => me.navigateKeyDownHandler(e, data));
|
477
|
+
subject.addEventListener('mousedown', data.l2 = e => me.navigateMouseDownHandler(e, data));
|
478
|
+
subject.addEventListener('click', data.l3 = e => me.navigateClickHandler(e, data));
|
479
|
+
subject.addEventListener('focusin', data.l4 = e => me.navigateFocusInHandler(e, data));
|
480
|
+
subject.addEventListener('focusout', data.l5 = e => me.navigateFocusOutHandler(e, data));
|
444
481
|
}
|
445
482
|
|
446
|
-
|
447
|
-
|
483
|
+
/**
|
484
|
+
* @param {Object} data
|
485
|
+
*/
|
486
|
+
unsubscribe(data) {
|
487
|
+
const target = DomAccess.getElement(data.id);
|
488
|
+
|
489
|
+
data = target?.$navigator;
|
490
|
+
|
491
|
+
if (data) {
|
492
|
+
delete target.$navigator;
|
493
|
+
data.targetMutationMonitor.disconnect();
|
494
|
+
data.eventSource.removeEventListener('keydown', data.l1);
|
495
|
+
target.removeEventListener('mousedown', data.l2);
|
496
|
+
target.removeEventListener('click', data.l3);
|
497
|
+
target.removeEventListener('focusin', data.l4);
|
498
|
+
target.removeEventListener('focusout', data.l5);
|
499
|
+
}
|
448
500
|
}
|
449
501
|
}
|
450
502
|
|
@@ -1,53 +0,0 @@
|
|
1
|
-
import PageSectionsList from './PageSectionsList.mjs';
|
2
|
-
import Panel from '../../../../src/container/Panel.mjs';
|
3
|
-
|
4
|
-
/**
|
5
|
-
* @class Portal.view.learn.PageSectionsPanel
|
6
|
-
* @extends Neo.container.Panel
|
7
|
-
*/
|
8
|
-
class PageSectionsPanel extends Panel {
|
9
|
-
static config = {
|
10
|
-
/**
|
11
|
-
* @member {String} className='Portal.view.learn.PageSectionsPanel'
|
12
|
-
* @protected
|
13
|
-
*/
|
14
|
-
className: 'Portal.view.learn.PageSectionsPanel',
|
15
|
-
/**
|
16
|
-
* @member {String[]} cls=['portal-page-sections-panel']
|
17
|
-
*/
|
18
|
-
cls: ['portal-page-sections-panel'],
|
19
|
-
/**
|
20
|
-
* @member {Object[]} headers
|
21
|
-
*/
|
22
|
-
headers: [{
|
23
|
-
dock : 'top',
|
24
|
-
items: [{
|
25
|
-
ntype: 'label',
|
26
|
-
text : 'On this page'
|
27
|
-
}, '->', {
|
28
|
-
iconCls: 'fas fa-chevron-right',
|
29
|
-
ui : 'secondary',
|
30
|
-
tooltip: 'Collapse Sections'
|
31
|
-
}]
|
32
|
-
}],
|
33
|
-
/**
|
34
|
-
* @member {Object[]} items
|
35
|
-
*/
|
36
|
-
items: [{
|
37
|
-
module : PageSectionsList,
|
38
|
-
reference: 'list'
|
39
|
-
}]
|
40
|
-
}
|
41
|
-
|
42
|
-
/**
|
43
|
-
* Convenience shortcut
|
44
|
-
* @member {Portal.view.learn.PageSectionsList} list
|
45
|
-
*/
|
46
|
-
get list() {
|
47
|
-
return this.getReference('list')
|
48
|
-
}
|
49
|
-
}
|
50
|
-
|
51
|
-
Neo.setupClass(PageSectionsPanel);
|
52
|
-
|
53
|
-
export default PageSectionsPanel;
|
@@ -1,24 +0,0 @@
|
|
1
|
-
.portal-page-sections-panel.neo-panel {
|
2
|
-
border: none; // reset the default 1px
|
3
|
-
|
4
|
-
@media only screen and (max-width: 1200px) {
|
5
|
-
display: none;
|
6
|
-
}
|
7
|
-
|
8
|
-
.neo-panel-header-toolbar {
|
9
|
-
border : none; // reset the default 1px
|
10
|
-
border-bottom: 1px solid #f2f2f2;
|
11
|
-
|
12
|
-
.neo-button {
|
13
|
-
// todo: we need styling for toolbar buttons within neo-theme-neo-light
|
14
|
-
border-radius: 4px;
|
15
|
-
height : inherit;
|
16
|
-
min-width : inherit;
|
17
|
-
padding : 5px 12px;
|
18
|
-
|
19
|
-
.neo-button-glyph {
|
20
|
-
color: var(--panel-header-text-color);
|
21
|
-
}
|
22
|
-
}
|
23
|
-
}
|
24
|
-
}
|