mirror of
https://github.com/hansjone/mind-map.git
synced 2026-10-09 14:10:47 +08:00
feat: glass cards with readable attribute lists
Replace raw JSON on card faces with key-value lists, simulate frosted glass on canvas, and use a list editor plus real backdrop blur for the selected overlay. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4c6e5964a8
commit
200c8bd450
13 changed files with 1090 additions and 286 deletions
|
|
@ -1,29 +1,48 @@
|
|||
import type { MindNode } from "@mind-map/shared";
|
||||
import { visiblePropRows } from "./registry";
|
||||
import { descriptionChips } from "./description-display";
|
||||
|
||||
export const CARD_WIDTH = { comfortable: 288, compact: 248 } as const;
|
||||
export const CARD_HEADER_H = 36;
|
||||
export const CARD_HEADER_H = 40;
|
||||
export const CARD_PAD_Y = 12;
|
||||
export const CARD_PAD_X = 12;
|
||||
export const CARD_PAD_X = 14;
|
||||
export const CARD_GAP = 10;
|
||||
export const CARD_HERO_H = { comfortable: 108, compact: 90 } as const;
|
||||
export const CARD_CHIP_H = 18;
|
||||
export const CARD_FOOTER_H = 24;
|
||||
|
||||
/** Layout / hit-test height for a card node. */
|
||||
/** Layout / hit-test height for a glass card node (title → image → note → chips → footer). */
|
||||
export function estimateCardSize(
|
||||
node: MindNode,
|
||||
dens: boolean,
|
||||
forced: ReadonlySet<string> = new Set(),
|
||||
_forced: ReadonlySet<string> = new Set(),
|
||||
): { w: number; h: number } {
|
||||
const w = dens ? CARD_WIDTH.compact : CARD_WIDTH.comfortable;
|
||||
const rows = visiblePropRows(node, forced);
|
||||
let body = 0;
|
||||
for (const { def } of rows) {
|
||||
if (def.id === "text") continue;
|
||||
// Stacked label+value needs a bit more than legacy side-by-side rows.
|
||||
const rh =
|
||||
def.imageRow ? (dens ? 52 : 64) + 4 : Math.max(def.rowHeight + 12, dens ? 28 : 32);
|
||||
body += rh + CARD_GAP;
|
||||
|
||||
if (node.imageUrl?.trim()) {
|
||||
body += (dens ? CARD_HERO_H.compact : CARD_HERO_H.comfortable) + CARD_GAP;
|
||||
}
|
||||
|
||||
if (node.note?.trim()) {
|
||||
body += (dens ? 40 : 48) + CARD_GAP;
|
||||
}
|
||||
|
||||
const chips = descriptionChips(node.description);
|
||||
if (chips.length) {
|
||||
body += chips.length * CARD_CHIP_H + Math.max(0, chips.length - 1) * 4 + CARD_GAP;
|
||||
}
|
||||
|
||||
const hasFooter =
|
||||
Boolean(node.tags?.length) ||
|
||||
Boolean(node.links?.length) ||
|
||||
node.startAt != null ||
|
||||
node.dueAt != null ||
|
||||
Boolean(node.pinned);
|
||||
if (hasFooter) {
|
||||
body += CARD_FOOTER_H + CARD_GAP;
|
||||
}
|
||||
|
||||
if (body > 0) body -= CARD_GAP;
|
||||
const h = CARD_HEADER_H + CARD_PAD_Y * 2 + Math.max(body, 12);
|
||||
return { w, h: Math.max(h, dens ? 84 : 100) };
|
||||
const h = CARD_HEADER_H + CARD_PAD_Y * 2 + Math.max(body, 8);
|
||||
return { w, h: Math.max(h, dens ? 88 : 104) };
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue