Releases: neomjs/neo
v10.3.2 Hotfix Release
This hotfix addresses an issue where changing the tabBarPosition config for tab.Container did not correctly update the UI. Additionally, a broader refactoring was applied to improve component lifecycle management.
Fixes
- tab.Container: Resolved an issue where switching
tabBarPositiondid not correctly update the UI. ThetabBarcomponent'sdockconfig now properly reflects the new position, ensuring correct rendering. This fix involved addingtabBarPositionto theconfigobject, and implementingafterSetTabBarPositionandbeforeSetTabBarPositionmethods to manage UI updates and component creation. - Component Lifecycle: Replaced
this.renderedwiththis.vnodeInitializedacross various components (Circle,Gallery,Helix,Dialog,Textfield,GridBody,Flexbox,List,TableBody). This change refines the component lifecycle management, ensuring that UI updates and other operations are performed when the virtual DOM node is properly initialized. - Font Awesome v7 Adjusted 3 spots inside our theming, where v6 was still in use.
- Earthquakes Tutorial Fixed a malformed code closing tag, added a warning that the labs are currently not working.
Neo.mjs v10.3.1: Build Process Reliability
This is a patch release focused on improving the stability and reliability of the core build process.
Key Fix: Build Process Dependency Order
The Problem
The main buildAll.mjs script could fail on a clean repository checkout. The build steps that process HTML templates (e.g., buildESModules) have a dependency on the dist/parse5.mjs bundle. However, the script did not guarantee that this bundle was created before it was needed, leading to a potential crash.
The Solution
We have updated buildAll.mjs to explicitly run the bundleParse5.mjs script as one of its first actions, immediately after the optional npm install.
The Impact
This change ensures the parse5 dependency is always available for subsequent build tasks. It makes the build process more robust and predictable, particularly for developers setting up the project for the first time.
Neo.mjs v10.3.0: Introducing HTML Templates
This release marks a major milestone in the evolution of Neo.mjs, introducing an intuitive, HTML-like syntax for building component VDOMs. This has been a significant undertaking, designed to lower the barrier to entry for new developers while holding true to the framework's core principles of performance and adherence to web standards.
This feature is the culmination of the work tracked in our public epic: #7130.
Key Feature: HTML Templates
You can now define a component's VDOM using familiar HTML-like syntax, powered by standard JavaScript Tagged Template Literals. This provides an alternative to the traditional JSON-based VDOM structure, making UI development more approachable.
import { html } from '../../src/functional/util/html.mjs';
import Button from '../../src/button/Base.mjs';
// Inside a component's render() method:
return html`
<div class="my-container">
<p>${this.myText}</p>
<${Button} text="Click Me" handler="${this.onButtonClick}" />
</div>
`;The Philosophy: Why Not JSX?
This new feature is built on a core Neo.mjs principle: a commitment to a zero-builds development experience.
- Standard JavaScript: Unlike JSX, which requires a compiler,
htmltemplates are a standard JavaScript feature. Your code runs directly in the browser without a mandatory build step, providing an instant feedback loop. - No Hidden Magic: Logic is handled with plain JavaScript (
if/else,.map()), not special template directives. What you write is what you get.
The Dual-Mode Architecture
To achieve both developer convenience and production performance, the framework uses a sophisticated dual-mode approach:
- Development Mode: Templates are parsed live in the browser using
parse5. This parser is only loaded if templates are actually used, ensuring zero overhead for applications that stick to the JSON VDOM. - Production Mode: For
dist/esm,dist/dev, anddist/prodbuilds, a powerful build-time AST transformation converts templates directly into optimized VDOM objects. This eliminates theparse5dependency from production builds entirely, resulting in zero runtime parsing overhead and maximum performance. TheenableHtmlTemplatesflag is also automatically set tofalsein production environments, ensuring that the runtime parser is never accidentally used.
As a developer convenience, if you name your template-generating method render(), the build process will automatically rename it to createVdom() for you, aligning with the framework's lifecycle methods while providing a familiar entry point.
Foundational Enhancements
The introduction of HTML templates was made possible by a series of significant enhancements to the framework's core and build scripts:
- Component Lifecycle Integration (
src/functional/component/Base.mjs): The functional component base class was updated to recognize and process the newHtmlTemplatereturn type fromrender(), seamlessly integrating the parsing process into the component lifecycle. - Runtime Parsing (
src/functional/util/HtmlTemplateProcessor.mjs): A new runtime processor that intelligently flattens nested templates, handles dynamic values, and usesparse5to convert the HTML string into a VDOM structure. - Build-Time AST Processing (
buildScripts/util/astTemplateProcessor.mjs): A new, robust build-time processor that usesacornto parse source code into an Abstract Syntax Tree (AST), replaces template literals with their VDOM object counterparts, and generates new, optimized code withastring. - Webpack Integration (
buildScripts/webpack/loader/template-loader.mjs): A new Webpack loader that hooks the AST processor into thedist/devanddist/prodbuild pipelines, applied only to the app worker where components live.
New Documentation
To support this major new feature, we have added two comprehensive guides:
- Using HTML Templates: A guide focused on the syntax, features, and best practices for using the new template system.
- Under the Hood: HTML Templates: A deep dive into the philosophy and the dual-mode architecture, explaining how templates work in both development and production environments.
All changes combined into 1 commit: 0841e7e
We are incredibly excited about this release and believe it makes Neo.mjs more powerful and accessible than ever. Please explore the new feature, read the documentation, and share your feedback!
Try it out by yourself:
https://neomjs.com/examples/functional/nestedTemplateComponent/
https://neomjs.com/dist/esm/examples/functional/nestedTemplateComponent/
https://neomjs.com/dist/development/examples/functional/nestedTemplateComponent/

