@mintjamsinc/ichigojs 0.1.66 → 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 +114 -10
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +114 -10
- 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 +114 -10
- 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.cjs
CHANGED
|
@@ -11537,6 +11537,15 @@
|
|
|
11537
11537
|
* Mouse button modifiers (MouseEvent): `.left`, `.middle`, `.right`.
|
|
11538
11538
|
* System modifiers (KeyboardEvent and MouseEvent): `.shift`, `.ctrl`, `.alt`, `.meta`, plus `.exact` to require that no other system modifiers are held.
|
|
11539
11539
|
*
|
|
11540
|
+
* Listen target and filter modifiers (two orthogonal axes):
|
|
11541
|
+
* - Listen target (where the listener is attached): `.window`, `.document`. When omitted the listener
|
|
11542
|
+
* is attached to the bound element. This is useful for global / cross-component events, e.g.
|
|
11543
|
+
* `@webtop-message.document="onMessage"`, and the listener is removed automatically on unmount.
|
|
11544
|
+
* - Filter (whether the handler runs): `.self` fires only when `event.target` is the bound element;
|
|
11545
|
+
* `.outside` fires only when `event.target` is outside the bound element (e.g. click-outside to
|
|
11546
|
+
* close a popup). `.outside` implies listening on `document` (capture phase) even without `.document`,
|
|
11547
|
+
* and `.self` / `.outside` are mutually exclusive.
|
|
11548
|
+
*
|
|
11540
11549
|
* Additionally, this directive supports lifecycle hooks:
|
|
11541
11550
|
* @mount="onMount" - Called before the VNode is mounted to the DOM element
|
|
11542
11551
|
* @mounted="onMounted" - Called after the VNode is mounted to the DOM element
|
|
@@ -11575,6 +11584,26 @@
|
|
|
11575
11584
|
* The event listener function for DOM events.
|
|
11576
11585
|
*/
|
|
11577
11586
|
#listener;
|
|
11587
|
+
/**
|
|
11588
|
+
* The resolved target the listener is attached to (element, document, or window).
|
|
11589
|
+
* Stored so destroy() removes the listener from the same target it was added to.
|
|
11590
|
+
*/
|
|
11591
|
+
#resolvedTarget;
|
|
11592
|
+
/**
|
|
11593
|
+
* The resolved capture flag. Shared by attach and destroy so they stay in sync,
|
|
11594
|
+
* since `.outside` forces capture phase regardless of the `.capture` modifier.
|
|
11595
|
+
*/
|
|
11596
|
+
#useCapture = false;
|
|
11597
|
+
/**
|
|
11598
|
+
* Whether the listener has actually been attached. `.outside` defers attachment by a
|
|
11599
|
+
* microtask, so destroy() must not attempt removal before it is attached.
|
|
11600
|
+
*/
|
|
11601
|
+
#attached = false;
|
|
11602
|
+
/**
|
|
11603
|
+
* Whether the directive has been destroyed. Guards the deferred `.outside` attachment
|
|
11604
|
+
* from attaching after the node was already unmounted.
|
|
11605
|
+
*/
|
|
11606
|
+
#destroyed = false;
|
|
11578
11607
|
/**
|
|
11579
11608
|
* Map of lifecycle hook names to their handler functions.
|
|
11580
11609
|
*/
|
|
@@ -11598,6 +11627,12 @@
|
|
|
11598
11627
|
this.#eventName = parts[0];
|
|
11599
11628
|
parts.slice(1).forEach(mod => this.#modifiers.add(mod));
|
|
11600
11629
|
}
|
|
11630
|
+
// `.self` and `.outside` are mutually exclusive filters; together they can never fire.
|
|
11631
|
+
if (this.#modifiers.has('self') && this.#modifiers.has('outside')) {
|
|
11632
|
+
context.vNode.vApplication.logManager
|
|
11633
|
+
.getLogger('VOnDirective')
|
|
11634
|
+
.warn(`The '.self' and '.outside' modifiers on '${attrName}' are mutually exclusive; the handler will never fire.`);
|
|
11635
|
+
}
|
|
11601
11636
|
// Parse the expression to extract identifiers and create the handler wrapper.
|
|
11602
11637
|
// Event handlers are parsed in script mode so that users can write multi-statement bodies
|
|
11603
11638
|
// (e.g. "a=1; b=2"), declarations, and control-flow constructs — matching Vue semantics.
|
|
@@ -11707,11 +11742,10 @@
|
|
|
11707
11742
|
* @inheritdoc
|
|
11708
11743
|
*/
|
|
11709
11744
|
destroy() {
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
element.removeEventListener(this.#eventName, this.#listener, useCapture);
|
|
11745
|
+
this.#destroyed = true;
|
|
11746
|
+
// Remove the event listener from the same target/phase it was attached to.
|
|
11747
|
+
if (this.#eventName && this.#listener && this.#resolvedTarget && this.#attached) {
|
|
11748
|
+
this.#resolvedTarget.removeEventListener(this.#eventName, this.#listener, this.#useCapture);
|
|
11715
11749
|
}
|
|
11716
11750
|
}
|
|
11717
11751
|
/**
|
|
@@ -11727,8 +11761,21 @@
|
|
|
11727
11761
|
}
|
|
11728
11762
|
const element = this.#vNode.node;
|
|
11729
11763
|
const eventName = this.#eventName;
|
|
11730
|
-
const useCapture = this.#modifiers.has('capture');
|
|
11731
11764
|
const isOnce = this.#modifiers.has('once');
|
|
11765
|
+
const isOutside = this.#modifiers.has('outside');
|
|
11766
|
+
// Resolve the listen target (orthogonal to filters): `.window` / `.document` attach
|
|
11767
|
+
// the listener globally; `.outside` also requires a global listener to detect events
|
|
11768
|
+
// originating outside the element, so it implies `document`.
|
|
11769
|
+
this.#resolvedTarget = this.#modifiers.has('window')
|
|
11770
|
+
? window
|
|
11771
|
+
: (this.#modifiers.has('document') || isOutside)
|
|
11772
|
+
? document
|
|
11773
|
+
: element;
|
|
11774
|
+
// `.outside` listens in capture phase so it is not suppressed by a descendant's
|
|
11775
|
+
// stopPropagation(); otherwise the capture flag follows the `.capture` modifier.
|
|
11776
|
+
this.#useCapture = this.#modifiers.has('capture') || isOutside;
|
|
11777
|
+
const useCapture = this.#useCapture;
|
|
11778
|
+
const target = this.#resolvedTarget;
|
|
11732
11779
|
// System modifier keys (held during the event) shared by KeyboardEvent and MouseEvent.
|
|
11733
11780
|
const systemModifiers = ['shift', 'ctrl', 'alt', 'meta'];
|
|
11734
11781
|
// Create the event listener function
|
|
@@ -11814,6 +11861,14 @@
|
|
|
11814
11861
|
if (this.#modifiers.has('self') && event.target !== element) {
|
|
11815
11862
|
return;
|
|
11816
11863
|
}
|
|
11864
|
+
// `.outside`: only fire when the event originates outside the bound element.
|
|
11865
|
+
// A non-Node target (e.g. window) is treated as outside.
|
|
11866
|
+
if (isOutside) {
|
|
11867
|
+
const eventTarget = event.target;
|
|
11868
|
+
if (eventTarget instanceof Node && element.contains(eventTarget)) {
|
|
11869
|
+
return;
|
|
11870
|
+
}
|
|
11871
|
+
}
|
|
11817
11872
|
// Call the pre-generated handler wrapper (if exists)
|
|
11818
11873
|
if (this.#handlerWrapper) {
|
|
11819
11874
|
this.#handlerWrapper(event);
|
|
@@ -11822,11 +11877,26 @@
|
|
|
11822
11877
|
// No need to manually call scheduleUpdate() here
|
|
11823
11878
|
// If 'once' modifier is used, remove the listener after first execution
|
|
11824
11879
|
if (isOnce && this.#listener) {
|
|
11825
|
-
|
|
11880
|
+
target.removeEventListener(eventName, this.#listener, useCapture);
|
|
11881
|
+
this.#attached = false;
|
|
11826
11882
|
}
|
|
11827
11883
|
};
|
|
11828
|
-
|
|
11829
|
-
|
|
11884
|
+
if (isOutside) {
|
|
11885
|
+
// Defer attachment by one microtask so the listener does not catch the same
|
|
11886
|
+
// interaction that mounted this element (e.g. the click that opened a popup,
|
|
11887
|
+
// which would otherwise immediately close it). Skip if already destroyed.
|
|
11888
|
+
queueMicrotask(() => {
|
|
11889
|
+
if (this.#destroyed || !this.#listener) {
|
|
11890
|
+
return;
|
|
11891
|
+
}
|
|
11892
|
+
target.addEventListener(eventName, this.#listener, useCapture);
|
|
11893
|
+
this.#attached = true;
|
|
11894
|
+
});
|
|
11895
|
+
}
|
|
11896
|
+
else {
|
|
11897
|
+
target.addEventListener(eventName, this.#listener, useCapture);
|
|
11898
|
+
this.#attached = true;
|
|
11899
|
+
}
|
|
11830
11900
|
}
|
|
11831
11901
|
/**
|
|
11832
11902
|
* Checks if the event name is a lifecycle hook.
|
|
@@ -13610,6 +13680,7 @@
|
|
|
13610
13680
|
// Inject utility methods into bindings
|
|
13611
13681
|
this.#bindings.set('$nextTick', (callback) => this.#nextTick(callback));
|
|
13612
13682
|
this.#bindings.set('$markRaw', (obj) => ReactiveProxy.markRaw(obj));
|
|
13683
|
+
this.#bindings.set('$emit', (name, detail, options) => this.#emit(name, detail, options));
|
|
13613
13684
|
// Add methods
|
|
13614
13685
|
if (this.#options.methods) {
|
|
13615
13686
|
for (const [key, method] of Object.entries(this.#options.methods)) {
|
|
@@ -13855,6 +13926,38 @@
|
|
|
13855
13926
|
compute(key);
|
|
13856
13927
|
}
|
|
13857
13928
|
}
|
|
13929
|
+
/**
|
|
13930
|
+
* Dispatches a CustomEvent, providing the framework-level `$emit` available in expressions
|
|
13931
|
+
* and methods. By default the event is dispatched on the application root element with
|
|
13932
|
+
* `bubbles: true`, so a parent component can listen for it via `v-on` / `@` on the component
|
|
13933
|
+
* tag (the root is rendered inside the host custom element, so the event bubbles out of it).
|
|
13934
|
+
*
|
|
13935
|
+
* The dispatch target can be overridden via `options.target` (e.g. `document` / `window`) to
|
|
13936
|
+
* use a global event bus, interoperating with native `addEventListener` listeners.
|
|
13937
|
+
*
|
|
13938
|
+
* @param name The event name (e.g. "selected"). Listened to as `@selected` on the parent side.
|
|
13939
|
+
* @param detail The payload exposed as `event.detail`.
|
|
13940
|
+
* @param options Dispatch options (bubbles, cancelable, composed, target).
|
|
13941
|
+
* @returns The result of dispatchEvent: false if a listener called preventDefault(), otherwise true.
|
|
13942
|
+
*/
|
|
13943
|
+
#emit(name, detail, options) {
|
|
13944
|
+
// Documentation/validation only: warn when emitting an event not declared in `emits`.
|
|
13945
|
+
if (this.#options.emits && !this.#options.emits.includes(name)) {
|
|
13946
|
+
this.#logger.warn(`Event '${name}' is emitted but not declared in the 'emits' option.`);
|
|
13947
|
+
}
|
|
13948
|
+
const target = options?.target ?? this.#vNode?.node;
|
|
13949
|
+
if (!target) {
|
|
13950
|
+
this.#logger.warn(`$emit('${name}') was called before the application was mounted; the event was not dispatched.`);
|
|
13951
|
+
return false;
|
|
13952
|
+
}
|
|
13953
|
+
const event = new CustomEvent(name, {
|
|
13954
|
+
detail,
|
|
13955
|
+
bubbles: options?.bubbles ?? true,
|
|
13956
|
+
cancelable: options?.cancelable ?? true,
|
|
13957
|
+
composed: options?.composed ?? false,
|
|
13958
|
+
});
|
|
13959
|
+
return target.dispatchEvent(event);
|
|
13960
|
+
}
|
|
13858
13961
|
/**
|
|
13859
13962
|
* Executes a callback after the next DOM update.
|
|
13860
13963
|
* @param callback The callback to execute.
|
|
@@ -14147,7 +14250,7 @@
|
|
|
14147
14250
|
* @param options Component options including template selector and optional props.
|
|
14148
14251
|
*/
|
|
14149
14252
|
function defineComponent(tagName, options) {
|
|
14150
|
-
const { props = [], template, data, computed, methods, watch, logLevel } = options;
|
|
14253
|
+
const { props = [], template, data, computed, methods, watch, emits, logLevel } = options;
|
|
14151
14254
|
// Build a subclass of IchigoElement specific to this component
|
|
14152
14255
|
class ComponentElement extends IchigoElement {
|
|
14153
14256
|
static _template = template;
|
|
@@ -14169,6 +14272,7 @@
|
|
|
14169
14272
|
computed,
|
|
14170
14273
|
methods,
|
|
14171
14274
|
watch,
|
|
14275
|
+
emits,
|
|
14172
14276
|
logLevel,
|
|
14173
14277
|
};
|
|
14174
14278
|
}
|