@primer/behaviors 1.8.1-rc.f4a3edb → 1.8.2-rc.0fdf228

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.
@@ -4,6 +4,7 @@ var eventListenerSignal = require('./polyfills/event-listener-signal.js');
4
4
  var userAgent = require('./utils/user-agent.js');
5
5
  var iterateFocusableElements = require('./utils/iterate-focusable-elements.js');
6
6
  var uniqueId = require('./utils/unique-id.js');
7
+ var isEditableElement = require('./utils/is-editable-element.js');
7
8
 
8
9
  eventListenerSignal.polyfill();
9
10
  exports.FocusKeys = void 0;
@@ -82,15 +83,11 @@ function getDirection(keyboardEvent) {
82
83
  function shouldIgnoreFocusHandling(keyboardEvent, activeElement) {
83
84
  const key = keyboardEvent.key;
84
85
  const keyLength = [...key].length;
85
- const isTextInput = (activeElement instanceof HTMLInputElement && activeElement.type === 'text') ||
86
- activeElement instanceof HTMLTextAreaElement;
87
- if (isTextInput && (keyLength === 1 || key === 'Home' || key === 'End')) {
86
+ const isEditable = isEditableElement.isEditableElement(activeElement);
87
+ if (isEditable && (keyLength === 1 || key === 'Home' || key === 'End')) {
88
88
  return true;
89
89
  }
90
90
  if (activeElement instanceof HTMLSelectElement) {
91
- if (keyLength === 1) {
92
- return true;
93
- }
94
91
  if (key === 'ArrowDown' && userAgent.isMacOS() && !keyboardEvent.metaKey) {
95
92
  return true;
96
93
  }
@@ -98,20 +95,23 @@ function shouldIgnoreFocusHandling(keyboardEvent, activeElement) {
98
95
  return true;
99
96
  }
100
97
  }
101
- if (activeElement instanceof HTMLTextAreaElement && (key === 'PageUp' || key === 'PageDown')) {
102
- return true;
103
- }
104
- if (isTextInput) {
105
- const textInput = activeElement;
106
- const cursorAtStart = textInput.selectionStart === 0 && textInput.selectionEnd === 0;
107
- const cursorAtEnd = textInput.selectionStart === textInput.value.length && textInput.selectionEnd === textInput.value.length;
98
+ if (isEditable) {
99
+ const isInputElement = activeElement instanceof HTMLTextAreaElement || activeElement instanceof HTMLInputElement;
100
+ const cursorAtStart = isInputElement && activeElement.selectionStart === 0 && activeElement.selectionEnd === 0;
101
+ const cursorAtEnd = isInputElement &&
102
+ activeElement.selectionStart === activeElement.value.length &&
103
+ activeElement.selectionEnd === activeElement.value.length;
108
104
  if (key === 'ArrowLeft' && !cursorAtStart) {
109
105
  return true;
110
106
  }
111
107
  if (key === 'ArrowRight' && !cursorAtEnd) {
112
108
  return true;
113
109
  }
114
- if (textInput instanceof HTMLTextAreaElement) {
110
+ const isContentEditable = activeElement instanceof HTMLElement && activeElement.isContentEditable;
111
+ if (activeElement instanceof HTMLTextAreaElement || isContentEditable) {
112
+ if (key === 'PageUp' || key === 'PageDown') {
113
+ return true;
114
+ }
115
115
  if (key === 'ArrowUp' && !cursorAtStart) {
116
116
  return true;
117
117
  }
@@ -0,0 +1 @@
1
+ export declare function isEditableElement(target: EventTarget | null): boolean;
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+
3
+ const nonEditableInputTypes = new Set([
4
+ 'button',
5
+ 'checkbox',
6
+ 'color',
7
+ 'file',
8
+ 'hidden',
9
+ 'image',
10
+ 'radio',
11
+ 'range',
12
+ 'reset',
13
+ 'submit',
14
+ ]);
15
+ function isEditableElement(target) {
16
+ var _a, _b;
17
+ if (!(target instanceof HTMLElement))
18
+ return false;
19
+ const name = target.nodeName.toLowerCase();
20
+ const type = (_b = (_a = target.getAttribute('type')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'text';
21
+ const isReadonly = target.ariaReadOnly === 'true' ||
22
+ target.getAttribute('aria-readonly') === 'true' ||
23
+ target.getAttribute('readonly') !== null;
24
+ return ((name === 'select' ||
25
+ name === 'textarea' ||
26
+ (name === 'input' && !nonEditableInputTypes.has(type)) ||
27
+ target.isContentEditable) &&
28
+ !isReadonly);
29
+ }
30
+
31
+ exports.isEditableElement = isEditableElement;
@@ -2,6 +2,7 @@ import { polyfill } from './polyfills/event-listener-signal.mjs';
2
2
  import { isMacOS } from './utils/user-agent.mjs';
3
3
  import { iterateFocusableElements } from './utils/iterate-focusable-elements.mjs';
4
4
  import { uniqueId } from './utils/unique-id.mjs';
5
+ import { isEditableElement } from './utils/is-editable-element.mjs';
5
6
 
6
7
  polyfill();
7
8
  var FocusKeys;
@@ -80,15 +81,11 @@ function getDirection(keyboardEvent) {
80
81
  function shouldIgnoreFocusHandling(keyboardEvent, activeElement) {
81
82
  const key = keyboardEvent.key;
82
83
  const keyLength = [...key].length;
83
- const isTextInput = (activeElement instanceof HTMLInputElement && activeElement.type === 'text') ||
84
- activeElement instanceof HTMLTextAreaElement;
85
- if (isTextInput && (keyLength === 1 || key === 'Home' || key === 'End')) {
84
+ const isEditable = isEditableElement(activeElement);
85
+ if (isEditable && (keyLength === 1 || key === 'Home' || key === 'End')) {
86
86
  return true;
87
87
  }
88
88
  if (activeElement instanceof HTMLSelectElement) {
89
- if (keyLength === 1) {
90
- return true;
91
- }
92
89
  if (key === 'ArrowDown' && isMacOS() && !keyboardEvent.metaKey) {
93
90
  return true;
94
91
  }
@@ -96,20 +93,23 @@ function shouldIgnoreFocusHandling(keyboardEvent, activeElement) {
96
93
  return true;
97
94
  }
98
95
  }
99
- if (activeElement instanceof HTMLTextAreaElement && (key === 'PageUp' || key === 'PageDown')) {
100
- return true;
101
- }
102
- if (isTextInput) {
103
- const textInput = activeElement;
104
- const cursorAtStart = textInput.selectionStart === 0 && textInput.selectionEnd === 0;
105
- const cursorAtEnd = textInput.selectionStart === textInput.value.length && textInput.selectionEnd === textInput.value.length;
96
+ if (isEditable) {
97
+ const isInputElement = activeElement instanceof HTMLTextAreaElement || activeElement instanceof HTMLInputElement;
98
+ const cursorAtStart = isInputElement && activeElement.selectionStart === 0 && activeElement.selectionEnd === 0;
99
+ const cursorAtEnd = isInputElement &&
100
+ activeElement.selectionStart === activeElement.value.length &&
101
+ activeElement.selectionEnd === activeElement.value.length;
106
102
  if (key === 'ArrowLeft' && !cursorAtStart) {
107
103
  return true;
108
104
  }
109
105
  if (key === 'ArrowRight' && !cursorAtEnd) {
110
106
  return true;
111
107
  }
112
- if (textInput instanceof HTMLTextAreaElement) {
108
+ const isContentEditable = activeElement instanceof HTMLElement && activeElement.isContentEditable;
109
+ if (activeElement instanceof HTMLTextAreaElement || isContentEditable) {
110
+ if (key === 'PageUp' || key === 'PageDown') {
111
+ return true;
112
+ }
113
113
  if (key === 'ArrowUp' && !cursorAtStart) {
114
114
  return true;
115
115
  }
@@ -0,0 +1 @@
1
+ export declare function isEditableElement(target: EventTarget | null): boolean;
@@ -0,0 +1,29 @@
1
+ const nonEditableInputTypes = new Set([
2
+ 'button',
3
+ 'checkbox',
4
+ 'color',
5
+ 'file',
6
+ 'hidden',
7
+ 'image',
8
+ 'radio',
9
+ 'range',
10
+ 'reset',
11
+ 'submit',
12
+ ]);
13
+ function isEditableElement(target) {
14
+ var _a, _b;
15
+ if (!(target instanceof HTMLElement))
16
+ return false;
17
+ const name = target.nodeName.toLowerCase();
18
+ const type = (_b = (_a = target.getAttribute('type')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'text';
19
+ const isReadonly = target.ariaReadOnly === 'true' ||
20
+ target.getAttribute('aria-readonly') === 'true' ||
21
+ target.getAttribute('readonly') !== null;
22
+ return ((name === 'select' ||
23
+ name === 'textarea' ||
24
+ (name === 'input' && !nonEditableInputTypes.has(type)) ||
25
+ target.isContentEditable) &&
26
+ !isReadonly);
27
+ }
28
+
29
+ export { isEditableElement };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/behaviors",
3
- "version": "1.8.1-rc.f4a3edb",
3
+ "version": "1.8.2-rc.0fdf228",
4
4
  "description": "Shared behaviors for JavaScript components",
5
5
  "type": "commonjs",
6
6
  "main": "dist/cjs/index.js",
@@ -69,7 +69,7 @@
69
69
  }
70
70
  ],
71
71
  "devDependencies": {
72
- "@arethetypeswrong/cli": "^0.17.0",
72
+ "@arethetypeswrong/cli": "^0.18.0",
73
73
  "@changesets/changelog-github": "^0.5.0",
74
74
  "@changesets/cli": "^2.18.1",
75
75
  "@github/prettier-config": "^0.0.6",
@@ -78,22 +78,23 @@
78
78
  "@size-limit/preset-small-lib": "^11.1.4",
79
79
  "@testing-library/react": "^16.0.0",
80
80
  "@testing-library/user-event": "^14.5.1",
81
- "@types/jest": "^29.5.11",
82
- "@types/node": "^22.0.0",
81
+ "@types/jest": "^30.0.0",
82
+ "@types/node": "^24.0.10",
83
83
  "@types/react": "^19.0.1",
84
- "esbuild": "^0.24.0",
84
+ "esbuild": "^0.25.0",
85
85
  "esbuild-jest": "^0.5.0",
86
86
  "eslint": "^8.50.0",
87
87
  "eslint-plugin-github": "^5.0.0",
88
88
  "eslint-plugin-prettier": "^5.0.0",
89
- "jest": "^29.7.0",
90
- "jest-environment-jsdom": "^29.7.0",
89
+ "jest": "^30.0.4",
90
+ "jest-environment-jsdom": "^30.0.4",
91
91
  "prettier": "^3.0.3",
92
92
  "react": "^19.0.0",
93
93
  "react-dom": "^19.0.0",
94
94
  "rimraf": "^6.0.1",
95
95
  "rollup": "^4.18.0",
96
96
  "size-limit": "^11.1.4",
97
+ "tslib": "^2.8.1",
97
98
  "typescript": "^5.2.2"
98
99
  }
99
100
  }