@mintjamsinc/ichigojs 0.1.65 → 0.1.67
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/ichigo.cjs +191 -45
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +191 -45
- package/dist/ichigo.esm.js.map +1 -1
- package/dist/ichigo.esm.min.js +1 -1
- package/dist/ichigo.min.cjs +1 -1
- package/dist/ichigo.umd.js +191 -45
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/types/ichigo/VApplicationOptions.d.ts +7 -0
- package/dist/types/ichigo/VEmitOptions.d.ts +27 -0
- package/dist/types/ichigo/directives/VOnDirective.d.ts +9 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/ichigo.esm.js
CHANGED
|
@@ -6859,11 +6859,16 @@ class ExpressionUtils {
|
|
|
6859
6859
|
const ast = parse(source, { ecmaVersion: "latest" });
|
|
6860
6860
|
const dependencies = new Set();
|
|
6861
6861
|
const declaredVariables = new Set();
|
|
6862
|
+
const thisAliases = new Set();
|
|
6862
6863
|
// First, collect all declared variables (const, let, var, function params, etc.)
|
|
6863
6864
|
ancestor(ast, {
|
|
6864
6865
|
VariableDeclarator(node) {
|
|
6865
6866
|
if (node.id.type === 'Identifier') {
|
|
6866
6867
|
declaredVariables.add(node.id.name);
|
|
6868
|
+
// Detect aliases assigned from `this`, e.g. `let vm = this;`
|
|
6869
|
+
if (node.init && node.init.type === 'ThisExpression') {
|
|
6870
|
+
thisAliases.add(node.id.name);
|
|
6871
|
+
}
|
|
6867
6872
|
}
|
|
6868
6873
|
},
|
|
6869
6874
|
FunctionDeclaration(node) {
|
|
@@ -6915,9 +6920,14 @@ class ExpressionUtils {
|
|
|
6915
6920
|
}
|
|
6916
6921
|
},
|
|
6917
6922
|
MemberExpression(node) {
|
|
6918
|
-
// Handle 'this.propertyName' patterns
|
|
6919
|
-
if (node.
|
|
6920
|
-
|
|
6923
|
+
// Handle 'this.propertyName' patterns and aliases like 'vm.x' when 'vm = this'
|
|
6924
|
+
if (node.property.type === 'Identifier') {
|
|
6925
|
+
if (node.object.type === 'ThisExpression') {
|
|
6926
|
+
dependencies.add(node.property.name);
|
|
6927
|
+
}
|
|
6928
|
+
else if (node.object.type === 'Identifier' && thisAliases.has(node.object.name)) {
|
|
6929
|
+
dependencies.add(node.property.name);
|
|
6930
|
+
}
|
|
6921
6931
|
}
|
|
6922
6932
|
}
|
|
6923
6933
|
});
|
|
@@ -7011,7 +7021,7 @@ class ExpressionUtils {
|
|
|
7011
7021
|
return expression;
|
|
7012
7022
|
}
|
|
7013
7023
|
try {
|
|
7014
|
-
// Build a map of positions to replace: { start: number, end: number, name: string }[]
|
|
7024
|
+
// Build a map of positions to replace: { start: number, end: number, name: string, asThisAlias?: boolean }[]
|
|
7015
7025
|
const replacements = [];
|
|
7016
7026
|
// In script mode we must not wrap in parens (that would make multi-statement input invalid).
|
|
7017
7027
|
// Offsets from the parser therefore refer directly to the original expression, so no shift.
|
|
@@ -7020,13 +7030,17 @@ class ExpressionUtils {
|
|
|
7020
7030
|
const offsetShift = asScript ? 0 : 1;
|
|
7021
7031
|
const parsedAst = parse(source, { ecmaVersion: 'latest' });
|
|
7022
7032
|
// Track identifiers that are locally declared within the handler body (let/const/var, function
|
|
7023
|
-
// params) so we don't rewrite them to `this.xxx`.
|
|
7024
|
-
//
|
|
7033
|
+
// params) so we don't rewrite them to `this.xxx`. Additionally detect `this` aliases such as
|
|
7034
|
+
// `let vm = this;` so that `vm.x` can be rewritten to `this.x` even though `vm` is locally declared.
|
|
7025
7035
|
const locallyDeclared = new Set();
|
|
7036
|
+
const thisAliases = new Set();
|
|
7026
7037
|
if (asScript) {
|
|
7027
7038
|
full(parsedAst, (node) => {
|
|
7028
7039
|
if (node.type === 'VariableDeclarator' && node.id?.type === 'Identifier') {
|
|
7029
7040
|
locallyDeclared.add(node.id.name);
|
|
7041
|
+
if (node.init && node.init.type === 'ThisExpression') {
|
|
7042
|
+
thisAliases.add(node.id.name);
|
|
7043
|
+
}
|
|
7030
7044
|
}
|
|
7031
7045
|
else if (node.type === 'FunctionDeclaration' && node.id?.type === 'Identifier') {
|
|
7032
7046
|
locallyDeclared.add(node.id.name);
|
|
@@ -7043,20 +7057,34 @@ class ExpressionUtils {
|
|
|
7043
7057
|
if (!bindingIdentifiers.has(node.name)) {
|
|
7044
7058
|
return;
|
|
7045
7059
|
}
|
|
7046
|
-
//
|
|
7060
|
+
// Locally declared identifiers must not be rewritten to `this.xxx`. The one
|
|
7061
|
+
// exception is a `this`-alias (e.g. `let vm = this;`): when such an alias is
|
|
7062
|
+
// used as the OBJECT of a MemberExpression (`vm.x`), we replace just the
|
|
7063
|
+
// object with `this` so that `vm.x` becomes `this.x`. In every other position
|
|
7064
|
+
// (the declaration LHS, a bare reference such as `console.log(vm)`, an
|
|
7065
|
+
// argument, etc.) the alias must be left untouched — rewriting it to
|
|
7066
|
+
// `this.vm` would either produce a syntax error (`let this.vm = this;`) or
|
|
7067
|
+
// change the meaning at runtime.
|
|
7068
|
+
// walk.fullAncestor includes the visited node itself as the last entry of
|
|
7069
|
+
// `ancestors`, so the actual parent node is at length - 2.
|
|
7070
|
+
const parentNode = ancestors.length >= 2 ? ancestors[ancestors.length - 2] : undefined;
|
|
7071
|
+
const isAliasAsMemberObject = parentNode?.type === 'MemberExpression' && parentNode.object === node;
|
|
7047
7072
|
if (locallyDeclared.has(node.name)) {
|
|
7073
|
+
if (!thisAliases.has(node.name) || !isAliasAsMemberObject) {
|
|
7074
|
+
return;
|
|
7075
|
+
}
|
|
7076
|
+
replacements.push({
|
|
7077
|
+
start: node.start - offsetShift,
|
|
7078
|
+
end: node.end - offsetShift,
|
|
7079
|
+
name: node.name,
|
|
7080
|
+
asThisAlias: true
|
|
7081
|
+
});
|
|
7048
7082
|
return;
|
|
7049
7083
|
}
|
|
7050
|
-
//
|
|
7051
|
-
// (e.g., in
|
|
7052
|
-
if (
|
|
7053
|
-
|
|
7054
|
-
if (parent.type === 'MemberExpression') {
|
|
7055
|
-
// Skip if this identifier is the property (not the object) of a non-computed member access
|
|
7056
|
-
if (!parent.computed && parent.property === node) {
|
|
7057
|
-
return;
|
|
7058
|
-
}
|
|
7059
|
-
}
|
|
7084
|
+
// Skip identifiers that are the property (not the object) of a non-computed
|
|
7085
|
+
// member access (e.g., the `prop` in `obj.prop`).
|
|
7086
|
+
if (parentNode?.type === 'MemberExpression' && !parentNode.computed && parentNode.property === node) {
|
|
7087
|
+
return;
|
|
7060
7088
|
}
|
|
7061
7089
|
// Add to replacements list (adjust for the wrapping parentheses in expression mode)
|
|
7062
7090
|
replacements.push({
|
|
@@ -7070,9 +7098,8 @@ class ExpressionUtils {
|
|
|
7070
7098
|
// Apply replacements
|
|
7071
7099
|
let result = expression;
|
|
7072
7100
|
for (const replacement of replacements) {
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
result.substring(replacement.end);
|
|
7101
|
+
const insertion = replacement.asThisAlias ? 'this' : `this.${replacement.name}`;
|
|
7102
|
+
result = result.substring(0, replacement.start) + insertion + result.substring(replacement.end);
|
|
7076
7103
|
}
|
|
7077
7104
|
return result;
|
|
7078
7105
|
}
|
|
@@ -11164,12 +11191,23 @@ class VModelDirective {
|
|
|
11164
11191
|
#collectDependentIdentifiers() {
|
|
11165
11192
|
const ids = new Set(this.#evaluator?.dependentIdentifiers ?? []);
|
|
11166
11193
|
const element = this.#vNode.node;
|
|
11167
|
-
if (element instanceof HTMLInputElement
|
|
11194
|
+
if (element instanceof HTMLInputElement) {
|
|
11168
11195
|
const manager = this.#vNode.directiveManager;
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11196
|
+
// For checkboxes and radios, v-model's rendered state depends on
|
|
11197
|
+
// the element's typed `:value` binding (if present). Checkboxes
|
|
11198
|
+
// additionally depend on `:true-value` / `:false-value` bindings.
|
|
11199
|
+
if (element.type === 'checkbox' || element.type === 'radio') {
|
|
11200
|
+
const valueBind = manager?.findBindDirective('value');
|
|
11201
|
+
if (valueBind) {
|
|
11202
|
+
valueBind.dependentIdentifiers.forEach(id => ids.add(id));
|
|
11203
|
+
}
|
|
11204
|
+
}
|
|
11205
|
+
if (element.type === 'checkbox') {
|
|
11206
|
+
for (const attrName of ['true-value', 'false-value']) {
|
|
11207
|
+
const bindDirective = manager?.findBindDirective(attrName);
|
|
11208
|
+
if (bindDirective) {
|
|
11209
|
+
bindDirective.dependentIdentifiers.forEach(id => ids.add(id));
|
|
11210
|
+
}
|
|
11173
11211
|
}
|
|
11174
11212
|
}
|
|
11175
11213
|
}
|
|
@@ -11256,11 +11294,13 @@ class VModelDirective {
|
|
|
11256
11294
|
this.#renderCheckbox(element, value);
|
|
11257
11295
|
}
|
|
11258
11296
|
else if (element.type === 'radio') {
|
|
11259
|
-
// Prefer the
|
|
11260
|
-
//
|
|
11261
|
-
const
|
|
11262
|
-
|
|
11263
|
-
|
|
11297
|
+
// Prefer the typed value from a sibling :value binding when present,
|
|
11298
|
+
// falling back to any stored `_value` or the raw string `value`.
|
|
11299
|
+
const manager = this.#vNode.directiveManager;
|
|
11300
|
+
const bindDirective = manager?.findBindDirective('value');
|
|
11301
|
+
const radioValue = bindDirective !== undefined
|
|
11302
|
+
? bindDirective.evaluate()
|
|
11303
|
+
: (element._value !== undefined ? element._value : element.value);
|
|
11264
11304
|
element.checked = radioValue === value;
|
|
11265
11305
|
}
|
|
11266
11306
|
else {
|
|
@@ -11289,11 +11329,13 @@ class VModelDirective {
|
|
|
11289
11329
|
newValue = this.#computeCheckboxNewValue(target);
|
|
11290
11330
|
}
|
|
11291
11331
|
else if (target.type === 'radio') {
|
|
11292
|
-
// Prefer the
|
|
11293
|
-
//
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11332
|
+
// Prefer the typed value from a sibling :value binding when present,
|
|
11333
|
+
// falling back to any stored `_value` or the raw string `value`.
|
|
11334
|
+
const manager = this.#vNode.directiveManager;
|
|
11335
|
+
const bindDirective = manager?.findBindDirective('value');
|
|
11336
|
+
newValue = bindDirective !== undefined
|
|
11337
|
+
? bindDirective.evaluate()
|
|
11338
|
+
: (target._value !== undefined ? target._value : target.value);
|
|
11297
11339
|
}
|
|
11298
11340
|
else {
|
|
11299
11341
|
newValue = target.value;
|
|
@@ -11489,6 +11531,15 @@ class VModelDirective {
|
|
|
11489
11531
|
* Mouse button modifiers (MouseEvent): `.left`, `.middle`, `.right`.
|
|
11490
11532
|
* System modifiers (KeyboardEvent and MouseEvent): `.shift`, `.ctrl`, `.alt`, `.meta`, plus `.exact` to require that no other system modifiers are held.
|
|
11491
11533
|
*
|
|
11534
|
+
* Listen target and filter modifiers (two orthogonal axes):
|
|
11535
|
+
* - Listen target (where the listener is attached): `.window`, `.document`. When omitted the listener
|
|
11536
|
+
* is attached to the bound element. This is useful for global / cross-component events, e.g.
|
|
11537
|
+
* `@webtop-message.document="onMessage"`, and the listener is removed automatically on unmount.
|
|
11538
|
+
* - Filter (whether the handler runs): `.self` fires only when `event.target` is the bound element;
|
|
11539
|
+
* `.outside` fires only when `event.target` is outside the bound element (e.g. click-outside to
|
|
11540
|
+
* close a popup). `.outside` implies listening on `document` (capture phase) even without `.document`,
|
|
11541
|
+
* and `.self` / `.outside` are mutually exclusive.
|
|
11542
|
+
*
|
|
11492
11543
|
* Additionally, this directive supports lifecycle hooks:
|
|
11493
11544
|
* @mount="onMount" - Called before the VNode is mounted to the DOM element
|
|
11494
11545
|
* @mounted="onMounted" - Called after the VNode is mounted to the DOM element
|
|
@@ -11527,6 +11578,26 @@ class VOnDirective {
|
|
|
11527
11578
|
* The event listener function for DOM events.
|
|
11528
11579
|
*/
|
|
11529
11580
|
#listener;
|
|
11581
|
+
/**
|
|
11582
|
+
* The resolved target the listener is attached to (element, document, or window).
|
|
11583
|
+
* Stored so destroy() removes the listener from the same target it was added to.
|
|
11584
|
+
*/
|
|
11585
|
+
#resolvedTarget;
|
|
11586
|
+
/**
|
|
11587
|
+
* The resolved capture flag. Shared by attach and destroy so they stay in sync,
|
|
11588
|
+
* since `.outside` forces capture phase regardless of the `.capture` modifier.
|
|
11589
|
+
*/
|
|
11590
|
+
#useCapture = false;
|
|
11591
|
+
/**
|
|
11592
|
+
* Whether the listener has actually been attached. `.outside` defers attachment by a
|
|
11593
|
+
* microtask, so destroy() must not attempt removal before it is attached.
|
|
11594
|
+
*/
|
|
11595
|
+
#attached = false;
|
|
11596
|
+
/**
|
|
11597
|
+
* Whether the directive has been destroyed. Guards the deferred `.outside` attachment
|
|
11598
|
+
* from attaching after the node was already unmounted.
|
|
11599
|
+
*/
|
|
11600
|
+
#destroyed = false;
|
|
11530
11601
|
/**
|
|
11531
11602
|
* Map of lifecycle hook names to their handler functions.
|
|
11532
11603
|
*/
|
|
@@ -11550,6 +11621,12 @@ class VOnDirective {
|
|
|
11550
11621
|
this.#eventName = parts[0];
|
|
11551
11622
|
parts.slice(1).forEach(mod => this.#modifiers.add(mod));
|
|
11552
11623
|
}
|
|
11624
|
+
// `.self` and `.outside` are mutually exclusive filters; together they can never fire.
|
|
11625
|
+
if (this.#modifiers.has('self') && this.#modifiers.has('outside')) {
|
|
11626
|
+
context.vNode.vApplication.logManager
|
|
11627
|
+
.getLogger('VOnDirective')
|
|
11628
|
+
.warn(`The '.self' and '.outside' modifiers on '${attrName}' are mutually exclusive; the handler will never fire.`);
|
|
11629
|
+
}
|
|
11553
11630
|
// Parse the expression to extract identifiers and create the handler wrapper.
|
|
11554
11631
|
// Event handlers are parsed in script mode so that users can write multi-statement bodies
|
|
11555
11632
|
// (e.g. "a=1; b=2"), declarations, and control-flow constructs — matching Vue semantics.
|
|
@@ -11659,11 +11736,10 @@ class VOnDirective {
|
|
|
11659
11736
|
* @inheritdoc
|
|
11660
11737
|
*/
|
|
11661
11738
|
destroy() {
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
element.removeEventListener(this.#eventName, this.#listener, useCapture);
|
|
11739
|
+
this.#destroyed = true;
|
|
11740
|
+
// Remove the event listener from the same target/phase it was attached to.
|
|
11741
|
+
if (this.#eventName && this.#listener && this.#resolvedTarget && this.#attached) {
|
|
11742
|
+
this.#resolvedTarget.removeEventListener(this.#eventName, this.#listener, this.#useCapture);
|
|
11667
11743
|
}
|
|
11668
11744
|
}
|
|
11669
11745
|
/**
|
|
@@ -11679,8 +11755,21 @@ class VOnDirective {
|
|
|
11679
11755
|
}
|
|
11680
11756
|
const element = this.#vNode.node;
|
|
11681
11757
|
const eventName = this.#eventName;
|
|
11682
|
-
const useCapture = this.#modifiers.has('capture');
|
|
11683
11758
|
const isOnce = this.#modifiers.has('once');
|
|
11759
|
+
const isOutside = this.#modifiers.has('outside');
|
|
11760
|
+
// Resolve the listen target (orthogonal to filters): `.window` / `.document` attach
|
|
11761
|
+
// the listener globally; `.outside` also requires a global listener to detect events
|
|
11762
|
+
// originating outside the element, so it implies `document`.
|
|
11763
|
+
this.#resolvedTarget = this.#modifiers.has('window')
|
|
11764
|
+
? window
|
|
11765
|
+
: (this.#modifiers.has('document') || isOutside)
|
|
11766
|
+
? document
|
|
11767
|
+
: element;
|
|
11768
|
+
// `.outside` listens in capture phase so it is not suppressed by a descendant's
|
|
11769
|
+
// stopPropagation(); otherwise the capture flag follows the `.capture` modifier.
|
|
11770
|
+
this.#useCapture = this.#modifiers.has('capture') || isOutside;
|
|
11771
|
+
const useCapture = this.#useCapture;
|
|
11772
|
+
const target = this.#resolvedTarget;
|
|
11684
11773
|
// System modifier keys (held during the event) shared by KeyboardEvent and MouseEvent.
|
|
11685
11774
|
const systemModifiers = ['shift', 'ctrl', 'alt', 'meta'];
|
|
11686
11775
|
// Create the event listener function
|
|
@@ -11766,6 +11855,14 @@ class VOnDirective {
|
|
|
11766
11855
|
if (this.#modifiers.has('self') && event.target !== element) {
|
|
11767
11856
|
return;
|
|
11768
11857
|
}
|
|
11858
|
+
// `.outside`: only fire when the event originates outside the bound element.
|
|
11859
|
+
// A non-Node target (e.g. window) is treated as outside.
|
|
11860
|
+
if (isOutside) {
|
|
11861
|
+
const eventTarget = event.target;
|
|
11862
|
+
if (eventTarget instanceof Node && element.contains(eventTarget)) {
|
|
11863
|
+
return;
|
|
11864
|
+
}
|
|
11865
|
+
}
|
|
11769
11866
|
// Call the pre-generated handler wrapper (if exists)
|
|
11770
11867
|
if (this.#handlerWrapper) {
|
|
11771
11868
|
this.#handlerWrapper(event);
|
|
@@ -11774,11 +11871,26 @@ class VOnDirective {
|
|
|
11774
11871
|
// No need to manually call scheduleUpdate() here
|
|
11775
11872
|
// If 'once' modifier is used, remove the listener after first execution
|
|
11776
11873
|
if (isOnce && this.#listener) {
|
|
11777
|
-
|
|
11874
|
+
target.removeEventListener(eventName, this.#listener, useCapture);
|
|
11875
|
+
this.#attached = false;
|
|
11778
11876
|
}
|
|
11779
11877
|
};
|
|
11780
|
-
|
|
11781
|
-
|
|
11878
|
+
if (isOutside) {
|
|
11879
|
+
// Defer attachment by one microtask so the listener does not catch the same
|
|
11880
|
+
// interaction that mounted this element (e.g. the click that opened a popup,
|
|
11881
|
+
// which would otherwise immediately close it). Skip if already destroyed.
|
|
11882
|
+
queueMicrotask(() => {
|
|
11883
|
+
if (this.#destroyed || !this.#listener) {
|
|
11884
|
+
return;
|
|
11885
|
+
}
|
|
11886
|
+
target.addEventListener(eventName, this.#listener, useCapture);
|
|
11887
|
+
this.#attached = true;
|
|
11888
|
+
});
|
|
11889
|
+
}
|
|
11890
|
+
else {
|
|
11891
|
+
target.addEventListener(eventName, this.#listener, useCapture);
|
|
11892
|
+
this.#attached = true;
|
|
11893
|
+
}
|
|
11782
11894
|
}
|
|
11783
11895
|
/**
|
|
11784
11896
|
* Checks if the event name is a lifecycle hook.
|
|
@@ -13562,6 +13674,7 @@ class VApplication {
|
|
|
13562
13674
|
// Inject utility methods into bindings
|
|
13563
13675
|
this.#bindings.set('$nextTick', (callback) => this.#nextTick(callback));
|
|
13564
13676
|
this.#bindings.set('$markRaw', (obj) => ReactiveProxy.markRaw(obj));
|
|
13677
|
+
this.#bindings.set('$emit', (name, detail, options) => this.#emit(name, detail, options));
|
|
13565
13678
|
// Add methods
|
|
13566
13679
|
if (this.#options.methods) {
|
|
13567
13680
|
for (const [key, method] of Object.entries(this.#options.methods)) {
|
|
@@ -13807,6 +13920,38 @@ class VApplication {
|
|
|
13807
13920
|
compute(key);
|
|
13808
13921
|
}
|
|
13809
13922
|
}
|
|
13923
|
+
/**
|
|
13924
|
+
* Dispatches a CustomEvent, providing the framework-level `$emit` available in expressions
|
|
13925
|
+
* and methods. By default the event is dispatched on the application root element with
|
|
13926
|
+
* `bubbles: true`, so a parent component can listen for it via `v-on` / `@` on the component
|
|
13927
|
+
* tag (the root is rendered inside the host custom element, so the event bubbles out of it).
|
|
13928
|
+
*
|
|
13929
|
+
* The dispatch target can be overridden via `options.target` (e.g. `document` / `window`) to
|
|
13930
|
+
* use a global event bus, interoperating with native `addEventListener` listeners.
|
|
13931
|
+
*
|
|
13932
|
+
* @param name The event name (e.g. "selected"). Listened to as `@selected` on the parent side.
|
|
13933
|
+
* @param detail The payload exposed as `event.detail`.
|
|
13934
|
+
* @param options Dispatch options (bubbles, cancelable, composed, target).
|
|
13935
|
+
* @returns The result of dispatchEvent: false if a listener called preventDefault(), otherwise true.
|
|
13936
|
+
*/
|
|
13937
|
+
#emit(name, detail, options) {
|
|
13938
|
+
// Documentation/validation only: warn when emitting an event not declared in `emits`.
|
|
13939
|
+
if (this.#options.emits && !this.#options.emits.includes(name)) {
|
|
13940
|
+
this.#logger.warn(`Event '${name}' is emitted but not declared in the 'emits' option.`);
|
|
13941
|
+
}
|
|
13942
|
+
const target = options?.target ?? this.#vNode?.node;
|
|
13943
|
+
if (!target) {
|
|
13944
|
+
this.#logger.warn(`$emit('${name}') was called before the application was mounted; the event was not dispatched.`);
|
|
13945
|
+
return false;
|
|
13946
|
+
}
|
|
13947
|
+
const event = new CustomEvent(name, {
|
|
13948
|
+
detail,
|
|
13949
|
+
bubbles: options?.bubbles ?? true,
|
|
13950
|
+
cancelable: options?.cancelable ?? true,
|
|
13951
|
+
composed: options?.composed ?? false,
|
|
13952
|
+
});
|
|
13953
|
+
return target.dispatchEvent(event);
|
|
13954
|
+
}
|
|
13810
13955
|
/**
|
|
13811
13956
|
* Executes a callback after the next DOM update.
|
|
13812
13957
|
* @param callback The callback to execute.
|
|
@@ -14099,7 +14244,7 @@ class IchigoElement extends HTMLElement {
|
|
|
14099
14244
|
* @param options Component options including template selector and optional props.
|
|
14100
14245
|
*/
|
|
14101
14246
|
function defineComponent(tagName, options) {
|
|
14102
|
-
const { props = [], template, data, computed, methods, watch, logLevel } = options;
|
|
14247
|
+
const { props = [], template, data, computed, methods, watch, emits, logLevel } = options;
|
|
14103
14248
|
// Build a subclass of IchigoElement specific to this component
|
|
14104
14249
|
class ComponentElement extends IchigoElement {
|
|
14105
14250
|
static _template = template;
|
|
@@ -14121,6 +14266,7 @@ function defineComponent(tagName, options) {
|
|
|
14121
14266
|
computed,
|
|
14122
14267
|
methods,
|
|
14123
14268
|
watch,
|
|
14269
|
+
emits,
|
|
14124
14270
|
logLevel,
|
|
14125
14271
|
};
|
|
14126
14272
|
}
|