neo.mjs 10.3.0 → 10.3.2
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.3.0.md +20 -3
- package/.github/RELEASE_NOTES/v10.3.1.md +14 -0
- package/.github/RELEASE_NOTES/v10.3.2.md +10 -0
- package/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/buildScripts/buildAll.mjs +4 -0
- package/examples/functional/nestedTemplateComponent/Component.mjs +4 -4
- package/learn/guides/uibuildingblocks/HtmlTemplatesUnderTheHood.md +6 -6
- package/learn/tutorials/Earthquakes.md +7 -1
- package/package.json +1 -2
- package/resources/scss/src/apps/portal/about/MemberContainer.scss +1 -1
- package/resources/scss/src/apps/portal/learn/ContentComponent.scss +1 -1
- package/resources/scss/src/form/field/FileUpload.scss +1 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Circle.mjs +6 -6
- package/src/component/Gallery.mjs +3 -3
- package/src/component/Helix.mjs +3 -3
- package/src/dialog/Base.mjs +2 -2
- package/src/form/field/Text.mjs +3 -4
- package/src/grid/Body.mjs +1 -1
- package/src/layout/Flexbox.mjs +1 -1
- package/src/list/Base.mjs +1 -1
- package/src/tab/BodyContainer.mjs +2 -2
- package/src/table/Body.mjs +1 -1
- package/buildScripts/util/vdomToString.mjs +0 -46
|
@@ -33,7 +33,9 @@ This new feature is built on a core Neo.mjs principle: **a commitment to a zero-
|
|
|
33
33
|
To achieve both developer convenience and production performance, the framework uses a sophisticated dual-mode approach:
|
|
34
34
|
|
|
35
35
|
1. **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.
|
|
36
|
-
2. **Production Mode:** For `dist/esm`, `dist/dev`, and `dist/prod` builds, a powerful **build-time AST transformation** converts templates directly into optimized VDOM objects. This eliminates the `parse5` dependency from production builds entirely, resulting in **zero runtime parsing overhead** and maximum performance.
|
|
36
|
+
2. **Production Mode:** For `dist/esm`, `dist/dev`, and `dist/prod` builds, a powerful **build-time AST transformation** converts templates directly into optimized VDOM objects. This eliminates the `parse5` dependency from production builds entirely, resulting in **zero runtime parsing overhead** and maximum performance. The `enableHtmlTemplates` flag is also automatically set to `false` in production environments, ensuring that the runtime parser is never accidentally used.
|
|
37
|
+
|
|
38
|
+
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.
|
|
37
39
|
|
|
38
40
|
## Foundational Enhancements
|
|
39
41
|
|
|
@@ -48,7 +50,22 @@ The introduction of HTML templates was made possible by a series of significant
|
|
|
48
50
|
|
|
49
51
|
To support this major new feature, we have added two comprehensive guides:
|
|
50
52
|
|
|
51
|
-
- [Using HTML Templates](
|
|
52
|
-
- [Under the Hood: HTML Templates](
|
|
53
|
+
- [Using HTML Templates](https://github.com/neomjs/neo/blob/dev/learn/guides/uibuildingblocks/HtmlTemplates.md): A guide focused on the syntax, features, and best practices for using the new template system.
|
|
54
|
+
- [Under the Hood: HTML Templates](https://github.com/neomjs/neo/blob/dev/learn/guides/uibuildingblocks/HtmlTemplatesUnderTheHood.md): A deep dive into the philosophy and the dual-mode architecture, explaining how templates work in both development and production environments.
|
|
55
|
+
|
|
56
|
+
All changes combined into 1 commit: https://github.com/neomjs/neo/commit/0841e7e1a715c7afe67d07eebb8229e54828eedd
|
|
53
57
|
|
|
54
58
|
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!
|
|
59
|
+
|
|
60
|
+
Try it out by yourself:</br>
|
|
61
|
+
https://neomjs.com/examples/functional/nestedTemplateComponent/
|
|
62
|
+
|
|
63
|
+
<img width="1603" height="1292" alt="Screenshot 2025-08-02 at 17 01 25" src="https://github.com/user-attachments/assets/79cb4aad-b791-4b03-bf25-7147bbeeed39" />
|
|
64
|
+
|
|
65
|
+
https://neomjs.com/dist/esm/examples/functional/nestedTemplateComponent/
|
|
66
|
+
|
|
67
|
+
<img width="1606" height="1062" alt="Screenshot 2025-08-02 at 17 00 12" src="https://github.com/user-attachments/assets/7a21638f-cb68-4f28-ba04-6ebaccb3b3f3" />
|
|
68
|
+
|
|
69
|
+
https://neomjs.com/dist/development/examples/functional/nestedTemplateComponent/
|
|
70
|
+
|
|
71
|
+
<img width="1602" height="1179" alt="Screenshot 2025-08-02 at 17 06 24" src="https://github.com/user-attachments/assets/2c1d3ef7-2008-41a1-9025-2859d907ce2d" />
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Neo.mjs v10.3.1: Build Process Reliability
|
|
2
|
+
|
|
3
|
+
This is a patch release focused on improving the stability and reliability of the core build process.
|
|
4
|
+
|
|
5
|
+
## Key Fix: Build Process Dependency Order
|
|
6
|
+
|
|
7
|
+
### The Problem
|
|
8
|
+
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.
|
|
9
|
+
|
|
10
|
+
### The Solution
|
|
11
|
+
We have updated `buildAll.mjs` to explicitly run the `bundleParse5.mjs` script as one of its first actions, immediately after the optional `npm install`.
|
|
12
|
+
|
|
13
|
+
### The Impact
|
|
14
|
+
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.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# v10.3.2 Hotfix Release
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## Fixes
|
|
6
|
+
|
|
7
|
+
- **tab.Container:** Resolved an issue where switching `tabBarPosition` did not correctly update the UI. The `tabBar` component's `dock` config now properly reflects the new position, ensuring correct rendering. This fix involved adding `tabBarPosition` to the `config` object, and implementing `afterSetTabBarPosition` and `beforeSetTabBarPosition` methods to manage UI updates and component creation.
|
|
8
|
+
- **Component Lifecycle:** Replaced `this.rendered` with `this.vnodeInitialized` across various components (`Circle`, `Gallery`, `Helix`, `Dialog`, `Text` field, `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.
|
|
9
|
+
- **Font Awesome v7** Adjusted 3 spots inside our theming, where v6 was still in use.
|
|
10
|
+
- **Earthquakes Tutorial** Fixed a malformed code closing tag, added a warning that the labs are currently not working.
|
package/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
|
@@ -129,6 +129,10 @@ if (programOpts.info) {
|
|
|
129
129
|
childProcess.status && process.exit(childProcess.status);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
console.log(chalk.blue('Bundling parse5...'));
|
|
133
|
+
childProcess = spawnSync('node', [`${neoPath}/buildScripts/bundleParse5.mjs`], cpOpts);
|
|
134
|
+
childProcess.status && process.exit(childProcess.status);
|
|
135
|
+
|
|
132
136
|
if (themes === 'yes') {
|
|
133
137
|
childProcess = spawnSync('node', [`${neoPath}/buildScripts/buildThemes.mjs`].concat(cpArgs), cpOpts);
|
|
134
138
|
childProcess.status && process.exit(childProcess.status);
|
|
@@ -31,7 +31,7 @@ export default defineComponent({
|
|
|
31
31
|
},
|
|
32
32
|
|
|
33
33
|
render(config) {
|
|
34
|
-
const [isActive, setIsActive]
|
|
34
|
+
const [isActive, setIsActive] = useConfig(true);
|
|
35
35
|
const [showDetails, setShowDetails] = useConfig(false);
|
|
36
36
|
|
|
37
37
|
// This event listener is for the main container to toggle the active state
|
|
@@ -39,15 +39,15 @@ export default defineComponent({
|
|
|
39
39
|
// Stop the event from bubbling up to avoid toggling the active state
|
|
40
40
|
// when the button is clicked. The button has its own handler.
|
|
41
41
|
if (event.target.id === 'details-button') {
|
|
42
|
-
event.stopPropagation()
|
|
42
|
+
event.stopPropagation()
|
|
43
43
|
} else {
|
|
44
|
-
setIsActive(prev => !prev)
|
|
44
|
+
setIsActive(prev => !prev)
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
// The idiomatic way to handle a button click is with the handler config.
|
|
49
49
|
const onButtonClick = () => {
|
|
50
|
-
setShowDetails(prev => !prev)
|
|
50
|
+
setShowDetails(prev => !prev)
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
const cardStyle = {
|
|
@@ -40,7 +40,7 @@ To parse HTML strings, we need an HTML parser. Neo.mjs uses `parse5`, a robust a
|
|
|
40
40
|
This is why the parser is **only loaded if a component on the page actually uses an HTML template**. This check happens
|
|
41
41
|
inside the `initAsync` method of `Neo.functional.component.Base`.
|
|
42
42
|
|
|
43
|
-
```javascript
|
|
43
|
+
```javascript readonly
|
|
44
44
|
// src/functional/component/Base.mjs
|
|
45
45
|
async initAsync() {
|
|
46
46
|
await super.initAsync();
|
|
@@ -61,7 +61,7 @@ If `enableHtmlTemplates` is true, the component dynamically imports the `HtmlTem
|
|
|
61
61
|
|
|
62
62
|
When a component's `createVdom()` method returns an `HtmlTemplate` object, it's handed off to the `HtmlTemplateProcessor`.
|
|
63
63
|
You can inspect its source code here:
|
|
64
|
-
[src/functional/util/HtmlTemplateProcessor.mjs](
|
|
64
|
+
[src/functional/util/HtmlTemplateProcessor.mjs](../../../src/functional/util/HtmlTemplateProcessor.mjs).
|
|
65
65
|
|
|
66
66
|
The processor executes a series of steps to convert the template literal into a VDOM object, which are detailed in the
|
|
67
67
|
expandable section below.
|
|
@@ -93,9 +93,9 @@ parsing overhead**. This is accomplished with a powerful build-time AST (Abstrac
|
|
|
93
93
|
|
|
94
94
|
This work is handled by two main scripts:
|
|
95
95
|
|
|
96
|
-
- [buildScripts/util/templateBuildProcessor.mjs](
|
|
96
|
+
- [buildScripts/util/templateBuildProcessor.mjs](../../../buildScripts/util/templateBuildProcessor.mjs):
|
|
97
97
|
Contains the core logic for parsing the template string and converting it to a serializable VDOM object.
|
|
98
|
-
- [buildScripts/util/astTemplateProcessor.mjs](
|
|
98
|
+
- [buildScripts/util/astTemplateProcessor.mjs](../../../buildScripts/util/astTemplateProcessor.mjs):
|
|
99
99
|
Orchestrates the overall process of reading a JS file, finding `html` templates, and replacing them with the final
|
|
100
100
|
VDOM object via AST manipulation.
|
|
101
101
|
|
|
@@ -119,10 +119,10 @@ renames the method to `createVdom`.
|
|
|
119
119
|
|
|
120
120
|
This logic is seamlessly integrated into all three of Neo.mjs's production build environments:
|
|
121
121
|
|
|
122
|
-
- **`dist/esm`:** The [buildScripts/buildESModules.mjs](
|
|
122
|
+
- **`dist/esm`:** The [buildScripts/buildESModules.mjs](../../../buildScripts/buildESModules.mjs) script directly
|
|
123
123
|
invokes the `processFileContent` function from the `astTemplateProcessor` for each JavaScript file before minification.
|
|
124
124
|
- **`dist/dev` & `dist/prod`:** These environments use Webpack. The transformation is handled by a custom loader:
|
|
125
|
-
[buildScripts/webpack/loader/template-loader.mjs](
|
|
125
|
+
[buildScripts/webpack/loader/template-loader.mjs](../../../buildScripts/webpack/loader/template-loader.mjs).
|
|
126
126
|
This loader is strategically applied **only to the App worker's build configuration**, an optimization that saves
|
|
127
127
|
build time by not processing code for other workers.
|
|
128
128
|
|
|
@@ -5,6 +5,11 @@ and show the information in two views: a table, and a map.
|
|
|
5
5
|
|
|
6
6
|
You'll do this in a series of labs.
|
|
7
7
|
|
|
8
|
+
<span style='color: red;'>
|
|
9
|
+
Important: The labs inside this Tutorial cannot run currently, since the Google Maps API changed
|
|
10
|
+
and our addon needs adjustments. The chapters still contain valuable input.
|
|
11
|
+
</span>
|
|
12
|
+
|
|
8
13
|
## Goals
|
|
9
14
|
|
|
10
15
|
What are the goals of this lengthy topic?
|
|
@@ -167,7 +172,8 @@ If you look in `neo-config.json` you should see this content. Note the `mainThre
|
|
|
167
172
|
"mainPath" : "../node_modules/neo.mjs/src/Main.mjs",
|
|
168
173
|
"mainThreadAddons": ["DragDrop", "Navigator", "Stylesheet"],
|
|
169
174
|
"workerBasePath" : "../../node_modules/neo.mjs/src/worker/"
|
|
170
|
-
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
171
177
|
|
|
172
178
|
You're free to edit `neo-config.json` if you were to change your mind later about the theme or need for other add-ons.
|
|
173
179
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neo.mjs",
|
|
3
|
-
"version": "10.3.
|
|
3
|
+
"version": "10.3.2",
|
|
4
4
|
"description": "Neo.mjs: The multi-threaded UI framework for building ultra-fast, desktop-like web applications with uncompromised responsiveness, inherent security, and a transpilation-free dev mode.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"inject-package-version": "node ./buildScripts/injectPackageVersion.mjs",
|
|
30
30
|
"server-start": "webpack serve -c ./buildScripts/webpack/webpack.server.config.mjs --open",
|
|
31
31
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
32
|
-
"build-single-file": "node ./buildScripts/buildSingleFile.mjs",
|
|
33
32
|
"watch-themes": "node ./buildScripts/watchThemes.mjs"
|
|
34
33
|
},
|
|
35
34
|
"keywords": [
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
|
|
54
54
|
details summary::before {
|
|
55
55
|
color : #c4c4c4;
|
|
56
|
-
font-family: var(--fa-style-family, "Font Awesome
|
|
56
|
+
font-family: var(--fa-style-family, "Font Awesome 7 Free");
|
|
57
57
|
font-size : 1em;
|
|
58
58
|
font-weight: var(--fa-style, 900);
|
|
59
59
|
margin : 0.4em 0.4em 0.4em 0;
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
flex : 0 0 2rem;
|
|
45
45
|
height : 2rem;
|
|
46
46
|
border-radius : 50%;
|
|
47
|
-
font-family : var(--fa-style-family,"Font Awesome
|
|
47
|
+
font-family : var(--fa-style-family,"Font Awesome 7 Free");
|
|
48
48
|
display : flex;
|
|
49
49
|
align-items : center;
|
|
50
50
|
justify-content : center;
|
package/src/DefaultConfig.mjs
CHANGED
|
@@ -299,12 +299,12 @@ const DefaultConfig = {
|
|
|
299
299
|
useVdomWorker: true,
|
|
300
300
|
/**
|
|
301
301
|
* buildScripts/injectPackageVersion.mjs will update this value
|
|
302
|
-
* @default '10.3.
|
|
302
|
+
* @default '10.3.2'
|
|
303
303
|
* @memberOf! module:Neo
|
|
304
304
|
* @name config.version
|
|
305
305
|
* @type String
|
|
306
306
|
*/
|
|
307
|
-
version: '10.3.
|
|
307
|
+
version: '10.3.2'
|
|
308
308
|
};
|
|
309
309
|
|
|
310
310
|
Object.assign(DefaultConfig, {
|
package/src/component/Circle.mjs
CHANGED
|
@@ -248,7 +248,7 @@ class Circle extends Component {
|
|
|
248
248
|
* @protected
|
|
249
249
|
*/
|
|
250
250
|
afterSetMaxItems(value, oldValue) {
|
|
251
|
-
if (oldValue && this.
|
|
251
|
+
if (oldValue && this.vnodeInitialized) {
|
|
252
252
|
let me = this,
|
|
253
253
|
frontEl = me.getFrontEl();
|
|
254
254
|
|
|
@@ -289,7 +289,7 @@ class Circle extends Component {
|
|
|
289
289
|
afterSetItemSize(value, oldValue) {
|
|
290
290
|
let me = this;
|
|
291
291
|
|
|
292
|
-
if (oldValue && me.
|
|
292
|
+
if (oldValue && me.vnodeInitialized) {
|
|
293
293
|
!me.collapsed && me.updateOuterCircle(true);
|
|
294
294
|
me.updateItemPositions()
|
|
295
295
|
}
|
|
@@ -302,7 +302,7 @@ class Circle extends Component {
|
|
|
302
302
|
* @protected
|
|
303
303
|
*/
|
|
304
304
|
afterSetRotateX(value, oldValue) {
|
|
305
|
-
oldValue && this.
|
|
305
|
+
oldValue && this.vnodeInitialized && this.rotate()
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
/**
|
|
@@ -312,7 +312,7 @@ class Circle extends Component {
|
|
|
312
312
|
* @protected
|
|
313
313
|
*/
|
|
314
314
|
afterSetRotateY(value, oldValue) {
|
|
315
|
-
oldValue && this.
|
|
315
|
+
oldValue && this.vnodeInitialized && this.rotate()
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
/**
|
|
@@ -322,7 +322,7 @@ class Circle extends Component {
|
|
|
322
322
|
* @protected
|
|
323
323
|
*/
|
|
324
324
|
afterSetRotateZ(value, oldValue) {
|
|
325
|
-
oldValue && this.
|
|
325
|
+
oldValue && this.vnodeInitialized && this.rotate()
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
/**
|
|
@@ -344,7 +344,7 @@ class Circle extends Component {
|
|
|
344
344
|
* @protected
|
|
345
345
|
*/
|
|
346
346
|
afterSetSelectionModel(value, oldValue) {
|
|
347
|
-
this.
|
|
347
|
+
this.vnodeInitialized && value.register(this);
|
|
348
348
|
}
|
|
349
349
|
|
|
350
350
|
/**
|
|
@@ -245,7 +245,7 @@ class Gallery extends Component {
|
|
|
245
245
|
afterSetMaxItems(value, oldValue) {
|
|
246
246
|
let me = this;
|
|
247
247
|
|
|
248
|
-
if (value && me.
|
|
248
|
+
if (value && me.vnodeInitialized) {
|
|
249
249
|
if (oldValue > value) {
|
|
250
250
|
me.destroyItems(value, oldValue - value)
|
|
251
251
|
} else {
|
|
@@ -310,7 +310,7 @@ class Gallery extends Component {
|
|
|
310
310
|
len = Math.min(me.maxItems, me.store.items.length),
|
|
311
311
|
view = me.getItemsRoot();
|
|
312
312
|
|
|
313
|
-
if (me.
|
|
313
|
+
if (me.vnodeInitialized) {
|
|
314
314
|
me.refreshImageReflection();
|
|
315
315
|
|
|
316
316
|
me.timeout(50).then(() => {
|
|
@@ -338,7 +338,7 @@ class Gallery extends Component {
|
|
|
338
338
|
*/
|
|
339
339
|
afterSetSelectionModel(value, oldValue) {
|
|
340
340
|
oldValue?.destroy();
|
|
341
|
-
this.
|
|
341
|
+
this.vnodeInitialized && value.register(this)
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
afterSetTranslateX() {this.moveOrigin()}
|
package/src/component/Helix.mjs
CHANGED
|
@@ -348,7 +348,7 @@ class Helix extends Component {
|
|
|
348
348
|
afterSetMaxItems(value, oldValue) {
|
|
349
349
|
let me = this;
|
|
350
350
|
|
|
351
|
-
if (value && me.
|
|
351
|
+
if (value && me.vnodeInitialized) {
|
|
352
352
|
if (oldValue > value) {
|
|
353
353
|
me.destroyItems(value, oldValue - value)
|
|
354
354
|
} else {
|
|
@@ -399,7 +399,7 @@ class Helix extends Component {
|
|
|
399
399
|
* @protected
|
|
400
400
|
*/
|
|
401
401
|
afterSetSelectionModel(value, oldValue) {
|
|
402
|
-
this.
|
|
402
|
+
this.vnodeInitialized && value.register(this)
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
/**
|
|
@@ -411,7 +411,7 @@ class Helix extends Component {
|
|
|
411
411
|
afterSetUrl(value, oldValue) {
|
|
412
412
|
let me = this;
|
|
413
413
|
|
|
414
|
-
if (me.
|
|
414
|
+
if (me.vnodeInitialized) {
|
|
415
415
|
me.destroyItems();
|
|
416
416
|
me.loadData()
|
|
417
417
|
}
|
package/src/dialog/Base.mjs
CHANGED
|
@@ -269,7 +269,7 @@ class Dialog extends Panel {
|
|
|
269
269
|
NeoArray.toggle(me.vdom.cls, 'neo-modal', value);
|
|
270
270
|
me.update();
|
|
271
271
|
|
|
272
|
-
me.
|
|
272
|
+
me.vnodeInitialized && me.syncModalMask()
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
/**
|
|
@@ -432,7 +432,7 @@ class Dialog extends Panel {
|
|
|
432
432
|
}
|
|
433
433
|
|
|
434
434
|
// rendered outside the visible area
|
|
435
|
-
await me.
|
|
435
|
+
await me.initVnode(true);
|
|
436
436
|
|
|
437
437
|
let [dialogRect, bodyRect] = await me.waitForDomRect({id: [me.id, 'document.body']});
|
|
438
438
|
|
package/src/form/field/Text.mjs
CHANGED
|
@@ -1579,8 +1579,7 @@ class Text extends Field {
|
|
|
1579
1579
|
}
|
|
1580
1580
|
|
|
1581
1581
|
/**
|
|
1582
|
-
* Since triggers do not get
|
|
1583
|
-
* todo: this could be handled by component.Base
|
|
1582
|
+
* Since triggers do not get vnodeInitialized, assign the relevant props
|
|
1584
1583
|
*/
|
|
1585
1584
|
updateTriggerVnodes() {
|
|
1586
1585
|
let me = this,
|
|
@@ -1593,8 +1592,8 @@ class Text extends Field {
|
|
|
1593
1592
|
|
|
1594
1593
|
trigger && Object.assign(trigger, {
|
|
1595
1594
|
vnode,
|
|
1596
|
-
|
|
1597
|
-
|
|
1595
|
+
_mounted : true,
|
|
1596
|
+
_vnodeInitialized: true
|
|
1598
1597
|
})
|
|
1599
1598
|
})
|
|
1600
1599
|
}
|
package/src/grid/Body.mjs
CHANGED
package/src/layout/Flexbox.mjs
CHANGED
|
@@ -295,7 +295,7 @@ class Flexbox extends Base {
|
|
|
295
295
|
{container, prefix} = me,
|
|
296
296
|
{wrapperCls} = container;
|
|
297
297
|
|
|
298
|
-
if (container?.
|
|
298
|
+
if (container?.vnodeInitialized) {
|
|
299
299
|
NeoArray.remove(wrapperCls, prefix + propertyName + '-' + oldValue);
|
|
300
300
|
|
|
301
301
|
if (value !== null) {
|
package/src/list/Base.mjs
CHANGED
|
@@ -12,10 +12,10 @@ class BodyContainer extends Container {
|
|
|
12
12
|
*/
|
|
13
13
|
className: 'Neo.tab.BodyContainer',
|
|
14
14
|
/**
|
|
15
|
-
* @member {String[]} baseCls=['neo-container',
|
|
15
|
+
* @member {String[]} baseCls=['neo-tab-body-container','neo-container']
|
|
16
16
|
* @protected
|
|
17
17
|
*/
|
|
18
|
-
baseCls: ['neo-container', 'neo-
|
|
18
|
+
baseCls: ['neo-tab-body-container', 'neo-container']
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
package/src/table/Body.mjs
CHANGED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A regex to check if a string is a valid JavaScript identifier.
|
|
3
|
-
* @member {RegExp} validIdentifierRegex=/^[a-zA-Z_$][a-zA-Z0-9_$]*$/
|
|
4
|
-
*/
|
|
5
|
-
const validIdentifierRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Serializes a VDOM object into a JavaScript object literal string.
|
|
9
|
-
* This is a custom implementation to ensure keys are unquoted if they are
|
|
10
|
-
* valid identifiers, and correctly quoted otherwise. It also handles
|
|
11
|
-
* special placeholders for runtime expressions.
|
|
12
|
-
* @param {Object} vdom The VDOM object to serialize.
|
|
13
|
-
* @returns {String} The string representation of the VDOM.
|
|
14
|
-
*/
|
|
15
|
-
export function vdomToString(vdom) {
|
|
16
|
-
if (vdom === null) {
|
|
17
|
-
return 'null';
|
|
18
|
-
}
|
|
19
|
-
if (typeof vdom !== 'object') {
|
|
20
|
-
// It's a primitive value (string, number, boolean)
|
|
21
|
-
// Check for our special expression placeholder
|
|
22
|
-
if (typeof vdom === 'string') {
|
|
23
|
-
const match = vdom.match(/##__NEO_EXPR__(.*)##__NEO_EXPR__##/);
|
|
24
|
-
if (match) {
|
|
25
|
-
return match[1]; // Return the raw expression
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
// Otherwise, stringify it normally
|
|
29
|
-
return JSON.stringify(vdom);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (Array.isArray(vdom)) {
|
|
33
|
-
return `[${vdom.map(vdomToString).join(',')}]`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const parts = [];
|
|
37
|
-
for (const key in vdom) {
|
|
38
|
-
if (Object.prototype.hasOwnProperty.call(vdom, key)) {
|
|
39
|
-
const value = vdom[key];
|
|
40
|
-
const keyString = validIdentifierRegex.test(key) ? key : `'${key}'`;
|
|
41
|
-
parts.push(`${keyString}:${vdomToString(value)}`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return `{${parts.join(',')}}`;
|
|
46
|
-
}
|