/** Shared visual constants: palette, notebook covers, sidebar folders. */ export const COLORS = [ "#0d1117", "#e94560", "#0f3460", "#533483", "#e07c24", "#21bf73", "#fd5e53", "#3282b8", "#ff6b6b", "#4ecdc4", "#f7dc6f", "#bb8fce", "#85c1e9", "#f8c471", "#82e0aa", "#f1948a", "#aeb6bf", "#ffffff", "#f39c12", "#000000", ]; export const COVERS = [ { bg: "linear-gradient(135deg,#0f0c29,#302b63,#24243e)", spine: "#1a1540", accent: "#6c63ff" }, { bg: "linear-gradient(135deg,#1a1a2e,#16213e,#0f3460)", spine: "#0a1628", accent: "#4fc3f7" }, { bg: "linear-gradient(135deg,#134e5e,#71b280)", spine: "#0e3d4a", accent: "#a5d6a7" }, { bg: "linear-gradient(135deg,#8e2de2,#4a00e0)", spine: "#3a0099", accent: "#ce93d8" }, { bg: "linear-gradient(135deg,#fc4a1a,#f7b733)", spine: "#c43d15", accent: "#ffe082" }, { bg: "linear-gradient(135deg,#c94b4b,#4b134f)", spine: "#3d0f40", accent: "#f48fb1" }, { bg: "linear-gradient(135deg,#11998e,#38ef7d)", spine: "#0d7a71", accent: "#b9f6ca" }, { bg: "linear-gradient(135deg,#373b44,#4286f4)", spine: "#2a2e35", accent: "#90caf9" }, { bg: "linear-gradient(135deg,#141e30,#243b55)", spine: "#0e1520", accent: "#78909c" }, { bg: "linear-gradient(135deg,#f12711,#f5af19)", spine: "#c01f0d", accent: "#fff59d" }, { bg: "linear-gradient(135deg,#2c3e50,#3498db)", spine: "#1e2b38", accent: "#81d4fa" }, { bg: "linear-gradient(135deg,#0f2027,#203a43,#2c5364)", spine: "#0a171c", accent: "#80cbc4" }, { bg: "linear-gradient(135deg,#aa4b6b,#6b6b83,#3b8d99)", spine: "#7a3550", accent: "#f48fb1" }, { bg: "linear-gradient(135deg,#1f1c2c,#928dab)", spine: "#15131f", accent: "#b39ddb" }, { bg: "linear-gradient(135deg,#654ea3,#eaafc8)", spine: "#4e3c7e", accent: "#f8bbd0" }, ]; /** * Colours a chapter's icon can be given. * * A short, named list rather than the full palette: the point is telling one * chapter from another at a glance, and twenty near-identical blues do not help * with that. Each is legible on both themes. */ export const CHAPTER_COLORS = [ { label: "Red", value: "#e5534b" }, { label: "Orange", value: "#e07c24" }, { label: "Yellow", value: "#d4a017" }, { label: "Green", value: "#2da44e" }, { label: "Teal", value: "#1f9c96" }, { label: "Blue", value: "#4a8ff5" }, { label: "Purple", value: "#a371f7" }, { label: "Pink", value: "#db61a2" }, ]; /* The icon is a key rather than an emoji: the sidebar draws it from the app's * own set, so it matches the stroke weight of everything around it and looks * the same on every machine. */ export const DEFAULT_FOLDERS = [ { id: "all", name: "All Notes", icon: "stack" }, { id: "starred", name: "Starred", icon: "star" }, { id: "trash", name: "Trash", icon: "trash" }, ]; /** * A pattern laid over a cover, chosen separately from its colour. * * Two decisions rather than one list: a cover is a colour *and* a texture, and * offering every combination as its own entry would mean fifteen gradients times * a dozen patterns in a grid nobody could take in. Picking each in turn is both * shorter and gives every combination, not the handful someone wrote out. * * `layers` are CSS background layers laid **over** the gradient — no image * files, nothing to upload, crisp at any size and offline like the rest of the * app. They are deliberately faint: a cover is read at the size of a thumb with * a title across it, and anything louder fights the title. One idea each, too — * two crossed diagonals meant as a chevron came out as noisy plaid at that size. */ export const PATTERNS = [ { emblem: "ring", id: "plain", label: "Plain", layers: "" }, { id: "ruled", emblem: "none", label: "Ruled", layers: "repeating-linear-gradient(0deg,rgba(255,255,255,.12) 0 1px,transparent 1px 17px)", }, { id: "grid", emblem: "square", label: "Grid", layers: "repeating-linear-gradient(0deg,rgba(255,255,255,.10) 0 1px,transparent 1px 20px), repeating-linear-gradient(90deg,rgba(255,255,255,.10) 0 1px,transparent 1px 20px)", }, { id: "pinstripe", emblem: "diamond", label: "Pinstripe", layers: "repeating-linear-gradient(45deg,rgba(255,255,255,.09) 0 6px,transparent 6px 14px)", }, { id: "bands", emblem: "none", label: "Bands", layers: "repeating-linear-gradient(0deg,rgba(0,0,0,.18) 0 13px,transparent 13px 26px)", }, { id: "dots", emblem: "dot", label: "Dots", layers: "radial-gradient(rgba(255,255,255,.18) 1.4px,transparent 1.5px) 0 0/13px 13px", }, { id: "hatch", emblem: "cross", label: "Cross-hatch", layers: "repeating-linear-gradient(45deg,rgba(255,255,255,.08) 0 1px,transparent 1px 11px), repeating-linear-gradient(-45deg,rgba(255,255,255,.08) 0 1px,transparent 1px 11px)", }, { id: "linen", emblem: "arc", label: "Linen", layers: "repeating-linear-gradient(0deg,rgba(255,255,255,.07) 0 1px,transparent 1px 4px), repeating-linear-gradient(90deg,rgba(0,0,0,.07) 0 1px,transparent 1px 4px)", }, { id: "ledger", emblem: "bars", label: "Ledger", layers: "repeating-linear-gradient(90deg,rgba(255,255,255,.09) 0 1px,transparent 1px 26px)", }, { id: "glow", emblem: "none", label: "Corner light", layers: "radial-gradient(120% 85% at 18% 0%,rgba(255,255,255,.20),transparent 62%)", }, { id: "foot", emblem: "square", label: "Foot band", layers: "linear-gradient(0deg,rgba(0,0,0,.34) 0 22%,transparent 22%)", }, ]; /** * Covers written before patterns were their own choice. * * Twelve patterned entries were appended to `COVERS` for a day, so a notebook * may still hold an index into them. Rather than let those repaint themselves, * each is read back as the colour-and-pattern pair it was drawn as. */ const LEGACY_COVER = { 15: [11, 1], 16: [2, 2], 17: [3, 3], 18: [9, 4], 19: [5, 5], 20: [8, 6], 21: [12, 7], 22: [4, 4], 23: [8, 9], 24: [0, 9], 25: [2, 10], 26: [8, 8], }; /** The colour and pattern a notebook is actually drawn with. */ export function coverParts(cover, pattern) { const legacy = LEGACY_COVER[cover]; if (legacy) return { cover: legacy[0], pattern: legacy[1] }; return { cover: ((cover % COVERS.length) + COVERS.length) % COVERS.length, pattern: pattern || 0 }; } /** The CSS `background` for a cover: its pattern laid over its colour. */ export function coverBackground(cover, pattern) { const parts = coverParts(cover, pattern); const base = COVERS[parts.cover]; const layers = PATTERNS[parts.pattern]?.layers; return layers ? `${layers}, ${base.bg}` : base.bg; } /** * The mark in the middle of a cover. * * It used to be the same pair of rings on every notebook, whatever cover was * chosen — which, with the same title frame and the same three dots, is why a * shelf of them all looked alike. It belongs to the design now: some wear a * ring, some a diamond, and the ones whose pattern already fills the face wear * nothing at all. */ export const coverEmblem = (cover, pattern) => PATTERNS[coverParts(cover, pattern).pattern]?.emblem || "none"; /** The rest of a cover's colours — the spine, and the accent used beside it. */ export const coverStyle = (cover, pattern) => COVERS[coverParts(cover, pattern).cover];