neo.mjs 10.0.0-beta.6 → 10.0.0
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/.github/RELEASE_NOTES/v10.0.0-beta.1.md +20 -0
- package/.github/RELEASE_NOTES/v10.0.0-beta.2.md +73 -0
- package/.github/RELEASE_NOTES/v10.0.0-beta.3.md +39 -0
- package/.github/RELEASE_NOTES/v10.0.0.md +52 -0
- package/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/ViewportController.mjs +6 -4
- package/apps/portal/view/examples/List.mjs +28 -19
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/examples/functional/button/base/MainContainer.mjs +207 -0
- package/examples/functional/button/base/app.mjs +6 -0
- package/examples/functional/button/base/index.html +11 -0
- package/examples/functional/button/base/neo-config.json +6 -0
- package/learn/blog/v10-deep-dive-functional-components.md +293 -0
- package/learn/blog/v10-deep-dive-reactivity.md +522 -0
- package/learn/blog/v10-deep-dive-state-provider.md +432 -0
- package/learn/blog/v10-deep-dive-vdom-revolution.md +194 -0
- package/learn/blog/v10-post1-love-story.md +383 -0
- package/learn/guides/uibuildingblocks/WorkingWithVDom.md +26 -2
- package/package.json +3 -3
- package/src/DefaultConfig.mjs +2 -2
- package/src/Neo.mjs +47 -45
- package/src/component/Abstract.mjs +412 -0
- package/src/component/Base.mjs +18 -380
- package/src/core/Base.mjs +34 -33
- package/src/core/Effect.mjs +30 -34
- package/src/core/EffectManager.mjs +101 -14
- package/src/core/Observable.mjs +69 -65
- package/src/form/field/Text.mjs +11 -5
- package/src/functional/button/Base.mjs +384 -0
- package/src/functional/component/Base.mjs +51 -145
- package/src/layout/Cube.mjs +8 -4
- package/src/manager/VDomUpdate.mjs +179 -94
- package/src/mixin/VdomLifecycle.mjs +4 -1
- package/src/state/Provider.mjs +41 -27
- package/src/util/VDom.mjs +11 -4
- package/src/util/vdom/TreeBuilder.mjs +38 -62
- package/src/worker/mixin/RemoteMethodAccess.mjs +1 -6
- package/test/siesta/siesta.js +15 -3
- package/test/siesta/tests/VdomCalendar.mjs +7 -7
- package/test/siesta/tests/VdomHelper.mjs +7 -7
- package/test/siesta/tests/classic/Button.mjs +113 -0
- package/test/siesta/tests/core/EffectBatching.mjs +46 -41
- package/test/siesta/tests/functional/Button.mjs +113 -0
- package/test/siesta/tests/state/ProviderNestedDataConfigs.mjs +59 -0
- package/test/siesta/tests/vdom/Advanced.mjs +14 -8
- package/test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs +9 -9
- package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +6 -6
- package/test/siesta/tests/vdom/layout/Cube.mjs +11 -7
- package/test/siesta/tests/vdom/table/Container.mjs +9 -5
- package/src/core/EffectBatchManager.mjs +0 -67
@@ -0,0 +1,20 @@
|
|
1
|
+
## Neo.mjs v10.0.0-beta.1 Release Notes
|
2
|
+
|
3
|
+
We are excited to announce the release of Neo.mjs v10.0.0-beta.1, bringing significant architectural improvements, enhanced developer experience, and various stability fixes.
|
4
|
+
|
5
|
+
### Key Highlights:
|
6
|
+
|
7
|
+
* **Asynchronous Initialization with `initAsync()`**: The `core.Base` class now includes a powerful `async initAsync()` method, allowing asynchronous code to be executed outside of the traditional constructor chain, leveraging the microtask queue. This is a crucial improvement for registering **Remote Method Access** earlier in the application lifecycle, effectively eliminating a previously observed 4ms delay caused by reliance on the macro task queue.
|
8
|
+
* **Enhanced `main.addon.Base`**: The `main.addon.Base` class has received substantial enhancements to dynamically load files based on the new `initAsync` mechanism and properly respect the new `isReady_` configuration.
|
9
|
+
* **Revamped Learning Content Structure**: The entire Learning Content has been reorganized and moved into a new `learn` top-level repository folder.
|
10
|
+
* **Improved Learning Content Rendering**: The comprehensive Learning Content has been significantly enhanced to render more beautifully across different viewing environments. This was achieved by adopting standard Markdown fenced code blocks with info strings (e.g., ````javascript live-preview````). This ensures native syntax highlighting and excellent readability when viewed directly on the GitHub repository. Simultaneously, Neo.mjs's `ContentComponent.mjs` is now capable of dynamically processing these blocks for interactive features (such as `live-preview` and `neo-component` instantiation) and specialized styling (like `readonly` code blocks) within the Neo.mjs website. Specific SCSS adjustments in `ContentComponent.scss` further guarantee consistent and correct rendering of various code block types, including plain text/directory structures, by utilizing precise selectors like `:not(.hljs)` to prevent conflicts with Highlight.js and maintain visual integrity.
|
11
|
+
* **Grid and Table Refactoring Polish**: The extensive refactoring of `grid.View` to `grid.Body` and `table.View` to `table.Body` has been thoroughly polished and is now considered fully stable.
|
12
|
+
* **Delta Generation Fix**: A critical glitch within the v10 delta generation logic has been fixed, significantly reducing the amount of created deltas and ensuring that changes applied to the DOM are once again minimized to the bare essential.
|
13
|
+
|
14
|
+
## Try it out here
|
15
|
+
|
16
|
+
`dist/esm`:
|
17
|
+
https://neomjs.com/dist/esm/apps/portal/
|
18
|
+
|
19
|
+
`dist/production`:
|
20
|
+
https://neomjs.com/dist/production/apps/portal/
|
@@ -0,0 +1,73 @@
|
|
1
|
+
## Neo.mjs v10.0.0-beta.2 Release Notes
|
2
|
+
|
3
|
+
This beta release brings significant enhancements across documentation, core framework capabilities, and **a major focus on improving component rendering performance and security**, alongside an enhanced developer experience.
|
4
|
+
|
5
|
+
### Documentation & Learning Content
|
6
|
+
|
7
|
+
We've made substantial updates to the `learn` section to provide clearer, more comprehensive guidance:
|
8
|
+
|
9
|
+
* **Enhanced Benefits Guides**:
|
10
|
+
* **Forms Engine**: Improved introduction, detailed benefits, and business value connections for state management, unmounted
|
11
|
+
* validation, and nested/lazy-loaded forms.
|
12
|
+
* **Multi-Window Applications**: Expanded use cases and clearer explanations of seamless data/state sharing.
|
13
|
+
* **Quick Application Development**: Detailed how property lifecycle hooks, elegant state management, and powerful debugging
|
14
|
+
* contribute to rapid development.
|
15
|
+
* **Effort vs. Complexity**: Refined explanation of Neo.mjs's linear scaling of effort with complexity, including the initial learning curve.
|
16
|
+
* **Speed**: Improved introduction highlighting web worker benefits for performance.
|
17
|
+
* **Features Summary**: Updated with direct links to detailed benefit guides for easier navigation.
|
18
|
+
* **New RPC Layer Guide**: A dedicated guide (`learn/benefits/RPCLayer.md`) explaining the RPC layer's role in seamless
|
19
|
+
* communication across Web Workers, Main Threads, and backend services, including practical examples.
|
20
|
+
* **Updated Glossary**: The `learn/Glossary.md` has been significantly expanded and polished
|
21
|
+
* **Instance Lifecycle Guide**: New comprehensive guide (`learn/guides/InstanceLifecycle.md`) detailing the synchronous and
|
22
|
+
asynchronous phases of component creation and destruction, including `constructor()` vs. `construct()` and `isReady` concepts.
|
23
|
+
* **Main Thread Addons Guide**: Enhanced with visualizations for remote method access and explanations of `interceptRemotes` for
|
24
|
+
automatic method caching.
|
25
|
+
* **Learning Path Refinements**: The `learn/tree.json` structure has been reordered to provide a more logical learning progression for
|
26
|
+
guides.
|
27
|
+
* **Code Block Improvements**: Various formatting and rendering fixes for code blocks across documentation.
|
28
|
+
|
29
|
+
### Core Framework & Features
|
30
|
+
|
31
|
+
* **Remote Method Interception for Addons**: `addon.Base` now intercepts remote calls that arrive before an addon is fully
|
32
|
+
`isReady`, enabling more robust asynchronous initialization for addon methods.
|
33
|
+
* **New Class Hierarchy Manager**: Introduction of `manager.ClassHierarchy` (`#6876`), a new core manager that provides robust
|
34
|
+
class hierarchy information, including memoized `isA()` queries and integration into `Neo.Main` and other workers.
|
35
|
+
|
36
|
+
### Rendering & Components
|
37
|
+
|
38
|
+
* **Enhanced VDom Security & Performance (DomApiRenderer Integration)**: A major internal refactoring has been completed to
|
39
|
+
replace `html` with `text` on VDom node properties across
|
40
|
+
hundreds of components (`app/*`, `Neo.*`, `component.*`, `form.field.FileUpload`, `Neo.calendar.view.*`, `Portal.view.*`). This
|
41
|
+
significant change leverages the `DomApiRenderer` introduced in v10 to:
|
42
|
+
* **Improve Security**: By defaulting to `text` content, Neo.mjs now inherently prevents Cross-Site Scripting (XSS) vulnerabilities
|
43
|
+
by escaping HTML, making applications more secure by design.
|
44
|
+
* **Boost Performance**: Direct text manipulation is generally more performant than parsing and injecting HTML, leading to faster
|
45
|
+
and more efficient DOM updates.
|
46
|
+
* **`component.Base` `text_` Config**: Added a new `text_` config to `component.Base` for direct text content management.
|
47
|
+
* **Grid/Table Rendering**: `grid.Body` and `table.Body` now support the `text` property in `applyRendererOutput()`, offering an
|
48
|
+
alternative to `html` for rendering.
|
49
|
+
|
50
|
+
### Internal Improvements & Refactoring
|
51
|
+
|
52
|
+
* **`main.DeltaUpdates` Enhanced Initialization**: The `main.DeltaUpdates` module now utilizes `initAsync()`, a significant
|
53
|
+
improvement for its initialization process, alongside updated JSDoc comments.
|
54
|
+
* Minor code cleanups and method reordering in `vdom.Helper`.
|
55
|
+
* Minor fixes in `component.MagicMoveText` and `Portal.view.learn.ContentComponent`.
|
56
|
+
|
57
|
+
---
|
58
|
+
|
59
|
+
This release focuses heavily on improving the learning experience and solidifying core architectural patterns. We encourage you to explore the updated documentation and leverage the new features for more robust and performant applications.
|
60
|
+
|
61
|
+
All changes in 1 commit: https://github.com/neomjs/neo/commit/ee8ccd1943a4fc198ec440dcb44146c9f1787193
|
62
|
+
|
63
|
+
### Call To Action
|
64
|
+
|
65
|
+
We're excited for you to dive into the enhanced learning experience!
|
66
|
+
|
67
|
+
* **Explore the New Guides**: Discover the power of Neo.mjs by exploring updated sections like
|
68
|
+
* [Main Thread Addons Guide](
|
69
|
+
https://neomjs.com/dist/esm/apps/portal/#/learn/guides.MainThreadAddons)
|
70
|
+
* [Forms Engine benefits](https://neomjs.com/dist/esm/apps/portal/#/learn/benefits.FormsEngine)
|
71
|
+
* [Glossary](https://neomjs.com/dist/esm/apps/portal/#/learn/Glossary).
|
72
|
+
* **Share Your Feedback**: Your input is invaluable! Please let us know what you think, report any issues, or suggest further
|
73
|
+
improvements via [GitHub Issues](https://github.com/neomjs/neo/issues) or our [Slack Channel](https://join.slack.com/t/neomjs/shared_invite/zt-6c50ueeu-3E1~M4T9xkNnb~M_prEEOA).
|
@@ -0,0 +1,39 @@
|
|
1
|
+
## Neo.mjs v10.0.0-beta.3 Release Notes
|
2
|
+
|
3
|
+
This beta release significantly expands our learning resources, introducing **seven new comprehensive guides** designed to accelerate developer onboarding and mastery of the neo.mjs framework. We've also invested in enhancing the overall styling and user experience of the learning section.
|
4
|
+
|
5
|
+
### Documentation & Learning Content
|
6
|
+
|
7
|
+
We are excited to announce a major update to the `learn` section, with seven new guides to provide in-depth knowledge on key neo.mjs concepts.
|
8
|
+
|
9
|
+
**For the optimal learning experience, including live code previews and interactive examples, we strongly recommend viewing these guides on our website: [neomjs.com#/learn](https://neomjs.com/dist/production/apps/portal/index.html#/learn)**
|
10
|
+
|
11
|
+
* **New In-Depth Guides**:
|
12
|
+
* **Collections**: A comprehensive guide to understanding and utilizing neo.mjs collections for efficient data management.
|
13
|
+
* **Custom Components**: Learn how to create your own custom components to build modular and reusable UI elements.
|
14
|
+
* **Extending neo.mjs Classes**: A guide to extending the framework's core classes to add custom functionality and behavior.
|
15
|
+
* **Forms**: Learn how to build powerful and flexible forms with the neo.mjs forms engine.
|
16
|
+
* **Layouts**: A guide to using layouts to create responsive and adaptive user interfaces.
|
17
|
+
* **Records**: An in-depth look at working with data records, a fundamental aspect of the neo.mjs data package.
|
18
|
+
* **ComboBox Field**: A dedicated guide to the versatile ComboBox field, covering its configuration and use cases.
|
19
|
+
* **Enhanced Learning Experience**:
|
20
|
+
* The styling of the learning section has been improved for displaying code blocks inside headlines and code blocks inside lists.
|
21
|
+
---
|
22
|
+
|
23
|
+
This release is focused on empowering developers with the knowledge and resources needed to build exceptional applications with neo.mjs. We encourage you to explore the new guides and see how they can help you in your projects.
|
24
|
+
|
25
|
+
All changes in 1 commit: https://github.com/neomjs/neo/commit/c68a0c9fab1d5578bbd5120ba97bbd7707093b7c
|
26
|
+
|
27
|
+
### Call To Action
|
28
|
+
|
29
|
+
We're excited for you to dive into the enhanced learning experience!
|
30
|
+
|
31
|
+
* **Explore the New Guides**: Discover the power of Neo.mjs by exploring the new guides on our website:
|
32
|
+
* [Collections](https://neomjs.com/dist/esm/apps/portal/#/learn/guides.Collections)
|
33
|
+
* [Custom Components](https://neomjs.com/dist/esm/apps/portal/#/learn/guides.CustomComponents)
|
34
|
+
* [Extending neo.mjs Classes](https://neomjs.com/dist/esm/apps/portal/#/learn/guides.ExtendingNeoClasses)
|
35
|
+
* [Forms](https://neomjs.com/dist/esm/apps/portal/#/learn/guides.Forms)
|
36
|
+
* [Layouts](https://neomjs.com/dist/esm/apps/portal/#/learn/guides.Layouts)
|
37
|
+
* [Records](https://neomjs.com/dist/esm/apps/portal/#/learn/guides.Records)
|
38
|
+
* [ComboBox Field](https://neomjs.com/dist/esm/apps/portal/#/learn/guides.form_fields.ComboBox)
|
39
|
+
* **Share Your Feedback**: Your input is invaluable! Please let us know what you think, report any issues, or suggest further improvements via [GitHub Issues](https://github.com/neomjs/neo/issues) or our [Slack Channel](https://join.slack.com/t/neomjs/shared_invite/zt-6c50ueeu-3E1~M4T9xkNnb~M_prEEOA).
|
@@ -0,0 +1,52 @@
|
|
1
|
+
### Neo.mjs v10.0.0 Stable Release Notes
|
2
|
+
|
3
|
+
This release brings significant enhancements and refactorings, improving performance, reactivity, and the overall developer experience.
|
4
|
+
|
5
|
+
#### Core Framework Improvements
|
6
|
+
|
7
|
+
* **Reactive Core Refactoring (`core.Observable`):**
|
8
|
+
* Architectural refactoring of `core.Observable` to a fully reactive mixin (`#7090`).
|
9
|
+
* **Modernized `core.Observable`:** Refactored `core.Observable` to align with the reactive config system. This involved converting the `listeners` property to a reactive `listeners_` config, eliminating manual initialization, and establishing true encapsulation using a module-scoped `Symbol` (`eventMapSymbol`) for internal event registry management. A bug in `removeListener` related to incorrect state access was also fixed. (`#7090`)
|
10
|
+
* Listeners are now managed as a reactive config within `core.Observable` (`#7089`).
|
11
|
+
* **Effect Management System:**
|
12
|
+
* **Foundational Refactoring of Effect Management:** The core reactivity system has been refactored and unified under a single `Neo.core.EffectManager` (`#7085`). This introduces a clear distinction between:
|
13
|
+
* **Execution Batching (`pause()` / `resume()`):** Replaced the old `isPaused` flag with a numeric `pauseCounter` for robust, nested batching of UI updates. Effects are queued and executed only when the counter is zero.
|
14
|
+
* **Dependency Tracking Suppression (`pauseTracking()` / `resumeTracking()`):** A new mechanism (`isTrackingPaused` flag) to temporarily stop active effects from collecting new dependencies, solving self-dependency issues.
|
15
|
+
* The `EffectBatchManager` singleton has been completely removed, and its functionality absorbed by the enhanced `EffectManager`. This results in a more predictable, robust, and resilient reactive system.
|
16
|
+
* **State Management:**
|
17
|
+
* **State Provider Refactoring & Deep Merging:**
|
18
|
+
* Refactored `state.Provider`'s `internalSetData()` method to support intuitive deep-merging of nested objects, allowing dynamic creation of new, fully reactive data structures at runtime. This resolves inconsistent behavior and aligns with expected merge operations. (`#7099`)
|
19
|
+
* **Enhanced Reactivity & Atomic Updates:** `state.Provider` now features "Reactivity Bubbling," where changes to leaf properties recursively update parent objects, correctly triggering effects on intermediate data objects. Public `setData()` and `setDataAtSameLevel()` methods are now wrapped with `Neo.batch()` (leveraging the new `EffectManager`'s batching capabilities) to ensure all reactive updates are collected, de-duplicated, and executed atomically, preventing race conditions and improving performance. A new test suite (`ProviderNestedDataConfigs.mjs`) validates this functionality.
|
20
|
+
* Moved all state provider related logic (configs like `bind`, `modelData`, `stateProvider_`, `data_`, `parentComponent_`, and methods like `getStateProvider()`, `getState()`, `setState()`, `beforeGetData()`, `getConfigInstanceByNtype()`, along with lifecycle logic and two-way binding logic) from `src/component/Base.mjs` to `src/component/Abstract.mjs`. This makes state providers available to both classic class-based components and modern functional components. (`#7100`)
|
21
|
+
* **Component Base Classes:**
|
22
|
+
* **Common Abstract Base Class:** Introduced `Neo.component.Abstract` as a new common base class for both `Neo.component.Base` (classic) and `Neo.functional.component.Base` (functional) components. This refactoring centralizes shared logic (e.g., `set()`, `destroy()`, `mountedPromise`, core configs, `DomEvents`, `Observable`, `VdomLifecycle` mixins), improving code reusability, enhancing consistency, and simplifying maintenance by removing duplicated code. (`#7089`)
|
23
|
+
* Removed redundant `createBindings()` calls from `onConstructed` (`#7101`).
|
24
|
+
|
25
|
+
#### Functional Components
|
26
|
+
|
27
|
+
* **VDOM Reconciliation:** Enhanced Functional Component VDOM Reconciliation (`#7086`).
|
28
|
+
* **Lifecycle Hook:** Introduced a new `beforeUpdate()` lifecycle method to `Neo.functional.component.Base` (`#7084`). This hook executes after all state changes from a reactive `Effect` have been processed and just before `updateVdom()`. It provides a predictable entry point for pre-render logic and allows conditionally canceling a VDOM update by returning `false`.
|
29
|
+
* **Functional Button Component:** Introduced a new `Neo.functional.button.Base` component (`#7087`). This component serves as a key UI element built using the functional component paradigm, demonstrating integration with the reactive VDOM system and leveraging automatic VDOM node ID generation for efficient diffing. A dedicated test suite and demo application were created.
|
30
|
+
* `functional.button.Base`: `beforeSetBadgePosition()`, `beforeSetIconPosition()` now use constructor access for future class extensions.
|
31
|
+
|
32
|
+
#### VDOM & Rendering
|
33
|
+
|
34
|
+
* `util.vdom.TreeBuilder`: Improvements to `buildTree()`: Refactored `getVdomTree` and `getVnodeTree` into a single, DRY method (`#7098`).
|
35
|
+
* `util.VDom`: `syncVdomIds()` enhanced for future-proofing and improved filtering.
|
36
|
+
* `manager.VDomUpdate`: Significantly enhanced JSDoc comments and method order/cleanup.
|
37
|
+
|
38
|
+
#### Other Enhancements & Fixes
|
39
|
+
|
40
|
+
* **Dependencies:** Updated FontAwesome to v7.
|
41
|
+
* **Examples Website:** Fixed flakiness on Safari (`#7102`).
|
42
|
+
* **Tests:** All 770 unit tests now pass successfully, including a significant number of new tests added since beta.6.
|
43
|
+
* `form.field.Text`: `onInputValueChange()` intent made clearer.
|
44
|
+
* `Portal.view.ViewportController`: Cube-layout timing adjustments.
|
45
|
+
* `core.core.EffectManager`: Optimized `Neo.batch` usage.
|
46
|
+
* Removed obsolete `onNeoConfigChange()` calls from tests.
|
47
|
+
* Updated `test/siesta/tests/vdom/layout/Cube.mjs` to match current `VdomHelper.create()` signature.
|
48
|
+
|
49
|
+
#### Documentation Updates
|
50
|
+
|
51
|
+
* The `learn/guides/datahandling/StateProviders.md` guide has been updated to accurately describe the new deep-merge behavior of state providers.
|
52
|
+
* Code examples in the `learn/blog/v10-deep-dive-state-provider.md` blog post have been updated to demonstrate the intuitive API usage.
|
package/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
@@ -319,11 +319,10 @@ class ViewportController extends Controller {
|
|
319
319
|
|
320
320
|
// enable "fast clicking" on main nav items => do not replace a cube layout with a new instance of cube
|
321
321
|
if (container.layout.ntype !== 'layout-cube') {
|
322
|
-
container.
|
322
|
+
await container.set({
|
323
323
|
layout: {ntype: 'cube', activeIndex, fitContainer: true, hideInactiveCardsOnDestroy: true}
|
324
324
|
});
|
325
|
-
await
|
326
|
-
await me.timeout(50);
|
325
|
+
await me.timeout(20)
|
327
326
|
}
|
328
327
|
|
329
328
|
container.layout.activeIndex = index;
|
@@ -331,7 +330,10 @@ class ViewportController extends Controller {
|
|
331
330
|
await me.timeout(1100);
|
332
331
|
|
333
332
|
if (transitionId === me.#transitionId) {
|
334
|
-
container.
|
333
|
+
await container.set({
|
334
|
+
layout: {ntype: 'card', activeIndex: index}
|
335
|
+
});
|
336
|
+
await me.timeout(20)
|
335
337
|
}
|
336
338
|
}
|
337
339
|
|
@@ -103,16 +103,18 @@ class List extends BaseList {
|
|
103
103
|
|
104
104
|
/**
|
105
105
|
* @param {Object} record
|
106
|
+
* @param {Number} index
|
106
107
|
*/
|
107
|
-
createItemContent(record) {
|
108
|
-
let me
|
108
|
+
createItemContent(record, index) {
|
109
|
+
let me = this,
|
110
|
+
imageStyle = index < 4 ? me.getBackgroundImageStyle(record) : null;
|
109
111
|
|
110
112
|
return [
|
111
113
|
{cls: ['content', 'neo-relative'], data: {recordId: record.id}, removeDom: me.isHiddenItem(record), cn: [
|
112
114
|
{cls: ['neo-multi-window'], data: {neoTooltip: 'Multi Window Demo'}, removeDom: !record.sharedWorkers, cn: [
|
113
115
|
{cls: ['far', 'fa-window-restore']}
|
114
116
|
]},
|
115
|
-
{cls: ['neo-full-size', 'preview-image'], flag: `image-${record.id}
|
117
|
+
{cls: ['neo-full-size', 'preview-image'], flag: `image-${record.id}`, style: imageStyle},
|
116
118
|
{cls: ['neo-absolute', 'neo-item-bottom-position'], cn: [
|
117
119
|
{...me.createLink(record)},
|
118
120
|
{cls: ['neo-top-20'], cn: [
|
@@ -177,6 +179,22 @@ class List extends BaseList {
|
|
177
179
|
return vdom
|
178
180
|
}
|
179
181
|
|
182
|
+
/**
|
183
|
+
* @param record
|
184
|
+
* @returns {{backgroundImage: string}}
|
185
|
+
*/
|
186
|
+
getBackgroundImageStyle(record) {
|
187
|
+
return {
|
188
|
+
backgroundImage: [
|
189
|
+
`url('${this.imageBasePath}/${record.image}'),`,
|
190
|
+
'linear-gradient(',
|
191
|
+
'var(--portal-examples-list-gradient-start),',
|
192
|
+
'var(--portal-examples-list-gradient-end)',
|
193
|
+
')'
|
194
|
+
].join('')
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
180
198
|
/**
|
181
199
|
* @returns {Object}
|
182
200
|
*/
|
@@ -209,12 +227,12 @@ class List extends BaseList {
|
|
209
227
|
* @param {Object} data
|
210
228
|
*/
|
211
229
|
onIntersect(data) {
|
212
|
-
let me
|
213
|
-
{
|
214
|
-
record
|
215
|
-
i
|
216
|
-
len
|
217
|
-
needsUpdate
|
230
|
+
let me = this,
|
231
|
+
{store} = me,
|
232
|
+
record = store.get(parseInt(data.data.recordId)),
|
233
|
+
i = store.indexOf(record),
|
234
|
+
len = Math.min(i + me.preloadImages, store.getCount()),
|
235
|
+
needsUpdate = false,
|
218
236
|
node;
|
219
237
|
|
220
238
|
for (; i < len; i++) {
|
@@ -222,16 +240,7 @@ class List extends BaseList {
|
|
222
240
|
|
223
241
|
if (!node.style) {
|
224
242
|
needsUpdate = true;
|
225
|
-
|
226
|
-
node.style = {
|
227
|
-
backgroundImage: [
|
228
|
-
`url('${imageBasePath}/${record.image}'),`,
|
229
|
-
'linear-gradient(',
|
230
|
-
'var(--portal-examples-list-gradient-start),',
|
231
|
-
'var(--portal-examples-list-gradient-end)',
|
232
|
-
')'
|
233
|
-
].join('')
|
234
|
-
}
|
243
|
+
node.style = me.getBackgroundImageStyle(record)
|
235
244
|
}
|
236
245
|
}
|
237
246
|
|
@@ -0,0 +1,207 @@
|
|
1
|
+
import CheckBox from '../../../../src/form/field/CheckBox.mjs';
|
2
|
+
import ComboBox from '../../../../src/form/field/ComboBox.mjs';
|
3
|
+
import ConfigurationViewport from '../../../ConfigurationViewport.mjs';
|
4
|
+
import FunctionalButton from '../../../../src/functional/button/Base.mjs';
|
5
|
+
import NumberField from '../../../../src/form/field/Number.mjs';
|
6
|
+
import Radio from '../../../../src/form/field/Radio.mjs';
|
7
|
+
import TextField from '../../../../src/form/field/Text.mjs';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @class Neo.examples.functional.button.base.MainContainer
|
11
|
+
* @extends Neo.examples.ConfigurationViewport
|
12
|
+
*/
|
13
|
+
class MainContainer extends ConfigurationViewport {
|
14
|
+
static config = {
|
15
|
+
className : 'Neo.examples.functional.button.base.MainContainer',
|
16
|
+
configItemLabelWidth: 160,
|
17
|
+
configItemWidth : 280,
|
18
|
+
layout : {ntype: 'hbox', align: 'stretch'}
|
19
|
+
}
|
20
|
+
|
21
|
+
createConfigurationComponents() {
|
22
|
+
let me = this;
|
23
|
+
|
24
|
+
return [{
|
25
|
+
module : Radio,
|
26
|
+
checked : me.exampleComponent.badgePosition === 'bottom-left',
|
27
|
+
hideValueLabel: false,
|
28
|
+
labelText : 'badgePosition',
|
29
|
+
listeners : {change: me.onRadioChange.bind(me, 'badgePosition', 'bottom-left')},
|
30
|
+
name : 'badgePosition',
|
31
|
+
valueLabelText: 'bottom-left'
|
32
|
+
}, {
|
33
|
+
module : Radio,
|
34
|
+
checked : me.exampleComponent.badgePosition === 'bottom-right',
|
35
|
+
hideValueLabel: false,
|
36
|
+
labelText : '',
|
37
|
+
listeners : {change: me.onRadioChange.bind(me, 'badgePosition', 'bottom-right')},
|
38
|
+
name : 'badgePosition',
|
39
|
+
valueLabelText: 'bottom-right'
|
40
|
+
}, {
|
41
|
+
module : Radio,
|
42
|
+
checked : me.exampleComponent.badgePosition === 'top-left',
|
43
|
+
hideValueLabel: false,
|
44
|
+
labelText : '',
|
45
|
+
listeners : {change: me.onRadioChange.bind(me, 'badgePosition', 'top-left')},
|
46
|
+
name : 'badgePosition',
|
47
|
+
valueLabelText: 'top-left'
|
48
|
+
}, {
|
49
|
+
module : Radio,
|
50
|
+
checked : me.exampleComponent.badgePosition === 'top-right',
|
51
|
+
hideValueLabel: false,
|
52
|
+
labelText : '',
|
53
|
+
listeners : {change: me.onRadioChange.bind(me, 'badgePosition', 'top-right')},
|
54
|
+
name : 'badgePosition',
|
55
|
+
valueLabelText: 'top-right'
|
56
|
+
}, {
|
57
|
+
module : TextField,
|
58
|
+
labelText : 'badgeText',
|
59
|
+
listeners : {change: me.onConfigChange.bind(me, 'badgeText')},
|
60
|
+
style : {marginTop: '10px'},
|
61
|
+
value : me.exampleComponent.badgeText
|
62
|
+
}, {
|
63
|
+
module : CheckBox,
|
64
|
+
checked : me.exampleComponent.disabled,
|
65
|
+
labelText: 'disabled',
|
66
|
+
listeners: {change: me.onConfigChange.bind(me, 'disabled')},
|
67
|
+
style : {marginTop: '10px'}
|
68
|
+
}, {
|
69
|
+
module : NumberField,
|
70
|
+
clearable : true,
|
71
|
+
labelText : 'height',
|
72
|
+
listeners : {change: me.onConfigChange.bind(me, 'height')},
|
73
|
+
maxValue : 300,
|
74
|
+
minValue : 30,
|
75
|
+
stepSize : 5,
|
76
|
+
style : {marginTop: '10px'},
|
77
|
+
value : me.exampleComponent.height
|
78
|
+
}, {
|
79
|
+
module : TextField, // todo: selectField with options
|
80
|
+
labelText : 'iconCls',
|
81
|
+
listeners : {change: me.onConfigChange.bind(me, 'iconCls')},
|
82
|
+
value : me.exampleComponent.iconCls
|
83
|
+
}, {
|
84
|
+
module : TextField, // todo: colorPickerField
|
85
|
+
clearable : true,
|
86
|
+
labelText : 'iconColor',
|
87
|
+
listeners : {change: me.onConfigChange.bind(me, 'iconColor')},
|
88
|
+
value : me.exampleComponent.iconColor
|
89
|
+
}, {
|
90
|
+
module : Radio,
|
91
|
+
checked : me.exampleComponent.iconPosition === 'top',
|
92
|
+
hideValueLabel: false,
|
93
|
+
labelText : 'iconPosition',
|
94
|
+
listeners : {change: me.onRadioChange.bind(me, 'iconPosition', 'top')},
|
95
|
+
name : 'iconPosition',
|
96
|
+
style : {marginTop: '10px'},
|
97
|
+
valueLabelText: 'top'
|
98
|
+
}, {
|
99
|
+
module : Radio,
|
100
|
+
checked : me.exampleComponent.iconPosition === 'right',
|
101
|
+
hideValueLabel: false,
|
102
|
+
labelText : '',
|
103
|
+
listeners : {change: me.onRadioChange.bind(me, 'iconPosition', 'right')},
|
104
|
+
name : 'iconPosition',
|
105
|
+
valueLabelText: 'right'
|
106
|
+
}, {
|
107
|
+
module : Radio,
|
108
|
+
checked : me.exampleComponent.iconPosition === 'bottom',
|
109
|
+
hideValueLabel: false,
|
110
|
+
labelText : '',
|
111
|
+
listeners : {change: me.onRadioChange.bind(me, 'iconPosition', 'bottom')},
|
112
|
+
name : 'iconPosition',
|
113
|
+
valueLabelText: 'bottom'
|
114
|
+
}, {
|
115
|
+
module : Radio,
|
116
|
+
checked : me.exampleComponent.iconPosition === 'left',
|
117
|
+
hideValueLabel: false,
|
118
|
+
labelText : '',
|
119
|
+
listeners : {change: me.onRadioChange.bind(me, 'iconPosition', 'left')},
|
120
|
+
name : 'iconPosition',
|
121
|
+
valueLabelText: 'left'
|
122
|
+
}, {
|
123
|
+
module : NumberField,
|
124
|
+
clearable : true,
|
125
|
+
labelText : 'rippleEffectDuration',
|
126
|
+
listeners : {change: me.onConfigChange.bind(me, 'rippleEffectDuration')},
|
127
|
+
maxValue : 5000,
|
128
|
+
minValue : 100,
|
129
|
+
stepSize : 100,
|
130
|
+
style : {marginTop: '10px'},
|
131
|
+
value : me.exampleComponent.rippleEffectDuration
|
132
|
+
}, {
|
133
|
+
module : TextField,
|
134
|
+
clearable : true,
|
135
|
+
labelText : 'text',
|
136
|
+
listeners : {change: me.onConfigChange.bind(me, 'text')},
|
137
|
+
style : {marginTop: '10px'},
|
138
|
+
value : me.exampleComponent.text
|
139
|
+
}, {
|
140
|
+
module : TextField,
|
141
|
+
clearable : true,
|
142
|
+
labelText : 'tooltip',
|
143
|
+
listeners : {change: me.onConfigChange.bind(me, 'tooltip')},
|
144
|
+
style : {marginTop: '10px'},
|
145
|
+
value : me.exampleComponent.tooltip
|
146
|
+
}, {
|
147
|
+
module : ComboBox,
|
148
|
+
forceSelection: true,
|
149
|
+
labelText : 'ui',
|
150
|
+
listeners : {change: me.onConfigRecordChange.bind(me, 'ui')},
|
151
|
+
style : {marginTop: '10px'},
|
152
|
+
value : me.exampleComponent.ui,
|
153
|
+
|
154
|
+
store: {
|
155
|
+
data: [
|
156
|
+
{id: 'primary', name: 'primary'},
|
157
|
+
{id: 'secondary', name: 'secondary'},
|
158
|
+
{id: 'tertiary', name: 'tertiary'}
|
159
|
+
]
|
160
|
+
}
|
161
|
+
}, {
|
162
|
+
module : CheckBox,
|
163
|
+
checked : me.exampleComponent.useRippleEffect,
|
164
|
+
labelText: 'useRippleEffect',
|
165
|
+
listeners: {change: me.onConfigChange.bind(me, 'useRippleEffect')},
|
166
|
+
style : {marginTop: '10px'}
|
167
|
+
}, {
|
168
|
+
module : NumberField,
|
169
|
+
clearable : true,
|
170
|
+
labelText : 'width',
|
171
|
+
listeners : {change: me.onConfigChange.bind(me, 'width')},
|
172
|
+
maxValue : 300,
|
173
|
+
minValue : 100,
|
174
|
+
stepSize : 5,
|
175
|
+
style : {marginTop: '10px'},
|
176
|
+
value : me.exampleComponent.width
|
177
|
+
}];
|
178
|
+
}
|
179
|
+
|
180
|
+
/**
|
181
|
+
* @returns {Neo.component.Base}
|
182
|
+
*/
|
183
|
+
createExampleComponent() {
|
184
|
+
return Neo.create({
|
185
|
+
module : FunctionalButton,
|
186
|
+
badgeText: 'Badge',
|
187
|
+
flex : 'none',
|
188
|
+
handler : data => console.log('button click =>', data.component.id),
|
189
|
+
height : 50,
|
190
|
+
iconCls : 'fa fa-home',
|
191
|
+
style : {marginBottom: '1500px', marginTop: '500px'},
|
192
|
+
text : 'Hello World',
|
193
|
+
ui : 'primary',
|
194
|
+
width : 150
|
195
|
+
})
|
196
|
+
}
|
197
|
+
|
198
|
+
/**
|
199
|
+
* @param {String} config
|
200
|
+
* @param {Object} opts
|
201
|
+
*/
|
202
|
+
onConfigRecordChange(config, opts) {
|
203
|
+
this.exampleComponent[config] = opts.value['id']
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
export default Neo.setupClass(MainContainer);
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!DOCTYPE HTML>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<title>Neo Functional Button</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<script src="../../../../src/MicroLoader.mjs" type="module"></script>
|
10
|
+
</body>
|
11
|
+
</html>
|