@zenith-open/zenithcms-admin 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -0
  3. package/dist/assets/ApiExplorerPage-UJpoKRI0.js +42 -0
  4. package/dist/assets/ApiExplorerPage-UJpoKRI0.js.map +1 -0
  5. package/dist/assets/AuditLogPage-8xYlRl1I.js +1 -0
  6. package/dist/assets/AuditLogPage-8xYlRl1I.js.map +1 -0
  7. package/dist/assets/BlockBuilderPage-DcOo3Vnt.js +1 -0
  8. package/dist/assets/BlockBuilderPage-DcOo3Vnt.js.map +1 -0
  9. package/dist/assets/BuilderPage-Iu8F_bN1.js +1 -0
  10. package/dist/assets/BuilderPage-Iu8F_bN1.js.map +1 -0
  11. package/dist/assets/CollectionHooksPage-Dn_ujtlp.js +7 -0
  12. package/dist/assets/CollectionHooksPage-Dn_ujtlp.js.map +1 -0
  13. package/dist/assets/CollectionsPage-BSPHf7H2.js +1 -0
  14. package/dist/assets/CollectionsPage-BSPHf7H2.js.map +1 -0
  15. package/dist/assets/ComponentBuilderPage-CT6S12LA.js +14 -0
  16. package/dist/assets/ComponentBuilderPage-CT6S12LA.js.map +1 -0
  17. package/dist/assets/DashboardBuilder-Cbi9Ddiu.js +1 -0
  18. package/dist/assets/DashboardBuilder-Cbi9Ddiu.js.map +1 -0
  19. package/dist/assets/EmptyState-X_SXKpQY.js +1 -0
  20. package/dist/assets/EmptyState-X_SXKpQY.js.map +1 -0
  21. package/dist/assets/MediaLibrary-BzXE95xo.js +1 -0
  22. package/dist/assets/MediaLibrary-BzXE95xo.js.map +1 -0
  23. package/dist/assets/PluginsPage-5YRpbP-N.js +10 -0
  24. package/dist/assets/PluginsPage-5YRpbP-N.js.map +1 -0
  25. package/dist/assets/RedirectsPage-D_4jAdaI.js +1 -0
  26. package/dist/assets/RedirectsPage-D_4jAdaI.js.map +1 -0
  27. package/dist/assets/SchemaBuilderPage-EFA5XIAa.js +14 -0
  28. package/dist/assets/SchemaBuilderPage-EFA5XIAa.js.map +1 -0
  29. package/dist/assets/SettingsPage-BRpcMw48.js +33 -0
  30. package/dist/assets/SettingsPage-BRpcMw48.js.map +1 -0
  31. package/dist/assets/SetupWizard-D57HIkrs.js +62 -0
  32. package/dist/assets/SetupWizard-D57HIkrs.js.map +1 -0
  33. package/dist/assets/SpatialEditor-CPgS7Zrd.js +3 -0
  34. package/dist/assets/SpatialEditor-CPgS7Zrd.js.map +1 -0
  35. package/dist/assets/TemplatesPage-B-nNYv3o.js +1 -0
  36. package/dist/assets/TemplatesPage-B-nNYv3o.js.map +1 -0
  37. package/dist/assets/TrashPage-Ccusal1w.js +1 -0
  38. package/dist/assets/TrashPage-Ccusal1w.js.map +1 -0
  39. package/dist/assets/index-ChcKY5Xe.js +11 -0
  40. package/dist/assets/index-ChcKY5Xe.js.map +1 -0
  41. package/dist/assets/index-CxhwdV2K.css +1 -0
  42. package/dist/assets/login-bg.png +0 -0
  43. package/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
  44. package/dist/assets/useUnsavedGuard-CMMKQT9a.js +1 -0
  45. package/dist/assets/useUnsavedGuard-CMMKQT9a.js.map +1 -0
  46. package/dist/assets/utils-fgvbH6CB.js +1 -0
  47. package/dist/assets/utils-fgvbH6CB.js.map +1 -0
  48. package/dist/assets/vendor-C-9IqjvY.js +1 -0
  49. package/dist/assets/vendor-C-9IqjvY.js.map +1 -0
  50. package/dist/assets/vendor-forms-BnBLxarY.js +1 -0
  51. package/dist/assets/vendor-forms-BnBLxarY.js.map +1 -0
  52. package/dist/assets/vendor-react-DQVTOTFO.js +195 -0
  53. package/dist/assets/vendor-react-DQVTOTFO.js.map +1 -0
  54. package/dist/favicon.svg +1 -0
  55. package/dist/icons.svg +24 -0
  56. package/dist/index.html +30 -0
  57. package/dist/logo/zenith.svg +9 -0
  58. package/dist/sw.js +3 -0
  59. package/dist/sw.js.map +1 -0
  60. package/dist/workbox-9c191d2f.js +3 -0
  61. package/dist/workbox-9c191d2f.js.map +1 -0
  62. package/dist/zenith.svg +9 -0
  63. package/package.json +60 -0
