chore: 恢复旧布局基线(迁移改动丢失后重建,apps/packages 布局暂存)

This commit is contained in:
logan committed 2026-10-14 20:31:17 +08:00
1 parent a9510235bb
commit 456fa6954b
203 files changed
+18787 -48

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
/**
* 模块级输入对话框(C6 契约)
*
* 独立于 store.ts(避免与 WS-C 文件冲突):内部维护一个微型订阅队列,
* 由 NotifyHost 内嵌的 DialogHost 订阅并以 OpsModal input 变体渲染。
* 业务侧只需 `const name = await askInput({ title: "分组名称" })`,
* 确认返回输入字符串,Esc/取消返回 null(替代 WKWebView 下返回 null 的 window.prompt)。
*/
import { useSyncExternalStore } from "react";
export type AskInputOptions = {
title: string;
label?: string;
defaultValue?: string;
placeholder?: string;
};
type InputRequest = AskInputOptions & {
/** 递增 id,供渲染侧作 React key(连续请求时强制重挂,重置输入框状态) */
id: number;
resolve: (value: string | null) => void;
};
// 请求队列:允许连续发起多个 askInput,逐个展示
let queue: InputRequest[] = [];
let nextId = 1;
const listeners = new Set<() => void>();
function emit() {
listeners.forEach((l) => l());
}
/** C6 契约:弹出令牌化输入框,确认返回值 / Esc 或取消返回 null */
export function askInput(opts: AskInputOptions): Promise<string | null> {
return new Promise((resolve) => {
queue = [...queue, { ...opts, id: nextId++, resolve }];
emit();
});
}
function subscribe(listener: () => void): () => void {
listeners.add(listener);
return () => {
listeners.delete(listener);
};
}
function getSnapshot(): InputRequest | null {
return queue[0] ?? null;
}
/** 内部:NotifyHost 的 DialogHost 订阅当前待处理的输入请求 */
export function useInputRequest(): InputRequest | null {
return useSyncExternalStore(subscribe, getSnapshot);
}
/** 内部:消费当前请求(确认传值,取消传 null),并出队下一个 */
export function settleInputRequest(value: string | null) {
const [cur, ...rest] = queue;
queue = rest;
cur?.resolve(value);
emit();
}