mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
Merge pull request #141 from MisaLiu/fix_select
使用自制的 `<setting-select>` 组件来避免下拉框滚动不跟随问题
This commit is contained in:
commit
ead79a39f7
@ -1,11 +1,77 @@
|
|||||||
import { SettingOption } from "./option";
|
import { SettingOption } from "./option";
|
||||||
|
|
||||||
|
interface MouseEventExtend extends MouseEvent {
|
||||||
|
target: HTMLElement,
|
||||||
|
}
|
||||||
|
|
||||||
|
// <ob-setting-select>
|
||||||
|
const SelectTemplate = document.createElement('template');
|
||||||
|
SelectTemplate.innerHTML = `<style>
|
||||||
|
.hidden { display: none !important; }
|
||||||
|
</style>
|
||||||
|
<div part="parent">
|
||||||
|
<div part="button">
|
||||||
|
<input type="text" placeholder="请选择" part="current-text" />
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" part="button-arrow">
|
||||||
|
<path d="M12 6.0001L8.00004 10L4 6" stroke="currentColor" stroke-linejoin="round"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<ul class="hidden" part="option-list"><slot></slot></ul>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
window.customElements.define('ob-setting-select', class extends HTMLElement {
|
||||||
|
readonly _button: HTMLDivElement;
|
||||||
|
readonly _text: HTMLInputElement;
|
||||||
|
readonly _context: HTMLUListElement;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.attachShadow({ mode: 'open' });
|
||||||
|
this.shadowRoot.append(SelectTemplate.content.cloneNode(true));
|
||||||
|
|
||||||
|
this._button = this.shadowRoot.querySelector('div[part="button"]');
|
||||||
|
this._text = this.shadowRoot.querySelector('input[part="current-text"]');
|
||||||
|
this._context = this.shadowRoot.querySelector('ul[part="option-list"]');
|
||||||
|
|
||||||
|
const buttonClick = () => {
|
||||||
|
const isHidden = this._context.classList.toggle('hidden');
|
||||||
|
window[`${isHidden ? 'remove': 'add'}EventListener`]('pointerdown', windowPointerDown);
|
||||||
|
};
|
||||||
|
|
||||||
|
const windowPointerDown = ({ target }) => {
|
||||||
|
if (!this.contains(target)) buttonClick();
|
||||||
|
};
|
||||||
|
|
||||||
|
this._button.addEventListener('click', buttonClick);
|
||||||
|
this._context.addEventListener('click', ({ target }: MouseEventExtend) => {
|
||||||
|
if (target.tagName !== 'SETTING-OPTION') return;
|
||||||
|
buttonClick();
|
||||||
|
|
||||||
|
if (target.hasAttribute('is-selected')) return;
|
||||||
|
|
||||||
|
this.querySelectorAll('setting-option[is-selected]').forEach(dom => dom.toggleAttribute('is-selected'));
|
||||||
|
target.toggleAttribute('is-selected');
|
||||||
|
|
||||||
|
this._text.value = target.textContent;
|
||||||
|
this.dispatchEvent(new CustomEvent('selected', {
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
detail: {
|
||||||
|
name: target.textContent,
|
||||||
|
value: target.dataset.value,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
this._text.value = this.querySelector('setting-option[is-selected]').textContent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const SettingSelect = (items: Array<{ text: string, value: string }>, configKey?: string, configValue?: any) => {
|
export const SettingSelect = (items: Array<{ text: string, value: string }>, configKey?: string, configValue?: any) => {
|
||||||
return `<setting-select ${configKey ? `data-config-key="${configKey}"` : ''}>
|
return `<ob-setting-select ${configKey ? `data-config-key="${configKey}"` : ''}>
|
||||||
<div>
|
${items.map((e, i) => {
|
||||||
${items.map((e, i) => {
|
return SettingOption(e.text, e.value, (configKey && configValue ? configValue === e.value : i === 0));
|
||||||
return SettingOption(e.text, e.value, (configKey && configValue ? configValue === e.value : i === 0));
|
}).join('')}
|
||||||
}).join('')}
|
</ob-setting-select>`;
|
||||||
</div>
|
|
||||||
</setting-select>`;
|
|
||||||
}
|
}
|
@ -14,9 +14,6 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
const configKey = key.split('.');
|
const configKey = key.split('.');
|
||||||
|
|
||||||
if (key.indexOf('ob11') === 0) {
|
if (key.indexOf('ob11') === 0) {
|
||||||
if (configKey[1] === "messagePostFormat") {
|
|
||||||
value = value ? "string" : "array"
|
|
||||||
}
|
|
||||||
if (configKey.length === 2) ob11Config[configKey[1]] = value;
|
if (configKey.length === 2) ob11Config[configKey[1]] = value;
|
||||||
else ob11Config[key] = value;
|
else ob11Config[key] = value;
|
||||||
} else {
|
} else {
|
||||||
@ -95,11 +92,10 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'启用CQ码上报格式,不启用则为消息段格式',
|
'启用CQ码上报格式,不启用则为消息段格式',
|
||||||
'如客户端无特殊需求推荐保持默认设置,两者的详细差异可参考 <a href="javascript:LiteLoader.api.openExternal(\'https://github.com/botuniverse/onebot-11/tree/master/message#readme\');">OneBot v11 文档</a>',
|
'如客户端无特殊需求推荐保持默认设置,两者的详细差异可参考 <a href="javascript:LiteLoader.api.openExternal(\'https://github.com/botuniverse/onebot-11/tree/master/message#readme\');">OneBot v11 文档</a>',
|
||||||
// SettingSelect([
|
SettingSelect([
|
||||||
// {text: '消息段', value: 'array'},
|
{text: '消息段', value: 'array'},
|
||||||
// {text: 'CQ码', value: 'string'},
|
{text: 'CQ码', value: 'string'},
|
||||||
// ], 'ob11.messagePostFormat', config.ob11.messagePostFormat),
|
], 'ob11.messagePostFormat', config.ob11.messagePostFormat),
|
||||||
SettingSwitch('ob11.messagePostFormat', config.ob11.messagePostFormat === "string"),
|
|
||||||
),
|
),
|
||||||
SettingItem(
|
SettingItem(
|
||||||
'ffmpeg 路径,发送语音、视频需要,同时保证ffprobe和ffmpeg在一起', ` <a href="javascript:LiteLoader.api.openExternal(\'https://llonebot.github.io/zh-CN/guide/ffmpeg\');">下载地址</a> <span id="config-ffmpeg-path-text">, 路径:${!isEmpty(config.ffmpeg) ? config.ffmpeg : '未指定'}</span>`,
|
'ffmpeg 路径,发送语音、视频需要,同时保证ffprobe和ffmpeg在一起', ` <a href="javascript:LiteLoader.api.openExternal(\'https://llonebot.github.io/zh-CN/guide/ffmpeg\');">下载地址</a> <span id="config-ffmpeg-path-text">, 路径:${!isEmpty(config.ffmpeg) ? config.ffmpeg : '未指定'}</span>`,
|
||||||
@ -307,7 +303,7 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 下拉框
|
// 下拉框
|
||||||
doc.querySelectorAll('setting-select').forEach((dom: HTMLElement) => {
|
doc.querySelectorAll('ob-setting-select[data-config-key]').forEach((dom: HTMLElement) => {
|
||||||
dom.addEventListener('selected', (e: CustomEvent) => {
|
dom.addEventListener('selected', (e: CustomEvent) => {
|
||||||
const configKey = dom.dataset.configKey;
|
const configKey = dom.dataset.configKey;
|
||||||
const configValue = e.detail.value;
|
const configValue = e.detail.value;
|
||||||
|
@ -63,10 +63,103 @@ setting-item a:visited {
|
|||||||
color: var(--text-link);
|
color: var(--text-link);
|
||||||
}
|
}
|
||||||
|
|
||||||
#llonebot-error{
|
ob-setting-select {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob-setting-select,
|
||||||
|
ob-setting-select::part(parent),
|
||||||
|
ob-setting-select::part(button) {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
height: 24px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 24px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob-setting-select::part(button) {
|
||||||
|
display: flex;
|
||||||
|
padding: 0px 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--border_dark);
|
||||||
|
z-index: 5;
|
||||||
|
cursor: default;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob-setting-select::part(current-text) {
|
||||||
|
display: block;
|
||||||
|
margin-right: 8px;
|
||||||
|
padding: 0px;
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text_primary);
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
border-radius: 0px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
overflow: hidden;
|
||||||
|
appearance: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: default;
|
||||||
|
flex: 1;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
-o-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-pointer-events: none;
|
||||||
|
-moz-pointer-events: none;
|
||||||
|
-ms-pointer-events: none;
|
||||||
|
-o-pointer-events: none;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob-setting-select::part(button-arrow) {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: var(--icon_primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
ob-setting-select::part(option-list) {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
margin: 5px 0px;
|
||||||
|
width: 100%;
|
||||||
|
max-height: var(--q-contextmenu-max-height);
|
||||||
|
background-color: var(--blur_middle_standard);
|
||||||
|
background-clip: padding-box;
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
font-size: 12px;
|
||||||
|
box-shadow: var(--shadow_bg_middle_secondary);
|
||||||
|
border: 1px solid var(--border_secondary);
|
||||||
|
border-radius: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
app-region: no-drag;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
list-style: none;
|
||||||
|
z-index: 999;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#llonebot-error {
|
||||||
color: red;
|
color: red;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user