初始化奇妙小屏幕控制器项目

This commit is contained in:
2026-09-08 22:56:52 +08:00
commit 8d368de3b5
491 changed files with 67678 additions and 0 deletions
@@ -0,0 +1,129 @@
const bootstrap = globalThis.__UI_COPY_EDITOR_BUILD__ || null;
const placeholderPattern = /\{([a-zA-Z][a-zA-Z0-9_]*)\}/g;
const targetRegistry = new Map();
const accessibleNameState = new WeakMap();
let activeDraft = bootstrap?.initial_draft || { overrides: {} };
function formatTemplate(text, values = {}) {
return String(text).replace(placeholderPattern, (_match, name) => values[name] ?? `{${name}}`);
}
function preserveAccessibleName(record, text) {
const host = record.host;
if (!host) return;
if (!accessibleNameState.has(host)) accessibleNameState.set(host, host.getAttribute("aria-label"));
host.setAttribute("aria-label", text || record.defaultText);
}
function restoreAccessibleName(record) {
if (!record.host || !accessibleNameState.has(record.host)) return;
const original = accessibleNameState.get(record.host);
if (original === null) record.host.removeAttribute("aria-label");
else record.host.setAttribute("aria-label", original);
accessibleNameState.delete(record.host);
}
function applyRecord(record) {
if (!record.target.isConnected) return;
const override = activeDraft.overrides?.[record.copyId] || {};
const sourceText = override.text ?? record.defaultText;
const renderedText = formatTemplate(sourceText, record.values);
if (record.attribute) {
record.target.setAttribute(record.attribute, renderedText);
return;
}
const hidden = Object.hasOwn(override, "hidden") ? override.hidden : Boolean(record.defaultHidden);
record.target.textContent = hidden ? "" : renderedText;
if (hidden) preserveAccessibleName(record, renderedText);
else restoreAccessibleName(record);
if (override.font_size_px) {
if (!record.fontCaptured) {
record.originalFontSize = record.target.style.fontSize;
record.fontCaptured = true;
}
record.target.style.fontSize = `${override.font_size_px}px`;
} else if (record.fontCaptured) {
record.target.style.fontSize = record.originalFontSize;
record.fontCaptured = false;
}
record.target.classList.toggle("ui-copy-has-override", Boolean(activeDraft.overrides?.[record.copyId]));
}
function registerRecord(record) {
const previous = targetRegistry.get(record.target);
if (previous) {
record.originalFontSize = previous.originalFontSize;
record.fontCaptured = previous.fontCaptured;
}
targetRegistry.set(record.target, record);
if (bootstrap) record.target.dataset.uiCopyId = record.copyId;
applyRecord(record);
return record;
}
export function renderUiCopy(copyId, element, defaultText, values = {}, options = {}) {
if (!(element instanceof Element)) return;
if (!bootstrap) {
const renderedText = formatTemplate(defaultText, values);
const record = { host: element, defaultText };
element.textContent = options.defaultHidden ? "" : renderedText;
if (options.defaultHidden) preserveAccessibleName(record, renderedText);
else restoreAccessibleName(record);
return;
}
registerRecord({
copyId,
target: element,
host: element,
defaultText,
values,
kind: "dynamic_template",
attribute: null,
defaultHidden: Boolean(options.defaultHidden),
});
}
export function renderUiValue(element, value) {
if (!(element instanceof Element)) return;
const priorRecord = targetRegistry.get(element);
restoreAccessibleName(priorRecord || { host: element });
targetRegistry.delete(element);
delete element.dataset.uiCopyId;
element.textContent = String(value ?? "");
}
export function registerStaticUiCopy(copyId, target, host, defaultText, kind, attribute = null, defaultHidden = false) {
if (!bootstrap || !(target instanceof Element)) return null;
return registerRecord({
copyId,
target,
host: host || target,
defaultText,
values: {},
kind,
attribute,
defaultHidden: Boolean(defaultHidden),
});
}
export function setUiCopyDraft(nextDraft) {
activeDraft = nextDraft;
for (const record of targetRegistry.values()) applyRecord(record);
}
export function applyUiCopyId(copyId) {
for (const record of targetRegistry.values()) {
if (record.copyId === copyId) applyRecord(record);
}
}
export function uiCopyRecords(copyId = null) {
const records = Array.from(targetRegistry.values()).filter((record) => record.target.isConnected);
return copyId === null ? records : records.filter((record) => record.copyId === copyId);
}
export function unregisterUiCopySubtree(root) {
for (const [target] of targetRegistry) {
if (!target.isConnected || target === root || root?.contains?.(target)) targetRegistry.delete(target);
}
}