feat(720-2): 최상위 폴더 만들기 — 폴더 · 문서 줄 메뉴 + 단가산출 · 일위대가 층 줄 「+」(구조물 조합과 같은 addFolder([]))
- 구조물 조합 나무 「〇〇로 복사…」 몸을 TreePanel_CopyTo 로 뗌(TreePanel 700 → 688 줄 · 동작 같음) - 낡은 시험 test_m02_layer_screen(복사 대상 글 자리 = CopyTo) · test_m02_precombo_scope(층 줄 add 인자) 새 꼴로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,10 +8,11 @@
|
||||
* 여럿(구조물 조합 나무 꼴 · `TreePanel_Pick`) — Ctrl · Shift 클릭 고름 · 오른쪽 클릭 · Ctrl+C · Ctrl+V ·
|
||||
* Delete 가 고른 것 전부에 · 복사는 읽을 수 있는 층 어디서나 → 쓸 수 있는 층에 붙여넣기(새 키).
|
||||
* 문서 누름 = 편집 칸 · 켜진 층 단추 다시 누름 = 목록표(페이지 몫).
|
||||
* 최상위 폴더(720-2) — 층 단추 옆 「+」(맨 위 메뉴) · 폴더 · 문서 줄 [최상위 폴더 만들기] = 같은 `addFolder([])`.
|
||||
* ========================================================================== */
|
||||
|
||||
import { isCtrlKey } from "../A00_Common/key_shortcut";
|
||||
import { el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
|
||||
import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
|
||||
import { createEmpty } from "@ui/ui_template_empty";
|
||||
import { t as L } from "@ui/ui_template_locale";
|
||||
import {
|
||||
@@ -58,8 +59,8 @@ export interface LibraryScope {
|
||||
export interface LibraryOptions {
|
||||
kind: LibraryKind;
|
||||
scope: () => LibraryScope;
|
||||
/** 층 단추 줄(페이지가 만듦 · 그릴 때마다 새로 — 켜진 단추가 바뀜) */
|
||||
bar: () => HTMLElement;
|
||||
/** 층 단추 줄(페이지가 만듦 · 그릴 때마다 새로 — 켜진 단추가 바뀜) · `add` = 단추 옆 「+」(720-2) */
|
||||
bar: (add: HTMLElement) => HTMLElement;
|
||||
confirmLeave: () => Promise<boolean>;
|
||||
onOpen: (sel: Selection | null) => void;
|
||||
getOpen: () => Selection | null;
|
||||
@@ -130,6 +131,15 @@ export function buildLibrarySection(opt: LibraryOptions): LibraryHandle {
|
||||
className: "ui-tree m02-tree__body",
|
||||
attrs: { "data-library-tree": kind, tabindex: "0" },
|
||||
});
|
||||
// 층 단추 옆 「+」(720-2 · 구조물 조합 꼴) — 맨 위 메뉴 · 읽기만 층 = 숨김(그릴 때)
|
||||
const add = createButton({
|
||||
label: "+",
|
||||
variant: "ghost",
|
||||
onClick: (event) => openTreeMenu(event, menuAt([])),
|
||||
});
|
||||
add.classList.add("m02-tree__add");
|
||||
add.title = L("M02_TreeAddTop");
|
||||
add.setAttribute("aria-label", L("M02_TreeAddTop"));
|
||||
const leaves = new Map<string, HTMLElement>();
|
||||
const toggled = new Map<string, boolean>(); // 손으로 펴고 접은 폴더 — 다시 그려도 그대로
|
||||
const targets = new Map<string, Target>();
|
||||
@@ -255,6 +265,7 @@ export function buildLibrarySection(opt: LibraryOptions): LibraryHandle {
|
||||
item(opt.text.newHere, () => make(path)),
|
||||
...(path.length
|
||||
? [
|
||||
item(L("M02_TreeAddTopFolder"), () => void addFolder([])),
|
||||
item(L("M02_TreeRename"), () => void rename(path)),
|
||||
item(L("M02_Delete"), () => void remove([target])),
|
||||
{ label: L("M02_TreeCopy").replace("{n}", "1"), run: () => copy([target]) },
|
||||
@@ -288,12 +299,14 @@ export function buildLibrarySection(opt: LibraryOptions): LibraryHandle {
|
||||
const item = { key: row.이름, 열: row.이름, 경로: [...folder, label], 이름: label };
|
||||
const target: Target = { kind: "item", item };
|
||||
targets.set(id, target);
|
||||
const off = (): string | undefined => (opt.scope().canWrite ? undefined : tc("ReadOnly"));
|
||||
const single = (): TreeMenuItem[] => [
|
||||
{ label: L("M02_TreeAddTopFolder"), run: () => void addFolder([]), disabledReason: off() },
|
||||
{ label: L("M02_TreeCopy").replace("{n}", "1"), run: () => copy([target]) },
|
||||
{
|
||||
label: L("M02_Delete"),
|
||||
run: () => void remove([target]),
|
||||
disabledReason: opt.scope().canWrite ? undefined : tc("ReadOnly"),
|
||||
disabledReason: off(),
|
||||
},
|
||||
...(opt.more?.(row.이름, label) ?? []),
|
||||
];
|
||||
@@ -424,7 +437,8 @@ export function buildLibrarySection(opt: LibraryOptions): LibraryHandle {
|
||||
const refresh = async (keep = false): Promise<void> => {
|
||||
const mine = ++seq;
|
||||
const at = opt.scope();
|
||||
barHost.replaceChildren(opt.bar());
|
||||
add.hidden = !at.canWrite;
|
||||
barHost.replaceChildren(opt.bar(add));
|
||||
if (!keep) treeHost.replaceChildren(createEmpty({ text: tc("Loading"), small: true }));
|
||||
const [got, tree] = await Promise.all([
|
||||
// 못 받으면 빈 나무(목록표에서 까닭) · 폴더를 못 받으면 문서는 모두 뿌리
|
||||
|
||||
Reference in New Issue
Block a user