Build Studio visual layout library with recoverable design CRUD
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import type {IncomingMessage} from 'node:http';
|
||||
import {parameters,uuid} from './layout-parameters';
|
||||
import layouts from '../content/templates/layouts.json';
|
||||
import fixedLayouts from '../content/templates/layouts.json';
|
||||
import standardLayout from '../content/standard-layout.json';
|
||||
const layouts=[...fixedLayouts,standardLayout];
|
||||
import type {Design} from './native-layout';
|
||||
|
||||
/** Only forward the session to our fixed private Wiki service, never a request Host. */
|
||||
@@ -16,5 +18,6 @@ export async function readDesign(id:unknown,req:IncomingMessage):Promise<Design|
|
||||
const {design}=await response.json() as {design:Design};
|
||||
const layout=layouts.find(l=>l.id===design.layoutId);
|
||||
if(!layout||design.id!==id)throw new Error('Invalid saved layout');
|
||||
if((design as Design&{archived?:boolean}).archived)return null;
|
||||
return {...design,parameters:parameters(layout,design.parameters)};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/** References in the retained toolbox are internal Wiki media, displayed as derivatives. */
|
||||
export function referencePreview(source:string){
|
||||
const path=new URL(source,'http://wiki.internal').pathname;
|
||||
if(!/^\/api\/media\/[0-9a-f-]{36}$/.test(path))throw Error('Invalid reference media');
|
||||
return '/api/preview?'+new URLSearchParams({source:path,width:'960'});
|
||||
}
|
||||
@@ -9,8 +9,21 @@ export const designUrl=(layoutId:string,id:string)=>`/studio/layouts/${layoutId}
|
||||
export function nativeLayout(layout:Layout):Layout {
|
||||
return {id:layout.id,name:layout.name,width:layout.width,height:layout.height,elements:layout.elements.map(({id,kind,role,box,direction,text,reading})=>({id,kind,role,box,direction,text,reading}))};
|
||||
}
|
||||
export function paperColor(id:string){return ['ref-04','ref-22'].includes(id)?'#a8b0ae':'#f5f5ef'}
|
||||
export function textColor(id:string,slot:Slot){return (id==='ref-04'&&['T01','T02'].includes(slot.id))||(id==='ref-22'&&slot.id==='T01')||(id==='ref-27'&&slot.id==='T01')||(id==='ref-10'&&slot.id==='T03')?'#f9faf5':'#28312e'}
|
||||
// Four coordinated inks per composition: paper, ink, image field and accent.
|
||||
const palettes=[
|
||||
['#f3eee4','#293b42','#7c9a9e','#c4d5cb'],['#f5f2e9','#344335','#879782','#d7c39f'],['#efede7','#383d4a','#8996a6','#c5d0d7'],
|
||||
['#647c7a','#f5f0e5','#b6c8be','#d9ded0'],['#f5eddf','#5c3b32','#b47d68','#d9bba0'],['#eceee8','#263d43','#688a94','#b4c7c7'],
|
||||
['#f3eddf','#4c4a36','#a1a185','#d8cba9'],['#edf0ef','#23424b','#73929a','#b6cbd2'],['#f5f1e9','#2f3e38','#7f9688','#d1d7ba'],
|
||||
['#eeece4','#344b57','#526e80','#afc4c9'],['#f4eee8','#4e393b','#a58a90','#d8bdb3'],['#f1f0e9','#424b36','#8c997b','#d1c7aa'],
|
||||
['#f3ebe5','#5b3e39','#b48e7e','#dec6ab'],['#eef0e7','#384c42','#789485','#c4d1b5'],['#e9edee','#2e4555','#839ba8','#c6d3d4'],
|
||||
['#f4f0e7','#50483a','#ada18a','#d9d1c0'],['#eeeee5','#394d42','#7e9785','#c8d5bc'],['#f2ede6','#3e424e','#8a92a3','#d0c7c0'],
|
||||
['#f5eede','#443d31','#a79b7a','#dbca9f'],['#eeefe8','#34463f','#809b89','#c5d3ba'],['#f0ebe5','#51413d','#a48b7f','#d5bfb3'],
|
||||
['#64797d','#f8f2e8','#9fb3b5','#cbd4c9'],['#f0efe9','#2f414d','#8199a7','#c5d2d6'],['#f4eee5','#5a443b','#ae927b','#dfc8ac'],
|
||||
['#ebeee8','#344b41','#829c8b','#c7d5bb'],['#edece8','#3c4354','#8b93aa','#c5cbd7'],['#f2ece2','#3b4e4b','#6f918c','#b8cdc3']
|
||||
];
|
||||
export function layoutPalette(id:string){return palettes[Number(id.slice(4))-1]||['#ffe5df','#303d43','#a9bec0','#f0bca6']}
|
||||
export function paperColor(id:string){return layoutPalette(id)[0]}
|
||||
export function textColor(id:string,slot:Slot){return (id==='ref-04'&&['T01','T02'].includes(slot.id))||(id==='ref-22'&&slot.id==='T01')||(id==='ref-27'&&slot.id==='T01')||(id==='ref-10'&&slot.id==='T03')?'#f9faf5':layoutPalette(id)[1]}
|
||||
// The screenshot's illegible small print is replaced with editable editorial copy.
|
||||
export function defaultText(layout:Layout,slot:Slot):string {
|
||||
if(slot.text)return slot.text;
|
||||
@@ -19,7 +32,7 @@ export function defaultText(layout:Layout,slot:Slot):string {
|
||||
if(slot.role.includes('英文')||slot.role.includes('品牌')||slot.role.includes('标识'))return 'BULUBLUE DESIGN';
|
||||
if(slot.role.includes('图注')||slot.role.includes('标签')||slot.box[3]<10)return 'FORM / SPACE / DESIGN';
|
||||
if(slot.direction==='vertical')return '设计灵感 · 日常观察';
|
||||
return '在留白之间,\n寻找新的秩序。\n让文字与形状相遇,\n记录日常的设计灵感。';
|
||||
return slot.box[2]<25?'留白之间\n观察日常\n记录灵感':'让文字与形状相遇。\n在留白之间,寻找新的秩序。';
|
||||
}
|
||||
export function slotPosition(layout:Layout,slot:Slot):CSSProperties {
|
||||
const [x,y,w,h]=slot.box;return {left:`${x/layout.width*100}%`,top:`${y/layout.height*100}%`,width:`${w/layout.width*100}%`,height:`${h/layout.height*100}%`};
|
||||
@@ -33,15 +46,15 @@ export function textSize(layout:Layout,slot:Slot,text:string):number {
|
||||
return Math.min(h/(lines.length*1.15),w/Math.max(1,...lines.map(length)))*.92;
|
||||
}
|
||||
export function imageShape(layout:Layout,slot:Slot):CSSProperties {
|
||||
const n=Number(layout.id.slice(4)),s:CSSProperties={backgroundColor:slot.id==='I01'?'#9ba6a3':'#788785'};
|
||||
const n=Number(layout.id.slice(4)),s:CSSProperties={backgroundColor:layoutPalette(layout.id)[slot.id==='I01'?2:3],backgroundImage:'linear-gradient(145deg,#ffffff12,transparent 65%)'};
|
||||
if([4,5,7,13,19,20].includes(n)||(n===17&&slot.id==='I02'))s.borderRadius='50%';
|
||||
if(n===4)s.transform='rotate(-9deg)';
|
||||
if(n===15&&slot.id==='I01')s.borderRadius='100% 0 0 0';
|
||||
if(n===22)s.clipPath=slot.id==='I01'?'polygon(0 0,100% 0,100% 48%,0 100%)':slot.id==='I02'?'polygon(0 30%,100% 0,100% 70%,0 100%)':'polygon(0 50%,100% 0,100% 100%,0 100%)';
|
||||
if(n===27)s.clipPath=slot.id==='I01'?'polygon(0 0,100% 35%,100% 100%,0 68%)':'polygon(0 40%,100% 0,100% 100%,0 100%)';
|
||||
if(n===10)s.backgroundColor='#596c67';
|
||||
if(n===16)s.backgroundColor=slot.id==='I01'?'#b6bfba':'#7e8e87';
|
||||
if(n===20&&slot.id==='I02')s.backgroundColor='#e3e6dc';
|
||||
if(n===10)s.backgroundColor=layoutPalette(layout.id)[2];
|
||||
if(n===16)s.backgroundColor=layoutPalette(layout.id)[slot.id==='I01'?3:2];
|
||||
if(n===20&&slot.id==='I02')s.backgroundColor=layoutPalette(layout.id)[3];
|
||||
return s;
|
||||
}
|
||||
export function decorationKind(slot:Slot){
|
||||
|
||||
Reference in New Issue
Block a user