// Right-side panels: Properties, Layers, Brand Kit, AI Assist, History.
// ============ LAYERS PANEL ============
const LAYERS = [
{ id: 'schedule', name: 'Critical Dates · Table', type: 'group', depth: 0, visible: true, locked: false, children: [
{ id: 'sch-head', name: 'Table Header', type: 'rect', depth: 1, visible: true, locked: false },
{ id: 'sch-row-1', name: 'Row · Publication', type: 'group', depth: 1, visible: true, locked: false },
{ id: 'sch-row-2', name: 'Row · Pre-Bid', type: 'group', depth: 1, visible: true, locked: false },
{ id: 'sch-row-3', name: 'Row · Submission', type: 'group', depth: 1, visible: true, locked: false },
{ id: 'sch-row-4', name: 'Row · Opening', type: 'group', depth: 1, visible: true, locked: false },
]},
{ id: 'body', name: 'Notice Body · Bilingual', type: 'text', depth: 0, visible: true, locked: false },
{ id: 'notice-head', name: 'Notice Header · Title', type: 'text', depth: 0, visible: true, locked: false },
{ id: 'rule', name: 'Rule · Double', type: 'shape', depth: 0, visible: true, locked: true },
{ id: 'emblem', name: 'Emblem · Ashoka', type: 'symbol', depth: 0, visible: true, locked: true },
{ id: 'emd', name: 'Value Blocks · Grid', type: 'group', depth: 0, visible: true, locked: false },
{ id: 'footer', name: 'Signature Block', type: 'group', depth: 0, visible: true, locked: false },
{ id: 'guides', name: '· margins · guides', type: 'guide', depth: 0, visible: false, locked: true },
];
function LayersPanel({ selectedId, onSelect }) {
const [expanded, setExpanded] = React.useState({ schedule: true });
const rows = [];
LAYERS.forEach((l) => {
rows.push(l);
if (l.children && expanded[l.id]) {
l.children.forEach((c) => rows.push(c));
}
});
return (
} size={20} />
} size={20} />
}>
{rows.map((l) => {
const isSel = selectedId === l.id;
const hasChildren = LAYERS.find(x => x.id === l.id)?.children;
return (
onSelect(l.id)}
style={{
display: 'flex',
alignItems: 'center',
gap: 6,
padding: '4px 12px',
paddingLeft: 12 + l.depth * 14,
background: isSel ? 'var(--bg-panel-2)' : 'transparent',
borderLeft: isSel ? '2px solid var(--gold)' : '2px solid transparent',
cursor: 'pointer',
fontSize: 11.5,
}}
onMouseEnter={(e) => { if (!isSel) e.currentTarget.style.background = 'rgba(0,0,0,0.02)'; }}
onMouseLeave={(e) => { if (!isSel) e.currentTarget.style.background = 'transparent'; }}
>
{hasChildren ? (
{ e.stopPropagation(); setExpanded({ ...expanded, [l.id]: !expanded[l.id] }); }} style={{ padding: 0, background: 'none', border: 'none', display: 'flex', color: 'var(--ink-muted)' }}>
) : }
{l.type === 'group' && }
{l.type === 'text' && }
{l.type === 'shape' && }
{l.type === 'symbol' && }
{l.type === 'rect' && }
{l.type === 'guide' && }
{l.name}
{l.visible ? : }
);
})}
{[1,2,3,4].map((n) => (
{String(n).padStart(2, '0')} Page {n}
A4
))}
);
}
// ============ PROPERTIES PANEL ============
function PropertiesPanel({ selectedId }) {
const info = getSelectionInfo(selectedId);
return (
X
Y
W
H
ANGLE
} title="Constrain proportions" size={22}/>
#0A1F3D
100%
None
}>Shadow
}>Blur
{info.hasText && (
Fraunces · Serif
Noto Sans Devanagari
Inter
JetBrains Mono
Semibold Regular Medium Bold
A↕
A↔
} active/>
}/>
}/>
}/>
}/>
}/>
OpenType · liga · dlig · calt · ss01
)}
{[I.align_l, I.align_c, I.align_r].map((Ic, i) => }/>)}
{[I.align_l, I.align_c, I.align_r].map((Ic, i) => }/>)}
id · {info.id || '—'}
type · {info.type}
parent · Page 01
modified · 14:32:18 IST
author · A. Rao
);
}
function getSelectionInfo(id) {
const map = {
'emblem': { id: 'emblem', type: 'symbol', x: 15, y: 15, w: 22, h: 22, hasText: false },
'notice-head': { id: 'notice-head', type: 'text · group', x: 15, y: 45, w: 180, h: 40, hasText: true },
'body': { id: 'body', type: 'text · frame', x: 15, y: 100, w: 180, h: 60, hasText: true },
'schedule': { id: 'schedule', type: 'group', x: 15, y: 170, w: 180, h: 45, hasText: false },
'emd': { id: 'emd', type: 'group · grid', x: 15, y: 225, w: 180, h: 22, hasText: false },
};
return map[id] || { id: null, type: 'no selection', x: 0, y: 0, w: 0, h: 0, hasText: false };
}
const selectStyle = {
width: '100%',
height: 22,
padding: '0 6px',
background: 'var(--bg-elevated)',
border: '1px solid var(--line-2)',
borderRadius: 2,
fontSize: 11.5,
fontFamily: 'inherit',
color: 'var(--ink)',
appearance: 'none',
backgroundImage: `url("data:image/svg+xml;utf8, ")`,
backgroundRepeat: 'no-repeat',
backgroundPosition: 'right 6px center',
};
// ============ BRAND KIT PANEL ============
function BrandKitPanel() {
return (
Ministry of Rural Development
Ministry of Electronics & IT
Bharat Sanchar Nigam
Internal — Design Cell
Enforced
rev · 04 · 12 Jul 2026
{[
{ c: '#0A1F3D', n: 'Ashoka Ink' },
{ c: '#1E4E8C', n: 'Bharat Blue' },
{ c: '#A67C1F', n: 'Emblem Gold' },
{ c: '#8B2E1F', n: 'Rakta Red' },
{ c: '#2F6B3E', n: 'Kaziranga' },
{ c: '#F5F1E8', n: 'Ivory' },
].map((s) => (
))}
CMYK · PMS mappings available for print.
{[
{ fam: 'Fraunces', role: 'Display · Headings', sample: 'Aa 123 गं' },
{ fam: 'Noto Sans Devanagari', role: 'Body · Devanagari', sample: 'क ख ग घ · अ' },
{ fam: 'Inter', role: 'UI · Labels', sample: 'Aa 123' },
{ fam: 'JetBrains Mono', role: 'Metadata · Codes', sample: 'Aa 0123' },
].map((t) => (
))}
{['Emblem · Colour','Emblem · Mono','Emblem · Reversed','Ministry Mark','Watermark','Seal · Round'].map((n) => (
च
))}
);
}
// ============ AI ASSIST PANEL ============
function AIAssistPanel() {
const [prompt, setPrompt] = React.useState('Make the schedule table more scannable — increase row spacing and align dates right.');
const [loading, setLoading] = React.useState(false);
const [output, setOutput] = React.useState(null);
const suggestions = [
'Convert schedule to a two-column layout',
'Add bilingual footer with contact details',
'Improve contrast for accessibility (WCAG AA)',
'Generate an alternate cover in landscape',
];
const run = async () => {
if (!prompt.trim()) return;
setLoading(true);
setOutput(null);
try {
const text = await window.genspark.complete({
messages: [
{ role: 'user', content: `You are a design assistant inside ChitraKar, an Indian government design platform. A designer is working on a bilingual (English + Hindi/Devanagari) tender notice cover for the Ministry of Rural Development. They ask: "${prompt}". Reply in 3–5 short bullet points with specific, formal design recommendations. Keep tone professional. Use plain text only, no markdown symbols.` },
],
});
setOutput(text);
} catch (e) {
setOutput('Unable to reach AI Studio. Please retry or check network policy.');
}
setLoading(false);
};
return (
Beta}>
brand-aware
on-prem model
}>
{loading ? 'Working…' : 'Run'}
{loading && (
Consulting local inference · MoRD brand rules loaded
)}
{output && (
{output}
Apply
Refine
gen · 1.2s
)}
{suggestions.map((s) => (
setPrompt(s)}
style={{
textAlign: 'left',
padding: '7px 10px',
background: 'var(--bg-elevated)',
border: '1px solid var(--line-2)',
fontSize: 11.5,
color: 'var(--ink-3)',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: 8,
}}
onMouseEnter={(e) => e.currentTarget.style.borderColor = 'var(--gold)'}
onMouseLeave={(e) => e.currentTarget.style.borderColor = 'var(--line-2)'}
>
{s}
))}
} style={{ width: '100%', justifyContent: 'flex-start' }}>Text to Image
} style={{ width: '100%', justifyContent: 'flex-start' }}>Text to Vector
} style={{ width: '100%', justifyContent: 'flex-start' }}>Logo · Emblem
} style={{ width: '100%', justifyContent: 'flex-start' }}>Palette Extractor
);
}
function CheckRow({ label, state, note }) {
const stateMap = {
ok: { icon: , color: 'var(--status-ok)' },
warn: { icon: , color: 'var(--status-warn)' },
err: { icon: , color: 'var(--status-err)' },
}[state];
return (
{stateMap.icon}
{label}
{note && {note} }
);
}
// ============ HISTORY / COMMENTS PANEL ============
function HistoryPanel() {
const events = [
{ t: '14:32', who: 'A. Rao', what: 'Updated critical dates table', me: true },
{ t: '14:18', who: 'A. Rao', what: 'Set body copy · Devanagari', me: true },
{ t: '13:50', who: 'S. Iyer', what: 'Comment · "Right-align dates?"', me: false },
{ t: '13:22', who: 'A. Rao', what: 'Added schedule table', me: true },
{ t: '12:47', who: 'M. Nair', what: 'Placed emblem from Brand Kit', me: false },
{ t: '11:30', who: 'A. Rao', what: 'Created from Template · Tender', me: true },
{ t: 'Yday', who: 'System', what: 'Version snapshot · v0.4', me: false },
];
return (
{events.map((e, i) => (
{e.t}
{e.what}
{e.who}{e.me ? ' · you' : ''}
))}
);
}
Object.assign(window, { LayersPanel, PropertiesPanel, BrandKitPanel, AIAssistPanel, HistoryPanel });