@mintjamsinc/ichigojs 0.1.61 → 0.1.63

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/README.md CHANGED
@@ -277,7 +277,27 @@ Event handling with modifiers:
277
277
  <div @click.stop="handleClick">Stop propagation</div>
278
278
  ```
279
279
 
280
- Supported modifiers: `.stop`, `.prevent`, `.capture`, `.self`, `.once`
280
+ Event modifiers: `.stop`, `.prevent`, `.capture`, `.self`, `.once`
281
+
282
+ Key modifiers (KeyboardEvent): `.enter`, `.tab`, `.delete` (matches Delete/Backspace), `.esc` / `.escape`, `.space`, `.up`, `.down`, `.left`, `.right`
283
+
284
+ Mouse button modifiers (MouseEvent): `.left`, `.middle`, `.right`
285
+
286
+ System modifier keys (KeyboardEvent and MouseEvent): `.shift`, `.ctrl`, `.alt`, `.meta`. Add `.exact` to require that no other system modifiers are held.
287
+
288
+ ```html
289
+ <!-- Shift + Click -->
290
+ <button @click.shift="onShiftClick">Shift+Click</button>
291
+
292
+ <!-- Right-click without bringing up the browser menu -->
293
+ <div @contextmenu.prevent="onMenu">Right-click me</div>
294
+
295
+ <!-- Middle-click -->
296
+ <a @mousedown.middle="onMiddleClick">Middle-click</a>
297
+
298
+ <!-- Ctrl+Click only (no other modifiers held) -->
299
+ <button @click.ctrl.exact="onCtrlClickOnly">Ctrl+Click only</button>
300
+ ```
281
301
 
282
302
  **Event Handlers with Context:**
283
303
 
package/dist/ichigo.cjs CHANGED
@@ -7621,7 +7621,9 @@
7621
7621
  * (lowercased) HTML attribute name. HTML attributes are always lowercase,
7622
7622
  * but custom element props are typically camelCase. This method checks the
7623
7623
  * element's declared _props (set by defineComponent) for a case-insensitive
7624
- * match, falling back to scanning the prototype's own property descriptors.
7624
+ * match against both the raw attribute name and its kebab-case → camelCase
7625
+ * conversion (so `user-name` resolves to `userName`), falling back to the
7626
+ * original name when no match is found.
7625
7627
  */
7626
7628
  #resolveCustomElementPropertyName(element, name) {
7627
7629
  // Fast path: exact match already exists
@@ -7632,13 +7634,23 @@
7632
7634
  const props = element.constructor._props;
7633
7635
  if (Array.isArray(props)) {
7634
7636
  const lowerName = name.toLowerCase();
7635
- const match = props.find(p => p.toLowerCase() === lowerName);
7637
+ const camelName = this.#kebabToCamel(lowerName);
7638
+ const match = props.find(p => {
7639
+ const lowerProp = p.toLowerCase();
7640
+ return lowerProp === lowerName || lowerProp === camelName.toLowerCase() || p === camelName;
7641
+ });
7636
7642
  if (match) {
7637
7643
  return match;
7638
7644
  }
7639
7645
  }
7640
7646
  return name;
7641
7647
  }
7648
+ /**
7649
+ * Converts kebab-case to camelCase (e.g. `user-name` → `userName`).
7650
+ */
7651
+ #kebabToCamel(str) {
7652
+ return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
7653
+ }
7642
7654
  /**
7643
7655
  * Checks if the attribute should be set as a DOM property.
7644
7656
  */
@@ -11322,6 +11334,10 @@
11322
11334
  * The `v-on` directive supports event modifiers such as `.stop`, `.prevent`, `.capture`, `.self`, and `.once` to modify the behavior of the event listener.
11323
11335
  * For example, `v-on:click.stop="handleClick"` will stop the event from propagating up the DOM tree.
11324
11336
  *
11337
+ * Key modifiers (KeyboardEvent): `.enter`, `.tab`, `.delete` (Delete/Backspace), `.esc` / `.escape`, `.space`, `.up`, `.down`, `.left`, `.right`.
11338
+ * Mouse button modifiers (MouseEvent): `.left`, `.middle`, `.right`.
11339
+ * System modifiers (KeyboardEvent and MouseEvent): `.shift`, `.ctrl`, `.alt`, `.meta`, plus `.exact` to require that no other system modifiers are held.
11340
+ *
11325
11341
  * Additionally, this directive supports lifecycle hooks:
11326
11342
  * @mount="onMount" - Called before the VNode is mounted to the DOM element
11327
11343
  * @mounted="onMounted" - Called after the VNode is mounted to the DOM element
@@ -11514,14 +11530,14 @@
11514
11530
  const eventName = this.#eventName;
11515
11531
  const useCapture = this.#modifiers.has('capture');
11516
11532
  const isOnce = this.#modifiers.has('once');
11533
+ // System modifier keys (held during the event) shared by KeyboardEvent and MouseEvent.
11534
+ const systemModifiers = ['shift', 'ctrl', 'alt', 'meta'];
11517
11535
  // Create the event listener function
11518
11536
  this.#listener = (event) => {
11519
- // Check key modifiers for keyboard events
11537
+ // Check key modifiers for keyboard events.
11538
+ // The `.left` / `.right` aliases here mean ArrowLeft / ArrowRight; the same tokens
11539
+ // map to mouse buttons further below, dispatched by event type to avoid ambiguity.
11520
11540
  if (event instanceof KeyboardEvent) {
11521
- // Map of modifier alias -> KeyboardEvent.key values it matches.
11522
- // Multiple values allow a single modifier to match several physical keys
11523
- // (e.g. `.delete` matches both Delete and Backspace, matching Vue's behavior).
11524
- // Multiple aliases pointing to the same key are allowed (e.g. `.esc` / `.escape`).
11525
11541
  const keyMap = {
11526
11542
  'enter': ['Enter'],
11527
11543
  'tab': ['Tab'],
@@ -11549,6 +11565,46 @@
11549
11565
  }
11550
11566
  }
11551
11567
  }
11568
+ // Check mouse button modifiers for mouse events.
11569
+ // `.left` / `.middle` / `.right` map to MouseEvent.button values 0 / 1 / 2.
11570
+ if (event instanceof MouseEvent) {
11571
+ const buttonMap = {
11572
+ 'left': 0,
11573
+ 'middle': 1,
11574
+ 'right': 2
11575
+ };
11576
+ const hasButtonModifier = Object.keys(buttonMap).some(b => this.#modifiers.has(b));
11577
+ if (hasButtonModifier) {
11578
+ let buttonMatched = false;
11579
+ for (const [modifier, buttonValue] of Object.entries(buttonMap)) {
11580
+ if (this.#modifiers.has(modifier) && event.button === buttonValue) {
11581
+ buttonMatched = true;
11582
+ break;
11583
+ }
11584
+ }
11585
+ if (!buttonMatched) {
11586
+ return;
11587
+ }
11588
+ }
11589
+ }
11590
+ // Check system modifier keys (shift / ctrl / alt / meta) and `.exact`.
11591
+ // These properties exist on both KeyboardEvent and MouseEvent.
11592
+ if (event instanceof KeyboardEvent || event instanceof MouseEvent) {
11593
+ // Required system modifiers must be held.
11594
+ for (const mod of systemModifiers) {
11595
+ if (this.#modifiers.has(mod) && !event[`${mod}Key`]) {
11596
+ return;
11597
+ }
11598
+ }
11599
+ // `.exact` rejects events with extra system modifiers held that weren't listed.
11600
+ if (this.#modifiers.has('exact')) {
11601
+ for (const mod of systemModifiers) {
11602
+ if (event[`${mod}Key`] && !this.#modifiers.has(mod)) {
11603
+ return;
11604
+ }
11605
+ }
11606
+ }
11607
+ }
11552
11608
  // Apply event modifiers
11553
11609
  if (this.#modifiers.has('stop')) {
11554
11610
  event.stopPropagation();