housekeeping
Neo.mjs v10.2.1 Release Notes
Introduction
Version 10.2.1 is a patch release that addresses a critical layout regression discovered in lazy-loaded tabs and introduces a significant enhancement to the button.Base component, improving both its flexibility and security.
Key Changes
Enhancements
- Button Text as VDOM: The
textconfig forNeo.button.Basehas been enhanced to accept a VDOMcn(children) array in addition to a string. This allows for rich, complex button content to be defined in a structured, secure, and performant way, avoiding the need forinnerHTMLand enabling granular delta updates for the button's content. See ticket #7135.
Bug Fixes
-
Lazy-Loaded Tab Layout Regression: Fixed a critical regression where the
layoutconfig of a lazy-loaded tab (e.g., aPanel) was being mutated on the class prototype, causing subsequent lazy-loaded tabs to fail with a missingntypeerror. The fix, implemented incontainer.Base, ensures that each container instance gets a unique, deep-cloned copy of its layout config, preventing prototype pollution. See ticket #7134. -
Covid App Navigation Rendering: Fixed a rendering issue in the
GalleryContainerandHelixContainerof the Covid apps where the navigation instructions were not being displayed correctly. Thetextconfig was changed tohtmlon theBoxLabelcomponents to ensure the HTML content is rendered as expected. See issue #7133.
Stabilization, DX Improvements & Template PoC
Neo.mjs v10.2.0 Release Notes
Introduction
Following the major architectural changes in v10.0.0 with the new core and state provider, v10.2.0 is focused on stabilization, refinement, and developer experience. This release adjusts our demonstration applications to the new architecture, fixes key regressions in the single and multi-window Covid apps, and polishes the Big Data Grid example.
A key highlight is the introduction of an early-stage proof-of-concept for string-based VDOM templates, offering a more intuitive way to build functional components.
Key Changes
New Features & Enhancements
-
PoC: String-Based VDOM Templates: An initial proof-of-concept for using tagged template literals to define VDOM in functional components has been introduced. This feature can be enabled via the
enableHtmlTemplatesconfig and provides a more familiar, HTML-like syntax for building component views. See commita3bbca76653ffc822a102e9bde76dea3d8e7bb8b. -
Synchronous
fireChangeEvent: ThefireChangeEventmethod inComboBoxand other form fields is now fully synchronous. This resolves critical timing issues in applications like the Covid tracker, where dependent logic needs to execute immediately after a value changes to ensure state consistency. See issue #7129. -
Optimized ComboBox Selection: The
afterSetValuelogic for single-selectComboBoxfields has been optimized to prevent unnecessary processing when the selection has not changed, improving performance. See issue #7125. -
Refined StateProvider Logic: The
StateProviderchange notification logic has been improved to be more precise, preventing unnecessary component updates and ensuring a more efficient data flow. See issue #7124.
Bug Fixes
-
Form Field Value Sequencing: Addressed a bug related to the sequencing of
afterSetValuecalls in form fields, ensuring that values are processed in the correct order. See issue #7127. -
Big Data Grid Example: Fixed an issue in the Big Data Grid example where dropdowns in the controls container were not showing their initial values correctly. See issue #7126.
-
Covid App Regression: Fixed a regression bug in the Covid app that caused an infinite selection loop when choosing a country from the header dropdown. See issue #7123.
-
SharedCovid App Regression: Resolved a regression bug in the SharedCovid app where clicking on a table row would throw an error. See issue #7122.
-
State Provider Feedback Loop: Added a new test case to prevent feedback loops within the
StateProvider, enhancing its reliability. See issue #7128.
All changes combined into 1 commit: 95f9e75
Grid Column Header Drag&Drop Hotfix
Neo.mjs v10.1.1 Release Notes
This is a patch release that addresses a critical regression bug affecting drag-and-drop operations in grids.
Bug Fixes
Grid Column Drag & Drop
- Fixed a bug in
Neo.collection.Basewhere themove()method would fail to correctly swap adjacent items. This was caused by an unsafe, nestedsplice()operation that could lead to unpredictable behavior. - The direct impact of this bug was the failure of drag-and-drop for grid column reordering, which is a significant regression.
- The
move()method has been refactored to use a safer, two-step approach, ensuring the stability of all collection-based move operations. - See: #7118
This fix restores the expected drag-and-drop functionality for grid columns.
housekeeping
Neo.mjs v10.1.0 Release Notes
This release includes important fixes and minor improvements, primarily focusing on VDOM optimization, collection performance, and selection model improvements.
Key Updates:
-
VDOM Optimization &
neo-ignoreRefinement (Addresses #7114):
The internal handling of theneo-ignoreflag has been significantly improved. Previously,neo-ignorecould interfere with the VDOM's structural integrity, potentially leading to rendering anomalies, especially in complex layouts like grids, where elements might overlap. Now, a dedicatedneoIgnore: trueflag is added to VDOM nodes, preserving the originalcomponentIdandid. This ensures the VDOM engine can correctly identify and skip sub-trees during diffing, leading to more robust and efficient asymmetric VDOM updates and resolving visual rendering issues such as those observed in grid components. -
Collection Performance Enhancements (Addresses #7115):
Several methods withinsrc/collection/Base.mjs(e.g.,clear,findBy,pop,remove) have been optimized by replacingthis.getCount()method calls with direct access tothis.count. This change streamlines collection operations, leading to improved performance. -
Enhanced Selection Model (Addresses #7116):
Thesrc/selection/Model.mjshas been updated to provide more comprehensive data during selection changes. A newgetController()method has been added, and theselectionChangeevent now includes therecordsarray, offering richer context for selection handling and better integration with view controllers. -
Minor Fixes & Improvements (Addresses #7117):
This release also includes minor cleanups and documentation improvements, such as an updated JSDoc comment insrc/grid/Body.mjsand the removal of a debugconsole.logstatement insrc/main/DeltaUpdates.mjs.
v10 polishing
Neo.mjs v10.0.2 Release Notes
This release includes several enhancements and fixes since v10.0.1.
Key Updates:
README.md& Comparison Enhancements: Significant updates to theREADME.md, including a new section "🚀 Inside v10: A New Era of Frontend Architecture" with links to a five-part blog series. The architectural comparison table "🔍 Architectural Deep Dive: Neo.mjs vs. Main-Thread Frameworks" has been expanded, and detailed comparison documents (NeoVsAngular.md,NeoVsReact.md,NeoVsVue.md) have been updated to provide enhanced insights.- Data Model Enhancements: Default values for
recordsnow optionally support functions, enabled by changes indata.RecordFactory. - DOM Rendering:
DomApiRendererhas been improved for creating void attributes, enhancing rendering accuracy. - Core Component Fix: Re-added the lost
parentIddefault value tocomponent.Abstract, which resolves an issue with the tooltip singleton. - Dark Theme: Improved the styling for ghost buttons
- Tree List Polished drag&drop support for the edge case where stores are not using
idas the keyProperty.
Added 2 new v10 series blog posts to the neo website app
Neo.mjs v10: The Reactive Revolution
This release brings significant enhancements and refactorings, improving performance, reactivity, and the overall developer experience.
Core Framework Improvements
- Reactive Core Refactoring (
core.Observable):- Architectural refactoring of
core.Observableto a fully reactive mixin (#7090). - Modernized
core.Observable: Refactoredcore.Observableto align with the reactive config system. This involved converting thelistenersproperty to a reactivelisteners_config, eliminating manual initialization, and establishing true encapsulation using a module-scopedSymbol(eventMapSymbol) for internal event registry management. A bug inremoveListenerrelated to incorrect state access was also fixed. (#7090) - Listeners are now managed as a reactive config within
core.Observable(#7089).
- Architectural refactoring of
- Effect Management System:
- 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:- Execution Batching (
pause()/resume()): Replaced the oldisPausedflag with a numericpauseCounterfor robust, nested batching of UI updates. Effects are queued and executed only when the counter is zero. - Dependency Tracking Suppression (
pauseTracking()/resumeTracking()): A new mechanism (isTrackingPausedflag) to temporarily stop active effects from collecting new dependencies, solving self-dependency issues.
- Execution Batching (
- The
EffectBatchManagersingleton has been completely removed, and its functionality absorbed by the enhancedEffectManager. This results in a more predictable, robust, and resilient reactive system.
- Foundational Refactoring of Effect Management: The core reactivity system has been refactored and unified under a single
- State Management:
- State Provider Refactoring & Deep Merging:
- Refactored
state.Provider'sinternalSetData()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) - Enhanced Reactivity & Atomic Updates:
state.Providernow features "Reactivity Bubbling," where changes to leaf properties recursively update parent objects, correctly triggering effects on intermediate data objects. PublicsetData()andsetDataAtSameLevel()methods are now wrapped withNeo.batch()(leveraging the newEffectManager'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. - Moved all state provider related logic (configs like
bind,modelData,stateProvider_,data_,parentComponent_, and methods likegetStateProvider(),getState(),setState(),beforeGetData(),getConfigInstanceByNtype(), along with lifecycle logic and two-way binding logic) fromsrc/component/Base.mjstosrc/component/Abstract.mjs. This makes state providers available to both classic class-based components and modern functional components. (#7100)
- Refactored
- State Provider Refactoring & Deep Merging:
- Component Base Classes:
- Common Abstract Base Class: Introduced
Neo.component.Abstractas a new common base class for bothNeo.component.Base(classic) andNeo.functional.component.Base(functional) components. This refactoring centralizes shared logic (e.g.,set(),destroy(),mountedPromise, core configs,DomEvents,Observable,VdomLifecyclemixins), improving code reusability, enhancing consistency, and simplifying maintenance by removing duplicated code. (#7089) - Removed redundant
createBindings()calls fromonConstructed(#7101).
- Common Abstract Base Class: Introduced
Functional Components
- VDOM Reconciliation: Enhanced Functional Component VDOM Reconciliation (
#7086). - Lifecycle Hook: Introduced a new
beforeUpdate()lifecycle method toNeo.functional.component.Base(#7084). This hook executes after all state changes from a reactiveEffecthave been processed and just beforeupdateVdom(). It provides a predictable entry point for pre-render logic and allows conditionally canceling a VDOM update by returningfalse. - Functional Button Component: Introduced a new
Neo.functional.button.Basecomponent (#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. functional.button.Base:beforeSetBadgePosition(),beforeSetIconPosition()now use constructor access for future class extensions.
VDOM & Rendering
util.vdom.TreeBuilder: Improvements tobuildTree(): RefactoredgetVdomTreeandgetVnodeTreeinto a single, DRY method (#7098).util.VDom:syncVdomIds()enhanced for future-proofing and improved filtering.manager.VDomUpdate: Significantly enhanced JSDoc comments and method order/cleanup.
Other Enhancements & Fixes
- Dependencies: Updated FontAwesome to v7.
- Examples Website: Fixed flakiness on Safari (
#7102). - Tests: All 770 unit tests now pass successfully, including a significant number of new tests added since beta.6.
form.field.Text:onInputValueChange()intent made clearer.Portal.view.ViewportController: Cube-layout timing adjustments.core.EffectManager: OptimizedNeo.batchusage.- Removed obsolete
onNeoConfigChange()calls from tests. - Updated
test/siesta/tests/vdom/layout/Cube.mjsto match currentVdomHelper.create()signature.
Documentation Updates
- The
learn/guides/datahandling/StateProviders.mdguide has been updated to accurately describe the new deep-merge behavior of state providers. - Code examples in the
learn/blog/v10-deep-dive-state-provider.mdblog post have been updated to demonstrate the intuitive API usage.
All changes combined into 1 commit: c84a2cd