@@ -0,0 +1,14 @@
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{$n as t,Bt as n,C as r,Dn as i,Et as a,J as o,Jt as s,Ln as c,Lt as l,Mn as u,Mt as d,O as f,Ot as p,Q as m,R as h,Rn as g,T as _,Wt as ee,Zt as v,an as y,cn as te,d as b,fn as x,gt as ne,ir as S,l as C,mt as w,pt as T,rr as E,sn as D,un as O,vr as k,xr as A}from"./vendor-react-DQVTOTFO.js";import{a as re,o as j,t as M}from"./utils-fgvbH6CB.js";import{p as ie}from"./index-ChcKY5Xe.js";import{t as ae}from"./useUnsavedGuard-CMMKQT9a.js";var N=e(A(),1),P=k(),F=[{value:`text`,label:`Text`,icon:l,color:`#6b7280`},{value:`textarea`,label:`Textarea`,icon:i,color:`#6b7280`},{value:`number`,label:`Number`,icon:p,color:`#3b82f6`},{value:`email`,label:`Email`,icon:d,color:`var(--z-accent)`},{value:`password`,label:`Password`,icon:T,color:`#ef4444`},{value:`checkbox`,label:`Checkbox / Boolean`,icon:_,color:`var(--z-accent)`},{value:`date`,label:`Date`,icon:O,color:`#f59e0b`},{value:`select`,label:`Select / Enum`,icon:w,color:`#f97316`},{value:`media`,label:`Media / Image`,icon:a,color:`#06b6d4`},{value:`richtext`,label:`Rich Text`,icon:l,color:`#84cc16`},{value:`relation`,label:`Relation`,icon:ne,color:`#ec4899`},{value:`json`,label:`JSON Object`,icon:t,color:`#6366f1`},{value:`slug`,label:`Slug`,icon:f,color:`var(--z-accent)`},{value:`array`,label:`Array / Repeater`,icon:g,color:`#f59e0b`},{value:`blocks`,label:`Dynamic Blocks`,icon:x,color:`var(--z-accent)`},{value:`group`,label:`Field Group`,icon:h,color:`#3b82f6`},{value:`code`,label:`Code Editor`,icon:v,color:`#6b7280`},{value:`color`,label:`Color Picker`,icon:n,color:`#f97316`}],I={drafts:!0,timestamps:!0,versions:!1,publicRead:!1,singleton:!1,auth:!1,softDelete:!1};function L(e){return e.toLowerCase().replace(/\s+/g,`-`).replace(/[^a-z0-9-]/g,``)}function R({value:e,onChange:t,theme:n}){let[r,i]=(0,N.useState)(!1),a=F.find(t=>t.value===e),o=a?.icon||l;return(0,P.jsxs)(`div`,{className:`relative`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>i(!r),className:M(`flex items-center gap-2 px-3 py-2 border text-sm font-semibold transition-all w-full shadow-sm rounded-none`,`z-card-interactive`),children:[(0,P.jsx)(o,{size:12,style:{color:a?.color}}),(0,P.jsx)(`span`,{className:`flex-1 text-left`,children:a?.label||`Select type`}),(0,P.jsx)(D,{size:10,className:`text-z-secondary`})]}),(0,P.jsx)(S,{children:r&&(0,P.jsx)(E.div,{initial:{opacity:0,y:4},animate:{opacity:1,y:0},exit:{opacity:0,y:4},className:M(`absolute z-50 top-full left-0 mt-1 w-64 border shadow-sm max-h-72 overflow-y-auto rounded-none`,n===`dark`?`bg-z-popover backdrop-blur-xl border-z-border`:`bg-z-panel border-z-border`),children:F.map(r=>{let a=r.icon;return(0,P.jsxs)(`button`,{type:`button`,onClick:()=>{t(r.value),i(!1)},className:M(`w-full flex items-center gap-3 px-4 py-2.5 text-sm font-semibold transition-all rounded-none`,e===r.value?`bg-z-accent text-z-logo-text`:n===`dark`?`text-z-muted hover:bg-z-hover hover:text-z-primary`:`text-z-secondary hover:bg-[var(--z-bg-input)]`),children:[(0,P.jsx)(a,{size:12,style:{color:e===r.value?`white`:r.color}}),r.label]},r.value)})})})]})}function z({fields:e,onUpdate:t,theme:n,availableCollections:i}){let a=()=>{t([...e,{name:`nestedField${e.length+1}`,type:`text`,label:`Nested Field ${e.length+1}`}])},o=n=>{t(e.filter((e,t)=>t!==n))},s=(n,r,i)=>{let a=[...e];a[n]={...a[n],[r]:i},t(a)},c=M(`border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2 px-3 rounded-none shadow-sm`,`z-input`);return(0,P.jsxs)(`div`,{className:`mt-4 border-l-2 border-z-accent/50 pl-4 space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,P.jsxs)(`h4`,{className:`text-sm font-bold text-z-primary`,children:[`Nested Fields (`,e.length,`)`]}),(0,P.jsxs)(`button`,{onClick:a,type:`button`,className:`flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border border-z-border text-z-secondary text-sm font-semibold rounded-none transition-all`,children:[(0,P.jsx)(m,{size:12}),` Add Field`]})]}),e.length===0?(0,P.jsx)(`div`,{className:`p-4 border border-dashed border-z-border text-center text-z-secondary text-sm`,children:`No nested fields added yet.`}):(0,P.jsx)(`div`,{className:`space-y-4`,children:e.map((e,t)=>(0,P.jsxs)(`div`,{className:`p-4 relative group border border-z-border bg-z-panel`,children:[(0,P.jsx)(`button`,{type:`button`,onClick:()=>o(t),className:`absolute top-2 right-2 opacity-0 group-hover:opacity-100 p-1 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10 z-10`,children:(0,P.jsx)(r,{size:12})}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-6`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Field Name (key)`}),(0,P.jsx)(`input`,{type:`text`,value:e.name,onChange:e=>s(t,`name`,e.target.value.replace(/\s+/g,`_`).replace(/[^a-zA-Z0-9_]/g,``)),className:M(c,`w-full rounded-none font-mono text-xs`),placeholder:`fieldName`})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Field Type`}),(0,P.jsx)(R,{value:e.type,onChange:e=>s(t,`type`,e),theme:n})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Display Label`}),(0,P.jsx)(`input`,{type:`text`,value:e.label||``,onChange:e=>s(t,`label`,e.target.value),className:M(c,`w-full rounded-none text-xs`),placeholder:`Human readable label`})]})]}),(0,P.jsx)(B,{field:e,onUpdate:(e,n)=>s(t,e,n),theme:n,availableCollections:i})]},t))})]})}function B({field:e,onUpdate:t,theme:n,availableCollections:r}){let[i,a]=(0,N.useState)(!1),o=M(`w-full border p-2 text-sm font-mono outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors rounded-none shadow-sm`,`z-input`),s=`accent-gray-500 w-3.5 h-3.5`,c=`text-sm font-semibold text-z-secondary`;return(0,P.jsxs)(`div`,{className:`mt-2`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>a(!i),className:`flex items-center gap-1.5 text-sm font-semibold text-z-secondary hover:text-z-secondary transition-colors`,children:[i?(0,P.jsx)(D,{size:10}):(0,P.jsx)(y,{size:10}),`Advanced Options`]}),(0,P.jsx)(S,{children:i&&(0,P.jsx)(E.div,{initial:{height:0,opacity:0},animate:{height:`auto`,opacity:1},exit:{height:0,opacity:0},className:`overflow-hidden`,children:(0,P.jsxs)(`div`,{className:M(`mt-3 p-4 border space-y-4 rounded-none shadow-sm`,`z-panel shadow-sm`),children:[(0,P.jsx)(`div`,{className:`flex flex-wrap gap-x-6 gap-y-2`,children:[[`required`,`Required`],[`unique`,`Unique`],[`index`,`Index`],[`hidden`,`Hidden`],[`readOnly`,`Read Only`]].map(([n,r])=>(0,P.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,P.jsx)(`input`,{type:`checkbox`,checked:!!e[n],onChange:e=>t(n,e.target.checked),className:s}),(0,P.jsx)(`span`,{className:c,children:r})]},n))}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Placeholder`}),(0,P.jsx)(`input`,{type:`text`,value:e.placeholder||``,onChange:e=>t(`placeholder`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Default Value`}),(0,P.jsx)(`input`,{type:`text`,value:e.defaultValue??``,onChange:e=>t(`defaultValue`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Description`}),(0,P.jsx)(`input`,{type:`text`,value:e.description||``,onChange:e=>t(`description`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Width (e.g. 50%)`}),(0,P.jsx)(`input`,{type:`text`,value:e.width||``,onChange:e=>t(`width`,e.target.value),className:o})]}),(e.type===`text`||e.type===`textarea`)&&(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Min Length`}),(0,P.jsx)(`input`,{type:`number`,value:e.min??``,onChange:e=>t(`min`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Max Length`}),(0,P.jsx)(`input`,{type:`number`,value:e.max??``,onChange:e=>t(`max`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{className:`col-span-2`,children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Regex Pattern`}),(0,P.jsx)(`input`,{type:`text`,value:e.regex||``,onChange:e=>t(`regex`,e.target.value),className:o,placeholder:`^[a-z]+$`})]})]}),e.type===`number`&&(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Min`}),(0,P.jsx)(`input`,{type:`number`,value:e.min??``,onChange:e=>t(`min`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Max`}),(0,P.jsx)(`input`,{type:`number`,value:e.max??``,onChange:e=>t(`max`,Number(e.target.value)),className:o})]})]})]}),e.type===`relation`&&(0,P.jsxs)(`div`,{className:`space-y-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Relates To Collection`}),(0,P.jsxs)(`select`,{value:e.relationTo||``,onChange:e=>t(`relationTo`,e.target.value),className:M(o,`cursor-pointer`),children:[(0,P.jsx)(`option`,{value:``,children:`-- Select Collection --`}),r.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]})]}),(0,P.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,P.jsx)(`input`,{type:`checkbox`,checked:!!e.hasMany,onChange:e=>t(`hasMany`,e.target.checked),className:s}),(0,P.jsx)(`span`,{className:c,children:`Has Many (array of references)`})]})]}),(e.type===`array`||e.type===`group`)&&(0,P.jsx)(z,{fields:e.fields||[],onUpdate:e=>t(`fields`,e),theme:n,availableCollections:r}),e.type===`select`&&(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-2`),children:`Options`}),(0,P.jsxs)(`div`,{className:`space-y-2`,children:[(e.options||[]).map((n,r)=>(0,P.jsxs)(`div`,{className:`flex gap-2`,children:[(0,P.jsx)(`input`,{type:`text`,value:n.label,onChange:n=>{let i=[...e.options||[]];i[r]={...i[r],label:n.target.value},t(`options`,i)},placeholder:`Label`,className:M(o,`flex-1`)}),(0,P.jsx)(`input`,{type:`text`,value:n.value,onChange:n=>{let i=[...e.options||[]];i[r]={...i[r],value:n.target.value},t(`options`,i)},placeholder:`value`,className:M(o,`flex-1 font-mono`)}),(0,P.jsx)(`button`,{type:`button`,onClick:()=>t(`options`,(e.options||[]).filter((e,t)=>t!==r)),className:`p-2 text-red-500/60 hover:text-red-500 transition-colors`,children:(0,P.jsx)(b,{size:12})})]},r)),(0,P.jsxs)(`button`,{type:`button`,onClick:()=>t(`options`,[...e.options||[],{label:``,value:``}]),className:`flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary`,children:[(0,P.jsx)(m,{size:10}),` Add Option`]})]})]})]})})})]})}function V(){let{theme:e}=re(),t=e===`dark`,[n,i]=(0,N.useState)(`New Collection`),[a,l]=(0,N.useState)(`new-collection`),[d,f]=(0,N.useState)([]),[p,h]=(0,N.useState)(I),[_,y]=(0,N.useState)([]),[x,ne]=(0,N.useState)(!0),[w,D]=(0,N.useState)(null),O=_.find(e=>(e._id||e.id)===w),k=O?.isCodeFirst,[A,F]=(0,N.useState)(!1),[z,V]=(0,N.useState)(!1),[oe,H]=(0,N.useState)(!1),[se,U]=(0,N.useState)(!1),[W,ce]=(0,N.useState)(``),[G,K]=(0,N.useState)(!1),[q,le]=(0,N.useState)(``),[J,ue]=(0,N.useState)(!1),[de,Y]=(0,N.useState)(!1),[fe,pe]=(0,N.useState)([]),[me,he]=(0,N.useState)(!1);(0,N.useEffect)(()=>{let e=JSON.stringify({slug:a,collectionName:n,fields:d,settings:p});he(O?e!==JSON.stringify({slug:O.slug,collectionName:O.plural||O.slug,fields:O.fields||[],settings:{...I,...O.settings||{}}}):e!==JSON.stringify({slug:`new-collection`,collectionName:`New Collection`,fields:[],settings:I}))},[a,n,d,p,O]),ae({hasUnsavedChanges:me});let X=(0,N.useCallback)(async()=>{try{let[e,t]=await Promise.all([j.get(`/schemas`).catch(()=>({data:{data:[]}})),j.get(`/system/schemas`).catch(()=>({data:{data:{collections:[]}}}))]),n=e.data?.data,r=Array.isArray(n)?n:Array.isArray(n?.schemas)?n.schemas:[],i=t.data?.data?.collections||[],a=Array.isArray(i)?i.map(e=>({...e,id:e.slug,isCodeFirst:!0})):[],o=new Map;for(let e of[...r,...a])o.set(e.slug,e);y(Array.from(o.values()).sort((e,t)=>e.slug.localeCompare(t.slug)))}catch{y([])}finally{ne(!1)}},[]);(0,N.useEffect)(()=>{X(),j.get(`/schemas`).then(e=>{let t=e.data?.data;pe((Array.isArray(t?.collections)?t.collections:Array.isArray(t)?t:[]).map(e=>e.slug).filter(Boolean))}).catch(()=>{})},[X]);let ge=e=>{D(e._id||e.id||null),i(e.plural||e.slug),l(e.slug),f(e.fields||[]),h({...I,...e.settings||{}}),C.success(`Loaded schema: ${e.slug}`)},Z=()=>{D(null),i(`New Collection`),l(`new-collection`),f([]),h(I)},_e=()=>{f(e=>[...e,{name:`field${e.length+1}`,type:`text`,label:`Field ${e.length+1}`}])},ve=e=>{f(t=>t.filter((t,n)=>n!==e))},Q=(e,t,n)=>{f(r=>{let i=[...r];return i[e]={...i[e],[t]:n},i})},ye=async()=>{if(!a||!n)return C.error(`Name and slug required`);F(!0);try{let e={slug:a,singular:n,plural:n,fields:d,settings:p};if(w)await j.put(`/schemas/${w}`,e),C.success(`Schema updated!`);else{let t=await j.post(`/schemas`,e),n=t.data?.data?._id||t.data?.data?.id;n&&D(n),C.success(`Schema created!`)}await X(),await j.post(`/system/schema/reload`).catch(()=>{})}catch(e){C.error(e.response?.data?.error?.message||`Failed to save schema`)}finally{F(!1)}},be=async(e,t)=>{try{await j.delete(`/schemas/${e}`),C.success(`Schema "${t}" deleted`),w===e&&Z(),await X()}catch{C.error(`Failed to delete schema`)}},xe=async()=>{if(!W)return C.error(`Please provide a connection string`);K(!0);try{let e=(await j.post(`/system/introspect`,{connectionString:W})).data.data;if(e?.length>0){let t=e[0];i(t.name),l(L(t.name)),f(t.fields||[]),C.success(`Introspected: ${t.name}`),U(!1)}else C.error(`No tables found`)}catch(e){C.error(e.response?.data?.error||`Introspection failed`)}finally{K(!1)}},Se=async()=>{if(!q)return C.error(`Enter a prompt first`);ue(!0);try{let e=(await j.post(`/system/ai-architect`,{prompt:q})).data?.data;e&&(i(e.name||e.slug||`AI Collection`),l(e.slug||L(e.name||`ai-collection`)),f(e.fields||[]),C.success(`AI schema generated!`),Y(!1))}catch(e){C.error(e.response?.data?.error?.message||`AI generation failed`)}finally{ue(!1)}},Ce=()=>{let e=d.map(e=>{let t=` name: '${e.name}',\n type: '${e.type}',`;return e.label&&(t+=`\n label: '${e.label}',`),e.required&&(t+=`
2
+ required: true,`),e.unique&&(t+=`
3
+ unique: true,`),e.relationTo&&(t+=`\n relationTo: '${e.relationTo}',`),e.options?.length&&(t+=`\n options: ${JSON.stringify(e.options)},`),` {\n${t}\n },`}).join(`
4
+ `),t=Object.entries(p).filter(([,e])=>e===!0).map(([e])=>` ${e}: true,`).join(`
5
+ `);return`import { CollectionConfig } from '@zenith-open/zenithcms-types'
6
+
7
+ export const ${n.replace(/\s+/g,``)}: CollectionConfig = {
8
+ name: '${n}',
9
+ slug: '${a}',
10
+ ${t?t+`
11
+ `:``} fields: [
12
+ ${e}
13
+ ],
14
+ }`},$=M(`border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2.5 px-3 rounded-none shadow-sm`,`z-input`);return(0,P.jsxs)(`div`,{className:M(`flex h-[calc(100vh-4rem)] overflow-hidden`,t?`bg-app text-z-primary`:`bg-[var(--z-bg-input)] text-z-primary`),children:[(0,P.jsxs)(`div`,{className:M(`w-64 flex-shrink-0 border-r flex flex-col`,`border-z-border bg-z-panel`),children:[(0,P.jsxs)(`div`,{className:`p-4 border-b border-inherit flex items-center justify-between`,children:[(0,P.jsx)(`h2`,{className:`text-sm font-bold text-z-primary`,children:`Schemas`}),(0,P.jsx)(`button`,{onClick:Z,className:`p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors`,title:`New Schema`,children:(0,P.jsx)(m,{size:14})})]}),(0,P.jsx)(`div`,{className:`flex-1 overflow-auto p-2 space-y-1`,children:x?(0,P.jsx)(`div`,{className:`p-4 flex justify-center`,children:(0,P.jsx)(c,{className:`animate-spin text-z-muted`,size:16})}):_.length===0?(0,P.jsx)(`div`,{className:`p-4 text-center text-sm text-z-secondary`,children:`No schemas yet`}):_.map(e=>{let n=e._id||e.id||``,i=w===n;return(0,P.jsxs)(`div`,{className:`group flex items-center gap-1`,children:[(0,P.jsxs)(`button`,{onClick:()=>ge(e),className:M(`flex-1 flex items-center justify-between text-left px-3 py-2.5 text-sm font-semibold transition-colors rounded-none truncate`,i?`bg-z-accent text-z-logo-text shadow-sm`:t?`text-z-muted hover:bg-z-hover hover:text-z-primary`:`text-z-secondary hover:bg-[var(--z-bg-input)]`),children:[(0,P.jsx)(`span`,{children:e.slug}),e.isCodeFirst&&(0,P.jsx)(T,{size:10,className:i?`text-z-primary`:`text-z-secondary`})]}),!e.isCodeFirst&&(0,P.jsx)(`button`,{onClick:()=>be(n,e.slug),className:`opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all`,children:(0,P.jsx)(r,{size:12})})]},n)})})]}),(0,P.jsxs)(`div`,{className:`flex-1 flex flex-col overflow-hidden`,children:[(0,P.jsx)(ie,{title:`Schema Builder`,backLink:{to:`/`,label:`Dashboard`},actions:(0,P.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,P.jsx)(`button`,{onClick:()=>Y(!0),className:`px-4 py-2 bg-z-active-bg text-z-accent hover:opacity-80 text-sm font-bold rounded-none transition-all`,children:`AI Generate`}),(0,P.jsx)(`button`,{onClick:()=>U(!0),className:`px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all`,children:`Introspect DB`}),(0,P.jsx)(`button`,{onClick:()=>V(!0),className:`px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all`,children:`View Code`}),(0,P.jsx)(`button`,{onClick:ye,disabled:A||k,className:`px-4 py-2 bg-z-accent hover:bg-z-accent/90 text-z-primary text-sm font-bold rounded-none transition-all disabled:opacity-50 disabled:cursor-not-allowed`,children:A?`Saving...`:k?`Locked`:`Save`})]})}),(0,P.jsxs)(`div`,{className:`flex-1 overflow-auto p-6 space-y-6 custom-editor-scrollbar`,children:[k&&(0,P.jsxs)(`div`,{className:`px-4 py-3 border border-amber-500/30 bg-amber-500/10 text-amber-500 text-sm font-bold flex items-center justify-between`,children:[(0,P.jsx)(`span`,{children:`Code-First Schema (Read Only)`}),(0,P.jsx)(T,{size:14})]}),(0,P.jsxs)(`div`,{className:M(`rounded-none border p-6 space-y-4 shadow-sm transition-all`,`z-panel`),children:[(0,P.jsx)(`h3`,{className:`text-sm font-bold text-z-primary`,children:`Collection Settings`}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Display Name`}),(0,P.jsx)(`input`,{type:`text`,value:n,readOnly:k,onChange:e=>{k||(i(e.target.value),l(L(e.target.value)))},className:M($,`w-full rounded-none`,k&&`opacity-70 cursor-not-allowed`),placeholder:`e.g. Blog Posts`})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Slug (API ID)`}),(0,P.jsx)(`input`,{type:`text`,value:a,readOnly:k,onChange:e=>{k||l(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g,``))},className:M($,`w-full rounded-none font-mono`,k&&`opacity-70 cursor-not-allowed`),placeholder:`e.g. blog-posts`})]})]}),(0,P.jsx)(`div`,{className:`flex flex-wrap gap-x-6 gap-y-3 pt-2 border-t border-z-border`,children:Object.keys(I).map(e=>(0,P.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer group`,children:[(0,P.jsx)(`div`,{onClick:()=>{k||h(t=>({...t,[e]:!t[e]}))},className:M(`w-8 h-4 rounded-full relative transition-all cursor-pointer border border-transparent shadow-inner`,p[e]?`bg-z-accent`:t?`bg-gray-700`:`bg-gray-300`,k&&`opacity-50 cursor-not-allowed`),children:(0,P.jsx)(`div`,{className:M(`absolute top-[1.5px] w-3 h-3 rounded-full bg-white shadow-sm transition-all`,p[e]?`left-[17px]`:`left-[1.5px]`)})}),(0,P.jsx)(`span`,{className:`text-sm font-bold capitalize text-z-muted group-hover:text-z-primary transition-colors`,children:e.replace(/([A-Z])/g,` $1`).trim()})]},e))})]}),(0,P.jsxs)(`div`,{className:M(`rounded-none border shadow-sm transition-all`,`z-panel`),children:[(0,P.jsxs)(`div`,{className:`px-6 py-4 border-b border-inherit flex items-center justify-between`,children:[(0,P.jsxs)(`h3`,{className:`text-sm font-bold text-z-primary`,children:[`Fields (`,d.length,`)`]}),!k&&(0,P.jsxs)(`button`,{onClick:_e,className:`flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary text-sm font-semibold rounded-none transition-all`,children:[(0,P.jsx)(m,{size:12}),` Add Field`]})]}),(0,P.jsxs)(`div`,{className:`p-4 space-y-3`,children:[(0,P.jsx)(S,{children:d.map((t,n)=>(0,P.jsxs)(E.div,{layout:!0,initial:{opacity:0,y:8},animate:{opacity:1,y:0},exit:{opacity:0,scale:.97},className:M(`p-4 relative group z-panel`,k&&`opacity-70`),children:[!k&&(0,P.jsx)(`button`,{onClick:()=>ve(n),className:`absolute top-3 right-3 opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10`,children:(0,P.jsx)(r,{size:14})}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-8`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Field Name (key)`}),(0,P.jsx)(`input`,{type:`text`,value:t.name,readOnly:k,onChange:e=>{k||Q(n,`name`,e.target.value.replace(/\s+/g,`_`).replace(/[^a-zA-Z0-9_]/g,``))},className:M($,`w-full rounded-none-none font-mono text-sm`,k&&`cursor-not-allowed`),placeholder:`fieldName`})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Field Type`}),(0,P.jsx)(`div`,{className:M(k&&`opacity-70 pointer-events-none`),children:(0,P.jsx)(R,{value:t.type,onChange:e=>Q(n,`type`,e),theme:e})})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Display Label`}),(0,P.jsx)(`input`,{type:`text`,value:t.label||``,readOnly:k,onChange:e=>{k||Q(n,`label`,e.target.value)},className:M($,`w-full rounded-none-none`,k&&`cursor-not-allowed`),placeholder:`Human readable label`})]})]}),(0,P.jsx)(`div`,{className:`flex items-center gap-5 mt-3 pt-2 border-t border-z-border`,children:[[`required`,`Required`],[`unique`,`Unique`],[`index`,`Index`]].map(([e,r])=>(0,P.jsxs)(`label`,{className:`flex items-center gap-1.5 cursor-pointer`,children:[(0,P.jsx)(`input`,{type:`checkbox`,checked:!!t[e],disabled:k,onChange:t=>{k||Q(n,e,t.target.checked)},className:`accent-gray-500 w-3 h-3 disabled:opacity-50 disabled:cursor-not-allowed`}),(0,P.jsx)(`span`,{className:`text-sm font-semibold text-z-secondary`,children:r})]},e))}),!k&&(0,P.jsx)(B,{field:t,onUpdate:(e,t)=>Q(n,e,t),theme:e,availableCollections:fe})]},n))}),d.length===0&&(0,P.jsxs)(`div`,{className:`py-16 text-center`,children:[(0,P.jsx)(g,{size:40,className:`mx-auto text-z-primary mb-4`,strokeWidth:1}),(0,P.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary`,children:`No fields yet`}),(0,P.jsx)(`p`,{className:`text-sm text-z-secondary mt-1`,children:`Click "Add Field" or use AI Generate to get started`})]})]})]})]})]}),(0,P.jsx)(S,{children:z&&(0,P.jsx)(E.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:`fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4`,children:(0,P.jsxs)(E.div,{initial:{scale:.95},animate:{scale:1},exit:{scale:.95},className:`w-full max-w-3xl border rounded-none-none shadow-2xl p-6 relative flex flex-col h-[80vh] bg-app border-z-border`,children:[(0,P.jsx)(`button`,{onClick:()=>V(!1),className:`absolute top-4 right-4 text-z-secondary hover:text-z-primary`,children:(0,P.jsx)(b,{size:20})}),(0,P.jsxs)(`h2`,{className:`text-xl font-semibold mb-4 flex items-center gap-3`,children:[(0,P.jsx)(v,{className:`text-z-secondary `}),` Generated TypeScript`]}),(0,P.jsxs)(`div`,{className:`flex-1 bg-[#1E1E1E] border border-z-border p-5 overflow-auto text-sm font-mono text-z-secondary relative rounded-none-none`,children:[(0,P.jsx)(`button`,{onClick:()=>{navigator.clipboard.writeText(Ce()),H(!0),setTimeout(()=>H(!1),2e3)},className:`absolute top-3 right-3 p-2 bg-z-panel/10 hover:bg-z-panel/20 text-z-primary transition-colors rounded-none-none`,children:oe?(0,P.jsx)(te,{size:14}):(0,P.jsx)(s,{size:14})}),(0,P.jsx)(`pre`,{children:(0,P.jsx)(`code`,{children:Ce()})})]})]})})}),(0,P.jsx)(S,{children:de&&(0,P.jsx)(E.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:`fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4`,children:(0,P.jsxs)(E.div,{initial:{scale:.95},animate:{scale:1},exit:{scale:.95},className:`w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border`,children:[(0,P.jsx)(`button`,{onClick:()=>Y(!1),className:`absolute top-4 right-4 text-z-secondary hover:text-z-primary`,children:(0,P.jsx)(b,{size:20})}),(0,P.jsxs)(`h2`,{className:`text-xl font-semibold mb-2 flex items-center gap-3`,children:[(0,P.jsx)(u,{className:`text-purple-400`}),` AI Schema Architect`]}),(0,P.jsx)(`p`,{className:`text-sm text-z-muted mb-5 font-medium`,children:`Describe what you need — the AI will generate a complete schema with fields, types, and relations.`}),(0,P.jsx)(`textarea`,{rows:4,value:q,onChange:e=>le(e.target.value),placeholder:`e.g. "A blog post collection with title, slug, content, featured image, author relation to users, published date, and category select field with options."`,className:`w-full bg-app border border-z-border focus:border-z-active-border/50 p-4 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary resize-none mb-4`}),(0,P.jsx)(`button`,{disabled:J||!q,onClick:Se,className:`w-full py-3.5 bg-z-accent hover:opacity-80 text-z-logo-text text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none disabled:opacity-50`,children:J?(0,P.jsxs)(P.Fragment,{children:[(0,P.jsx)(c,{size:14,className:`animate-spin`}),` Generating...`]}):(0,P.jsxs)(P.Fragment,{children:[(0,P.jsx)(u,{size:14}),` Generate Schema`]})})]})})}),(0,P.jsx)(S,{children:se&&(0,P.jsx)(E.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:`fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4`,children:(0,P.jsxs)(E.div,{initial:{scale:.95},animate:{scale:1},exit:{scale:.95},className:`w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border`,children:[(0,P.jsx)(`button`,{onClick:()=>U(!1),className:`absolute top-4 right-4 text-z-secondary hover:text-z-primary`,children:(0,P.jsx)(b,{size:20})}),(0,P.jsxs)(`h2`,{className:`text-xl font-semibold mb-2 flex items-center gap-3`,children:[(0,P.jsx)(ee,{className:`text-z-secondary `}),` DB Introspection`]}),(0,P.jsx)(`p`,{className:`text-sm text-z-muted mb-5 font-medium`,children:`Connect to a Postgres database to reverse-engineer tables into Zenith schema fields.`}),(0,P.jsx)(`input`,{type:`text`,placeholder:`postgresql://user:password@localhost:5432/mydb`,value:W,onChange:e=>ce(e.target.value),className:`w-full bg-app border border-z-border focus:border-z-border/50 p-3.5 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary mb-4 font-mono`}),(0,P.jsx)(`button`,{disabled:G,onClick:xe,className:`w-full py-3.5 bg-z-border hover:bg-z-input text-z-primary text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none`,children:G?(0,P.jsxs)(P.Fragment,{children:[(0,P.jsx)(c,{size:14,className:`animate-spin`}),` Scanning...`]}):(0,P.jsxs)(P.Fragment,{children:[(0,P.jsx)(o,{size:14}),` Analyze Database`]})})]})})})]})}export{V as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaBuilderPage-EFA5XIAa.js","names":[],"sources":["../../src/pages/SchemaBuilderPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n Plus, Database, Code, Copy, Check, Trash2, Box, Layers, Settings, X,\n Save, Loader2, ChevronDown, ChevronRight, Sparkles, RefreshCw, List,\n AlertCircle, Eye, EyeOff, Hash, Globe, Lock, Calendar, FileText,\n Image, Link2, ToggleLeft, AlignLeft, Braces, Tag\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\nimport { cn } from '../lib/utils'\nimport { useUnsavedGuard } from '../hooks/useUnsavedGuard'\n\n// ── Full field type catalogue ────────────────────────────────────────────────\nconst FIELD_TYPES = [\n { value: 'text', label: 'Text', icon: FileText, color: '#6b7280' },\n { value: 'textarea', label: 'Textarea', icon: AlignLeft, color: '#6b7280' },\n { value: 'number', label: 'Number', icon: Hash, color: '#3b82f6' },\n { value: 'email', label: 'Email', icon: Globe, color: 'var(--z-accent)' },\n { value: 'password', label: 'Password', icon: Lock, color: '#ef4444' },\n { value: 'checkbox', label: 'Checkbox / Boolean', icon: ToggleLeft, color: 'var(--z-accent)' },\n { value: 'date', label: 'Date', icon: Calendar, color: '#f59e0b' },\n { value: 'select', label: 'Select / Enum', icon: List, color: '#f97316' },\n { value: 'media', label: 'Media / Image', icon: Image, color: '#06b6d4' },\n { value: 'richtext', label: 'Rich Text', icon: FileText, color: '#84cc16' },\n { value: 'relation', label: 'Relation', icon: Link2, color: '#ec4899' },\n { value: 'json', label: 'JSON Object', icon: Braces, color: '#6366f1' },\n { value: 'slug', label: 'Slug', icon: Tag, color: 'var(--z-accent)' },\n { value: 'array', label: 'Array / Repeater', icon: Layers, color: '#f59e0b' },\n { value: 'blocks', label: 'Dynamic Blocks', icon: Box, color: 'var(--z-accent)' },\n { value: 'group', label: 'Field Group', icon: Settings, color: '#3b82f6' },\n { value: 'code', label: 'Code Editor', icon: Code, color: '#6b7280' },\n { value: 'color', label: 'Color Picker', icon: Eye, color: '#f97316' },\n] as const\n\ntype FieldType = typeof FIELD_TYPES[number]['value']\n\ninterface FieldConfig {\n name: string\n type: FieldType\n label?: string\n required?: boolean\n unique?: boolean\n index?: boolean\n hidden?: boolean\n readOnly?: boolean\n placeholder?: string\n description?: string\n defaultValue?: any\n min?: number\n max?: number\n regex?: string\n width?: string\n // select options\n options?: { label: string; value: string }[]\n // relation\n relationTo?: string\n hasMany?: boolean\n // array sub-fields\n fields?: FieldConfig[]\n}\n\ninterface CollectionSettings {\n drafts: boolean\n timestamps: boolean\n versions: boolean\n publicRead: boolean\n singleton: boolean\n auth: boolean\n softDelete: boolean\n}\n\ninterface SavedSchema {\n _id?: string\n id?: string\n slug: string\n singular?: string\n plural?: string\n fields?: FieldConfig[]\n settings?: CollectionSettings\n createdAt?: string\n isCodeFirst?: boolean\n}\n\nconst DEFAULT_SETTINGS: CollectionSettings = {\n drafts: true,\n timestamps: true,\n versions: false,\n publicRead: false,\n singleton: false,\n auth: false,\n softDelete: false,\n}\n\n// ── Helper ────────────────────────────────────────────────────────────────────\nfunction makeSlug(name: string): string {\n return name.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')\n}\n\n// ── Field Type Picker ─────────────────────────────────────────────────────────\nfunction FieldTypePicker({ value, onChange, theme }: { value: FieldType; onChange: (t: FieldType) => void; theme: string }) {\n const [open, setOpen] = useState(false)\n const current = FIELD_TYPES.find(t => t.value === value)\n const Icon = current?.icon || FileText\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 border text-sm font-semibold transition-all w-full shadow-sm rounded-none',\n 'z-card-interactive'\n )}\n >\n <Icon size={12} style={{ color: current?.color }} />\n <span className=\"flex-1 text-left\">{current?.label || 'Select type'}</span>\n <ChevronDown size={10} className=\"text-z-secondary\" />\n </button>\n <AnimatePresence>\n {open && (\n <motion.div\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 4 }}\n className={cn(\n 'absolute z-50 top-full left-0 mt-1 w-64 border shadow-sm max-h-72 overflow-y-auto rounded-none',\n theme === 'dark' ? 'bg-z-popover backdrop-blur-xl border-z-border' : 'bg-z-panel border-z-border'\n )}\n >\n {FIELD_TYPES.map(ft => {\n const FtIcon = ft.icon\n return (\n <button\n key={ft.value}\n type=\"button\"\n onClick={() => { onChange(ft.value); setOpen(false) }}\n className={cn(\n 'w-full flex items-center gap-3 px-4 py-2.5 text-sm font-semibold transition-all rounded-none',\n value === ft.value\n ? 'bg-z-accent text-z-logo-text'\n : theme === 'dark' ? 'text-z-muted hover:bg-z-hover hover:text-z-primary' : 'text-z-secondary hover:bg-[var(--z-bg-input)]'\n )}\n >\n <FtIcon size={12} style={{ color: value === ft.value ? 'white' : ft.color }} />\n {ft.label}\n </button>\n )\n })}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n\n\n\n// ── Nested Fields Editor ──────────────────────────────────────────────────────\nfunction NestedFieldsEditor({\n fields, onUpdate, theme, availableCollections\n}: {\n fields: FieldConfig[]\n onUpdate: (fields: FieldConfig[]) => void\n theme: string\n availableCollections: string[]\n}) {\n const addField = () => {\n onUpdate([...fields, { name: `nestedField${fields.length + 1}`, type: 'text', label: `Nested Field ${fields.length + 1}` }])\n }\n \n const removeField = (index: number) => {\n onUpdate(fields.filter((_, i) => i !== index))\n }\n\n const updateField = (index: number, key: string, value: any) => {\n const next = [...fields]\n next[index] = { ...next[index], [key]: value }\n onUpdate(next)\n }\n\n const inputClass = cn(\n 'border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2 px-3 rounded-none shadow-sm',\n 'z-input'\n )\n\n return (\n <div className=\"mt-4 border-l-2 border-z-accent/50 pl-4 space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h4 className=\"text-sm font-bold text-z-primary\">Nested Fields ({fields.length})</h4>\n <button\n onClick={addField}\n type=\"button\"\n className=\"flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border border-z-border text-z-secondary text-sm font-semibold rounded-none transition-all\"\n >\n <Plus size={12} /> Add Field\n </button>\n </div>\n \n {fields.length === 0 ? (\n <div className=\"p-4 border border-dashed border-z-border text-center text-z-secondary text-sm\">\n No nested fields added yet.\n </div>\n ) : (\n <div className=\"space-y-4\">\n {fields.map((field, i) => (\n <div key={i} className=\"p-4 relative group border border-z-border bg-z-panel\">\n <button\n type=\"button\"\n onClick={() => removeField(i)}\n className=\"absolute top-2 right-2 opacity-0 group-hover:opacity-100 p-1 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10 z-10\"\n >\n <Trash2 size={12} />\n </button>\n \n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-6\">\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Field Name (key)</label>\n <input\n type=\"text\"\n value={field.name}\n onChange={e => updateField(i, 'name', e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''))}\n className={cn(inputClass, 'w-full rounded-none font-mono text-xs')}\n placeholder=\"fieldName\"\n />\n </div>\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Field Type</label>\n <FieldTypePicker\n value={field.type}\n onChange={v => updateField(i, 'type', v)}\n theme={theme}\n />\n </div>\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Display Label</label>\n <input\n type=\"text\"\n value={field.label || ''}\n onChange={e => updateField(i, 'label', e.target.value)}\n className={cn(inputClass, 'w-full rounded-none text-xs')}\n placeholder=\"Human readable label\"\n />\n </div>\n </div>\n \n <FieldAdvancedPanel\n field={field}\n onUpdate={(key, value) => updateField(i, key, value)}\n theme={theme}\n availableCollections={availableCollections}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ── Advanced Field Panel ──────────────────────────────────────────────────────\nfunction FieldAdvancedPanel({\n field, onUpdate, theme, availableCollections\n}: {\n field: FieldConfig\n onUpdate: (key: string, value: any) => void\n theme: string\n availableCollections: string[]\n}) {\n const [open, setOpen] = useState(false)\n const inputClass = cn(\n 'w-full border p-2 text-sm font-mono outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors rounded-none shadow-sm',\n 'z-input'\n )\n const checkClass = 'accent-gray-500 w-3.5 h-3.5'\n const labelClass = 'text-sm font-semibold text-z-secondary'\n\n return (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className=\"flex items-center gap-1.5 text-sm font-semibold text-z-secondary hover:text-z-secondary transition-colors\"\n >\n {open ? <ChevronDown size={10} /> : <ChevronRight size={10} />}\n Advanced Options\n </button>\n <AnimatePresence>\n {open && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n className=\"overflow-hidden\"\n >\n <div className={cn('mt-3 p-4 border space-y-4 rounded-none shadow-sm', 'z-panel shadow-sm')}>\n {/* Flags */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-2\">\n {[\n ['required', 'Required'],\n ['unique', 'Unique'],\n ['index', 'Index'],\n ['hidden', 'Hidden'],\n ['readOnly', 'Read Only'],\n ].map(([key, lbl]) => (\n <label key={key} className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!(field as any)[key]}\n onChange={e => onUpdate(key, e.target.checked)}\n className={checkClass}\n />\n <span className={labelClass}>{lbl}</span>\n </label>\n ))}\n </div>\n\n {/* Text inputs */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Placeholder</label>\n <input type=\"text\" value={field.placeholder || ''} onChange={e => onUpdate('placeholder', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Default Value</label>\n <input type=\"text\" value={field.defaultValue ?? ''} onChange={e => onUpdate('defaultValue', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Description</label>\n <input type=\"text\" value={field.description || ''} onChange={e => onUpdate('description', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Width (e.g. 50%)</label>\n <input type=\"text\" value={field.width || ''} onChange={e => onUpdate('width', e.target.value)} className={inputClass} />\n </div>\n {(field.type === 'text' || field.type === 'textarea') && (\n <>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Min Length</label>\n <input type=\"number\" value={field.min ?? ''} onChange={e => onUpdate('min', Number(e.target.value))} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Max Length</label>\n <input type=\"number\" value={field.max ?? ''} onChange={e => onUpdate('max', Number(e.target.value))} className={inputClass} />\n </div>\n <div className=\"col-span-2\">\n <label className={cn(labelClass, 'block mb-1')}>Regex Pattern</label>\n <input type=\"text\" value={field.regex || ''} onChange={e => onUpdate('regex', e.target.value)} className={inputClass} placeholder=\"^[a-z]+$\" />\n </div>\n </>\n )}\n {field.type === 'number' && (\n <>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Min</label>\n <input type=\"number\" value={field.min ?? ''} onChange={e => onUpdate('min', Number(e.target.value))} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Max</label>\n <input type=\"number\" value={field.max ?? ''} onChange={e => onUpdate('max', Number(e.target.value))} className={inputClass} />\n </div>\n </>\n )}\n </div>\n\n {/* Relation options */}\n {field.type === 'relation' && (\n <div className=\"space-y-3\">\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Relates To Collection</label>\n <select\n value={field.relationTo || ''}\n onChange={e => onUpdate('relationTo', e.target.value)}\n className={cn(inputClass, 'cursor-pointer')}\n >\n <option value=\"\">-- Select Collection --</option>\n {availableCollections.map(col => (\n <option key={col} value={col}>{col}</option>\n ))}\n </select>\n </div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!field.hasMany}\n onChange={e => onUpdate('hasMany', e.target.checked)}\n className={checkClass}\n />\n <span className={labelClass}>Has Many (array of references)</span>\n </label>\n </div>\n )}\n\n {/* Nested fields for array/group */}\n {(field.type === 'array' || field.type === 'group') && (\n <NestedFieldsEditor\n fields={field.fields || []}\n onUpdate={newFields => onUpdate('fields', newFields)}\n theme={theme}\n availableCollections={availableCollections}\n />\n )}\n\n {/* Select options editor */}\n {field.type === 'select' && (\n <div>\n <label className={cn(labelClass, 'block mb-2')}>Options</label>\n <div className=\"space-y-2\">\n {(field.options || []).map((opt, oi) => (\n <div key={oi} className=\"flex gap-2\">\n <input\n type=\"text\"\n value={opt.label}\n onChange={e => {\n const newOpts = [...(field.options || [])]\n newOpts[oi] = { ...newOpts[oi], label: e.target.value }\n onUpdate('options', newOpts)\n }}\n placeholder=\"Label\"\n className={cn(inputClass, 'flex-1')}\n />\n <input\n type=\"text\"\n value={opt.value}\n onChange={e => {\n const newOpts = [...(field.options || [])]\n newOpts[oi] = { ...newOpts[oi], value: e.target.value }\n onUpdate('options', newOpts)\n }}\n placeholder=\"value\"\n className={cn(inputClass, 'flex-1 font-mono')}\n />\n <button\n type=\"button\"\n onClick={() => onUpdate('options', (field.options || []).filter((_, i) => i !== oi))}\n className=\"p-2 text-red-500/60 hover:text-red-500 transition-colors\"\n >\n <X size={12} />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={() => onUpdate('options', [...(field.options || []), { label: '', value: '' }])}\n className=\"flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary\"\n >\n <Plus size={10} /> Add Option\n </button>\n </div>\n </div>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n\n// ── Main Schema Builder Page ──────────────────────────────────────────────────\nexport default function SchemaBuilderPage() {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n // Schema being edited\n const [collectionName, setCollectionName] = useState('New Collection')\n const [slug, setSlug] = useState('new-collection')\n const [fields, setFields] = useState<FieldConfig[]>([])\n const [settings, setSettings] = useState<CollectionSettings>(DEFAULT_SETTINGS)\n\n // Saved schemas list\n const [savedSchemas, setSavedSchemas] = useState<SavedSchema[]>([])\n const [loadingSchemas, setLoadingSchemas] = useState(true)\n const [activeSchemaId, setActiveSchemaId] = useState<string | null>(null)\n\n const activeSchemaObj = savedSchemas.find(s => (s._id || s.id) === activeSchemaId)\n const isCodeFirst = activeSchemaObj?.isCodeFirst\n\n // UI state\n const [saving, setSaving] = useState(false)\n const [showCode, setShowCode] = useState(false)\n const [copied, setCopied] = useState(false)\n const [showIntrospect, setShowIntrospect] = useState(false)\n const [dbUri, setDbUri] = useState('')\n const [isIntrospecting, setIsIntrospecting] = useState(false)\n const [aiPrompt, setAiPrompt] = useState('')\n const [isAIGenerating, setIsAIGenerating] = useState(false)\n const [showAI, setShowAI] = useState(false)\n const [availableCollections, setAvailableCollections] = useState<string[]>([])\n\n // Track unsaved changes\n const [isDirty, setIsDirty] = useState(false)\n useEffect(() => {\n const currentStr = JSON.stringify({ slug, collectionName, fields, settings })\n if (activeSchemaObj) {\n const activeStr = JSON.stringify({\n slug: activeSchemaObj.slug,\n collectionName: activeSchemaObj.plural || activeSchemaObj.slug,\n fields: activeSchemaObj.fields || [],\n settings: { ...DEFAULT_SETTINGS, ...(activeSchemaObj.settings || {}) }\n })\n setIsDirty(currentStr !== activeStr)\n } else {\n const defaultStr = JSON.stringify({\n slug: 'new-collection',\n collectionName: 'New Collection',\n fields: [],\n settings: DEFAULT_SETTINGS\n })\n setIsDirty(currentStr !== defaultStr)\n }\n }, [slug, collectionName, fields, settings, activeSchemaObj])\n\n useUnsavedGuard({ hasUnsavedChanges: isDirty })\n\n // Load saved schemas and collections list\n const loadSchemas = useCallback(async () => {\n try {\n // Fetch both Dynamic UI Schemas and Code-First JSON Schemas\n const [dbRes, systemRes] = await Promise.all([\n api.get('/schemas').catch(() => ({ data: { data: [] } })),\n api.get('/system/schemas').catch(() => ({ data: { data: { collections: [] } } }))\n ])\n\n const rawDb = dbRes.data?.data\n const dbList: SavedSchema[] = Array.isArray(rawDb) ? rawDb : Array.isArray(rawDb?.schemas) ? rawDb.schemas : []\n \n const rawSystem = systemRes.data?.data?.collections || []\n const systemList: SavedSchema[] = Array.isArray(rawSystem) \n ? rawSystem.map(c => ({\n ...c,\n id: c.slug, // Code-First schemas use slug as ID\n isCodeFirst: true\n }))\n : []\n\n // Combine and deduplicate (System Code-First schemas override DB schemas)\n const schemaMap = new Map<string, SavedSchema>()\n for (const s of [...dbList, ...systemList]) {\n schemaMap.set(s.slug, s)\n }\n const combined = Array.from(schemaMap.values()).sort((a, b) => a.slug.localeCompare(b.slug))\n setSavedSchemas(combined)\n } catch {\n setSavedSchemas([])\n } finally {\n setLoadingSchemas(false)\n }\n }, [])\n\n useEffect(() => {\n loadSchemas()\n // Load live collection slugs for relation field picker\n api.get('/schemas').then(res => {\n const d = res.data?.data\n const cols: any[] = Array.isArray(d?.collections) ? d.collections\n : Array.isArray(d) ? d : []\n setAvailableCollections(cols.map((c: any) => c.slug).filter(Boolean))\n }).catch(() => {})\n }, [loadSchemas])\n\n // Load a saved schema into the editor\n const loadSchema = (schema: SavedSchema) => {\n setActiveSchemaId(schema._id || schema.id || null)\n setCollectionName(schema.plural || schema.slug)\n setSlug(schema.slug)\n setFields(schema.fields || [])\n setSettings({ ...DEFAULT_SETTINGS, ...(schema.settings || {}) })\n toast.success(`Loaded schema: ${schema.slug}`)\n }\n\n const resetEditor = () => {\n setActiveSchemaId(null)\n setCollectionName('New Collection')\n setSlug('new-collection')\n setFields([])\n setSettings(DEFAULT_SETTINGS)\n }\n\n const addField = () => {\n setFields(prev => [...prev, { name: `field${prev.length + 1}`, type: 'text', label: `Field ${prev.length + 1}` }])\n }\n\n const removeField = (index: number) => {\n setFields(prev => prev.filter((_, i) => i !== index))\n }\n\n const updateField = (index: number, key: string, value: any) => {\n setFields(prev => {\n const next = [...prev]\n next[index] = { ...next[index], [key]: value }\n return next\n })\n }\n\n // Save schema to backend\n const handleSave = async () => {\n if (!slug || !collectionName) return toast.error('Name and slug required')\n setSaving(true)\n try {\n const payload = {\n slug,\n singular: collectionName,\n plural: collectionName,\n fields,\n settings,\n }\n if (activeSchemaId) {\n await api.put(`/schemas/${activeSchemaId}`, payload)\n toast.success('Schema updated!')\n } else {\n const res = await api.post('/schemas', payload)\n const id = res.data?.data?._id || res.data?.data?.id\n if (id) setActiveSchemaId(id)\n toast.success('Schema created!')\n }\n await loadSchemas()\n // Hot-reload backend routes\n await api.post('/system/schema/reload').catch(() => {})\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'Failed to save schema')\n } finally {\n setSaving(false)\n }\n }\n\n // Delete schema\n const handleDeleteSchema = async (id: string, slug: string) => {\n try {\n await api.delete(`/schemas/${id}`)\n toast.success(`Schema \"${slug}\" deleted`)\n if (activeSchemaId === id) resetEditor()\n await loadSchemas()\n } catch { toast.error('Failed to delete schema') }\n }\n\n // Introspect DB\n const handleIntrospect = async () => {\n if (!dbUri) return toast.error('Please provide a connection string')\n setIsIntrospecting(true)\n try {\n const res = await api.post('/system/introspect', { connectionString: dbUri })\n const collections = res.data.data\n if (collections?.length > 0) {\n const col = collections[0]\n setCollectionName(col.name)\n setSlug(makeSlug(col.name))\n setFields(col.fields || [])\n toast.success(`Introspected: ${col.name}`)\n setShowIntrospect(false)\n } else {\n toast.error('No tables found')\n }\n } catch (err: any) {\n toast.error(err.response?.data?.error || 'Introspection failed')\n } finally {\n setIsIntrospecting(false)\n }\n }\n\n // AI Generate\n const handleAIGenerate = async () => {\n if (!aiPrompt) return toast.error('Enter a prompt first')\n setIsAIGenerating(true)\n try {\n const res = await api.post('/system/ai-architect', { prompt: aiPrompt })\n const schema = res.data?.data\n if (schema) {\n setCollectionName(schema.name || schema.slug || 'AI Collection')\n setSlug(schema.slug || makeSlug(schema.name || 'ai-collection'))\n setFields(schema.fields || [])\n toast.success('AI schema generated!')\n setShowAI(false)\n }\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'AI generation failed')\n } finally {\n setIsAIGenerating(false)\n }\n }\n\n // Generate TypeScript code\n const generateCode = () => {\n const fieldsCode = fields.map(f => {\n let props = ` name: '${f.name}',\\n type: '${f.type}',`\n if (f.label) props += `\\n label: '${f.label}',`\n if (f.required) props += `\\n required: true,`\n if (f.unique) props += `\\n unique: true,`\n if (f.relationTo) props += `\\n relationTo: '${f.relationTo}',`\n if (f.options?.length) props += `\\n options: ${JSON.stringify(f.options)},`\n return ` {\\n${props}\\n },`\n }).join('\\n')\n\n const settingsCode = Object.entries(settings)\n .filter(([, v]) => v === true)\n .map(([k]) => ` ${k}: true,`)\n .join('\\n')\n\n return `import { CollectionConfig } from '@zenith-open/zenithcms-types'\n\nexport const ${collectionName.replace(/\\s+/g, '')}: CollectionConfig = {\n name: '${collectionName}',\n slug: '${slug}',\n${settingsCode ? settingsCode + '\\n' : ''} fields: [\n${fieldsCode}\n ],\n}`\n }\n\n const inputClass = cn(\n 'border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2.5 px-3 rounded-none shadow-sm',\n 'z-input'\n )\n\n return (\n <div className={cn('flex h-[calc(100vh-4rem)] overflow-hidden', dark ? 'bg-app text-z-primary' : 'bg-[var(--z-bg-input)] text-z-primary')}>\n\n {/* ── Schemas Sidebar ─────────────────────────────────────────────── */}\n <div className={cn('w-64 flex-shrink-0 border-r flex flex-col', 'border-z-border bg-z-panel')}>\n <div className=\"p-4 border-b border-inherit flex items-center justify-between\">\n <h2 className=\"text-sm font-bold text-z-primary\">\n Schemas\n </h2>\n <button\n onClick={resetEditor}\n className=\"p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors\"\n title=\"New Schema\"\n >\n <Plus size={14} />\n </button>\n </div>\n <div className=\"flex-1 overflow-auto p-2 space-y-1\">\n {loadingSchemas ? (\n <div className=\"p-4 flex justify-center\"><Loader2 className=\"animate-spin text-z-muted\" size={16} /></div>\n ) : savedSchemas.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-z-secondary\">\n No schemas yet\n </div>\n ) : savedSchemas.map(schema => {\n const id = schema._id || schema.id || ''\n const isActive = activeSchemaId === id\n return (\n <div key={id} className=\"group flex items-center gap-1\">\n <button\n onClick={() => loadSchema(schema)}\n className={cn(\n 'flex-1 flex items-center justify-between text-left px-3 py-2.5 text-sm font-semibold transition-colors rounded-none truncate',\n isActive ? 'bg-z-accent text-z-logo-text shadow-sm' : dark ? 'text-z-muted hover:bg-z-hover hover:text-z-primary' : 'text-z-secondary hover:bg-[var(--z-bg-input)]'\n )}\n >\n <span>{schema.slug}</span>\n {schema.isCodeFirst && <Lock size={10} className={isActive ? 'text-z-primary' : 'text-z-secondary'} />}\n </button>\n {!schema.isCodeFirst && (\n <button\n onClick={() => handleDeleteSchema(id, schema.slug)}\n className=\"opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all\"\n >\n <Trash2 size={12} />\n </button>\n )}\n </div>\n )\n })}\n </div>\n </div>\n\n {/* ── Main Editor ─────────────────────────────────────────────────── */}\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n {/* Header toolbar */}\n <PageHeader\n title=\"Schema Builder\"\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setShowAI(true)}\n className=\"px-4 py-2 bg-z-active-bg text-z-accent hover:opacity-80 text-sm font-bold rounded-none transition-all\"\n >\n AI Generate\n </button>\n <button\n onClick={() => setShowIntrospect(true)}\n className=\"px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all\"\n >\n Introspect DB\n </button>\n <button\n onClick={() => setShowCode(true)}\n className=\"px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all\"\n >\n View Code\n </button>\n <button\n onClick={handleSave}\n disabled={saving || isCodeFirst}\n className=\"px-4 py-2 bg-z-accent hover:bg-z-accent/90 text-z-primary text-sm font-bold rounded-none transition-all disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {saving ? 'Saving...' : isCodeFirst ? 'Locked' : 'Save'}\n </button>\n </div>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 space-y-6 custom-editor-scrollbar\">\n {isCodeFirst && (\n <div className=\"px-4 py-3 border border-amber-500/30 bg-amber-500/10 text-amber-500 text-sm font-bold flex items-center justify-between\">\n <span>Code-First Schema (Read Only)</span>\n <Lock size={14} />\n </div>\n )}\n\n {/* Collection Meta */}\n <div className={cn('rounded-none border p-6 space-y-4 shadow-sm transition-all', 'z-panel')}>\n <h3 className=\"text-sm font-bold text-z-primary\">\n Collection Settings\n </h3>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Name</label>\n <input\n type=\"text\"\n value={collectionName}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n setCollectionName(e.target.value)\n setSlug(makeSlug(e.target.value))\n }}\n className={cn(inputClass, 'w-full rounded-none', isCodeFirst && 'opacity-70 cursor-not-allowed')}\n placeholder=\"e.g. Blog Posts\"\n />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Slug (API ID)</label>\n <input\n type=\"text\"\n value={slug}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))\n }}\n className={cn(inputClass, 'w-full rounded-none font-mono', isCodeFirst && 'opacity-70 cursor-not-allowed')}\n placeholder=\"e.g. blog-posts\"\n />\n </div>\n </div>\n\n {/* Settings toggles */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-3 pt-2 border-t border-z-border\">\n {(Object.keys(DEFAULT_SETTINGS) as (keyof CollectionSettings)[]).map(key => (\n <label key={key} className=\"flex items-center gap-2 cursor-pointer group\">\n <div\n onClick={() => {\n if (isCodeFirst) return\n setSettings(prev => ({ ...prev, [key]: !prev[key] }))\n }}\n className={cn(\n 'w-8 h-4 rounded-full relative transition-all cursor-pointer border border-transparent shadow-inner',\n settings[key] ? (dark ? 'bg-z-accent' : 'bg-z-accent') : (dark ? 'bg-gray-700' : 'bg-gray-300'),\n isCodeFirst && 'opacity-50 cursor-not-allowed'\n )}\n >\n <div className={cn(\n 'absolute top-[1.5px] w-3 h-3 rounded-full bg-white shadow-sm transition-all',\n settings[key] ? 'left-[17px]' : 'left-[1.5px]'\n )} />\n </div>\n <span className=\"text-sm font-bold capitalize text-z-muted group-hover:text-z-primary transition-colors\">\n {key.replace(/([A-Z])/g, ' $1').trim()}\n </span>\n </label>\n ))}\n </div>\n </div>\n\n {/* Fields */}\n <div className={cn('rounded-none border shadow-sm transition-all', 'z-panel')}>\n <div className=\"px-6 py-4 border-b border-inherit flex items-center justify-between\">\n <h3 className=\"text-sm font-bold text-z-primary\">\n Fields ({fields.length})\n </h3>\n {!isCodeFirst && (\n <button\n onClick={addField}\n className=\"flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary text-sm font-semibold rounded-none transition-all\"\n >\n <Plus size={12} /> Add Field\n </button>\n )}\n </div>\n\n <div className=\"p-4 space-y-3\">\n <AnimatePresence>\n {fields.map((field, i) => (\n <motion.div\n key={i}\n layout\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.97 }}\n className={cn('p-4 relative group z-panel', isCodeFirst && 'opacity-70')}\n >\n {/* Delete button */}\n {!isCodeFirst && (\n <button\n onClick={() => removeField(i)}\n className=\"absolute top-3 right-3 opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10\"\n >\n <Trash2 size={14} />\n </button>\n )}\n\n {/* Main row */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-8\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Name (key)</label>\n <input\n type=\"text\"\n value={field.name}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, 'name', e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''))\n }}\n className={cn(inputClass, 'w-full rounded-none-none font-mono text-sm', isCodeFirst && 'cursor-not-allowed')}\n placeholder=\"fieldName\"\n />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Type</label>\n <div className={cn(isCodeFirst && 'opacity-70 pointer-events-none')}>\n <FieldTypePicker\n value={field.type}\n onChange={v => updateField(i, 'type', v)}\n theme={theme}\n />\n </div>\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Label</label>\n <input\n type=\"text\"\n value={field.label || ''}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, 'label', e.target.value)\n }}\n className={cn(inputClass, 'w-full rounded-none-none', isCodeFirst && 'cursor-not-allowed')}\n placeholder=\"Human readable label\"\n />\n </div>\n </div>\n\n {/* Quick flags row */}\n <div className=\"flex items-center gap-5 mt-3 pt-2 border-t border-z-border\">\n {[['required', 'Required'], ['unique', 'Unique'], ['index', 'Index']].map(([k, l]) => (\n <label key={k} className=\"flex items-center gap-1.5 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!(field as any)[k]}\n disabled={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, k, e.target.checked)\n }}\n className=\"accent-gray-500 w-3 h-3 disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <span className=\"text-sm font-semibold text-z-secondary\">{l}</span>\n </label>\n ))}\n </div>\n\n {/* Advanced panel */}\n {!isCodeFirst && (\n <FieldAdvancedPanel\n field={field}\n onUpdate={(key, value) => updateField(i, key, value)}\n theme={theme}\n availableCollections={availableCollections}\n />\n )}\n </motion.div>\n ))}\n </AnimatePresence>\n\n {fields.length === 0 && (\n <div className=\"py-16 text-center\">\n <Layers size={40} className=\"mx-auto text-z-primary mb-4\" strokeWidth={1} />\n <p className=\"text-sm font-semibold text-z-secondary\">No fields yet</p>\n <p className=\"text-sm text-z-secondary mt-1\">Click \"Add Field\" or use AI Generate to get started</p>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {/* ── Code Modal ─────────────────────────────────────────────────── */}\n <AnimatePresence>\n {showCode && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-3xl border rounded-none-none shadow-2xl p-6 relative flex flex-col h-[80vh] bg-app border-z-border\">\n <button onClick={() => setShowCode(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-4 flex items-center gap-3\">\n <Code className=\"text-z-secondary \" /> Generated TypeScript\n </h2>\n <div className=\"flex-1 bg-[#1E1E1E] border border-z-border p-5 overflow-auto text-sm font-mono text-z-secondary relative rounded-none-none\">\n <button\n onClick={() => { navigator.clipboard.writeText(generateCode()); setCopied(true); setTimeout(() => setCopied(false), 2000) }}\n className=\"absolute top-3 right-3 p-2 bg-z-panel/10 hover:bg-z-panel/20 text-z-primary transition-colors rounded-none-none\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n <pre><code>{generateCode()}</code></pre>\n </div>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* ── AI Generate Modal ───────────────────────────────────────────── */}\n <AnimatePresence>\n {showAI && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border\">\n <button onClick={() => setShowAI(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-2 flex items-center gap-3\">\n <Sparkles className=\"text-purple-400\" /> AI Schema Architect\n </h2>\n <p className=\"text-sm text-z-muted mb-5 font-medium\">\n Describe what you need — the AI will generate a complete schema with fields, types, and relations.\n </p>\n <textarea\n rows={4}\n value={aiPrompt}\n onChange={e => setAiPrompt(e.target.value)}\n placeholder='e.g. \"A blog post collection with title, slug, content, featured image, author relation to users, published date, and category select field with options.\"'\n className=\"w-full bg-app border border-z-border focus:border-z-active-border/50 p-4 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary resize-none mb-4\"\n />\n <button\n disabled={isAIGenerating || !aiPrompt}\n onClick={handleAIGenerate}\n className=\"w-full py-3.5 bg-z-accent hover:opacity-80 text-z-logo-text text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none disabled:opacity-50\"\n >\n {isAIGenerating ? <><Loader2 size={14} className=\"animate-spin\" /> Generating...</> : <><Sparkles size={14} /> Generate Schema</>}\n </button>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* ── Introspect Modal ─────────────────────────────────────────────── */}\n <AnimatePresence>\n {showIntrospect && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border\">\n <button onClick={() => setShowIntrospect(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-2 flex items-center gap-3\">\n <Database className=\"text-z-secondary \" /> DB Introspection\n </h2>\n <p className=\"text-sm text-z-muted mb-5 font-medium\">\n Connect to a Postgres database to reverse-engineer tables into Zenith schema fields.\n </p>\n <input\n type=\"text\"\n placeholder=\"postgresql://user:password@localhost:5432/mydb\"\n value={dbUri}\n onChange={e => setDbUri(e.target.value)}\n className=\"w-full bg-app border border-z-border focus:border-z-border/50 p-3.5 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary mb-4 font-mono\"\n />\n <button\n disabled={isIntrospecting}\n onClick={handleIntrospect}\n className=\"w-full py-3.5 bg-z-border hover:bg-z-input text-z-primary text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none\"\n >\n {isIntrospecting ? <><Loader2 size={14} className=\"animate-spin\" /> Scanning...</> : <><RefreshCw size={14} /> Analyze Database</>}\n </button>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n"],"mappings":"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"}