PluginProbe
Extendify / trunk
Extendify vtrunk
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | src/QuickEdit/lib/keyboard-entry.js +16 -49 3.1.1 → trunk View file →
@@ -1,13 +1,8 @@
1 1 import { __, sprintf } from '@wordpress/i18n';
2 +import { useQuickEditStore } from '../state/store';
2 3 import { resolveTarget } from './dom';
3 -import {
4 - askAiTarget,
5 - editTarget,
6 - hideBar,
7 - pillContextFor,
8 - showBar,
9 -} from './hover-bar';
4 +import { hideBar, isAgentWorking, pinTarget, showBar } from './hover-bar';
10 5
11 6 const SELECTOR = [
12 7 '[data-extendify-agent-block-id]',
13 8 '[data-extendify-part-block-id]',
@@ -34,34 +29,19 @@
34 29 }
35 30 return null;
36 31 };
37 32
38 -const buildAriaLabel = (el, target, { quickEditable, aiAvailable }) => {
33 +// Enter only reveals the pills, so announcing "Edit" promises too much.
34 +const buildAriaLabel = (el) => {
39 35 const text = (el.textContent || '').trim().replace(/\s+/g, ' ');
40 36 const snippet = text.length > 60 ? `${text.substring(0, 60)}…` : text;
41 - // Ask-AI-only blocks (group / columns / media-text) route Enter to the
42 - // agent, so announce that action rather than "Edit".
43 - if (aiAvailable && !quickEditable) {
44 - return snippet
45 - ? sprintf(
46 - // translators: %s is a snippet of the block's text content.
47 - __('Ask AI about "%s"', 'extendify-local'),
48 - snippet,
49 - )
50 - : __('Ask AI', 'extendify-local');
51 - }
52 - const verb =
53 - target?.blockType === 'core/image' || target?.blockType === 'core/cover'
54 - ? __('Replace image', 'extendify-local')
55 - : __('Edit', 'extendify-local');
56 37 return snippet
57 38 ? sprintf(
58 - // translators: %1$s is the action verb (Edit / Replace image), %2$s is a snippet of the block's text content.
59 - __('%1$s "%2$s"', 'extendify-local'),
60 - verb,
39 + // translators: %s is a snippet of the block's text content.
40 + __('Editing options for "%s"', 'extendify-local'),
61 41 snippet,
62 42 )
63 - : verb;
43 + : __('Editing options', 'extendify-local');
64 44 };
65 45
66 46 // Skips role="button" on headings/links/landmarks so SR users
67 47 // retain heading/link/landmark navigation. Enter/Space still
@@ -98,13 +78,9 @@
98 78 if (!isHeading && !isLink && !isLandmark) {
99 79 el.setAttribute('role', 'button');
100 80 }
101 81
102 - const target = resolveTarget(el);
103 - el.setAttribute(
104 - 'aria-label',
105 - buildAriaLabel(el, target, pillContextFor(target)),
106 - );
82 + el.setAttribute('aria-label', buildAriaLabel(el));
107 83 el.setAttribute(KB_READY_ATTR, '1');
108 84 }
109 85 };
110 86
@@ -133,8 +109,9 @@
133 109 decorate();
134 110
135 111 onFocusIn = (e) => {
136 112 if (getSession?.()) return;
113 + if (isAgentWorking()) return;
137 114 const el = findTagged(e.target);
138 115 if (!el) return;
139 116 hideBar();
140 117 showBar(el);
@@ -160,13 +137,17 @@
160 137 ) {
161 138 return;
162 139 }
163 140 if (target && !document.body.contains(target)) return;
141 + // A pinned bar outlives focus; only an outside click or Esc drops it.
142 + if (useQuickEditStore.getState().committedSelection) return;
164 143 const active = document.activeElement;
165 144 if (!active || active === document.body) {
166 145 hideBar();
167 146 return;
168 147 }
148 + // Pinning moves focus onto a pill, which lives outside the block.
149 + if (active.closest?.('.extendify-quick-edit-bar')) return;
169 150 if (findTagged(active)) return;
170 151 hideBar();
171 152 }, 0);
172 153 };
@@ -173,31 +154,17 @@
173 154
174 155 onActivate = (e) => {
175 156 if (e.key !== 'Enter' && e.key !== ' ') return;
176 157 if (getSession?.()) return;
158 + if (isAgentWorking()) return;
177 159 const el = findTagged(e.target);
178 160 if (!el) return;
179 161 // Skip activation when the keystroke came from a child with
180 162 // its own action (e.g. a link inside a nav item).
181 163 if (e.target !== el) return;
182 - const target = resolveTarget(el);
183 - if (!target?.blockType) return;
164 + if (!resolveTarget(el)?.blockType) return;
184 165 e.preventDefault();
185 - const { quickEditable, aiAvailable } = pillContextFor(target);
186 - // Quick-editable blocks open the inline editor (picker types need the
187 - // bar mounted first so the dropdown can anchor to it).
188 - if (quickEditable) {
189 - showBar(el);
190 - editTarget(target);
191 - return;
192 - }
193 - // Ask-AI-only blocks (group / columns / media-text) have no editor to
194 - // open; route Enter straight to the agent like the Ask AI pill does.
195 - if (aiAvailable) {
196 - askAiTarget(el);
197 - return;
198 - }
199 - showBar(el);
166 + pinTarget(el);
200 167 };
201 168
202 169 document.addEventListener('focusin', onFocusIn, true);
203 170 document.addEventListener('focusout', onFocusOut, true);