neo.mjs 10.0.0-beta.6 → 10.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.github/RELEASE_NOTES/v10.0.0-beta.1.md +20 -0
  2. package/.github/RELEASE_NOTES/v10.0.0-beta.2.md +73 -0
  3. package/.github/RELEASE_NOTES/v10.0.0-beta.3.md +39 -0
  4. package/.github/RELEASE_NOTES/v10.0.0.md +52 -0
  5. package/ServiceWorker.mjs +2 -2
  6. package/apps/portal/index.html +1 -1
  7. package/apps/portal/resources/data/blog.json +24 -0
  8. package/apps/portal/view/ViewportController.mjs +6 -4
  9. package/apps/portal/view/examples/List.mjs +28 -19
  10. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  11. package/examples/functional/button/base/MainContainer.mjs +207 -0
  12. package/examples/functional/button/base/app.mjs +6 -0
  13. package/examples/functional/button/base/index.html +11 -0
  14. package/examples/functional/button/base/neo-config.json +6 -0
  15. package/learn/blog/v10-deep-dive-functional-components.md +293 -0
  16. package/learn/blog/v10-deep-dive-reactivity.md +522 -0
  17. package/learn/blog/v10-deep-dive-state-provider.md +432 -0
  18. package/learn/blog/v10-deep-dive-vdom-revolution.md +194 -0
  19. package/learn/blog/v10-post1-love-story.md +383 -0
  20. package/learn/guides/uibuildingblocks/WorkingWithVDom.md +26 -2
  21. package/package.json +3 -3
  22. package/src/DefaultConfig.mjs +2 -2
  23. package/src/Neo.mjs +47 -45
  24. package/src/component/Abstract.mjs +412 -0
  25. package/src/component/Base.mjs +18 -380
  26. package/src/core/Base.mjs +34 -33
  27. package/src/core/Effect.mjs +30 -34
  28. package/src/core/EffectManager.mjs +101 -14
  29. package/src/core/Observable.mjs +69 -65
  30. package/src/form/field/Text.mjs +11 -5
  31. package/src/functional/button/Base.mjs +384 -0
  32. package/src/functional/component/Base.mjs +51 -145
  33. package/src/layout/Cube.mjs +8 -4
  34. package/src/manager/VDomUpdate.mjs +179 -94
  35. package/src/mixin/VdomLifecycle.mjs +4 -1
  36. package/src/state/Provider.mjs +41 -27
  37. package/src/util/VDom.mjs +11 -4
  38. package/src/util/vdom/TreeBuilder.mjs +38 -62
  39. package/src/worker/mixin/RemoteMethodAccess.mjs +1 -6
  40. package/test/siesta/siesta.js +15 -3
  41. package/test/siesta/tests/VdomCalendar.mjs +7 -7
  42. package/test/siesta/tests/VdomHelper.mjs +7 -7
  43. package/test/siesta/tests/classic/Button.mjs +113 -0
  44. package/test/siesta/tests/core/EffectBatching.mjs +46 -41
  45. package/test/siesta/tests/functional/Button.mjs +113 -0
  46. package/test/siesta/tests/state/ProviderNestedDataConfigs.mjs +59 -0
  47. package/test/siesta/tests/vdom/Advanced.mjs +14 -8
  48. package/test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs +9 -9
  49. package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +6 -6
  50. package/test/siesta/tests/vdom/layout/Cube.mjs +11 -7
  51. package/test/siesta/tests/vdom/table/Container.mjs +9 -5
  52. 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
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='10.0.0-beta.6'
23
+ * @member {String} version='10.0.1'
24
24
  */
25
- version: '10.0.0-beta.6'
25
+ version: '10.0.1'
26
26
  }
27
27
 
28
28
  /**
@@ -16,7 +16,7 @@
16
16
  "@type": "Organization",
17
17
  "name": "Neo.mjs"
18
18
  },
19
- "datePublished": "2025-07-18",
19
+ "datePublished": "2025-07-24",
20
20
  "publisher": {
21
21
  "@type": "Organization",
22
22
  "name": "Neo.mjs"
@@ -1,4 +1,28 @@
1
1
  [{
2
+ "author" : "Tobias Uhlig",
3
+ "authorImage" : "author_TobiasUhlig.jpeg",
4
+ "date" : "Jul 24, 2025",
5
+ "id" : 66,
6
+ "image" : "FrontendReactivityRevolution.png",
7
+ "name" : "Frontend Reactivity Revolution: Named vs. Anonymous State",
8
+ "provider" : "Medium",
9
+ "publisher" : "ITNEXT",
10
+ "selectedInto": [],
11
+ "type" : "Blog Post",
12
+ "url" : "https://itnext.io/frontend-reactivity-revolution-named-vs-anonymous-state-5428c1aa17b5?source=friends_link&sk=8391d8f6b8e18f68d37ac90129f355ff"
13
+ }, {
14
+ "author" : "Tobias Uhlig",
15
+ "authorImage" : "author_TobiasUhlig.jpeg",
16
+ "date" : "Jul 24, 2025",
17
+ "id" : 65,
18
+ "image" : "a_frontend_love_story.png",
19
+ "name" : "A Frontend Love Story",
20
+ "provider" : "Medium",
21
+ "publisher" : "ITNEXT",
22
+ "selectedInto": [],
23
+ "type" : "Blog Post",
24
+ "url" : "https://itnext.io/a-frontend-love-story-111e6eeea8a6?source=friends_link&sk=da33ff064e874dde2d215570fa580d00"
25
+ }, {
2
26
  "author" : "Tobias Uhlig",
3
27
  "authorImage" : "author_TobiasUhlig.jpeg",
4
28
  "date" : "Jun 02, 2025",
@@ -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.setSilent({
322
+ await container.set({
323
323
  layout: {ntype: 'cube', activeIndex, fitContainer: true, hideInactiveCardsOnDestroy: true}
324
324
  });
325
- await container.promiseUpdate();
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.layout = {ntype: 'card', activeIndex: index}
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 = this;
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 = this,
213
- {imageBasePath, store} = me,
214
- record = store.get(parseInt(data.data.recordId)),
215
- i = store.indexOf(record),
216
- len = Math.min(i + me.preloadImages, store.getCount()),
217
- needsUpdate = false,
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
 
@@ -108,7 +108,7 @@ class FooterContainer extends Container {
108
108
  }, {
109
109
  module: Component,
110
110
  cls : ['neo-version'],
111
- text : 'v10.0.0-beta.6'
111
+ text : 'v10.0.1'
112
112
  }]
113
113
  }],
114
114
  /**
@@ -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,6 @@
1
+ import MainContainer from './MainContainer.mjs';
2
+
3
+ export const onStart = () => Neo.app({
4
+ mainView: MainContainer,
5
+ name : 'Neo.examples.functional.button.base'
6
+ });
@@ -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>
@@ -0,0 +1,6 @@
1
+ {
2
+ "appPath" : "examples/functional/button/base/app.mjs",
3
+ "basePath" : "../../../../",
4
+ "environment": "development",
5
+ "mainPath" : "./Main.mjs"
6
+ }