@odoo/owl 3.0.0-alpha.28 → 3.0.0-alpha.29
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/LICENSE +856 -0
- package/README.md +106 -0
- package/dist/owl.cjs.js +58 -16
- package/dist/owl.es.js +58 -16
- package/dist/owl.iife.js +58 -16
- package/dist/owl.iife.min.js +8 -8
- package/dist/types/owl.d.ts +3 -2
- package/package.json +7 -5
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<h1 align="center">🦉 <a href="https://odoo.github.io/owl/">Owl</a> 🦉</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>A modern, lightweight UI framework for applications that scale</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
[](https://www.gnu.org/licenses/lgpl-3.0)
|
|
8
|
+
[](https://badge.fury.io/js/@odoo%2Fowl)
|
|
9
|
+
[](https://www.npmjs.com/package/@odoo/owl)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
> **Owl 3.0.0 Alpha:** This is an alpha release. The API and features are subject to change without notice.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Try it now
|
|
18
|
+
|
|
19
|
+
The fastest way to discover Owl is the **[online playground](https://odoo.github.io/owl/playground)**.
|
|
20
|
+
It features interactive examples, a live editor, and showcases all major features:
|
|
21
|
+
reactivity, components, plugins, and more. It also includes **guided tutorials**
|
|
22
|
+
and is the recommended way to learn about Owl.
|
|
23
|
+
|
|
24
|
+
## What is Owl?
|
|
25
|
+
|
|
26
|
+
Owl is a modern UI framework (~30kb gzipped, zero dependencies) written in TypeScript,
|
|
27
|
+
built by [Odoo](https://www.odoo.com/). It powers Odoo's web client, one of the largest
|
|
28
|
+
open-source business applications, but is equally suited for small projects and prototypes.
|
|
29
|
+
|
|
30
|
+
Key features:
|
|
31
|
+
|
|
32
|
+
- **Signal-based reactivity** — Explicit, composable, and debuggable state management
|
|
33
|
+
- **Plugin system** — Type-safe, composable sharing of state and services
|
|
34
|
+
- **Class-based components** — Familiar OOP patterns with ES6 classes
|
|
35
|
+
- **Declarative templates** — XML templates with a clean syntax
|
|
36
|
+
- **Async rendering** — Concurrent mode for smooth user experiences
|
|
37
|
+
|
|
38
|
+
## Quick Example
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import { Component, signal, computed, mount, xml } from "@odoo/owl";
|
|
42
|
+
|
|
43
|
+
class TodoList extends Component {
|
|
44
|
+
static template = xml`
|
|
45
|
+
<input placeholder="Add todo..." t-on-keydown="this.onKeydown"/>
|
|
46
|
+
<ul>
|
|
47
|
+
<t t-foreach="this.todos()" t-as="todo" t-key="todo.id">
|
|
48
|
+
<li t-att-class="{ done: todo.done }">
|
|
49
|
+
<input type="checkbox" t-model="todo.done"/>
|
|
50
|
+
<t t-out="todo.text"/>
|
|
51
|
+
</li>
|
|
52
|
+
</t>
|
|
53
|
+
</ul>
|
|
54
|
+
<p t-if="this.remaining() > 0">
|
|
55
|
+
<t t-out="this.remaining()"/> item(s) remaining
|
|
56
|
+
</p>`;
|
|
57
|
+
|
|
58
|
+
todos = signal.Array([
|
|
59
|
+
{ id: 1, text: "Learn Owl", done: false },
|
|
60
|
+
{ id: 2, text: "Build something", done: false },
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
remaining = computed(() => this.todos().filter((t) => !t.done).length);
|
|
64
|
+
|
|
65
|
+
onKeydown(ev) {
|
|
66
|
+
if (ev.key === "Enter" && ev.target.value) {
|
|
67
|
+
this.todos.push({
|
|
68
|
+
id: Date.now(),
|
|
69
|
+
text: ev.target.value,
|
|
70
|
+
done: false,
|
|
71
|
+
});
|
|
72
|
+
ev.target.value = "";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
mount(TodoList, document.body);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This example demonstrates Owl's reactivity: `todos` is a signal, `remaining`
|
|
81
|
+
is a computed value that updates automatically, and the UI reacts to changes
|
|
82
|
+
without manual subscription management.
|
|
83
|
+
|
|
84
|
+
## Documentation
|
|
85
|
+
|
|
86
|
+
The full documentation is available at **[odoo.github.io/owl/documentation](https://odoo.github.io/owl/documentation/)**.
|
|
87
|
+
|
|
88
|
+
For the Owl 2 documentation, see the [owl-2.x branch](https://github.com/odoo/owl/tree/owl-2.x).
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npm install @odoo/owl
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Or download directly: [latest release](https://github.com/odoo/owl/releases/latest)
|
|
97
|
+
|
|
98
|
+
## Devtools
|
|
99
|
+
|
|
100
|
+
The Owl devtools extension helps debug your applications with component tree
|
|
101
|
+
inspection, state visualization, and performance profiling. Download it from
|
|
102
|
+
the [releases page](https://github.com/odoo/owl/releases/latest).
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
Owl is released under the [LGPL v3](https://www.gnu.org/licenses/lgpl-3.0) license.
|
package/dist/owl.cjs.js
CHANGED
|
@@ -75,7 +75,7 @@ __export(index_exports, {
|
|
|
75
75
|
module.exports = __toCommonJS(index_exports);
|
|
76
76
|
|
|
77
77
|
// ../owl-runtime/dist/owl-runtime.es.js
|
|
78
|
-
var version = "3.0.0-alpha.
|
|
78
|
+
var version = "3.0.0-alpha.29";
|
|
79
79
|
var OwlError = class extends Error {
|
|
80
80
|
cause;
|
|
81
81
|
};
|
|
@@ -629,7 +629,7 @@ function buildSignal(value, set) {
|
|
|
629
629
|
};
|
|
630
630
|
return readSignal;
|
|
631
631
|
}
|
|
632
|
-
function
|
|
632
|
+
function triggerSignal(signal22) {
|
|
633
633
|
if (typeof signal22 !== "function" || signal22[atomSymbol]?.type !== "signal") {
|
|
634
634
|
throw new OwlError(`Value is not a signal (${signal22})`);
|
|
635
635
|
}
|
|
@@ -650,7 +650,7 @@ function signalSet(initialValue) {
|
|
|
650
650
|
function signal(value) {
|
|
651
651
|
return buildSignal(value, (atom) => atom.value);
|
|
652
652
|
}
|
|
653
|
-
signal.
|
|
653
|
+
signal.trigger = triggerSignal;
|
|
654
654
|
signal.Array = signalArray;
|
|
655
655
|
signal.Map = signalMap;
|
|
656
656
|
signal.Object = signalObject;
|
|
@@ -1283,6 +1283,9 @@ function invokeErrorHandlers(node, error, finalize, markFibers) {
|
|
|
1283
1283
|
}
|
|
1284
1284
|
function forwardErrorToParent(boundary) {
|
|
1285
1285
|
return (error, finalize) => {
|
|
1286
|
+
if (boundary.app.destroyed) {
|
|
1287
|
+
throw error;
|
|
1288
|
+
}
|
|
1286
1289
|
const { handled } = invokeErrorHandlers(boundary, error, finalize, false);
|
|
1287
1290
|
if (!handled) {
|
|
1288
1291
|
boundary.app._handleError(finalize());
|
|
@@ -1294,6 +1297,9 @@ function handleError(params) {
|
|
|
1294
1297
|
let node = "node" in params ? params.node : params.fiber.node;
|
|
1295
1298
|
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
|
1296
1299
|
const app = node.app;
|
|
1300
|
+
if (app.destroyed) {
|
|
1301
|
+
throw error;
|
|
1302
|
+
}
|
|
1297
1303
|
if (fiber) {
|
|
1298
1304
|
let current = fiber;
|
|
1299
1305
|
do {
|
|
@@ -1308,6 +1314,9 @@ function handleError(params) {
|
|
|
1308
1314
|
app.destroy();
|
|
1309
1315
|
} catch (e) {
|
|
1310
1316
|
}
|
|
1317
|
+
if (error instanceof OwlError) {
|
|
1318
|
+
return error;
|
|
1319
|
+
}
|
|
1311
1320
|
return Object.assign(new OwlError(`[Owl] Unhandled error. Destroying the root component`), {
|
|
1312
1321
|
cause: error
|
|
1313
1322
|
});
|
|
@@ -1542,17 +1551,48 @@ function toKebabCase(prop2) {
|
|
|
1542
1551
|
CSS_PROP_CACHE[prop2] = result;
|
|
1543
1552
|
return result;
|
|
1544
1553
|
}
|
|
1554
|
+
var IMPORTANT_RE = /\s*!\s*important\s*$/i;
|
|
1555
|
+
function setStyleProp(style, prop2, value) {
|
|
1556
|
+
if (IMPORTANT_RE.test(value)) {
|
|
1557
|
+
style.setProperty(prop2, value.replace(IMPORTANT_RE, ""), "important");
|
|
1558
|
+
} else {
|
|
1559
|
+
style.setProperty(prop2, value);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1545
1562
|
function toStyleObj(expr) {
|
|
1546
1563
|
const result = {};
|
|
1547
1564
|
switch (typeof expr) {
|
|
1548
1565
|
case "string": {
|
|
1549
|
-
const str =
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1566
|
+
const str = expr;
|
|
1567
|
+
const len = str.length;
|
|
1568
|
+
let i = 0;
|
|
1569
|
+
while (i < len) {
|
|
1570
|
+
const start = i;
|
|
1571
|
+
let depth = 0;
|
|
1572
|
+
let quote = 0;
|
|
1573
|
+
while (i < len) {
|
|
1574
|
+
const c = str.charCodeAt(i);
|
|
1575
|
+
if (quote) {
|
|
1576
|
+
if (c === 92) {
|
|
1577
|
+
i += 2;
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
if (c === quote) {
|
|
1581
|
+
quote = 0;
|
|
1582
|
+
}
|
|
1583
|
+
} else if (c === 34 || c === 39) {
|
|
1584
|
+
quote = c;
|
|
1585
|
+
} else if (c === 40) {
|
|
1586
|
+
depth++;
|
|
1587
|
+
} else if (c === 41) {
|
|
1588
|
+
if (depth > 0) depth--;
|
|
1589
|
+
} else if (c === 59 && depth === 0) {
|
|
1590
|
+
break;
|
|
1591
|
+
}
|
|
1592
|
+
i++;
|
|
1593
|
+
}
|
|
1594
|
+
const part = trim.call(str.slice(start, i));
|
|
1595
|
+
i++;
|
|
1556
1596
|
if (!part) {
|
|
1557
1597
|
continue;
|
|
1558
1598
|
}
|
|
@@ -1604,7 +1644,7 @@ function setStyle(val) {
|
|
|
1604
1644
|
val = val === "" ? {} : toStyleObj(val);
|
|
1605
1645
|
const style = this.style;
|
|
1606
1646
|
for (let prop2 in val) {
|
|
1607
|
-
style
|
|
1647
|
+
setStyleProp(style, prop2, val[prop2]);
|
|
1608
1648
|
}
|
|
1609
1649
|
}
|
|
1610
1650
|
function updateStyle(val, oldVal) {
|
|
@@ -1618,7 +1658,7 @@ function updateStyle(val, oldVal) {
|
|
|
1618
1658
|
}
|
|
1619
1659
|
for (let prop2 in val) {
|
|
1620
1660
|
if (val[prop2] !== oldVal[prop2]) {
|
|
1621
|
-
style
|
|
1661
|
+
setStyleProp(style, prop2, val[prop2]);
|
|
1622
1662
|
}
|
|
1623
1663
|
}
|
|
1624
1664
|
if (!style.cssText) {
|
|
@@ -3859,6 +3899,7 @@ var App = class _App extends TemplateSet {
|
|
|
3859
3899
|
scheduler = new Scheduler();
|
|
3860
3900
|
roots = /* @__PURE__ */ new Set();
|
|
3861
3901
|
pluginManager;
|
|
3902
|
+
destroyed = false;
|
|
3862
3903
|
constructor(config3 = {}) {
|
|
3863
3904
|
super(config3);
|
|
3864
3905
|
this.name = config3.name || "";
|
|
@@ -3969,6 +4010,7 @@ var App = class _App extends TemplateSet {
|
|
|
3969
4010
|
this.pluginManager.destroy();
|
|
3970
4011
|
this.scheduler.processTasks();
|
|
3971
4012
|
apps.delete(this);
|
|
4013
|
+
this.destroyed = true;
|
|
3972
4014
|
}
|
|
3973
4015
|
_handleError(error) {
|
|
3974
4016
|
throw error;
|
|
@@ -4323,8 +4365,8 @@ var blockDom = {
|
|
|
4323
4365
|
};
|
|
4324
4366
|
var __info__ = {
|
|
4325
4367
|
version: App.version,
|
|
4326
|
-
date: "2026-04-
|
|
4327
|
-
hash: "
|
|
4368
|
+
date: "2026-04-23T11:09:22.692Z",
|
|
4369
|
+
hash: "2220e1dd",
|
|
4328
4370
|
url: "https://github.com/odoo/owl"
|
|
4329
4371
|
};
|
|
4330
4372
|
|
|
@@ -4687,7 +4729,7 @@ function buildSignal2(value, set) {
|
|
|
4687
4729
|
};
|
|
4688
4730
|
return readSignal;
|
|
4689
4731
|
}
|
|
4690
|
-
function
|
|
4732
|
+
function triggerSignal2(signal22) {
|
|
4691
4733
|
if (typeof signal22 !== "function" || signal22[atomSymbol2]?.type !== "signal") {
|
|
4692
4734
|
throw new OwlError2(`Value is not a signal (${signal22})`);
|
|
4693
4735
|
}
|
|
@@ -4708,7 +4750,7 @@ function signalSet2(initialValue) {
|
|
|
4708
4750
|
function signal2(value) {
|
|
4709
4751
|
return buildSignal2(value, (atom) => atom.value);
|
|
4710
4752
|
}
|
|
4711
|
-
signal2.
|
|
4753
|
+
signal2.trigger = triggerSignal2;
|
|
4712
4754
|
signal2.Array = signalArray2;
|
|
4713
4755
|
signal2.Map = signalMap2;
|
|
4714
4756
|
signal2.Object = signalObject2;
|
package/dist/owl.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ../owl-runtime/dist/owl-runtime.es.js
|
|
2
|
-
var version = "3.0.0-alpha.
|
|
2
|
+
var version = "3.0.0-alpha.29";
|
|
3
3
|
var OwlError = class extends Error {
|
|
4
4
|
cause;
|
|
5
5
|
};
|
|
@@ -553,7 +553,7 @@ function buildSignal(value, set) {
|
|
|
553
553
|
};
|
|
554
554
|
return readSignal;
|
|
555
555
|
}
|
|
556
|
-
function
|
|
556
|
+
function triggerSignal(signal22) {
|
|
557
557
|
if (typeof signal22 !== "function" || signal22[atomSymbol]?.type !== "signal") {
|
|
558
558
|
throw new OwlError(`Value is not a signal (${signal22})`);
|
|
559
559
|
}
|
|
@@ -574,7 +574,7 @@ function signalSet(initialValue) {
|
|
|
574
574
|
function signal(value) {
|
|
575
575
|
return buildSignal(value, (atom) => atom.value);
|
|
576
576
|
}
|
|
577
|
-
signal.
|
|
577
|
+
signal.trigger = triggerSignal;
|
|
578
578
|
signal.Array = signalArray;
|
|
579
579
|
signal.Map = signalMap;
|
|
580
580
|
signal.Object = signalObject;
|
|
@@ -1207,6 +1207,9 @@ function invokeErrorHandlers(node, error, finalize, markFibers) {
|
|
|
1207
1207
|
}
|
|
1208
1208
|
function forwardErrorToParent(boundary) {
|
|
1209
1209
|
return (error, finalize) => {
|
|
1210
|
+
if (boundary.app.destroyed) {
|
|
1211
|
+
throw error;
|
|
1212
|
+
}
|
|
1210
1213
|
const { handled } = invokeErrorHandlers(boundary, error, finalize, false);
|
|
1211
1214
|
if (!handled) {
|
|
1212
1215
|
boundary.app._handleError(finalize());
|
|
@@ -1218,6 +1221,9 @@ function handleError(params) {
|
|
|
1218
1221
|
let node = "node" in params ? params.node : params.fiber.node;
|
|
1219
1222
|
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
|
1220
1223
|
const app = node.app;
|
|
1224
|
+
if (app.destroyed) {
|
|
1225
|
+
throw error;
|
|
1226
|
+
}
|
|
1221
1227
|
if (fiber) {
|
|
1222
1228
|
let current = fiber;
|
|
1223
1229
|
do {
|
|
@@ -1232,6 +1238,9 @@ function handleError(params) {
|
|
|
1232
1238
|
app.destroy();
|
|
1233
1239
|
} catch (e) {
|
|
1234
1240
|
}
|
|
1241
|
+
if (error instanceof OwlError) {
|
|
1242
|
+
return error;
|
|
1243
|
+
}
|
|
1235
1244
|
return Object.assign(new OwlError(`[Owl] Unhandled error. Destroying the root component`), {
|
|
1236
1245
|
cause: error
|
|
1237
1246
|
});
|
|
@@ -1466,17 +1475,48 @@ function toKebabCase(prop2) {
|
|
|
1466
1475
|
CSS_PROP_CACHE[prop2] = result;
|
|
1467
1476
|
return result;
|
|
1468
1477
|
}
|
|
1478
|
+
var IMPORTANT_RE = /\s*!\s*important\s*$/i;
|
|
1479
|
+
function setStyleProp(style, prop2, value) {
|
|
1480
|
+
if (IMPORTANT_RE.test(value)) {
|
|
1481
|
+
style.setProperty(prop2, value.replace(IMPORTANT_RE, ""), "important");
|
|
1482
|
+
} else {
|
|
1483
|
+
style.setProperty(prop2, value);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1469
1486
|
function toStyleObj(expr) {
|
|
1470
1487
|
const result = {};
|
|
1471
1488
|
switch (typeof expr) {
|
|
1472
1489
|
case "string": {
|
|
1473
|
-
const str =
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1490
|
+
const str = expr;
|
|
1491
|
+
const len = str.length;
|
|
1492
|
+
let i = 0;
|
|
1493
|
+
while (i < len) {
|
|
1494
|
+
const start = i;
|
|
1495
|
+
let depth = 0;
|
|
1496
|
+
let quote = 0;
|
|
1497
|
+
while (i < len) {
|
|
1498
|
+
const c = str.charCodeAt(i);
|
|
1499
|
+
if (quote) {
|
|
1500
|
+
if (c === 92) {
|
|
1501
|
+
i += 2;
|
|
1502
|
+
continue;
|
|
1503
|
+
}
|
|
1504
|
+
if (c === quote) {
|
|
1505
|
+
quote = 0;
|
|
1506
|
+
}
|
|
1507
|
+
} else if (c === 34 || c === 39) {
|
|
1508
|
+
quote = c;
|
|
1509
|
+
} else if (c === 40) {
|
|
1510
|
+
depth++;
|
|
1511
|
+
} else if (c === 41) {
|
|
1512
|
+
if (depth > 0) depth--;
|
|
1513
|
+
} else if (c === 59 && depth === 0) {
|
|
1514
|
+
break;
|
|
1515
|
+
}
|
|
1516
|
+
i++;
|
|
1517
|
+
}
|
|
1518
|
+
const part = trim.call(str.slice(start, i));
|
|
1519
|
+
i++;
|
|
1480
1520
|
if (!part) {
|
|
1481
1521
|
continue;
|
|
1482
1522
|
}
|
|
@@ -1528,7 +1568,7 @@ function setStyle(val) {
|
|
|
1528
1568
|
val = val === "" ? {} : toStyleObj(val);
|
|
1529
1569
|
const style = this.style;
|
|
1530
1570
|
for (let prop2 in val) {
|
|
1531
|
-
style
|
|
1571
|
+
setStyleProp(style, prop2, val[prop2]);
|
|
1532
1572
|
}
|
|
1533
1573
|
}
|
|
1534
1574
|
function updateStyle(val, oldVal) {
|
|
@@ -1542,7 +1582,7 @@ function updateStyle(val, oldVal) {
|
|
|
1542
1582
|
}
|
|
1543
1583
|
for (let prop2 in val) {
|
|
1544
1584
|
if (val[prop2] !== oldVal[prop2]) {
|
|
1545
|
-
style
|
|
1585
|
+
setStyleProp(style, prop2, val[prop2]);
|
|
1546
1586
|
}
|
|
1547
1587
|
}
|
|
1548
1588
|
if (!style.cssText) {
|
|
@@ -3783,6 +3823,7 @@ var App = class _App extends TemplateSet {
|
|
|
3783
3823
|
scheduler = new Scheduler();
|
|
3784
3824
|
roots = /* @__PURE__ */ new Set();
|
|
3785
3825
|
pluginManager;
|
|
3826
|
+
destroyed = false;
|
|
3786
3827
|
constructor(config3 = {}) {
|
|
3787
3828
|
super(config3);
|
|
3788
3829
|
this.name = config3.name || "";
|
|
@@ -3893,6 +3934,7 @@ var App = class _App extends TemplateSet {
|
|
|
3893
3934
|
this.pluginManager.destroy();
|
|
3894
3935
|
this.scheduler.processTasks();
|
|
3895
3936
|
apps.delete(this);
|
|
3937
|
+
this.destroyed = true;
|
|
3896
3938
|
}
|
|
3897
3939
|
_handleError(error) {
|
|
3898
3940
|
throw error;
|
|
@@ -4247,8 +4289,8 @@ var blockDom = {
|
|
|
4247
4289
|
};
|
|
4248
4290
|
var __info__ = {
|
|
4249
4291
|
version: App.version,
|
|
4250
|
-
date: "2026-04-
|
|
4251
|
-
hash: "
|
|
4292
|
+
date: "2026-04-23T11:09:22.692Z",
|
|
4293
|
+
hash: "2220e1dd",
|
|
4252
4294
|
url: "https://github.com/odoo/owl"
|
|
4253
4295
|
};
|
|
4254
4296
|
|
|
@@ -4611,7 +4653,7 @@ function buildSignal2(value, set) {
|
|
|
4611
4653
|
};
|
|
4612
4654
|
return readSignal;
|
|
4613
4655
|
}
|
|
4614
|
-
function
|
|
4656
|
+
function triggerSignal2(signal22) {
|
|
4615
4657
|
if (typeof signal22 !== "function" || signal22[atomSymbol2]?.type !== "signal") {
|
|
4616
4658
|
throw new OwlError2(`Value is not a signal (${signal22})`);
|
|
4617
4659
|
}
|
|
@@ -4632,7 +4674,7 @@ function signalSet2(initialValue) {
|
|
|
4632
4674
|
function signal2(value) {
|
|
4633
4675
|
return buildSignal2(value, (atom) => atom.value);
|
|
4634
4676
|
}
|
|
4635
|
-
signal2.
|
|
4677
|
+
signal2.trigger = triggerSignal2;
|
|
4636
4678
|
signal2.Array = signalArray2;
|
|
4637
4679
|
signal2.Map = signalMap2;
|
|
4638
4680
|
signal2.Object = signalObject2;
|
package/dist/owl.iife.js
CHANGED
|
@@ -75,7 +75,7 @@ var owl = (() => {
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
// ../owl-runtime/dist/owl-runtime.es.js
|
|
78
|
-
var version = "3.0.0-alpha.
|
|
78
|
+
var version = "3.0.0-alpha.29";
|
|
79
79
|
var OwlError = class extends Error {
|
|
80
80
|
cause;
|
|
81
81
|
};
|
|
@@ -629,7 +629,7 @@ var owl = (() => {
|
|
|
629
629
|
};
|
|
630
630
|
return readSignal;
|
|
631
631
|
}
|
|
632
|
-
function
|
|
632
|
+
function triggerSignal(signal22) {
|
|
633
633
|
if (typeof signal22 !== "function" || signal22[atomSymbol]?.type !== "signal") {
|
|
634
634
|
throw new OwlError(`Value is not a signal (${signal22})`);
|
|
635
635
|
}
|
|
@@ -650,7 +650,7 @@ var owl = (() => {
|
|
|
650
650
|
function signal(value) {
|
|
651
651
|
return buildSignal(value, (atom) => atom.value);
|
|
652
652
|
}
|
|
653
|
-
signal.
|
|
653
|
+
signal.trigger = triggerSignal;
|
|
654
654
|
signal.Array = signalArray;
|
|
655
655
|
signal.Map = signalMap;
|
|
656
656
|
signal.Object = signalObject;
|
|
@@ -1283,6 +1283,9 @@ ${issueStrings}`);
|
|
|
1283
1283
|
}
|
|
1284
1284
|
function forwardErrorToParent(boundary) {
|
|
1285
1285
|
return (error, finalize) => {
|
|
1286
|
+
if (boundary.app.destroyed) {
|
|
1287
|
+
throw error;
|
|
1288
|
+
}
|
|
1286
1289
|
const { handled } = invokeErrorHandlers(boundary, error, finalize, false);
|
|
1287
1290
|
if (!handled) {
|
|
1288
1291
|
boundary.app._handleError(finalize());
|
|
@@ -1294,6 +1297,9 @@ ${issueStrings}`);
|
|
|
1294
1297
|
let node = "node" in params ? params.node : params.fiber.node;
|
|
1295
1298
|
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
|
1296
1299
|
const app = node.app;
|
|
1300
|
+
if (app.destroyed) {
|
|
1301
|
+
throw error;
|
|
1302
|
+
}
|
|
1297
1303
|
if (fiber) {
|
|
1298
1304
|
let current = fiber;
|
|
1299
1305
|
do {
|
|
@@ -1308,6 +1314,9 @@ ${issueStrings}`);
|
|
|
1308
1314
|
app.destroy();
|
|
1309
1315
|
} catch (e) {
|
|
1310
1316
|
}
|
|
1317
|
+
if (error instanceof OwlError) {
|
|
1318
|
+
return error;
|
|
1319
|
+
}
|
|
1311
1320
|
return Object.assign(new OwlError(`[Owl] Unhandled error. Destroying the root component`), {
|
|
1312
1321
|
cause: error
|
|
1313
1322
|
});
|
|
@@ -1542,17 +1551,48 @@ ${issueStrings}`);
|
|
|
1542
1551
|
CSS_PROP_CACHE[prop2] = result;
|
|
1543
1552
|
return result;
|
|
1544
1553
|
}
|
|
1554
|
+
var IMPORTANT_RE = /\s*!\s*important\s*$/i;
|
|
1555
|
+
function setStyleProp(style, prop2, value) {
|
|
1556
|
+
if (IMPORTANT_RE.test(value)) {
|
|
1557
|
+
style.setProperty(prop2, value.replace(IMPORTANT_RE, ""), "important");
|
|
1558
|
+
} else {
|
|
1559
|
+
style.setProperty(prop2, value);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1545
1562
|
function toStyleObj(expr) {
|
|
1546
1563
|
const result = {};
|
|
1547
1564
|
switch (typeof expr) {
|
|
1548
1565
|
case "string": {
|
|
1549
|
-
const str =
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1566
|
+
const str = expr;
|
|
1567
|
+
const len = str.length;
|
|
1568
|
+
let i = 0;
|
|
1569
|
+
while (i < len) {
|
|
1570
|
+
const start = i;
|
|
1571
|
+
let depth = 0;
|
|
1572
|
+
let quote = 0;
|
|
1573
|
+
while (i < len) {
|
|
1574
|
+
const c = str.charCodeAt(i);
|
|
1575
|
+
if (quote) {
|
|
1576
|
+
if (c === 92) {
|
|
1577
|
+
i += 2;
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
if (c === quote) {
|
|
1581
|
+
quote = 0;
|
|
1582
|
+
}
|
|
1583
|
+
} else if (c === 34 || c === 39) {
|
|
1584
|
+
quote = c;
|
|
1585
|
+
} else if (c === 40) {
|
|
1586
|
+
depth++;
|
|
1587
|
+
} else if (c === 41) {
|
|
1588
|
+
if (depth > 0) depth--;
|
|
1589
|
+
} else if (c === 59 && depth === 0) {
|
|
1590
|
+
break;
|
|
1591
|
+
}
|
|
1592
|
+
i++;
|
|
1593
|
+
}
|
|
1594
|
+
const part = trim.call(str.slice(start, i));
|
|
1595
|
+
i++;
|
|
1556
1596
|
if (!part) {
|
|
1557
1597
|
continue;
|
|
1558
1598
|
}
|
|
@@ -1604,7 +1644,7 @@ ${issueStrings}`);
|
|
|
1604
1644
|
val = val === "" ? {} : toStyleObj(val);
|
|
1605
1645
|
const style = this.style;
|
|
1606
1646
|
for (let prop2 in val) {
|
|
1607
|
-
style
|
|
1647
|
+
setStyleProp(style, prop2, val[prop2]);
|
|
1608
1648
|
}
|
|
1609
1649
|
}
|
|
1610
1650
|
function updateStyle(val, oldVal) {
|
|
@@ -1618,7 +1658,7 @@ ${issueStrings}`);
|
|
|
1618
1658
|
}
|
|
1619
1659
|
for (let prop2 in val) {
|
|
1620
1660
|
if (val[prop2] !== oldVal[prop2]) {
|
|
1621
|
-
style
|
|
1661
|
+
setStyleProp(style, prop2, val[prop2]);
|
|
1622
1662
|
}
|
|
1623
1663
|
}
|
|
1624
1664
|
if (!style.cssText) {
|
|
@@ -3859,6 +3899,7 @@ ${issueStrings}`);
|
|
|
3859
3899
|
scheduler = new Scheduler();
|
|
3860
3900
|
roots = /* @__PURE__ */ new Set();
|
|
3861
3901
|
pluginManager;
|
|
3902
|
+
destroyed = false;
|
|
3862
3903
|
constructor(config3 = {}) {
|
|
3863
3904
|
super(config3);
|
|
3864
3905
|
this.name = config3.name || "";
|
|
@@ -3969,6 +4010,7 @@ ${issueStrings}`);
|
|
|
3969
4010
|
this.pluginManager.destroy();
|
|
3970
4011
|
this.scheduler.processTasks();
|
|
3971
4012
|
apps.delete(this);
|
|
4013
|
+
this.destroyed = true;
|
|
3972
4014
|
}
|
|
3973
4015
|
_handleError(error) {
|
|
3974
4016
|
throw error;
|
|
@@ -4323,8 +4365,8 @@ ${issueStrings}`);
|
|
|
4323
4365
|
};
|
|
4324
4366
|
var __info__ = {
|
|
4325
4367
|
version: App.version,
|
|
4326
|
-
date: "2026-04-
|
|
4327
|
-
hash: "
|
|
4368
|
+
date: "2026-04-23T11:09:22.692Z",
|
|
4369
|
+
hash: "2220e1dd",
|
|
4328
4370
|
url: "https://github.com/odoo/owl"
|
|
4329
4371
|
};
|
|
4330
4372
|
|
|
@@ -4687,7 +4729,7 @@ ${issueStrings}`);
|
|
|
4687
4729
|
};
|
|
4688
4730
|
return readSignal;
|
|
4689
4731
|
}
|
|
4690
|
-
function
|
|
4732
|
+
function triggerSignal2(signal22) {
|
|
4691
4733
|
if (typeof signal22 !== "function" || signal22[atomSymbol2]?.type !== "signal") {
|
|
4692
4734
|
throw new OwlError2(`Value is not a signal (${signal22})`);
|
|
4693
4735
|
}
|
|
@@ -4708,7 +4750,7 @@ ${issueStrings}`);
|
|
|
4708
4750
|
function signal2(value) {
|
|
4709
4751
|
return buildSignal2(value, (atom) => atom.value);
|
|
4710
4752
|
}
|
|
4711
|
-
signal2.
|
|
4753
|
+
signal2.trigger = triggerSignal2;
|
|
4712
4754
|
signal2.Array = signalArray2;
|
|
4713
4755
|
signal2.Map = signalMap2;
|
|
4714
4756
|
signal2.Object = signalObject2;
|