@odoo/owl 3.0.0-alpha.32 → 3.0.0-alpha.34
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/dist/owl.cjs.js +310 -208
- package/dist/owl.es.js +310 -208
- package/dist/owl.iife.js +310 -208
- package/dist/owl.iife.min.js +9 -9
- package/dist/types/owl.d.ts +121 -120
- package/package.json +4 -4
package/dist/owl.es.js
CHANGED
|
@@ -115,13 +115,15 @@ function removeSources(computation) {
|
|
|
115
115
|
sources.clear();
|
|
116
116
|
}
|
|
117
117
|
function disposeComputation(computation) {
|
|
118
|
-
|
|
118
|
+
const sources = computation.sources;
|
|
119
|
+
for (const source of sources) {
|
|
119
120
|
source.observers.delete(computation);
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
const derived = source;
|
|
122
|
+
if (derived.isDerived && derived.observers.size === 0) {
|
|
123
|
+
disposeComputation(derived);
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
|
-
|
|
126
|
+
sources.clear();
|
|
125
127
|
computation.state = 1;
|
|
126
128
|
}
|
|
127
129
|
function markDownstream(computation) {
|
|
@@ -162,6 +164,7 @@ function useScope() {
|
|
|
162
164
|
}
|
|
163
165
|
var Scope = class {
|
|
164
166
|
app;
|
|
167
|
+
pluginManager;
|
|
165
168
|
status = STATUS.NEW;
|
|
166
169
|
computations = [];
|
|
167
170
|
willStart = [];
|
|
@@ -169,6 +172,7 @@ var Scope = class {
|
|
|
169
172
|
_destroyCbs = null;
|
|
170
173
|
constructor(app) {
|
|
171
174
|
this.app = app;
|
|
175
|
+
this.pluginManager = app.pluginManager;
|
|
172
176
|
}
|
|
173
177
|
/**
|
|
174
178
|
* Pushes this scope on the stack for the duration of `callback`. Any code
|
|
@@ -612,14 +616,19 @@ function computed(getter, options = {}) {
|
|
|
612
616
|
}
|
|
613
617
|
function effect(fn) {
|
|
614
618
|
const computation = createComputation(() => {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
619
|
+
if (computation.value || computation.observers.size) {
|
|
620
|
+
setComputation(void 0);
|
|
621
|
+
unsubscribeEffect(computation);
|
|
622
|
+
setComputation(computation);
|
|
623
|
+
} else {
|
|
624
|
+
removeSources(computation);
|
|
625
|
+
}
|
|
618
626
|
return fn();
|
|
619
627
|
}, false);
|
|
620
628
|
getCurrentComputation()?.observers.add(computation);
|
|
621
629
|
updateComputation(computation);
|
|
622
630
|
return function cleanupEffect2() {
|
|
631
|
+
computation.state = 0;
|
|
623
632
|
const previousComputation = getCurrentComputation();
|
|
624
633
|
setComputation(void 0);
|
|
625
634
|
unsubscribeEffect(computation);
|
|
@@ -631,7 +640,6 @@ function unsubscribeEffect(effect2) {
|
|
|
631
640
|
cleanupEffect(effect2);
|
|
632
641
|
for (const childEffect of effect2.observers) {
|
|
633
642
|
childEffect.state = 0;
|
|
634
|
-
removeSources(childEffect);
|
|
635
643
|
unsubscribeEffect(childEffect);
|
|
636
644
|
}
|
|
637
645
|
effect2.observers.clear();
|
|
@@ -708,19 +716,27 @@ function asyncComputed(fetcher, options = {}) {
|
|
|
708
716
|
read.dispose = dispose;
|
|
709
717
|
return read;
|
|
710
718
|
}
|
|
719
|
+
function safeReplacer(knownObjects, _key, value) {
|
|
720
|
+
if (typeof value === "function") {
|
|
721
|
+
return value.name || "[Function]";
|
|
722
|
+
}
|
|
723
|
+
if (value && typeof value === "object") {
|
|
724
|
+
const ctor = value.constructor;
|
|
725
|
+
if (ctor && ctor !== Object && ctor !== Array) {
|
|
726
|
+
return `[Instance of ${ctor.name || "anonymous"}]`;
|
|
727
|
+
}
|
|
728
|
+
if (knownObjects.includes(value)) {
|
|
729
|
+
return `[Known object]`;
|
|
730
|
+
}
|
|
731
|
+
knownObjects.push(value);
|
|
732
|
+
}
|
|
733
|
+
return value;
|
|
734
|
+
}
|
|
711
735
|
function assertType(value, validation, errorMessage = "Value does not match the type") {
|
|
712
736
|
const issues = validateType(value, validation);
|
|
713
737
|
if (issues.length) {
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
(key, value2) => {
|
|
717
|
-
if (typeof value2 === "function") {
|
|
718
|
-
return value2.name;
|
|
719
|
-
}
|
|
720
|
-
return value2;
|
|
721
|
-
},
|
|
722
|
-
2
|
|
723
|
-
);
|
|
738
|
+
const knownObjects = [];
|
|
739
|
+
const issueStrings = JSON.stringify(issues, safeReplacer.bind(null, knownObjects), 2);
|
|
724
740
|
throw new OwlError(`${errorMessage}
|
|
725
741
|
${issueStrings}`);
|
|
726
742
|
}
|
|
@@ -736,7 +752,7 @@ function createContext(issues, value, path, parent) {
|
|
|
736
752
|
addIssue(issue) {
|
|
737
753
|
issues.push({
|
|
738
754
|
received: this.value,
|
|
739
|
-
path: this.path,
|
|
755
|
+
path: this.path.join(" > "),
|
|
740
756
|
...issue
|
|
741
757
|
});
|
|
742
758
|
},
|
|
@@ -861,15 +877,20 @@ function validateObject(context, schema, isStrict) {
|
|
|
861
877
|
return;
|
|
862
878
|
}
|
|
863
879
|
const isShape = !Array.isArray(schema);
|
|
864
|
-
let shape
|
|
865
|
-
|
|
880
|
+
let shape;
|
|
881
|
+
let keys;
|
|
882
|
+
if (isShape) {
|
|
883
|
+
keys = Object.keys(schema);
|
|
884
|
+
shape = schema;
|
|
885
|
+
} else {
|
|
886
|
+
keys = schema;
|
|
866
887
|
shape = {};
|
|
867
|
-
for (const key of
|
|
888
|
+
for (const key of keys) {
|
|
868
889
|
shape[key] = null;
|
|
869
890
|
}
|
|
870
891
|
}
|
|
871
892
|
const missingKeys = [];
|
|
872
|
-
for (const key
|
|
893
|
+
for (const key of keys) {
|
|
873
894
|
const property = key.endsWith("?") ? key.slice(0, -1) : key;
|
|
874
895
|
if (context.value[property] === void 0) {
|
|
875
896
|
if (!key.endsWith("?")) {
|
|
@@ -884,20 +905,22 @@ function validateObject(context, schema, isStrict) {
|
|
|
884
905
|
if (missingKeys.length) {
|
|
885
906
|
context.addIssue({
|
|
886
907
|
message: "object value has missing keys",
|
|
887
|
-
missingKeys
|
|
908
|
+
missingKeys,
|
|
909
|
+
expectedKeys: keys
|
|
888
910
|
});
|
|
889
911
|
}
|
|
890
912
|
if (isStrict) {
|
|
891
913
|
const unknownKeys = [];
|
|
892
914
|
for (const key in context.value) {
|
|
893
|
-
if (!(key
|
|
915
|
+
if (!keys.includes(key) && !(`${key}?` in shape)) {
|
|
894
916
|
unknownKeys.push(key);
|
|
895
917
|
}
|
|
896
918
|
}
|
|
897
919
|
if (unknownKeys.length) {
|
|
898
920
|
context.addIssue({
|
|
899
921
|
message: "object value has unknown keys",
|
|
900
|
-
unknownKeys
|
|
922
|
+
unknownKeys,
|
|
923
|
+
expectedKeys: keys
|
|
901
924
|
});
|
|
902
925
|
}
|
|
903
926
|
}
|
|
@@ -1103,6 +1126,13 @@ var Plugin = class {
|
|
|
1103
1126
|
static set id(shadowId) {
|
|
1104
1127
|
this._shadowId = shadowId;
|
|
1105
1128
|
}
|
|
1129
|
+
// Plugins passed to `startPlugins` are started in batches of equal sequence,
|
|
1130
|
+
// ascending (lower first), like Resource/Registry. Each batch's onWillStart
|
|
1131
|
+
// callbacks fully settle before the next batch is instantiated, so
|
|
1132
|
+
// foundational plugins (low sequence) are ready before later plugins even
|
|
1133
|
+
// run their setup. Explicit `plugin(X)` dependencies bypass batching and
|
|
1134
|
+
// start immediately.
|
|
1135
|
+
static sequence = 50;
|
|
1106
1136
|
__owl__;
|
|
1107
1137
|
constructor(manager) {
|
|
1108
1138
|
this.__owl__ = manager;
|
|
@@ -1113,14 +1143,17 @@ var Plugin = class {
|
|
|
1113
1143
|
var PluginManager = class extends Scope {
|
|
1114
1144
|
config;
|
|
1115
1145
|
plugins;
|
|
1116
|
-
// Resolves once all
|
|
1117
|
-
// scope transitions to MOUNTED as the last step
|
|
1118
|
-
// (
|
|
1119
|
-
// ready. `willStart` itself is inherited
|
|
1146
|
+
// Resolves once all batches of plugins have started and their willStart
|
|
1147
|
+
// callbacks have settled. The scope transitions to MOUNTED as the last step
|
|
1148
|
+
// of this chain. Consumers (the root's mount(), providePlugins) await this
|
|
1149
|
+
// before treating the manager as ready. `willStart` itself is inherited
|
|
1150
|
+
// from Scope.
|
|
1120
1151
|
ready = Promise.resolve();
|
|
1152
|
+
hasPendingReady = false;
|
|
1121
1153
|
constructor(app, options = {}) {
|
|
1122
1154
|
super(app);
|
|
1123
1155
|
this.config = options.config ?? {};
|
|
1156
|
+
this.pluginManager = this;
|
|
1124
1157
|
if (options.parent) {
|
|
1125
1158
|
const parent = options.parent;
|
|
1126
1159
|
parent.onDestroy(() => this.destroy());
|
|
@@ -1157,24 +1190,61 @@ var PluginManager = class extends Scope {
|
|
|
1157
1190
|
return plugin2;
|
|
1158
1191
|
}
|
|
1159
1192
|
startPlugins(pluginConstructors) {
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1193
|
+
const fresh = pluginConstructors.filter((ctor) => {
|
|
1194
|
+
if (!ctor.id || this.plugins.hasOwnProperty(ctor.id)) {
|
|
1195
|
+
this.startPlugin(ctor);
|
|
1196
|
+
return false;
|
|
1164
1197
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1198
|
+
return true;
|
|
1199
|
+
});
|
|
1200
|
+
if (!fresh.length) {
|
|
1201
|
+
return;
|
|
1167
1202
|
}
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1203
|
+
fresh.sort((p1, p2) => p1.sequence - p2.sequence);
|
|
1204
|
+
const batches = [];
|
|
1205
|
+
for (const ctor of fresh) {
|
|
1206
|
+
const batch = batches[batches.length - 1];
|
|
1207
|
+
if (batch && batch[0].sequence === ctor.sequence) {
|
|
1208
|
+
batch.push(ctor);
|
|
1209
|
+
} else {
|
|
1210
|
+
batches.push([ctor]);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
const startBatch = (batch) => {
|
|
1214
|
+
scopeStack.push(this);
|
|
1215
|
+
try {
|
|
1216
|
+
for (const ctor of batch) {
|
|
1217
|
+
this.startPlugin(ctor);
|
|
1173
1218
|
}
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1219
|
+
} finally {
|
|
1220
|
+
scopeStack.pop();
|
|
1221
|
+
}
|
|
1222
|
+
const pending = this.willStart.splice(0);
|
|
1223
|
+
return pending.length ? Promise.all(pending.map((fn) => fn())) : null;
|
|
1224
|
+
};
|
|
1225
|
+
let chain = this.hasPendingReady ? this.ready : null;
|
|
1226
|
+
for (const batch of batches) {
|
|
1227
|
+
if (chain) {
|
|
1228
|
+
chain = chain.then(() => startBatch(batch));
|
|
1229
|
+
} else {
|
|
1230
|
+
chain = startBatch(batch);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
if (!chain) {
|
|
1234
|
+
if (this.status < STATUS.MOUNTED) {
|
|
1235
|
+
this.status = STATUS.MOUNTED;
|
|
1236
|
+
}
|
|
1237
|
+
return;
|
|
1177
1238
|
}
|
|
1239
|
+
this.hasPendingReady = true;
|
|
1240
|
+
const ready = this.ready = chain.then(() => {
|
|
1241
|
+
if (this.status < STATUS.MOUNTED) {
|
|
1242
|
+
this.status = STATUS.MOUNTED;
|
|
1243
|
+
}
|
|
1244
|
+
if (this.ready === ready) {
|
|
1245
|
+
this.hasPendingReady = false;
|
|
1246
|
+
}
|
|
1247
|
+
});
|
|
1178
1248
|
}
|
|
1179
1249
|
};
|
|
1180
1250
|
function startPlugins(manager, plugins) {
|
|
@@ -1189,9 +1259,103 @@ function startPlugins(manager, plugins) {
|
|
|
1189
1259
|
);
|
|
1190
1260
|
}
|
|
1191
1261
|
}
|
|
1262
|
+
function onWillStart(fn) {
|
|
1263
|
+
const scope = useScope();
|
|
1264
|
+
scope.willStart.push(scope.decorate(fn, "onWillStart"));
|
|
1265
|
+
}
|
|
1266
|
+
function onWillDestroy(fn) {
|
|
1267
|
+
const scope = useScope();
|
|
1268
|
+
scope.onDestroy(scope.decorate(fn, "onWillDestroy"));
|
|
1269
|
+
}
|
|
1270
|
+
function useEffect(fn) {
|
|
1271
|
+
onWillDestroy(effect(fn));
|
|
1272
|
+
}
|
|
1273
|
+
function useListener(target, eventName, handler, eventParams) {
|
|
1274
|
+
if (typeof target === "function") {
|
|
1275
|
+
useEffect(() => {
|
|
1276
|
+
const el = target();
|
|
1277
|
+
if (el) {
|
|
1278
|
+
el.addEventListener(eventName, handler, eventParams);
|
|
1279
|
+
return () => el.removeEventListener(eventName, handler, eventParams);
|
|
1280
|
+
}
|
|
1281
|
+
return;
|
|
1282
|
+
});
|
|
1283
|
+
} else {
|
|
1284
|
+
target.addEventListener(eventName, handler, eventParams);
|
|
1285
|
+
onWillDestroy(() => target.removeEventListener(eventName, handler, eventParams));
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
function useApp() {
|
|
1289
|
+
return useScope().app;
|
|
1290
|
+
}
|
|
1291
|
+
function plugin(pluginType) {
|
|
1292
|
+
const scope = useScope();
|
|
1293
|
+
let plugin2 = scope.pluginManager.getPluginById(pluginType.id);
|
|
1294
|
+
if (!plugin2) {
|
|
1295
|
+
if (scope instanceof PluginManager) {
|
|
1296
|
+
plugin2 = scope.pluginManager.startPlugin(pluginType);
|
|
1297
|
+
} else {
|
|
1298
|
+
throw new OwlError(`Unknown plugin "${pluginType.id}"`);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
return plugin2;
|
|
1302
|
+
}
|
|
1303
|
+
function config(key, type, defaultValue) {
|
|
1304
|
+
const scope = useScope();
|
|
1305
|
+
if (!(scope instanceof PluginManager)) {
|
|
1306
|
+
throw new OwlError("Expected to be in a plugin scope");
|
|
1307
|
+
}
|
|
1308
|
+
if (scope.app.dev && type) {
|
|
1309
|
+
assertType(scope.config, types.object({ [key]: type }), "Config does not match the type");
|
|
1310
|
+
}
|
|
1311
|
+
const configValue = scope.config[key.endsWith("?") ? key.slice(0, -1) : key];
|
|
1312
|
+
return configValue === void 0 ? defaultValue : configValue;
|
|
1313
|
+
}
|
|
1314
|
+
var EventBus = class extends EventTarget {
|
|
1315
|
+
trigger(name, payload) {
|
|
1316
|
+
this.dispatchEvent(new CustomEvent(name, { detail: payload }));
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
var Markup = class extends String {
|
|
1320
|
+
};
|
|
1321
|
+
function htmlEscape(str) {
|
|
1322
|
+
if (str instanceof Markup) {
|
|
1323
|
+
return str;
|
|
1324
|
+
}
|
|
1325
|
+
if (str === void 0) {
|
|
1326
|
+
return markup("");
|
|
1327
|
+
}
|
|
1328
|
+
if (typeof str === "number") {
|
|
1329
|
+
return markup(String(str));
|
|
1330
|
+
}
|
|
1331
|
+
[
|
|
1332
|
+
["&", "&"],
|
|
1333
|
+
["<", "<"],
|
|
1334
|
+
[">", ">"],
|
|
1335
|
+
["'", "'"],
|
|
1336
|
+
['"', """],
|
|
1337
|
+
["`", "`"]
|
|
1338
|
+
].forEach((pairs) => {
|
|
1339
|
+
str = String(str).replace(new RegExp(pairs[0], "g"), pairs[1]);
|
|
1340
|
+
});
|
|
1341
|
+
return markup(str);
|
|
1342
|
+
}
|
|
1343
|
+
function markup(valueOrStrings, ...placeholders) {
|
|
1344
|
+
if (!Array.isArray(valueOrStrings)) {
|
|
1345
|
+
return new Markup(valueOrStrings);
|
|
1346
|
+
}
|
|
1347
|
+
const strings = valueOrStrings;
|
|
1348
|
+
let acc = "";
|
|
1349
|
+
let i = 0;
|
|
1350
|
+
for (; i < placeholders.length; ++i) {
|
|
1351
|
+
acc += strings[i] + htmlEscape(placeholders[i]);
|
|
1352
|
+
}
|
|
1353
|
+
acc += strings[i];
|
|
1354
|
+
return new Markup(acc);
|
|
1355
|
+
}
|
|
1192
1356
|
|
|
1193
1357
|
// ../owl-runtime/dist/owl-runtime.es.js
|
|
1194
|
-
var version = "3.0.0-alpha.
|
|
1358
|
+
var version = "3.0.0-alpha.34";
|
|
1195
1359
|
var fibersInError = /* @__PURE__ */ new WeakMap();
|
|
1196
1360
|
var nodeErrorHandlers = /* @__PURE__ */ new WeakMap();
|
|
1197
1361
|
function invokeErrorHandlers(node, error, finalize, markFibers) {
|
|
@@ -1264,7 +1428,7 @@ function filterOutModifiersFromData(dataList) {
|
|
|
1264
1428
|
}
|
|
1265
1429
|
return { modifiers, data: dataList };
|
|
1266
1430
|
}
|
|
1267
|
-
var
|
|
1431
|
+
var config2 = {
|
|
1268
1432
|
// whether or not blockdom should normalize DOM whenever a block is created.
|
|
1269
1433
|
// Normalizing dom mean removing empty text nodes (or containing only spaces)
|
|
1270
1434
|
shouldNormalizeDom: true,
|
|
@@ -1471,20 +1635,20 @@ function toClassObj(expr) {
|
|
|
1471
1635
|
}
|
|
1472
1636
|
}
|
|
1473
1637
|
var CSS_PROP_CACHE = {};
|
|
1474
|
-
function toKebabCase(
|
|
1475
|
-
if (
|
|
1476
|
-
return CSS_PROP_CACHE[
|
|
1638
|
+
function toKebabCase(prop) {
|
|
1639
|
+
if (prop in CSS_PROP_CACHE) {
|
|
1640
|
+
return CSS_PROP_CACHE[prop];
|
|
1477
1641
|
}
|
|
1478
|
-
const result =
|
|
1479
|
-
CSS_PROP_CACHE[
|
|
1642
|
+
const result = prop.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
|
|
1643
|
+
CSS_PROP_CACHE[prop] = result;
|
|
1480
1644
|
return result;
|
|
1481
1645
|
}
|
|
1482
1646
|
var IMPORTANT_RE = /\s*!\s*important\s*$/i;
|
|
1483
|
-
function setStyleProp(style,
|
|
1647
|
+
function setStyleProp(style, prop, value) {
|
|
1484
1648
|
if (IMPORTANT_RE.test(value)) {
|
|
1485
|
-
style.setProperty(
|
|
1649
|
+
style.setProperty(prop, value.replace(IMPORTANT_RE, ""), "important");
|
|
1486
1650
|
} else {
|
|
1487
|
-
style.setProperty(
|
|
1651
|
+
style.setProperty(prop, value);
|
|
1488
1652
|
}
|
|
1489
1653
|
}
|
|
1490
1654
|
function toStyleObj(expr) {
|
|
@@ -1528,19 +1692,19 @@ function toStyleObj(expr) {
|
|
|
1528
1692
|
if (colonIdx === -1) {
|
|
1529
1693
|
continue;
|
|
1530
1694
|
}
|
|
1531
|
-
const
|
|
1695
|
+
const prop = trim.call(part.slice(0, colonIdx));
|
|
1532
1696
|
const value = trim.call(part.slice(colonIdx + 1));
|
|
1533
|
-
if (
|
|
1534
|
-
result[
|
|
1697
|
+
if (prop && value && value !== "undefined") {
|
|
1698
|
+
result[prop] = value;
|
|
1535
1699
|
}
|
|
1536
1700
|
}
|
|
1537
1701
|
return result;
|
|
1538
1702
|
}
|
|
1539
1703
|
case "object":
|
|
1540
|
-
for (let
|
|
1541
|
-
const value = expr[
|
|
1704
|
+
for (let prop in expr) {
|
|
1705
|
+
const value = expr[prop];
|
|
1542
1706
|
if (value || value === 0) {
|
|
1543
|
-
result[toKebabCase(
|
|
1707
|
+
result[toKebabCase(prop)] = String(value);
|
|
1544
1708
|
}
|
|
1545
1709
|
}
|
|
1546
1710
|
return result;
|
|
@@ -1571,22 +1735,22 @@ function updateClass(val, oldVal) {
|
|
|
1571
1735
|
function setStyle(val) {
|
|
1572
1736
|
val = val === "" ? {} : toStyleObj(val);
|
|
1573
1737
|
const style = this.style;
|
|
1574
|
-
for (let
|
|
1575
|
-
setStyleProp(style,
|
|
1738
|
+
for (let prop in val) {
|
|
1739
|
+
setStyleProp(style, prop, val[prop]);
|
|
1576
1740
|
}
|
|
1577
1741
|
}
|
|
1578
1742
|
function updateStyle(val, oldVal) {
|
|
1579
1743
|
oldVal = oldVal === "" ? {} : toStyleObj(oldVal);
|
|
1580
1744
|
val = val === "" ? {} : toStyleObj(val);
|
|
1581
1745
|
const style = this.style;
|
|
1582
|
-
for (let
|
|
1583
|
-
if (!(
|
|
1584
|
-
style.removeProperty(
|
|
1746
|
+
for (let prop in oldVal) {
|
|
1747
|
+
if (!(prop in val)) {
|
|
1748
|
+
style.removeProperty(prop);
|
|
1585
1749
|
}
|
|
1586
1750
|
}
|
|
1587
|
-
for (let
|
|
1588
|
-
if (val[
|
|
1589
|
-
setStyleProp(style,
|
|
1751
|
+
for (let prop in val) {
|
|
1752
|
+
if (val[prop] !== oldVal[prop]) {
|
|
1753
|
+
setStyleProp(style, prop, val[prop]);
|
|
1590
1754
|
}
|
|
1591
1755
|
}
|
|
1592
1756
|
if (!style.cssText) {
|
|
@@ -1638,11 +1802,6 @@ function validateTarget(target) {
|
|
|
1638
1802
|
}
|
|
1639
1803
|
throw new OwlError("Cannot mount component: the target is not a valid DOM element");
|
|
1640
1804
|
}
|
|
1641
|
-
var EventBus = class extends EventTarget {
|
|
1642
|
-
trigger(name, payload) {
|
|
1643
|
-
this.dispatchEvent(new CustomEvent(name, { detail: payload }));
|
|
1644
|
-
}
|
|
1645
|
-
};
|
|
1646
1805
|
function whenReady(fn) {
|
|
1647
1806
|
return new Promise(function(resolve) {
|
|
1648
1807
|
if (document.readyState !== "loading") {
|
|
@@ -1653,43 +1812,6 @@ function whenReady(fn) {
|
|
|
1653
1812
|
}).then(fn || function() {
|
|
1654
1813
|
});
|
|
1655
1814
|
}
|
|
1656
|
-
var Markup = class extends String {
|
|
1657
|
-
};
|
|
1658
|
-
function htmlEscape(str) {
|
|
1659
|
-
if (str instanceof Markup) {
|
|
1660
|
-
return str;
|
|
1661
|
-
}
|
|
1662
|
-
if (str === void 0) {
|
|
1663
|
-
return markup("");
|
|
1664
|
-
}
|
|
1665
|
-
if (typeof str === "number") {
|
|
1666
|
-
return markup(String(str));
|
|
1667
|
-
}
|
|
1668
|
-
[
|
|
1669
|
-
["&", "&"],
|
|
1670
|
-
["<", "<"],
|
|
1671
|
-
[">", ">"],
|
|
1672
|
-
["'", "'"],
|
|
1673
|
-
['"', """],
|
|
1674
|
-
["`", "`"]
|
|
1675
|
-
].forEach((pairs) => {
|
|
1676
|
-
str = String(str).replace(new RegExp(pairs[0], "g"), pairs[1]);
|
|
1677
|
-
});
|
|
1678
|
-
return markup(str);
|
|
1679
|
-
}
|
|
1680
|
-
function markup(valueOrStrings, ...placeholders) {
|
|
1681
|
-
if (!Array.isArray(valueOrStrings)) {
|
|
1682
|
-
return new Markup(valueOrStrings);
|
|
1683
|
-
}
|
|
1684
|
-
const strings = valueOrStrings;
|
|
1685
|
-
let acc = "";
|
|
1686
|
-
let i = 0;
|
|
1687
|
-
for (; i < placeholders.length; ++i) {
|
|
1688
|
-
acc += strings[i] + htmlEscape(placeholders[i]);
|
|
1689
|
-
}
|
|
1690
|
-
acc += strings[i];
|
|
1691
|
-
return new Markup(acc);
|
|
1692
|
-
}
|
|
1693
1815
|
function createEventHandler(rawEvent) {
|
|
1694
1816
|
const eventName = rawEvent.split(".")[0];
|
|
1695
1817
|
const capture = rawEvent.includes(".capture");
|
|
@@ -1711,7 +1833,7 @@ function createElementHandler(evName, capture = false, passive = false) {
|
|
|
1711
1833
|
if (!currentTarget || !inOwnerDocument(currentTarget)) return;
|
|
1712
1834
|
const data = currentTarget[eventKey];
|
|
1713
1835
|
if (!data) return;
|
|
1714
|
-
|
|
1836
|
+
config2.mainEventHandler(data, ev, currentTarget);
|
|
1715
1837
|
}
|
|
1716
1838
|
const options = { capture, passive };
|
|
1717
1839
|
function setup(data) {
|
|
@@ -1751,7 +1873,7 @@ function nativeToSyntheticEvent(eventKey, event) {
|
|
|
1751
1873
|
const _data = dom[eventKey];
|
|
1752
1874
|
if (_data) {
|
|
1753
1875
|
for (const data of Object.values(_data)) {
|
|
1754
|
-
const stopped =
|
|
1876
|
+
const stopped = config2.mainEventHandler(data, event, dom);
|
|
1755
1877
|
if (stopped) return;
|
|
1756
1878
|
}
|
|
1757
1879
|
}
|
|
@@ -1997,7 +2119,7 @@ function createBlock(str) {
|
|
|
1997
2119
|
}
|
|
1998
2120
|
const doc = new DOMParser().parseFromString(`<t>${str}</t>`, "text/xml");
|
|
1999
2121
|
const node = doc.firstChild.firstChild;
|
|
2000
|
-
if (
|
|
2122
|
+
if (config2.shouldNormalizeDom) {
|
|
2001
2123
|
normalizeNode(node);
|
|
2002
2124
|
}
|
|
2003
2125
|
const tree = buildTree(node);
|
|
@@ -3120,12 +3242,15 @@ var ComponentNode = class extends Scope {
|
|
|
3120
3242
|
parent;
|
|
3121
3243
|
children = /* @__PURE__ */ Object.create(null);
|
|
3122
3244
|
willUpdateProps = [];
|
|
3245
|
+
// Fired right after `props` is applied to `node.props` on a parent re-render,
|
|
3246
|
+
// so reactive prop notifications happen once the new values are observable
|
|
3247
|
+
// (after user `onWillUpdateProps` hooks, including async ones, have run).
|
|
3248
|
+
propsUpdated = [];
|
|
3123
3249
|
willUnmount = [];
|
|
3124
3250
|
mounted = [];
|
|
3125
3251
|
willPatch = [];
|
|
3126
3252
|
patched = [];
|
|
3127
3253
|
signalComputation;
|
|
3128
|
-
pluginManager;
|
|
3129
3254
|
constructor(C, props2, app, parent, parentKey) {
|
|
3130
3255
|
super(app);
|
|
3131
3256
|
this.parent = parent;
|
|
@@ -3655,6 +3780,7 @@ function createComponent(app, name, isStatic, hasSlotsProp, hasDynamicPropList,
|
|
|
3655
3780
|
() => {
|
|
3656
3781
|
if (fiber !== node.fiber) return;
|
|
3657
3782
|
node.props = props2;
|
|
3783
|
+
for (const f of node.propsUpdated) f();
|
|
3658
3784
|
fiber.render();
|
|
3659
3785
|
},
|
|
3660
3786
|
(error) => {
|
|
@@ -3663,6 +3789,7 @@ function createComponent(app, name, isStatic, hasSlotsProp, hasDynamicPropList,
|
|
|
3663
3789
|
);
|
|
3664
3790
|
} else {
|
|
3665
3791
|
node.props = props2;
|
|
3792
|
+
for (const f of node.propsUpdated) f();
|
|
3666
3793
|
fiber.render();
|
|
3667
3794
|
}
|
|
3668
3795
|
}
|
|
@@ -4003,10 +4130,6 @@ var mainEventHandler = (data, ev, currentTarget) => {
|
|
|
4003
4130
|
}
|
|
4004
4131
|
return stopped;
|
|
4005
4132
|
};
|
|
4006
|
-
function onWillStart(fn) {
|
|
4007
|
-
const scope = useScope();
|
|
4008
|
-
scope.willStart.push(scope.decorate(fn, "onWillStart"));
|
|
4009
|
-
}
|
|
4010
4133
|
function onWillUpdateProps(fn) {
|
|
4011
4134
|
const scope = getComponentScope();
|
|
4012
4135
|
function swapped(s, nextProps) {
|
|
@@ -4030,10 +4153,6 @@ function onWillUnmount(fn) {
|
|
|
4030
4153
|
const scope = getComponentScope();
|
|
4031
4154
|
scope.willUnmount.unshift(scope.decorate(fn, "onWillUnmount"));
|
|
4032
4155
|
}
|
|
4033
|
-
function onWillDestroy(fn) {
|
|
4034
|
-
const scope = useScope();
|
|
4035
|
-
scope.onDestroy(scope.decorate(fn, "onWillDestroy"));
|
|
4036
|
-
}
|
|
4037
4156
|
function onError(callback) {
|
|
4038
4157
|
const scope = getComponentScope();
|
|
4039
4158
|
let handlers = nodeErrorHandlers.get(scope);
|
|
@@ -4043,6 +4162,24 @@ function onError(callback) {
|
|
|
4043
4162
|
}
|
|
4044
4163
|
handlers.push(callback.bind(scope.component));
|
|
4045
4164
|
}
|
|
4165
|
+
function staticProp(key, type, ...args) {
|
|
4166
|
+
const node = getComponentScope();
|
|
4167
|
+
const hasDefault = args.length > 0;
|
|
4168
|
+
const propValue = node.props[key];
|
|
4169
|
+
if (node.app.dev) {
|
|
4170
|
+
if (type !== void 0 && (!hasDefault || propValue !== void 0)) {
|
|
4171
|
+
assertType(propValue, type, `Invalid prop '${key}' in '${node.componentName}'`);
|
|
4172
|
+
}
|
|
4173
|
+
node.willUpdateProps.push((nextProps) => {
|
|
4174
|
+
if (nextProps[key] !== node.props[key]) {
|
|
4175
|
+
throw new OwlError(
|
|
4176
|
+
`Prop '${key}' changed in component '${node.componentName}'. Props declared with \`props.static()\` are static and should not change. If the prop is a signal, pass the same signal reference (its inner value may change).`
|
|
4177
|
+
);
|
|
4178
|
+
}
|
|
4179
|
+
});
|
|
4180
|
+
}
|
|
4181
|
+
return propValue === void 0 && hasDefault ? args[0] : propValue;
|
|
4182
|
+
}
|
|
4046
4183
|
function componentType() {
|
|
4047
4184
|
return constructorType(Component);
|
|
4048
4185
|
}
|
|
@@ -4064,35 +4201,51 @@ function validateDefaults(schema) {
|
|
|
4064
4201
|
}
|
|
4065
4202
|
return types2.strictObject(validation);
|
|
4066
4203
|
}
|
|
4067
|
-
function
|
|
4204
|
+
function makeProps(type, defaults) {
|
|
4068
4205
|
const node = getComponentScope();
|
|
4069
4206
|
const { app, componentName } = node;
|
|
4070
4207
|
if (defaults) {
|
|
4071
4208
|
node.defaultProps = Object.assign(node.defaultProps || {}, defaults);
|
|
4072
4209
|
}
|
|
4073
|
-
function
|
|
4074
|
-
if (
|
|
4210
|
+
function resolveValue(props2, key) {
|
|
4211
|
+
if (props2[key] === void 0 && defaults) {
|
|
4075
4212
|
return defaults[key];
|
|
4076
4213
|
}
|
|
4077
|
-
return
|
|
4214
|
+
return props2[key];
|
|
4078
4215
|
}
|
|
4216
|
+
const signals = /* @__PURE__ */ Object.create(null);
|
|
4079
4217
|
const result = /* @__PURE__ */ Object.create(null);
|
|
4080
|
-
function
|
|
4218
|
+
function defineProp(key) {
|
|
4219
|
+
signals[key] = signal(resolveValue(node.props, key));
|
|
4220
|
+
Reflect.defineProperty(result, key, {
|
|
4221
|
+
enumerable: true,
|
|
4222
|
+
configurable: true,
|
|
4223
|
+
get: signals[key]
|
|
4224
|
+
});
|
|
4225
|
+
}
|
|
4226
|
+
function defineProps(keys) {
|
|
4081
4227
|
for (const key of keys) {
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4228
|
+
defineProp(key);
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
function updateSignals(keys) {
|
|
4232
|
+
for (const key of keys) {
|
|
4233
|
+
signals[key].set(resolveValue(node.props, key));
|
|
4086
4234
|
}
|
|
4087
4235
|
}
|
|
4088
4236
|
if (type) {
|
|
4089
4237
|
const keys = (Array.isArray(type) ? type : Object.keys(type)).map(
|
|
4090
4238
|
(key) => key.endsWith("?") ? key.slice(0, -1) : key
|
|
4091
4239
|
);
|
|
4092
|
-
|
|
4240
|
+
defineProps(keys);
|
|
4241
|
+
node.propsUpdated.push(() => updateSignals(keys));
|
|
4093
4242
|
if (app.dev) {
|
|
4094
4243
|
if (defaults) {
|
|
4095
|
-
assertType(
|
|
4244
|
+
assertType(
|
|
4245
|
+
defaults,
|
|
4246
|
+
validateDefaults(type),
|
|
4247
|
+
`Invalid component default props (${componentName})`
|
|
4248
|
+
);
|
|
4096
4249
|
}
|
|
4097
4250
|
const validation = types2.object(type);
|
|
4098
4251
|
assertType(node.props, validation, `Invalid component props (${componentName})`);
|
|
@@ -4118,17 +4271,28 @@ function props(type, defaults) {
|
|
|
4118
4271
|
return keys2;
|
|
4119
4272
|
};
|
|
4120
4273
|
let keys = getKeys(node.props);
|
|
4121
|
-
|
|
4122
|
-
node.
|
|
4274
|
+
defineProps(keys);
|
|
4275
|
+
node.propsUpdated.push(() => {
|
|
4276
|
+
const nextKeys = getKeys(node.props);
|
|
4277
|
+
const nextKeySet = new Set(nextKeys);
|
|
4123
4278
|
for (const key of keys) {
|
|
4124
|
-
|
|
4279
|
+
if (!nextKeySet.has(key)) {
|
|
4280
|
+
Reflect.deleteProperty(result, key);
|
|
4281
|
+
delete signals[key];
|
|
4282
|
+
}
|
|
4125
4283
|
}
|
|
4126
|
-
|
|
4127
|
-
|
|
4284
|
+
for (const key of nextKeys) {
|
|
4285
|
+
if (!(key in signals)) {
|
|
4286
|
+
defineProp(key);
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
updateSignals(nextKeys);
|
|
4290
|
+
keys = nextKeys;
|
|
4128
4291
|
});
|
|
4129
4292
|
}
|
|
4130
4293
|
return result;
|
|
4131
4294
|
}
|
|
4295
|
+
var props = Object.assign(makeProps, { static: staticProp });
|
|
4132
4296
|
var ErrorBoundary = class extends Component {
|
|
4133
4297
|
static template = xml`
|
|
4134
4298
|
<t t-if="this.props.error()">
|
|
@@ -4143,27 +4307,7 @@ var ErrorBoundary = class extends Component {
|
|
|
4143
4307
|
onError((e) => this.props.error.set(e));
|
|
4144
4308
|
}
|
|
4145
4309
|
};
|
|
4146
|
-
|
|
4147
|
-
onWillDestroy(effect(fn));
|
|
4148
|
-
}
|
|
4149
|
-
function useListener(target, eventName, handler, eventParams) {
|
|
4150
|
-
if (typeof target === "function") {
|
|
4151
|
-
useEffect(() => {
|
|
4152
|
-
const el = target();
|
|
4153
|
-
if (el) {
|
|
4154
|
-
el.addEventListener(eventName, handler, eventParams);
|
|
4155
|
-
return () => el.removeEventListener(eventName, handler, eventParams);
|
|
4156
|
-
}
|
|
4157
|
-
return;
|
|
4158
|
-
});
|
|
4159
|
-
} else {
|
|
4160
|
-
target.addEventListener(eventName, handler, eventParams);
|
|
4161
|
-
onWillDestroy(() => target.removeEventListener(eventName, handler, eventParams));
|
|
4162
|
-
}
|
|
4163
|
-
}
|
|
4164
|
-
function useApp() {
|
|
4165
|
-
return useScope().app;
|
|
4166
|
-
}
|
|
4310
|
+
var useApp2 = useApp;
|
|
4167
4311
|
var PortalContent = class extends Component {
|
|
4168
4312
|
static template = xml`<t t-call-slot="default"/>`;
|
|
4169
4313
|
};
|
|
@@ -4247,47 +4391,6 @@ var Suspense = class extends Component {
|
|
|
4247
4391
|
onWillDestroy(() => root.destroy());
|
|
4248
4392
|
}
|
|
4249
4393
|
};
|
|
4250
|
-
function prop(key, type, ...args) {
|
|
4251
|
-
const node = getComponentScope();
|
|
4252
|
-
const hasDefault = args.length > 0;
|
|
4253
|
-
const propValue = node.props[key];
|
|
4254
|
-
if (node.app.dev) {
|
|
4255
|
-
if (type !== void 0 && (!hasDefault || propValue !== void 0)) {
|
|
4256
|
-
assertType(propValue, type, `Invalid prop '${key}' in '${node.componentName}'`);
|
|
4257
|
-
}
|
|
4258
|
-
node.willUpdateProps.push((nextProps) => {
|
|
4259
|
-
if (nextProps[key] !== node.props[key]) {
|
|
4260
|
-
throw new OwlError(
|
|
4261
|
-
`Prop '${key}' changed in component '${node.componentName}'. Props declared with \`prop()\` are static and should not change. If the prop is a signal, pass the same signal reference (its inner value may change).`
|
|
4262
|
-
);
|
|
4263
|
-
}
|
|
4264
|
-
});
|
|
4265
|
-
}
|
|
4266
|
-
return propValue === void 0 && hasDefault ? args[0] : propValue;
|
|
4267
|
-
}
|
|
4268
|
-
function plugin(pluginType) {
|
|
4269
|
-
const scope = useScope();
|
|
4270
|
-
const manager = scope instanceof ComponentNode ? scope.pluginManager : scope;
|
|
4271
|
-
let plugin2 = manager.getPluginById(pluginType.id);
|
|
4272
|
-
if (!plugin2) {
|
|
4273
|
-
if (scope instanceof PluginManager) {
|
|
4274
|
-
plugin2 = manager.startPlugin(pluginType);
|
|
4275
|
-
} else {
|
|
4276
|
-
throw new OwlError(`Unknown plugin "${pluginType.id}"`);
|
|
4277
|
-
}
|
|
4278
|
-
}
|
|
4279
|
-
return plugin2;
|
|
4280
|
-
}
|
|
4281
|
-
function config2(name, type) {
|
|
4282
|
-
const scope = useScope();
|
|
4283
|
-
if (!(scope instanceof PluginManager)) {
|
|
4284
|
-
throw new OwlError("Expected to be in a plugin scope");
|
|
4285
|
-
}
|
|
4286
|
-
if (scope.app.dev && type) {
|
|
4287
|
-
assertType(scope.config, types2.object({ [name]: type }), "Config does not match the type");
|
|
4288
|
-
}
|
|
4289
|
-
return scope.config[name.endsWith("?") ? name.slice(0, -1) : name];
|
|
4290
|
-
}
|
|
4291
4394
|
function providePlugins(pluginConstructors, config3) {
|
|
4292
4395
|
const node = getComponentScope();
|
|
4293
4396
|
const manager = new PluginManager(node.app, { parent: node.pluginManager, config: config3 });
|
|
@@ -4298,10 +4401,10 @@ function providePlugins(pluginConstructors, config3) {
|
|
|
4298
4401
|
onWillStart(() => manager.ready);
|
|
4299
4402
|
}
|
|
4300
4403
|
}
|
|
4301
|
-
|
|
4302
|
-
|
|
4404
|
+
config2.shouldNormalizeDom = false;
|
|
4405
|
+
config2.mainEventHandler = mainEventHandler;
|
|
4303
4406
|
var blockDom = {
|
|
4304
|
-
config,
|
|
4407
|
+
config: config2,
|
|
4305
4408
|
// bdom entry points
|
|
4306
4409
|
mount,
|
|
4307
4410
|
patch,
|
|
@@ -4316,8 +4419,8 @@ var blockDom = {
|
|
|
4316
4419
|
};
|
|
4317
4420
|
var __info__ = {
|
|
4318
4421
|
version: App.version,
|
|
4319
|
-
date: "2026-
|
|
4320
|
-
hash: "
|
|
4422
|
+
date: "2026-06-05T08:44:38.319Z",
|
|
4423
|
+
hash: "3206cf27",
|
|
4321
4424
|
url: "https://github.com/odoo/owl"
|
|
4322
4425
|
};
|
|
4323
4426
|
|
|
@@ -6511,7 +6614,7 @@ export {
|
|
|
6511
6614
|
batched,
|
|
6512
6615
|
blockDom,
|
|
6513
6616
|
computed,
|
|
6514
|
-
|
|
6617
|
+
config,
|
|
6515
6618
|
effect,
|
|
6516
6619
|
getScope,
|
|
6517
6620
|
globalTemplates,
|
|
@@ -6528,7 +6631,6 @@ export {
|
|
|
6528
6631
|
onWillUnmount,
|
|
6529
6632
|
onWillUpdateProps,
|
|
6530
6633
|
plugin,
|
|
6531
|
-
prop,
|
|
6532
6634
|
props,
|
|
6533
6635
|
providePlugins,
|
|
6534
6636
|
proxy,
|
|
@@ -6537,7 +6639,7 @@ export {
|
|
|
6537
6639
|
toRaw,
|
|
6538
6640
|
types2 as types,
|
|
6539
6641
|
untrack,
|
|
6540
|
-
useApp,
|
|
6642
|
+
useApp2 as useApp,
|
|
6541
6643
|
useEffect,
|
|
6542
6644
|
useListener,
|
|
6543
6645
|
useScope,
|