zine-styles.js (6.1 KB)
1 import { PAGE_WIDTH_IN, PAGE_HEIGHT_IN, PAGE_PADDING_IN, ALL_PAGES_SELECTOR, RIGHT_PAGES_SELECTOR, LEFT_PAGES_SELECTOR, SPREADS } from './constants.js'; 2 3 // Shared print CSS for zine layout (used by both editor preview and exported viewer) 4 export const ZINE_PRINT_CSS = ` 5 @page { size: 8.5in 11in portrait; margin: 0; } 6 html, body { width: 8.5in; height: 11in; } 7 body { 8 display: grid !important; 9 grid-template-columns: repeat(4, ${PAGE_WIDTH_IN}in); 10 grid-template-rows: repeat(2, ${PAGE_HEIGHT_IN}in); 11 transform: rotate(90deg); 12 transform-origin: center center; 13 position: absolute; 14 top: calc(50% - ${PAGE_HEIGHT_IN}in); 15 left: calc(50% - 5.5in); 16 width: 11in; 17 height: 8.5in; 18 } 19 ${ALL_PAGES_SELECTOR} { 20 display: block !important; 21 width: ${PAGE_WIDTH_IN}in !important; 22 height: ${PAGE_HEIGHT_IN}in !important; 23 padding: ${PAGE_PADDING_IN}in; 24 background: white; 25 overflow: hidden; 26 overflow-wrap: break-word; 27 aspect-ratio: auto !important; 28 box-shadow: none !important; 29 transform: none; 30 } 31 #front-cover { grid-row: 2; grid-column: 2; } 32 #page1 { grid-row: 2; grid-column: 3; } 33 #page2 { grid-row: 2; grid-column: 4; } 34 #page3 { grid-row: 1; grid-column: 4; transform: rotate(180deg); } 35 #page4 { grid-row: 1; grid-column: 3; transform: rotate(180deg); } 36 #page5 { grid-row: 1; grid-column: 2; transform: rotate(180deg); } 37 #page6 { grid-row: 1; grid-column: 1; transform: rotate(180deg); } 38 #back-cover { grid-row: 2; grid-column: 1; } 39 .zine-nav, .zine-empty, .spread-nav, .iframe-fullscreen-toggle, .zine-spread-container { display: contents !important; } 40 .zine-spread-container { transform: none !important; } 41 /* Hide flip animation elements for print - use original pages */ 42 .zine-book { display: none !important; } 43 .page { display: block !important; } 44 a { color: black; } 45 img { max-width: 100%; height: auto; } 46 `; 47 48 // CSS for 3D page flip animation 49 export const ZINE_FLIP_CSS = ` 50 .zine-book { 51 position: relative; 52 width: ${PAGE_WIDTH_IN * 2}in; 53 height: ${PAGE_HEIGHT_IN}in; 54 perspective: 2000px; 55 transform-style: preserve-3d; 56 transform-origin: center center; 57 } 58 59 .zine-leaf { 60 position: absolute; 61 width: ${PAGE_WIDTH_IN}in; 62 height: ${PAGE_HEIGHT_IN}in; 63 left: ${PAGE_WIDTH_IN}in; 64 top: 0; 65 transform-origin: left center; 66 transform-style: preserve-3d; 67 transition: none; 68 will-change: transform; 69 } 70 71 /* When flipping, use high z-index so it's on top during animation */ 72 .zine-leaf[data-state="flipping"] { 73 z-index: 20 !important; 74 transition: none; 75 } 76 77 .zine-leaf-front, 78 .zine-leaf-back { 79 position: absolute; 80 width: 100%; 81 height: 100%; 82 backface-visibility: hidden; 83 -webkit-backface-visibility: hidden; 84 transform: translateZ(0); 85 } 86 87 .zine-leaf-front { 88 transform: rotateY(0deg); 89 z-index: 2; 90 } 91 92 .zine-leaf-back { 93 transform: rotateY(180deg); 94 z-index: 1; 95 } 96 97 .zine-leaf-front .page, 98 .zine-leaf-back .page { 99 width: 100%; 100 height: 100%; 101 display: block !important; 102 } 103 104 /* Base pages - shown beneath the flipping leaves */ 105 .zine-base-pages { 106 position: absolute; 107 width: 100%; 108 height: 100%; 109 display: flex; 110 justify-content: center; 111 align-items: center; 112 z-index: 0; 113 } 114 115 .zine-base-page { 116 position: absolute; 117 width: ${PAGE_WIDTH_IN}in; 118 height: ${PAGE_HEIGHT_IN}in; 119 display: none !important; 120 z-index: 0; 121 } 122 123 /* Position base pages */ 124 .zine-base-page[data-page-id="front-cover"], 125 .zine-base-page[data-page-id="page2"], 126 .zine-base-page[data-page-id="page4"], 127 .zine-base-page[data-page-id="page6"] { 128 right: 0; 129 } 130 131 .zine-base-page[data-page-id="page1"], 132 .zine-base-page[data-page-id="page3"], 133 .zine-base-page[data-page-id="page5"], 134 .zine-base-page[data-page-id="back-cover"] { 135 left: 0; 136 } 137 `; 138 139 // Shared CSS for zine pages (used by both editor preview and exported viewer) 140 export const ZINE_PAGE_CSS = ` 141 ${ALL_PAGES_SELECTOR} { 142 display: none; 143 width: ${PAGE_WIDTH_IN}in; 144 height: ${PAGE_HEIGHT_IN}in; 145 flex-shrink: 0; 146 padding: ${PAGE_PADDING_IN}in; 147 overflow: hidden; 148 overflow-wrap: break-word; 149 } 150 .page { 151 background: white; 152 } 153 .zine-spread-container { 154 display: flex; 155 transform-origin: center center; 156 } 157 ${RIGHT_PAGES_SELECTOR} { 158 box-shadow: inset 4px 0 1.3px -3px rgba(0, 0, 0, 0.09), inset 8px 0 6px -6px rgba(0, 0, 0, 0.15); 159 } 160 ${LEFT_PAGES_SELECTOR} { 161 box-shadow: inset -4px 0 1.5px -3px rgba(0, 0, 0, 0.09), inset -8px 0 6px -6px rgba(0, 0, 0, 0.15); 162 } 163 .zine-empty { 164 width: ${PAGE_WIDTH_IN}in; 165 height: ${PAGE_HEIGHT_IN}in; 166 flex-shrink: 0; 167 border: 1px dashed #666; 168 } 169 .zine-empty:first-child { 170 border-right: none; 171 } 172 .zine-empty:last-child { 173 border-left: none; 174 } 175 img { 176 max-width: 100%; 177 } 178 `; 179 180 // Generate CSS to show only the current spread 181 export function generateSpreadCSS(spreadIndex) { 182 const spread = SPREADS[spreadIndex]; 183 const visiblePages = [spread.left, spread.right].filter(Boolean); 184 185 return ` 186 /* Base styles for all views */ 187 * { margin: 0; padding: 0; box-sizing: border-box; } 188 189 /* Screen view: show spread at actual size, then scale to fit */ 190 @media screen { 191 html, body { 192 height: 100% !important; 193 overflow: hidden !important; 194 } 195 196 body { 197 display: flex !important; 198 justify-content: center !important; 199 align-items: center !important; 200 } 201 202 body > *:not(.zine-spread-container):not(.iframe-fullscreen-toggle) { 203 display: none !important; 204 } 205 206 ${ZINE_PAGE_CSS} 207 208 .zine-spread-container { 209 display: flex !important; 210 position: relative; 211 } 212 213 ${ALL_PAGES_SELECTOR} { 214 display: none !important; 215 width: ${PAGE_WIDTH_IN}in !important; 216 height: ${PAGE_HEIGHT_IN}in !important; 217 } 218 219 /* Show visible pages */ 220 ${visiblePages.map(id => `#${id}`).join(', ')} { 221 display: block !important; 222 } 223 224 .zine-empty { 225 display: block !important; 226 width: ${PAGE_WIDTH_IN}in !important; 227 height: ${PAGE_HEIGHT_IN}in !important; 228 } 229 } 230 231 /* Print view: 8-page grid for mini-zine folding */ 232 @media print { 233 ${ZINE_PRINT_CSS} 234 } 235 `; 236 }