PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.87
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.87
51.1.87 51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 All 41 releases
← All changes | includes/admin/js/ai-textfield.js +141 -40 51.1.78 → 51.1.87 View file →
@@ -91,8 +91,64 @@
91 91
92 92 }
93 93 }
94 94
95 + /**
96 + * Flag the editor body when Elementor's panel is dark.
97 + *
98 + * Elementor has no stable "dark panel" class here, and its ui_theme
99 + * preference can be light, dark, or auto (following the OS), so the panel's
100 + * own background is measured instead. That keeps the AI controls readable
101 + * whichever way the theme was arrived at.
102 + */
103 + function syncPanelTheme() {
104 + var isDark = null;
105 +
106 + try {
107 + // Walk up from the control area to the first element that actually
108 + // paints a background. The panel's inner wrappers are transparent,
109 + // so asking any single one of them tells us nothing.
110 + var node = document.querySelector('#elementor-controls')
111 + || document.querySelector('#elementor-panel-content-wrapper')
112 + || document.querySelector('#elementor-panel');
113 +
114 + while (node) {
115 + var parts = getComputedStyle(node).backgroundColor.match(/[\d.]+/g);
116 + if (parts && parts.length >= 3 && (parts.length < 4 || parseFloat(parts[3]) > 0)) {
117 + var luminance = (0.2126 * parts[0] + 0.7152 * parts[1] + 0.0722 * parts[2]) / 255;
118 + isDark = luminance < 0.5;
119 + break;
120 + }
121 + node = node.parentElement;
122 + }
123 + } catch (e) {
124 + // Fall through to the media query below.
125 + }
126 +
127 + if (isDark === null) {
128 + try {
129 + isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
130 + } catch (e) {
131 + isDark = false;
132 + }
133 + }
134 +
135 + $('body').toggleClass('king-addons-ai-dark', !!isDark);
136 + }
137 +
138 + // Keep up with the OS switching themes while the editor is open.
139 + try {
140 + var colorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
141 + var onSchemeChange = function() { syncPanelTheme(); };
142 + if (colorSchemeQuery.addEventListener) {
143 + colorSchemeQuery.addEventListener('change', onSchemeChange);
144 + } else if (colorSchemeQuery.addListener) {
145 + colorSchemeQuery.addListener(onSchemeChange);
146 + }
147 + } catch (e) {
148 + // No media query support: the measured panel background still applies.
149 + }
150 +
95 151 // Add CSS for animations directly to the document
96 152 function injectAnimationStyles() {
97 153 if ($('#king-addons-ai-animations').length === 0) {
98 154 const animationStyles = `
@@ -120,13 +176,11 @@
120 176 animation: kingAddonsPulse 1.5s infinite cubic-bezier(0.66, 0, 0, 1) !important;
121 177 border-color: #5B03FF !important;
122 178 }
123 179 .king-addons-field-shine {
124 - background-image: linear-gradient(90deg,
125 - rgba(91,3,255,0) 0%,
126 - rgba(91,3,255,0.2) 25%,
127 - rgba(225,203,255,0.3) 50%,
128 - rgba(91,3,255,0.2) 75%,
180 + background-image: linear-gradient(90deg,
181 + rgba(91,3,255,0) 0%,
182 + rgba(91,3,255,0.14) 50%,
129 183 rgba(91,3,255,0) 100%);
130 184 background-position: -100px;
131 185 background-size: 140px 100%;
132 186 background-repeat: no-repeat;
@@ -146,18 +200,22 @@
146 200 transition: all 0.3s ease;
147 201 margin-top: 8px;
148 202 width: 100%;
149 203 }
204 + /* These two are unavailable while the prompt is open. Keeping
205 + the violet, only dimmed, reads as "not right now" instead of
206 + a grey block that looks like a styling failure. */
150 207 .king-addons-ai-buttons-wrapper.is-processing .ai-generate-btn,
151 208 .king-addons-ai-buttons-wrapper.is-processing .ai-change-btn {
152 - background: linear-gradient(135deg, #d6d6d6, #a0a0a0) !important;
153 - opacity: 0.7;
209 + background: rgba(91, 3, 255, .05) !important;
210 + color: rgba(74, 2, 214, .42) !important;
154 211 cursor: default;
155 212 box-shadow: none !important;
213 + transform: none !important;
156 214 pointer-events: none;
157 215 }
158 216 .king-addons-ai-buttons-wrapper.is-processing img {
159 - filter: grayscale(100%);
217 + opacity: .4 !important;
160 218 }
161 219 .ai-prompt-container {
162 220 display: flex;
163 221 align-items: center;
@@ -185,16 +243,78 @@
185 243 outline: none;
186 244 }
187 245 .ai-prompt-examples {
188 246 font-size: 11px;
189 - color: #6d7882;
247 + color: #5c666f;
190 248 margin-top: 4px;
191 249 line-height: 1.4;
192 250 }
193 251 .ai-prompt-examples strong {
194 - color: #556068;
195 - font-weight: 500;
252 + color: #3f4750;
253 + font-weight: 600;
196 254 }
255 +
256 + /*
257 + * Elementor's panel can be light or dark, and the setting
258 + * follows the OS when it is set to Auto, so the theme is
259 + * detected at runtime and flagged on <body>. Without this
260 + * the hint text is near-invisible on the dark panel.
261 + */
262 + body.king-addons-ai-dark .ai-prompt-examples {
263 + color: #a7aeb6;
264 + }
265 + body.king-addons-ai-dark .ai-prompt-examples strong {
266 + color: #e6e9ed;
267 + }
268 + body.king-addons-ai-dark .ai-prompt-input {
269 + background: #2a2d32;
270 + border-color: #45494f;
271 + color: #e6e9ed;
272 + }
273 + body.king-addons-ai-dark .ai-prompt-input::placeholder {
274 + color: #8d949c;
275 + }
276 + body.king-addons-ai-dark .ai-prompt-cancel {
277 + background: #2a2d32;
278 + border-color: #45494f;
279 + color: #d5d9de;
280 + }
281 + body.king-addons-ai-dark .ai-prompt-cancel:hover {
282 + background: #35393f;
283 + }
284 + body.king-addons-ai-dark .king-addons-ai-buttons-wrapper.is-processing .ai-generate-btn,
285 + body.king-addons-ai-dark .king-addons-ai-buttons-wrapper.is-processing .ai-change-btn {
286 + background: rgba(124, 77, 255, .09) !important;
287 + color: rgba(201, 182, 255, .45) !important;
288 + }
289 +
290 + /* The tint needs a lighter hue and a brighter label on the
291 + dark panel; the light-panel values are in ai-textfield.css. */
292 + body.king-addons-ai-dark .ai-generate-btn,
293 + body.king-addons-ai-dark .ai-change-btn {
294 + --ka-ai-btn-bg: rgba(124, 77, 255, .22);
295 + --ka-ai-btn-bg-hover: rgba(124, 77, 255, .32);
296 + --ka-ai-btn-bg-active: rgba(124, 77, 255, .40);
297 + --ka-ai-btn-fg: #C9B6FF;
298 + --ka-ai-btn-ring: #8C7DFF;
299 + }
300 +
301 + body.king-addons-ai-dark .ai-generate-btn img,
302 + body.king-addons-ai-dark .ai-change-btn img {
303 + /* The icon files are white already - let them through. */
304 + filter: none;
305 + opacity: .92;
306 + }
307 +
308 + body.king-addons-ai-dark .ai-prompt-submit {
309 + background: #7C4DFF;
310 + color: #ffffff;
311 + border-color: transparent;
312 + }
313 +
314 + body.king-addons-ai-dark .ai-prompt-submit:hover {
315 + background: #6B3DEE;
316 + }
197 317 .ai-prompt-cancel {
198 318 width: 24px;
199 319 height: 24px;
200 320 display: flex;
@@ -221,9 +341,9 @@
221 341 cursor: pointer;
222 342 transition: all 0.3s ease;
223 343 }
224 344 .ai-prompt-submit.is-processing {
225 - background: linear-gradient(135deg, #E1CBFF, #5B03FF) !important;
345 + background: #5B03FF !important;
226 346 border-color: transparent !important;
227 347 }
228 348 .ai-prompt-submit.is-processing img {
229 349 animation: kingAddonsRotatePulse 2s infinite ease-in-out;
@@ -250,8 +370,11 @@
250 370 function injectAiButtons($container) {
251 371
252 372 // Inject animation styles first
253 373 injectAnimationStyles();
374 +
375 + // The panel is rebuilt on every open, so re-check the theme here.
376 + syncPanelTheme();
254 377
255 378 // Handle standard text/textarea controls
256 379 $container.find('.elementor-control-type-text label.elementor-control-title, .elementor-control-type-textarea label.elementor-control-title').each(function(){
257 380 var $label = $(this);
@@ -305,31 +428,15 @@
305 428 if (!$inputWrapper.length) return;
306 429 }
307 430
308 431 // Create "Generate" button
309 - var $btnLabel = $('<button type="button" class="ai-generate-btn ai-generate-btn--futuristic" title="AI Generate"></button>').css({
310 - verticalAlign: 'middle',
311 - padding: '4px 8px',
312 - fontSize: '12px',
313 - cursor: 'pointer',
314 - background: 'linear-gradient(135deg, #E1CBFF, #5B03FF)',
315 - border: 'none',
316 - borderRadius: '4px',
317 - color: '#ffffff',
318 - display: 'inline-flex',
319 - alignItems: 'center',
320 - // boxShadow: '0 0 6px rgba(225,203,255,0.7), 0 0 12px rgba(91,3,255,0.5)',
321 - boxShadow: 'none',
322 - transition: 'box-shadow 0.3s ease'
323 - });
432 + // Appearance lives in ai-textfield.css so the buttons get real hover,
433 + // active, focus and disabled states instead of inline overrides.
434 + var $btnLabel = $('<button type="button" class="ai-generate-btn" title="AI Generate"></button>');
324 435 $btnLabel.append(
325 - $('<img>').attr('src', KingAddonsAiField.icon_url).css({ marginRight: '6px', width: '16px', height: '16px', verticalAlign: 'middle' }),
436 + $('<img>').attr({ src: KingAddonsAiField.icon_url, alt: '' }),
326 437 $('<span>').addClass('ai-generate-btn__label').text('AI Generate')
327 438 );
328 - $btnLabel.hover(
329 - function() { $(this).css('boxShadow', '0 0 8px rgba(225,203,255,0.9), 0 0 16px rgba(91,3,255,0.7)'); },
330 - function() { $(this).css('boxShadow', 'none'); }
331 - );
332 439
333 440 // Create "Change" button
334 441 var $changeBtn = $btnLabel.clone();
335 442 $changeBtn.removeClass('ai-generate-btn').addClass('ai-change-btn');
@@ -335,14 +442,8 @@
335 442 $changeBtn.removeClass('ai-generate-btn').addClass('ai-change-btn');
336 443 $changeBtn.find('span.ai-generate-btn__label').text('AI Change');
337 444 $changeBtn.attr('title', 'AI Change');
338 445 $changeBtn.find('img').attr('src', KingAddonsAiField.rewrite_icon_url || KingAddonsAiField.plugin_url + '/includes/admin/img/ai-rewrite.svg');
339 -
340 - // Add hover effect to the change button - cloning doesn't preserve hover handlers
341 - $changeBtn.hover(
342 - function() { $(this).css('boxShadow', '0 0 8px rgba(225,203,255,0.9), 0 0 16px rgba(91,3,255,0.7)'); },
343 - function() { $(this).css('boxShadow', 'none'); }
344 - );
345 446
346 447 // Add buttons to wrapper
347 448 $buttonsWrapper.append($btnLabel).append($changeBtn);
348 449
@@ -390,9 +491,9 @@
390 491 var settingsUrl = window.KingAddonsAiField && window.KingAddonsAiField.settings_url
391 492 ? window.KingAddonsAiField.settings_url
392 493 : '/wp-admin/admin.php?page=king-addons-ai-settings';
393 494 $errorMessage.html(
394 - '<span>OpenAI API key is missing or invalid. Please configure your API key in AI Settings.</span>' +
495 + '<span>' + ((window.KingAddonsAiField && KingAddonsAiField.missing_key_message) || 'The AI API key is missing or invalid. Please configure your API key in AI Settings.') + '</span>' +
395 496 '<a href="' + settingsUrl + '" style="color:#0073aa;text-decoration:underline;white-space:nowrap;margin-left:10px;" target="_blank">Settings</a>'
396 497 );
397 498 $errorMessage.insertAfter($buttonsWrapper).hide().fadeIn(200);
398 499 setTimeout(function() { $errorMessage.fadeOut(200, function() { $(this).remove(); }); }, 5000);
@@ -588,9 +689,9 @@
588 689 var settingsUrl = window.KingAddonsAiField && window.KingAddonsAiField.settings_url
589 690 ? window.KingAddonsAiField.settings_url
590 691 : '/wp-admin/admin.php?page=king-addons-ai-settings';
591 692 $errorMessage.html(
592 - '<span>OpenAI API key is missing or invalid. Please configure your API key in AI Settings.</span>' +
693 + '<span>' + ((window.KingAddonsAiField && KingAddonsAiField.missing_key_message) || 'The AI API key is missing or invalid. Please configure your API key in AI Settings.') + '</span>' +
593 694 '<a href="' + settingsUrl + '" style="color:#0073aa;text-decoration:underline;white-space:nowrap;margin-left:10px;" target="_blank">Settings</a>'
594 695 );
595 696 $errorMessage.insertAfter($buttonsWrapper).hide().fadeIn(200);
596 697 setTimeout(function() { $errorMessage.fadeOut(200, function() { $(this).remove(); }); }, 5000);