@jsenv/dom 0.14.3 → 0.14.4

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.
Files changed (2) hide show
  1. package/dist/jsenv_dom.js +53 -14
  2. package/package.json +1 -1
package/dist/jsenv_dom.js CHANGED
@@ -208,7 +208,7 @@ const dispatchInternalCustomEvent = (
208
208
  customEventDetail,
209
209
  ) => {
210
210
  const customEvent = new CustomEvent(customEventName, {
211
- detail: customEventDetail,
211
+ detail: customEventDetail || {},
212
212
  cancelable: true,
213
213
  });
214
214
  chainEvent(customEvent, customEventDetail?.event);
@@ -225,7 +225,7 @@ const dispatchPublicCustomEvent = (
225
225
  customEventDetail,
226
226
  ) => {
227
227
  const customEvent = new CustomEvent(customEventName, {
228
- detail: customEventDetail,
228
+ detail: customEventDetail || {},
229
229
  bubbles: true,
230
230
  cancelable: true,
231
231
  });
@@ -241,7 +241,7 @@ const dispatchPublicCustomEvent = (
241
241
  */
242
242
  const dispatchCustomEvent = (el, customEventName, customEventDetail) => {
243
243
  const customEvent = new CustomEvent(customEventName, {
244
- detail: customEventDetail,
244
+ detail: customEventDetail || {},
245
245
  cancelable: true,
246
246
  });
247
247
  chainEvent(customEvent, customEventDetail?.event);
@@ -253,6 +253,12 @@ const chainEvent = (customEvent, parentEvent) => {
253
253
  if (!parentEvent) {
254
254
  return customEvent;
255
255
  }
256
+ if (!customEvent.detail) {
257
+ console.warn(
258
+ `Event "${customEvent.type}" has no detail object. Cannot chain to parent event "${parentEvent.type}".`,
259
+ );
260
+ return customEvent;
261
+ }
256
262
  // Always build eventChain from the first wrapping so callers can rely on it
257
263
  // being present whenever `parentEvent` is set.
258
264
  // eventChain = [oldest, ..., parentEvent] — the full ancestor list including the direct parent.
@@ -316,15 +322,15 @@ const formatEventSideEffect = (e, sideEffect) => {
316
322
  const chain = e.detail.eventChain;
317
323
  const initiator = chain[0];
318
324
  parts.push(
319
- `"${initiator.type}" on ${getElementSignature(initiator.target)}`,
325
+ `"${getEventLabel(initiator)}" on ${getElementSignature(initiator.target)}`,
320
326
  );
321
327
  // chain[0] is shown as initiator above; chain includes event as last element
322
328
  for (const chainedEvent of chain.slice(1)) {
323
- parts.push(chainedEvent.type);
329
+ parts.push(getEventLabel(chainedEvent));
324
330
  }
325
- parts.push(e.type);
331
+ parts.push(getEventLabel(e));
326
332
  } else {
327
- parts.push(`"${e.type}" on ${getElementSignature(e.target)}`);
333
+ parts.push(`"${getEventLabel(e)}" on ${getElementSignature(e.target)}`);
328
334
  }
329
335
  return `${parts.join(" -> ")} -> ${sideEffect}`;
330
336
  };
@@ -374,8 +380,8 @@ const createEventGroupLogger = () => {
374
380
  console.groupEnd();
375
381
  }
376
382
  const label = initiator.target
377
- ? `"${initiator.type}" on ${getElementSignature(initiator.target)}`
378
- : `"${initiator.type}"`;
383
+ ? `"${getEventLabel(initiator)}" on ${getElementSignature(initiator.target)}`
384
+ : `"${getEventLabel(initiator)}"`;
379
385
  console.group(label);
380
386
  currentInitiator = initiator;
381
387
  }
@@ -400,12 +406,40 @@ const formatSideEffectLine = (e, prefix) => {
400
406
  // chain[0] is the root event, already shown as the group label — skip it.
401
407
  // chain includes the direct parent (e.detail.event) as its last element.
402
408
  for (const chainedEvent of chain.slice(1)) {
403
- parts.push(chainedEvent.type);
409
+ parts.push(getEventLabel(chainedEvent));
404
410
  }
405
411
  }
406
412
  return parts.join(" -> ");
407
413
  };
408
414
 
415
+ const getEventLabel = (e) => {
416
+ if (e.type === "mousedown" || e.type === "click") {
417
+ if (e.button !== 0) {
418
+ return `${e.type}:right_button`;
419
+ }
420
+ return e.type;
421
+ }
422
+ if (e.type === "keydown") {
423
+ const key = e.key === " " ? "space" : e.key.toLowerCase();
424
+ const modifiers = [];
425
+ if (e.ctrlKey) {
426
+ modifiers.push("ctrl");
427
+ }
428
+ if (e.metaKey) {
429
+ modifiers.push("meta");
430
+ }
431
+ if (e.altKey) {
432
+ modifiers.push("alt");
433
+ }
434
+ if (e.shiftKey) {
435
+ modifiers.push("shift");
436
+ }
437
+ modifiers.push(key);
438
+ return `keydown:${modifiers.join("+")}`;
439
+ }
440
+ return e.type;
441
+ };
442
+
409
443
  const createIterableWeakSet = () => {
410
444
  const objectWeakRefSet = new Set();
411
445
 
@@ -4328,10 +4362,7 @@ const elementIsFocusable = (node, { excludeAriaHidden } = {}) => {
4328
4362
  }
4329
4363
  return canFocus(node);
4330
4364
  }
4331
- if (
4332
- ["button", "select", "datalist", "iframe", "textarea"].indexOf(nodeName) >
4333
- -1
4334
- ) {
4365
+ if (FOCUSABLE_NODE_NAME_SET.has(nodeName)) {
4335
4366
  return canFocus(node);
4336
4367
  }
4337
4368
  if (["a", "area"].indexOf(nodeName) > -1) {
@@ -4357,6 +4388,14 @@ const elementIsFocusable = (node, { excludeAriaHidden } = {}) => {
4357
4388
  }
4358
4389
  return false;
4359
4390
  };
4391
+ const FOCUSABLE_NODE_NAME_SET = new Set([
4392
+ "button",
4393
+ "select",
4394
+ "datalist",
4395
+ "dialog",
4396
+ "iframe",
4397
+ "textarea",
4398
+ ]);
4360
4399
 
4361
4400
  const canInteract = (element) => {
4362
4401
  if (element.disabled) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/dom",
3
- "version": "0.14.3",
3
+ "version": "0.14.4",
4
4
  "type": "module",
5
5
  "description": "DOM utilities for writing frontend code",
6
6
  "repository": {