feat(admin): 添加形状选择器的原生覆盖层并改进交互体验

为形状选择器添加原生覆盖层,提供更好的视觉预览和交互体验
重构相关JavaScript代码,将覆盖层初始化逻辑移至主函数中
调整样式以保持UI一致性
This commit is contained in:
tikkhun 2025-12-12 16:27:17 +08:00
parent a64c19750f
commit 4698c4d793
2 changed files with 70 additions and 49 deletions

View File

@ -155,6 +155,57 @@
}
renderExistingShapeCardPreviews();
function initShapeNativeOverlay(){
if (!shapeNativeOverlay) { return; }
var nodes = shapeNativeOverlay.querySelectorAll('.yoone-snow-shape-native-item');
nodes.forEach(function(btn){
var key = btn.getAttribute('data-shape-key');
var host = btn.querySelector('.yoone-snow-shape-native-preview');
if (host && (!host.childNodes || host.childNodes.length === 0)){
var previewEl = createShapePreviewElement(key);
if (previewEl){
try { previewEl.style.backgroundColor = 'transparent'; } catch(e){}
try { previewEl.style.border = 'none'; } catch(e){}
try { previewEl.style.borderRadius = '0'; } catch(e){}
try { previewEl.style.marginRight = '0'; } catch(e){}
try { previewEl.style.margin = '0'; } catch(e){}
try { previewEl.style.width = '28px'; } catch(e){}
try { previewEl.style.height = '28px'; } catch(e){}
host.appendChild(previewEl);
}
}
btn.addEventListener('click', function(){
if (shapeLabelPreviewHost){
while (shapeLabelPreviewHost.firstChild){ shapeLabelPreviewHost.removeChild(shapeLabelPreviewHost.firstChild); }
var previewEl2 = createShapePreviewElement(key);
if (previewEl2){
try { previewEl2.style.backgroundColor = 'transparent'; } catch(e){}
try { previewEl2.style.border = 'none'; } catch(e){}
try { previewEl2.style.borderRadius = '0'; } catch(e){}
try { previewEl2.style.marginRight = '0'; } catch(e){}
try { previewEl2.style.margin = '0'; } catch(e){}
try { previewEl2.style.width = '28px'; } catch(e){}
try { previewEl2.style.height = '28px'; } catch(e){}
shapeLabelPreviewHost.style.display = 'flex';
shapeLabelPreviewHost.appendChild(previewEl2);
}
}
addShapeBox(key);
if (shapeNativeOverlay){ shapeNativeOverlay.style.display = 'none'; }
if (shapeAddSelect){ shapeAddSelect.value = ''; }
if (shapeLabelPreviewHost){
while (shapeLabelPreviewHost.firstChild){ shapeLabelPreviewHost.removeChild(shapeLabelPreviewHost.firstChild); }
shapeLabelPreviewHost.style.display = 'none';
}
});
});
document.addEventListener('click', function(e){
var t = e.target;
var inside = (t === shapeNativeOverlay || (shapeNativeOverlay && shapeNativeOverlay.contains(t)) || (shapeAddSelect && (t === shapeAddSelect || shapeAddSelect.contains(t))));
if (!inside && shapeNativeOverlay){ shapeNativeOverlay.style.display = 'none'; }
});
}
// 添加形状卡片 并插入预览与隐藏输入 用于保存选择
function addShapeBox(shapeKey){
if (!shapeListContainer) { return; }
@ -561,6 +612,16 @@
// 僅使用原生下拉 不再彈出自定義覆蓋列表
}
if (shapeAddSelect && shapeNativeOverlay){
initShapeNativeOverlay();
var openOverlay = function(){
try { shapeNativeOverlay.style.width = (shapeAddSelect.offsetWidth || 280) + 'px'; } catch(e){}
shapeNativeOverlay.style.display = 'block';
};
shapeAddSelect.addEventListener('mousedown', function(e){ e.preventDefault(); openOverlay(); });
shapeAddSelect.addEventListener('click', function(e){ e.preventDefault(); openOverlay(); });
}
// 切换类型面板 显示对应控件 其他隐藏
@ -667,52 +728,6 @@
initAdminMedia();
}
})();
// 初始化內嵌下拉的預覽與點擊交互
(function(){
if (!shapeNativeOverlay) { return; }
var nodes = shapeNativeOverlay.querySelectorAll('.yoone-snow-shape-native-item');
nodes.forEach(function(btn){
var key = btn.getAttribute('data-shape-key');
var host = btn.querySelector('.yoone-snow-shape-native-preview');
if (host && host.childNodes && host.childNodes.length === 0){
var previewEl = createShapePreviewElement(key);
if (previewEl){
try { previewEl.style.backgroundColor = 'transparent'; } catch(e){}
try { previewEl.style.border = 'none'; } catch(e){}
try { previewEl.style.borderRadius = '0'; } catch(e){}
host.appendChild(previewEl);
}
}
btn.addEventListener('click', function(){
// 先更新左側預覽 再添加卡片 並關閉內嵌下拉
if (shapeLabelPreviewHost){
while (shapeLabelPreviewHost.firstChild){ shapeLabelPreviewHost.removeChild(shapeLabelPreviewHost.firstChild); }
var previewEl2 = createShapePreviewElement(key);
if (previewEl2){
try { previewEl2.style.backgroundColor = 'transparent'; } catch(e){}
try { previewEl2.style.border = 'none'; } catch(e){}
try { previewEl2.style.borderRadius = '0'; } catch(e){}
shapeLabelPreviewHost.style.display = 'flex';
shapeLabelPreviewHost.appendChild(previewEl2);
}
}
addShapeBox(key);
if (shapeNativeOverlay){ shapeNativeOverlay.style.display = 'none'; }
// 重置原生下拉為未選中 清空左側預覽 保持簡潔
if (shapeAddSelect){ shapeAddSelect.value = ''; }
if (shapeLabelPreviewHost){
while (shapeLabelPreviewHost.firstChild){ shapeLabelPreviewHost.removeChild(shapeLabelPreviewHost.firstChild); }
shapeLabelPreviewHost.style.display = 'none';
}
});
});
// 外部點擊時關閉內嵌下拉
document.addEventListener('click', function(e){
var t = e.target;
var inside = (t === shapeNativeOverlay || shapeNativeOverlay.contains(t) || (shapeAddSelect && (t === shapeAddSelect || shapeAddSelect.contains(t))));
if (!inside){ shapeNativeOverlay.style.display = 'none'; }
});
})();
function t(key, fallback){
var dict = (typeof window !== 'undefined' && window.YooneSnowAdmin && window.YooneSnowAdmin.i18n) ? window.YooneSnowAdmin.i18n : {};
var val = dict[key];

View File

@ -514,14 +514,20 @@ function yoone_snow_register_settings() {
echo '</select></label>';
echo '</div>';
echo '<div id="yooneSnowAddDefaultPane" style="display:flex;gap:8px;align-items:center;position:relative;">';
echo '<div id="yooneSnowAddShapeLabelPreview" style="width:32px;height:32px;display:none;align-items:center;justify-content:center;"></div>';
echo '<div id="yooneSnowAddShapeLabelPreview" style="width:32px;height:32px;display:none;align-items:center;justify-content:center;background-color:#808080;border-radius:4px;"></div>';
echo '<select id="yooneSnowAddShapeSelect" style="min-width:240px;"><option value="">' . esc_html__('Select shape', 'yoone-snow') . '</option>';
foreach ($options as $key => $label) {
echo '<option value="' . esc_attr($key) . '">' . esc_html($label) . '</option>';
}
echo '</select>';
echo '<div id="yooneSnowShapeNativeOverlay" style="display:none;position:absolute;top:100%;left:0;width:280px;max-height:240px;overflow:auto;background:#fff;border:1px solid #ddd;border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,0.08);padding:6px;z-index:9999;">';
foreach ($options as $key => $label) {
echo '<button type="button" class="yoone-snow-shape-native-item" data-shape-key="' . esc_attr($key) . '" style="display:flex;align-items:center;width:100%;padding:6px;margin:0;background:none;border:none;border-radius:4px;cursor:pointer;text-align:left;">';
echo '<div class="yoone-snow-shape-native-preview" style="font-size:28px;line-height:32px;width:32px;height:32px;margin-right:8px;display:flex;align-items:center;justify-content:center;background-color:#e6e6e6;border:1px solid #ddd;border-radius:4px;"></div>';
echo '<span>' . esc_html($label) . '</span>';
echo '</button>';
}
echo '</div>';
echo '</div>';
echo '<div id="yooneSnowAddEmojiPane" style="display:none;gap:8px;align-items:center;">';
echo '<select id="yooneSnowEmojiSelect" style="min-width:240px;"><option value="">' . esc_html__('Select emoji', 'yoone-snow') . '</option></select>';