@hanzo/ui 5.3.43 → 5.4.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 (36) hide show
  1. package/dist/dash/dash-crud.js +2 -0
  2. package/dist/dash/dash-crud.mjs +2 -0
  3. package/dist/dash/dash-data-table.js +2 -0
  4. package/dist/dash/dash-data-table.mjs +2 -0
  5. package/dist/dash/dash-form.js +2 -0
  6. package/dist/dash/dash-form.mjs +2 -0
  7. package/dist/dash/dash-header.js +2 -0
  8. package/dist/dash/dash-header.mjs +2 -0
  9. package/dist/dash/dash-layout.js +2 -0
  10. package/dist/dash/dash-layout.mjs +2 -0
  11. package/dist/dash/dash-sidebar.js +3 -0
  12. package/dist/dash/dash-sidebar.mjs +3 -0
  13. package/dist/dash/index.js +3 -0
  14. package/dist/dash/index.mjs +3 -0
  15. package/dist/src/dash/dash-crud.d.ts +37 -0
  16. package/dist/src/dash/dash-crud.d.ts.map +1 -0
  17. package/dist/src/dash/dash-crud.js +74 -0
  18. package/dist/src/dash/dash-data-table.d.ts +50 -0
  19. package/dist/src/dash/dash-data-table.d.ts.map +1 -0
  20. package/dist/src/dash/dash-data-table.js +88 -0
  21. package/dist/src/dash/dash-form.d.ts +52 -0
  22. package/dist/src/dash/dash-form.d.ts.map +1 -0
  23. package/dist/src/dash/dash-form.js +90 -0
  24. package/dist/src/dash/dash-header.d.ts +28 -0
  25. package/dist/src/dash/dash-header.d.ts.map +1 -0
  26. package/dist/src/dash/dash-header.js +24 -0
  27. package/dist/src/dash/dash-layout.d.ts +16 -0
  28. package/dist/src/dash/dash-layout.d.ts.map +1 -0
  29. package/dist/src/dash/dash-layout.js +8 -0
  30. package/dist/src/dash/dash-sidebar.d.ts +31 -0
  31. package/dist/src/dash/dash-sidebar.d.ts.map +1 -0
  32. package/dist/src/dash/dash-sidebar.js +26 -0
  33. package/dist/src/dash/index.d.ts +21 -0
  34. package/dist/src/dash/index.d.ts.map +1 -0
  35. package/dist/src/dash/index.js +20 -0
  36. package/package.json +12 -1
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ 'use strict';var $=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var $__namespace=/*#__PURE__*/_interopNamespace($);var I=Object.defineProperty;var c=(e,a)=>I(e,"name",{value:a,configurable:true});function n(...e){return tailwindMerge.twMerge(clsx.clsx(e))}c(n,"cn");function Z({columns:e,data:a,rowKey:v,selectable:i=false,selectedKeys:m,onSelectionChange:p,searchable:y=false,searchPlaceholder:b="Search...",totalRows:o,page:u=0,pageSize:T=20,onPageChange:P,onPageSizeChange:L,actions:V,loading:q=false,emptyMessage:d="No data",className:l}){let[r,g]=$__namespace.useState(""),[w,K]=$__namespace.useState(null),z=$__namespace.useMemo(()=>{if(!r)return a;let t=r.toLowerCase();return a.filter(f=>e.some(M=>(M.cell?"":String(f[M.id]??"")).toLowerCase().includes(t)))},[a,r,e]),j=$__namespace.useMemo(()=>{if(!w)return z;let{column:t,direction:f}=w;return [...z].sort((M,R)=>{let H=M[t],Q=R[t];if(H==null&&Q==null)return 0;if(H==null)return 1;if(Q==null)return -1;let Y=String(H).localeCompare(String(Q),void 0,{numeric:true});return f==="asc"?Y:-Y})},[z,w]),O=o??j.length,E=Math.max(1,Math.ceil(O/T)),F=P?j:j.slice(u*T,(u+1)*T),D=m??new Set,W=F.length>0&&F.every(t=>D.has(v(t)));function _(){p&&p(W?new Set:new Set(F.map(v)));}c(_,"toggleAll");function A(t){if(!p)return;let f=new Set(D);f.has(t)?f.delete(t):f.add(t),p(f);}c(A,"toggleRow");function G(t){K(f=>f?.column===t?f.direction==="asc"?{column:t,direction:"desc"}:null:{column:t,direction:"asc"});}c(G,"handleSort");let x=V?[...e,{id:"__actions",header:"",width:"auto"}]:e;return jsxRuntime.jsxs("div",{className:n("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)]",l),children:[(y||i)&&jsxRuntime.jsxs("div",{className:"flex items-center gap-3 border-b border-[var(--dash-border)] px-4 py-3",children:[y&&jsxRuntime.jsx("input",{type:"text",placeholder:b,value:r,onChange:t=>g(t.target.value),className:n("h-8 w-64 max-w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]")}),i&&D.size>0&&jsxRuntime.jsxs("span",{className:"text-xs text-[var(--dash-text-muted)]",children:[D.size," selected"]})]}),jsxRuntime.jsx("div",{className:"overflow-x-auto",children:jsxRuntime.jsxs("table",{className:"w-full text-sm",children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{className:"border-b border-[var(--dash-border)]",children:[i&&jsxRuntime.jsx("th",{className:"w-10 px-4 py-2.5",children:jsxRuntime.jsx("input",{type:"checkbox",checked:W,onChange:_,className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),x.map(t=>jsxRuntime.jsx("th",{style:t.width?{width:t.width}:void 0,className:n("px-4 py-2.5 text-[var(--dash-text-dim)] font-medium",t.align==="center"&&"text-center",t.align==="right"&&"text-right",!t.align&&"text-left",t.sortable&&"cursor-pointer select-none hover:text-[var(--dash-text-muted)]"),onClick:t.sortable?()=>G(t.id):void 0,children:jsxRuntime.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.header,t.sortable&&w?.column===t.id&&jsxRuntime.jsx("span",{className:"text-[10px]",children:w.direction==="asc"?"\u2191":"\u2193"})]})},t.id))]})}),jsxRuntime.jsx("tbody",{children:q?jsxRuntime.jsx("tr",{children:jsxRuntime.jsx("td",{colSpan:x.length+(i?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:"Loading..."})}):F.length===0?jsxRuntime.jsx("tr",{children:jsxRuntime.jsx("td",{colSpan:x.length+(i?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:d})}):F.map(t=>{let f=v(t),M=D.has(f);return jsxRuntime.jsxs("tr",{className:n("border-b border-[var(--dash-border)] transition-colors",M?"bg-[var(--dash-surface-active)]":"hover:bg-[var(--dash-surface-hover)]"),children:[i&&jsxRuntime.jsx("td",{className:"w-10 px-4 py-2.5",children:jsxRuntime.jsx("input",{type:"checkbox",checked:M,onChange:()=>A(f),className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),e.map(R=>jsxRuntime.jsx("td",{className:n("px-4 py-2.5",R.align==="center"&&"text-center",R.align==="right"&&"text-right"),children:R.cell?R.cell(t):String(t[R.id]??"")},R.id)),V&&jsxRuntime.jsx("td",{className:"px-4 py-2.5 text-right",children:V(t)})]},f)})})]})}),E>1&&jsxRuntime.jsxs("div",{className:"flex items-center justify-between border-t border-[var(--dash-border)] px-4 py-2.5 text-xs text-[var(--dash-text-muted)]",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("span",{children:"Rows per page"}),jsxRuntime.jsx("select",{value:T,onChange:t=>L?.(Number(t.target.value)),className:"h-7 rounded border border-[var(--dash-border)] bg-[var(--dash-bg)] px-2 text-xs text-[var(--dash-text)] focus:outline-none",children:[10,20,50,100].map(t=>jsxRuntime.jsx("option",{value:t,children:t},t))})]}),jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsxs("span",{children:["Page ",u+1," of ",E]}),jsxRuntime.jsx("button",{type:"button",disabled:u===0,onClick:()=>P?.(u-1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),jsxRuntime.jsx("button",{type:"button",disabled:u>=E-1,onClick:()=>P?.(u+1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}c(Z,"DashDataTable");function U({title:e,fields:a,values:v,onSubmit:i,onCancel:m,submitLabel:p="Save",cancelLabel:y="Cancel",loading:b=false,className:o}){let[u,T]=$__namespace.useState(()=>{let d={};for(let l of a)d[l.name]=v?.[l.name]??l.defaultValue??(l.type==="toggle"?false:"");return d}),[P,L]=$__namespace.useState({});function V(d,l){T(r=>({...r,[d]:l})),L(r=>{if(!r[d])return r;let g={...r};return delete g[d],g});}c(V,"setValue");async function q(d){d.preventDefault();let l={};for(let r of a){let g=u[r.name];if(r.required&&(g===""||g===null||g===void 0)&&(l[r.name]=`${r.label} is required`),r.validate){let w=r.validate(g);w&&(l[r.name]=w);}}if(Object.keys(l).length>0){L(l);return}await i(u);}return c(q,"handleSubmit"),jsxRuntime.jsxs("form",{onSubmit:q,className:n("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6",o),children:[e&&jsxRuntime.jsx("h3",{className:"mb-4 text-lg font-semibold text-[var(--dash-text)]",children:e}),jsxRuntime.jsx("div",{className:"space-y-4",children:a.map(d=>jsxRuntime.jsx(ae,{field:d,value:u[d.name],error:P[d.name],onChange:l=>V(d.name,l)},d.name))}),jsxRuntime.jsxs("div",{className:"mt-6 flex items-center gap-3",children:[jsxRuntime.jsx("button",{type:"submit",disabled:b,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]","disabled:opacity-50 disabled:cursor-not-allowed"),children:b?"Saving...":p}),m&&jsxRuntime.jsx("button",{type:"button",onClick:m,disabled:b,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:y})]})]})}c(U,"DashForm");var J=n("w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 py-2 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","disabled:opacity-50 disabled:cursor-not-allowed","transition-colors");function ae({field:e,value:a,error:v,onChange:i}){let m=`dash-field-${e.name}`,p=jsxRuntime.jsxs("label",{htmlFor:m,className:"mb-1 block text-sm font-medium text-[var(--dash-text)]",children:[e.label,e.required&&jsxRuntime.jsx("span",{className:"ml-0.5 text-[var(--dash-error)]",children:"*"})]}),y=e.description?jsxRuntime.jsx("p",{className:"mt-1 text-xs text-[var(--dash-text-dim)]",children:e.description}):null,b=v?jsxRuntime.jsx("p",{className:"mt-1 text-xs text-[var(--dash-error)]",children:v}):null;switch(e.type){case "text":case "email":case "password":case "number":return jsxRuntime.jsxs("div",{children:[p,jsxRuntime.jsx("input",{id:m,type:e.type,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,onChange:o=>i(e.type==="number"?Number(o.target.value):o.target.value),className:n(J,v&&"border-[var(--dash-error)]")}),y,b]});case "textarea":return jsxRuntime.jsxs("div",{children:[p,jsxRuntime.jsx("textarea",{id:m,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,rows:e.rows??3,onChange:o=>i(o.target.value),className:n(J,"resize-y",v&&"border-[var(--dash-error)]")}),y,b]});case "select":case "relation":return jsxRuntime.jsxs("div",{children:[p,jsxRuntime.jsxs("select",{id:m,value:String(a??""),disabled:e.disabled,onChange:o=>i(o.target.value),className:n(J,v&&"border-[var(--dash-error)]"),children:[jsxRuntime.jsx("option",{value:"",children:e.placeholder??"Select..."}),(e.options??[]).map(o=>jsxRuntime.jsx("option",{value:o.value,children:o.label},o.value))]}),y,b]});case "toggle":return jsxRuntime.jsxs("div",{className:"flex items-center gap-3",children:[jsxRuntime.jsx("button",{id:m,type:"button",role:"switch","aria-checked":!!a,disabled:e.disabled,onClick:()=>i(!a),className:n("relative inline-flex h-5 w-9 flex-shrink-0 rounded-full transition-colors","focus:outline-none focus:ring-2 focus:ring-[var(--dash-primary)] focus:ring-offset-2 focus:ring-offset-[var(--dash-surface)]",a?"bg-[var(--dash-primary)]":"bg-[var(--dash-border)]",e.disabled&&"opacity-50 cursor-not-allowed"),children:jsxRuntime.jsx("span",{className:n("pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",a?"translate-x-4":"translate-x-0.5","mt-0.5")})}),jsxRuntime.jsx("label",{htmlFor:m,className:"text-sm text-[var(--dash-text)]",children:e.label}),y,b]});case "json":return jsxRuntime.jsxs("div",{children:[p,jsxRuntime.jsx("textarea",{id:m,value:typeof a=="string"?a:JSON.stringify(a,null,2),placeholder:e.placeholder??"{}",disabled:e.disabled,rows:e.rows??6,onChange:o=>{try{i(JSON.parse(o.target.value));}catch{i(o.target.value);}},className:n(J,"font-mono text-xs resize-y",v&&"border-[var(--dash-error)]")}),y,b]});case "file":return jsxRuntime.jsxs("div",{children:[p,jsxRuntime.jsx("input",{id:m,type:"file",accept:e.accept,disabled:e.disabled,onChange:o=>{let u=o.target.files?.[0];u&&i(u);},className:n("w-full text-sm text-[var(--dash-text-muted)]","file:mr-3 file:rounded-[var(--dash-radius-sm)] file:border-0 file:bg-[var(--dash-primary)] file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-[var(--dash-primary-text)]","file:cursor-pointer hover:file:bg-[var(--dash-primary-hover)]")}),y,b]});default:return null}}c(ae,"FieldRenderer");function we({resourceName:e,resourceNamePlural:a,columns:v,data:i,rowKey:m,fields:p,rowToValues:y,onCreate:b,onUpdate:o,onDelete:u,canCreate:T=true,canEdit:P=true,canDelete:L=true,tableProps:V,loading:q=false,className:d}){let l=a??`${e}s`,[r,g]=$__namespace.useState("list"),[w,K]=$__namespace.useState(null),[z,j]=$__namespace.useState({}),[O,E]=$__namespace.useState(null),[F,D]=$__namespace.useState(false);function W(x){let t=m(x);K(t),j(y?y(x):x),g("edit");}c(W,"handleEdit");function _(x){E(m(x));}c(_,"handleDeleteConfirm");async function A(){if(!(!O||!u)){D(true);try{await u(O);}finally{D(false),E(null);}}}c(A,"confirmDelete");function G(x){return jsxRuntime.jsxs("div",{className:"flex items-center justify-end gap-1",children:[P&&o&&jsxRuntime.jsx("button",{type:"button",onClick:()=>W(x),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors",children:"Edit"}),L&&u&&jsxRuntime.jsx("button",{type:"button",onClick:()=>_(x),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-error)] hover:bg-[var(--dash-error-dim)] transition-colors",children:"Delete"})]})}return c(G,"actionsRenderer"),r==="list"?jsxRuntime.jsxs("div",{className:n("space-y-4",d),children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsx("h2",{className:"text-xl font-semibold text-[var(--dash-text)]",children:l}),T&&b&&jsxRuntime.jsxs("button",{type:"button",onClick:()=>{K(null),j({}),g("create");},className:n("rounded-[var(--dash-radius)] px-3 py-1.5 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]"),children:["Create ",e]})]}),jsxRuntime.jsx(Z,{columns:v,data:i,rowKey:m,actions:P||L?G:void 0,loading:q,searchable:true,emptyMessage:`No ${l.toLowerCase()} found`,...V}),O!==null&&jsxRuntime.jsx(re,{resourceName:e,loading:F,onConfirm:A,onCancel:()=>E(null)})]}):jsxRuntime.jsxs("div",{className:n("space-y-4",d),children:[jsxRuntime.jsxs("button",{type:"button",onClick:()=>g("list"),className:"inline-flex items-center gap-1 text-sm text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:[jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),"Back to ",l]}),jsxRuntime.jsx(U,{title:r==="create"?`Create ${e}`:`Edit ${e}`,fields:p,values:r==="edit"?z:void 0,loading:F,submitLabel:r==="create"?"Create":"Save changes",onCancel:()=>g("list"),onSubmit:async x=>{D(true);try{r==="create"&&b?await b(x):r==="edit"&&w&&o&&await o(w,x),g("list");}finally{D(false);}}})]})}c(we,"DashCrud");function re({resourceName:e,loading:a,onConfirm:v,onCancel:i}){return jsxRuntime.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:jsxRuntime.jsxs("div",{className:"w-full max-w-sm rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6 shadow-lg",children:[jsxRuntime.jsxs("h3",{className:"text-lg font-semibold text-[var(--dash-text)]",children:["Delete ",e,"?"]}),jsxRuntime.jsxs("p",{className:"mt-2 text-sm text-[var(--dash-text-muted)]",children:["This action cannot be undone. The ",e.toLowerCase()," will be permanently removed."]}),jsxRuntime.jsxs("div",{className:"mt-6 flex items-center justify-end gap-3",children:[jsxRuntime.jsx("button",{type:"button",onClick:i,disabled:a,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:"Cancel"}),jsxRuntime.jsx("button",{type:"button",onClick:v,disabled:a,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-error)] text-white","hover:bg-red-600","disabled:opacity-50 disabled:cursor-not-allowed"),children:a?"Deleting...":"Delete"})]})]})})}c(re,"DeleteDialog");exports.DashCrud=we;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import*as $ from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';var I=Object.defineProperty;var c=(e,a)=>I(e,"name",{value:a,configurable:true});function n(...e){return twMerge(clsx(e))}c(n,"cn");function Z({columns:e,data:a,rowKey:v,selectable:i=false,selectedKeys:m,onSelectionChange:p,searchable:y=false,searchPlaceholder:b="Search...",totalRows:o,page:u=0,pageSize:T=20,onPageChange:P,onPageSizeChange:L,actions:V,loading:q=false,emptyMessage:d="No data",className:l}){let[r,g]=$.useState(""),[w,K]=$.useState(null),z=$.useMemo(()=>{if(!r)return a;let t=r.toLowerCase();return a.filter(f=>e.some(M=>(M.cell?"":String(f[M.id]??"")).toLowerCase().includes(t)))},[a,r,e]),j=$.useMemo(()=>{if(!w)return z;let{column:t,direction:f}=w;return [...z].sort((M,R)=>{let H=M[t],Q=R[t];if(H==null&&Q==null)return 0;if(H==null)return 1;if(Q==null)return -1;let Y=String(H).localeCompare(String(Q),void 0,{numeric:true});return f==="asc"?Y:-Y})},[z,w]),O=o??j.length,E=Math.max(1,Math.ceil(O/T)),F=P?j:j.slice(u*T,(u+1)*T),D=m??new Set,W=F.length>0&&F.every(t=>D.has(v(t)));function _(){p&&p(W?new Set:new Set(F.map(v)));}c(_,"toggleAll");function A(t){if(!p)return;let f=new Set(D);f.has(t)?f.delete(t):f.add(t),p(f);}c(A,"toggleRow");function G(t){K(f=>f?.column===t?f.direction==="asc"?{column:t,direction:"desc"}:null:{column:t,direction:"asc"});}c(G,"handleSort");let x=V?[...e,{id:"__actions",header:"",width:"auto"}]:e;return jsxs("div",{className:n("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)]",l),children:[(y||i)&&jsxs("div",{className:"flex items-center gap-3 border-b border-[var(--dash-border)] px-4 py-3",children:[y&&jsx("input",{type:"text",placeholder:b,value:r,onChange:t=>g(t.target.value),className:n("h-8 w-64 max-w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]")}),i&&D.size>0&&jsxs("span",{className:"text-xs text-[var(--dash-text-muted)]",children:[D.size," selected"]})]}),jsx("div",{className:"overflow-x-auto",children:jsxs("table",{className:"w-full text-sm",children:[jsx("thead",{children:jsxs("tr",{className:"border-b border-[var(--dash-border)]",children:[i&&jsx("th",{className:"w-10 px-4 py-2.5",children:jsx("input",{type:"checkbox",checked:W,onChange:_,className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),x.map(t=>jsx("th",{style:t.width?{width:t.width}:void 0,className:n("px-4 py-2.5 text-[var(--dash-text-dim)] font-medium",t.align==="center"&&"text-center",t.align==="right"&&"text-right",!t.align&&"text-left",t.sortable&&"cursor-pointer select-none hover:text-[var(--dash-text-muted)]"),onClick:t.sortable?()=>G(t.id):void 0,children:jsxs("span",{className:"inline-flex items-center gap-1",children:[t.header,t.sortable&&w?.column===t.id&&jsx("span",{className:"text-[10px]",children:w.direction==="asc"?"\u2191":"\u2193"})]})},t.id))]})}),jsx("tbody",{children:q?jsx("tr",{children:jsx("td",{colSpan:x.length+(i?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:"Loading..."})}):F.length===0?jsx("tr",{children:jsx("td",{colSpan:x.length+(i?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:d})}):F.map(t=>{let f=v(t),M=D.has(f);return jsxs("tr",{className:n("border-b border-[var(--dash-border)] transition-colors",M?"bg-[var(--dash-surface-active)]":"hover:bg-[var(--dash-surface-hover)]"),children:[i&&jsx("td",{className:"w-10 px-4 py-2.5",children:jsx("input",{type:"checkbox",checked:M,onChange:()=>A(f),className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),e.map(R=>jsx("td",{className:n("px-4 py-2.5",R.align==="center"&&"text-center",R.align==="right"&&"text-right"),children:R.cell?R.cell(t):String(t[R.id]??"")},R.id)),V&&jsx("td",{className:"px-4 py-2.5 text-right",children:V(t)})]},f)})})]})}),E>1&&jsxs("div",{className:"flex items-center justify-between border-t border-[var(--dash-border)] px-4 py-2.5 text-xs text-[var(--dash-text-muted)]",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsx("span",{children:"Rows per page"}),jsx("select",{value:T,onChange:t=>L?.(Number(t.target.value)),className:"h-7 rounded border border-[var(--dash-border)] bg-[var(--dash-bg)] px-2 text-xs text-[var(--dash-text)] focus:outline-none",children:[10,20,50,100].map(t=>jsx("option",{value:t,children:t},t))})]}),jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{children:["Page ",u+1," of ",E]}),jsx("button",{type:"button",disabled:u===0,onClick:()=>P?.(u-1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),jsx("button",{type:"button",disabled:u>=E-1,onClick:()=>P?.(u+1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}c(Z,"DashDataTable");function U({title:e,fields:a,values:v,onSubmit:i,onCancel:m,submitLabel:p="Save",cancelLabel:y="Cancel",loading:b=false,className:o}){let[u,T]=$.useState(()=>{let d={};for(let l of a)d[l.name]=v?.[l.name]??l.defaultValue??(l.type==="toggle"?false:"");return d}),[P,L]=$.useState({});function V(d,l){T(r=>({...r,[d]:l})),L(r=>{if(!r[d])return r;let g={...r};return delete g[d],g});}c(V,"setValue");async function q(d){d.preventDefault();let l={};for(let r of a){let g=u[r.name];if(r.required&&(g===""||g===null||g===void 0)&&(l[r.name]=`${r.label} is required`),r.validate){let w=r.validate(g);w&&(l[r.name]=w);}}if(Object.keys(l).length>0){L(l);return}await i(u);}return c(q,"handleSubmit"),jsxs("form",{onSubmit:q,className:n("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6",o),children:[e&&jsx("h3",{className:"mb-4 text-lg font-semibold text-[var(--dash-text)]",children:e}),jsx("div",{className:"space-y-4",children:a.map(d=>jsx(ae,{field:d,value:u[d.name],error:P[d.name],onChange:l=>V(d.name,l)},d.name))}),jsxs("div",{className:"mt-6 flex items-center gap-3",children:[jsx("button",{type:"submit",disabled:b,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]","disabled:opacity-50 disabled:cursor-not-allowed"),children:b?"Saving...":p}),m&&jsx("button",{type:"button",onClick:m,disabled:b,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:y})]})]})}c(U,"DashForm");var J=n("w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 py-2 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","disabled:opacity-50 disabled:cursor-not-allowed","transition-colors");function ae({field:e,value:a,error:v,onChange:i}){let m=`dash-field-${e.name}`,p=jsxs("label",{htmlFor:m,className:"mb-1 block text-sm font-medium text-[var(--dash-text)]",children:[e.label,e.required&&jsx("span",{className:"ml-0.5 text-[var(--dash-error)]",children:"*"})]}),y=e.description?jsx("p",{className:"mt-1 text-xs text-[var(--dash-text-dim)]",children:e.description}):null,b=v?jsx("p",{className:"mt-1 text-xs text-[var(--dash-error)]",children:v}):null;switch(e.type){case "text":case "email":case "password":case "number":return jsxs("div",{children:[p,jsx("input",{id:m,type:e.type,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,onChange:o=>i(e.type==="number"?Number(o.target.value):o.target.value),className:n(J,v&&"border-[var(--dash-error)]")}),y,b]});case "textarea":return jsxs("div",{children:[p,jsx("textarea",{id:m,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,rows:e.rows??3,onChange:o=>i(o.target.value),className:n(J,"resize-y",v&&"border-[var(--dash-error)]")}),y,b]});case "select":case "relation":return jsxs("div",{children:[p,jsxs("select",{id:m,value:String(a??""),disabled:e.disabled,onChange:o=>i(o.target.value),className:n(J,v&&"border-[var(--dash-error)]"),children:[jsx("option",{value:"",children:e.placeholder??"Select..."}),(e.options??[]).map(o=>jsx("option",{value:o.value,children:o.label},o.value))]}),y,b]});case "toggle":return jsxs("div",{className:"flex items-center gap-3",children:[jsx("button",{id:m,type:"button",role:"switch","aria-checked":!!a,disabled:e.disabled,onClick:()=>i(!a),className:n("relative inline-flex h-5 w-9 flex-shrink-0 rounded-full transition-colors","focus:outline-none focus:ring-2 focus:ring-[var(--dash-primary)] focus:ring-offset-2 focus:ring-offset-[var(--dash-surface)]",a?"bg-[var(--dash-primary)]":"bg-[var(--dash-border)]",e.disabled&&"opacity-50 cursor-not-allowed"),children:jsx("span",{className:n("pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",a?"translate-x-4":"translate-x-0.5","mt-0.5")})}),jsx("label",{htmlFor:m,className:"text-sm text-[var(--dash-text)]",children:e.label}),y,b]});case "json":return jsxs("div",{children:[p,jsx("textarea",{id:m,value:typeof a=="string"?a:JSON.stringify(a,null,2),placeholder:e.placeholder??"{}",disabled:e.disabled,rows:e.rows??6,onChange:o=>{try{i(JSON.parse(o.target.value));}catch{i(o.target.value);}},className:n(J,"font-mono text-xs resize-y",v&&"border-[var(--dash-error)]")}),y,b]});case "file":return jsxs("div",{children:[p,jsx("input",{id:m,type:"file",accept:e.accept,disabled:e.disabled,onChange:o=>{let u=o.target.files?.[0];u&&i(u);},className:n("w-full text-sm text-[var(--dash-text-muted)]","file:mr-3 file:rounded-[var(--dash-radius-sm)] file:border-0 file:bg-[var(--dash-primary)] file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-[var(--dash-primary-text)]","file:cursor-pointer hover:file:bg-[var(--dash-primary-hover)]")}),y,b]});default:return null}}c(ae,"FieldRenderer");function we({resourceName:e,resourceNamePlural:a,columns:v,data:i,rowKey:m,fields:p,rowToValues:y,onCreate:b,onUpdate:o,onDelete:u,canCreate:T=true,canEdit:P=true,canDelete:L=true,tableProps:V,loading:q=false,className:d}){let l=a??`${e}s`,[r,g]=$.useState("list"),[w,K]=$.useState(null),[z,j]=$.useState({}),[O,E]=$.useState(null),[F,D]=$.useState(false);function W(x){let t=m(x);K(t),j(y?y(x):x),g("edit");}c(W,"handleEdit");function _(x){E(m(x));}c(_,"handleDeleteConfirm");async function A(){if(!(!O||!u)){D(true);try{await u(O);}finally{D(false),E(null);}}}c(A,"confirmDelete");function G(x){return jsxs("div",{className:"flex items-center justify-end gap-1",children:[P&&o&&jsx("button",{type:"button",onClick:()=>W(x),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors",children:"Edit"}),L&&u&&jsx("button",{type:"button",onClick:()=>_(x),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-error)] hover:bg-[var(--dash-error-dim)] transition-colors",children:"Delete"})]})}return c(G,"actionsRenderer"),r==="list"?jsxs("div",{className:n("space-y-4",d),children:[jsxs("div",{className:"flex items-center justify-between",children:[jsx("h2",{className:"text-xl font-semibold text-[var(--dash-text)]",children:l}),T&&b&&jsxs("button",{type:"button",onClick:()=>{K(null),j({}),g("create");},className:n("rounded-[var(--dash-radius)] px-3 py-1.5 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]"),children:["Create ",e]})]}),jsx(Z,{columns:v,data:i,rowKey:m,actions:P||L?G:void 0,loading:q,searchable:true,emptyMessage:`No ${l.toLowerCase()} found`,...V}),O!==null&&jsx(re,{resourceName:e,loading:F,onConfirm:A,onCancel:()=>E(null)})]}):jsxs("div",{className:n("space-y-4",d),children:[jsxs("button",{type:"button",onClick:()=>g("list"),className:"inline-flex items-center gap-1 text-sm text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:[jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),"Back to ",l]}),jsx(U,{title:r==="create"?`Create ${e}`:`Edit ${e}`,fields:p,values:r==="edit"?z:void 0,loading:F,submitLabel:r==="create"?"Create":"Save changes",onCancel:()=>g("list"),onSubmit:async x=>{D(true);try{r==="create"&&b?await b(x):r==="edit"&&w&&o&&await o(w,x),g("list");}finally{D(false);}}})]})}c(we,"DashCrud");function re({resourceName:e,loading:a,onConfirm:v,onCancel:i}){return jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:jsxs("div",{className:"w-full max-w-sm rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6 shadow-lg",children:[jsxs("h3",{className:"text-lg font-semibold text-[var(--dash-text)]",children:["Delete ",e,"?"]}),jsxs("p",{className:"mt-2 text-sm text-[var(--dash-text-muted)]",children:["This action cannot be undone. The ",e.toLowerCase()," will be permanently removed."]}),jsxs("div",{className:"mt-6 flex items-center justify-end gap-3",children:[jsx("button",{type:"button",onClick:i,disabled:a,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:"Cancel"}),jsx("button",{type:"button",onClick:v,disabled:a,className:n("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-error)] text-white","hover:bg-red-600","disabled:opacity-50 disabled:cursor-not-allowed"),children:a?"Deleting...":"Delete"})]})]})})}c(re,"DeleteDialog");export{we as DashCrud};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ 'use strict';var u=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var u__namespace=/*#__PURE__*/_interopNamespace(u);var J=Object.defineProperty;var i=(s,h)=>J(s,"name",{value:h,configurable:true});function c(...s){return tailwindMerge.twMerge(clsx.clsx(s))}i(c,"cn");function ee({columns:s,data:h,rowKey:f,selectable:l=false,selectedKeys:P,onSelectionChange:m,searchable:D=false,searchPlaceholder:j="Search...",totalRows:z,page:o=0,pageSize:g=20,onPageChange:w,onPageSizeChange:B,actions:y,loading:V=false,emptyMessage:W="No data",className:_}){let[x,q]=u__namespace.useState(""),[p,A]=u__namespace.useState(null),N=u__namespace.useMemo(()=>{if(!x)return h;let e=x.toLowerCase();return h.filter(r=>s.some(d=>(d.cell?"":String(r[d.id]??"")).toLowerCase().includes(e)))},[h,x,s]),k=u__namespace.useMemo(()=>{if(!p)return N;let{column:e,direction:r}=p;return [...N].sort((d,n)=>{let C=d[e],T=n[e];if(C==null&&T==null)return 0;if(C==null)return 1;if(T==null)return -1;let M=String(C).localeCompare(String(T),void 0,{numeric:true});return r==="asc"?M:-M})},[N,p]),E=z??k.length,S=Math.max(1,Math.ceil(E/g)),b=w?k:k.slice(o*g,(o+1)*g),v=P??new Set,L=b.length>0&&b.every(e=>v.has(f(e)));function F(){m&&m(L?new Set:new Set(b.map(f)));}i(F,"toggleAll");function G(e){if(!m)return;let r=new Set(v);r.has(e)?r.delete(e):r.add(e),m(r);}i(G,"toggleRow");function H(e){A(r=>r?.column===e?r.direction==="asc"?{column:e,direction:"desc"}:null:{column:e,direction:"asc"});}i(H,"handleSort");let R=y?[...s,{id:"__actions",header:"",width:"auto"}]:s;return jsxRuntime.jsxs("div",{className:c("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)]",_),children:[(D||l)&&jsxRuntime.jsxs("div",{className:"flex items-center gap-3 border-b border-[var(--dash-border)] px-4 py-3",children:[D&&jsxRuntime.jsx("input",{type:"text",placeholder:j,value:x,onChange:e=>q(e.target.value),className:c("h-8 w-64 max-w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]")}),l&&v.size>0&&jsxRuntime.jsxs("span",{className:"text-xs text-[var(--dash-text-muted)]",children:[v.size," selected"]})]}),jsxRuntime.jsx("div",{className:"overflow-x-auto",children:jsxRuntime.jsxs("table",{className:"w-full text-sm",children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{className:"border-b border-[var(--dash-border)]",children:[l&&jsxRuntime.jsx("th",{className:"w-10 px-4 py-2.5",children:jsxRuntime.jsx("input",{type:"checkbox",checked:L,onChange:F,className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),R.map(e=>jsxRuntime.jsx("th",{style:e.width?{width:e.width}:void 0,className:c("px-4 py-2.5 text-[var(--dash-text-dim)] font-medium",e.align==="center"&&"text-center",e.align==="right"&&"text-right",!e.align&&"text-left",e.sortable&&"cursor-pointer select-none hover:text-[var(--dash-text-muted)]"),onClick:e.sortable?()=>H(e.id):void 0,children:jsxRuntime.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.header,e.sortable&&p?.column===e.id&&jsxRuntime.jsx("span",{className:"text-[10px]",children:p.direction==="asc"?"\u2191":"\u2193"})]})},e.id))]})}),jsxRuntime.jsx("tbody",{children:V?jsxRuntime.jsx("tr",{children:jsxRuntime.jsx("td",{colSpan:R.length+(l?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:"Loading..."})}):b.length===0?jsxRuntime.jsx("tr",{children:jsxRuntime.jsx("td",{colSpan:R.length+(l?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:W})}):b.map(e=>{let r=f(e),d=v.has(r);return jsxRuntime.jsxs("tr",{className:c("border-b border-[var(--dash-border)] transition-colors",d?"bg-[var(--dash-surface-active)]":"hover:bg-[var(--dash-surface-hover)]"),children:[l&&jsxRuntime.jsx("td",{className:"w-10 px-4 py-2.5",children:jsxRuntime.jsx("input",{type:"checkbox",checked:d,onChange:()=>G(r),className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),s.map(n=>jsxRuntime.jsx("td",{className:c("px-4 py-2.5",n.align==="center"&&"text-center",n.align==="right"&&"text-right"),children:n.cell?n.cell(e):String(e[n.id]??"")},n.id)),y&&jsxRuntime.jsx("td",{className:"px-4 py-2.5 text-right",children:y(e)})]},r)})})]})}),S>1&&jsxRuntime.jsxs("div",{className:"flex items-center justify-between border-t border-[var(--dash-border)] px-4 py-2.5 text-xs text-[var(--dash-text-muted)]",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("span",{children:"Rows per page"}),jsxRuntime.jsx("select",{value:g,onChange:e=>B?.(Number(e.target.value)),className:"h-7 rounded border border-[var(--dash-border)] bg-[var(--dash-bg)] px-2 text-xs text-[var(--dash-text)] focus:outline-none",children:[10,20,50,100].map(e=>jsxRuntime.jsx("option",{value:e,children:e},e))})]}),jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsxs("span",{children:["Page ",o+1," of ",S]}),jsxRuntime.jsx("button",{type:"button",disabled:o===0,onClick:()=>w?.(o-1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),jsxRuntime.jsx("button",{type:"button",disabled:o>=S-1,onClick:()=>w?.(o+1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}i(ee,"DashDataTable");exports.DashDataTable=ee;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import*as u from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';var J=Object.defineProperty;var i=(s,h)=>J(s,"name",{value:h,configurable:true});function c(...s){return twMerge(clsx(s))}i(c,"cn");function ee({columns:s,data:h,rowKey:f,selectable:l=false,selectedKeys:P,onSelectionChange:m,searchable:D=false,searchPlaceholder:j="Search...",totalRows:z,page:o=0,pageSize:g=20,onPageChange:w,onPageSizeChange:B,actions:y,loading:V=false,emptyMessage:W="No data",className:_}){let[x,q]=u.useState(""),[p,A]=u.useState(null),N=u.useMemo(()=>{if(!x)return h;let e=x.toLowerCase();return h.filter(r=>s.some(d=>(d.cell?"":String(r[d.id]??"")).toLowerCase().includes(e)))},[h,x,s]),k=u.useMemo(()=>{if(!p)return N;let{column:e,direction:r}=p;return [...N].sort((d,n)=>{let C=d[e],T=n[e];if(C==null&&T==null)return 0;if(C==null)return 1;if(T==null)return -1;let M=String(C).localeCompare(String(T),void 0,{numeric:true});return r==="asc"?M:-M})},[N,p]),E=z??k.length,S=Math.max(1,Math.ceil(E/g)),b=w?k:k.slice(o*g,(o+1)*g),v=P??new Set,L=b.length>0&&b.every(e=>v.has(f(e)));function F(){m&&m(L?new Set:new Set(b.map(f)));}i(F,"toggleAll");function G(e){if(!m)return;let r=new Set(v);r.has(e)?r.delete(e):r.add(e),m(r);}i(G,"toggleRow");function H(e){A(r=>r?.column===e?r.direction==="asc"?{column:e,direction:"desc"}:null:{column:e,direction:"asc"});}i(H,"handleSort");let R=y?[...s,{id:"__actions",header:"",width:"auto"}]:s;return jsxs("div",{className:c("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)]",_),children:[(D||l)&&jsxs("div",{className:"flex items-center gap-3 border-b border-[var(--dash-border)] px-4 py-3",children:[D&&jsx("input",{type:"text",placeholder:j,value:x,onChange:e=>q(e.target.value),className:c("h-8 w-64 max-w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]")}),l&&v.size>0&&jsxs("span",{className:"text-xs text-[var(--dash-text-muted)]",children:[v.size," selected"]})]}),jsx("div",{className:"overflow-x-auto",children:jsxs("table",{className:"w-full text-sm",children:[jsx("thead",{children:jsxs("tr",{className:"border-b border-[var(--dash-border)]",children:[l&&jsx("th",{className:"w-10 px-4 py-2.5",children:jsx("input",{type:"checkbox",checked:L,onChange:F,className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),R.map(e=>jsx("th",{style:e.width?{width:e.width}:void 0,className:c("px-4 py-2.5 text-[var(--dash-text-dim)] font-medium",e.align==="center"&&"text-center",e.align==="right"&&"text-right",!e.align&&"text-left",e.sortable&&"cursor-pointer select-none hover:text-[var(--dash-text-muted)]"),onClick:e.sortable?()=>H(e.id):void 0,children:jsxs("span",{className:"inline-flex items-center gap-1",children:[e.header,e.sortable&&p?.column===e.id&&jsx("span",{className:"text-[10px]",children:p.direction==="asc"?"\u2191":"\u2193"})]})},e.id))]})}),jsx("tbody",{children:V?jsx("tr",{children:jsx("td",{colSpan:R.length+(l?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:"Loading..."})}):b.length===0?jsx("tr",{children:jsx("td",{colSpan:R.length+(l?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:W})}):b.map(e=>{let r=f(e),d=v.has(r);return jsxs("tr",{className:c("border-b border-[var(--dash-border)] transition-colors",d?"bg-[var(--dash-surface-active)]":"hover:bg-[var(--dash-surface-hover)]"),children:[l&&jsx("td",{className:"w-10 px-4 py-2.5",children:jsx("input",{type:"checkbox",checked:d,onChange:()=>G(r),className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),s.map(n=>jsx("td",{className:c("px-4 py-2.5",n.align==="center"&&"text-center",n.align==="right"&&"text-right"),children:n.cell?n.cell(e):String(e[n.id]??"")},n.id)),y&&jsx("td",{className:"px-4 py-2.5 text-right",children:y(e)})]},r)})})]})}),S>1&&jsxs("div",{className:"flex items-center justify-between border-t border-[var(--dash-border)] px-4 py-2.5 text-xs text-[var(--dash-text-muted)]",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsx("span",{children:"Rows per page"}),jsx("select",{value:g,onChange:e=>B?.(Number(e.target.value)),className:"h-7 rounded border border-[var(--dash-border)] bg-[var(--dash-bg)] px-2 text-xs text-[var(--dash-text)] focus:outline-none",children:[10,20,50,100].map(e=>jsx("option",{value:e,children:e},e))})]}),jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{children:["Page ",o+1," of ",S]}),jsx("button",{type:"button",disabled:o===0,onClick:()=>w?.(o-1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),jsx("button",{type:"button",disabled:o>=S-1,onClick:()=>w?.(o+1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}i(ee,"DashDataTable");export{ee as DashDataTable};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ 'use strict';var f=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var f__namespace=/*#__PURE__*/_interopNamespace(f);var S=Object.defineProperty;var h=(e,t)=>S(e,"name",{value:t,configurable:true});function i(...e){return tailwindMerge.twMerge(clsx.clsx(e))}h(i,"cn");function J({title:e,fields:t,values:m,onSubmit:u,onCancel:l,submitLabel:b="Save",cancelLabel:p="Cancel",loading:d=false,className:a}){let[g,N]=f__namespace.useState(()=>{let s={};for(let o of t)s[o.name]=m?.[o.name]??o.defaultValue??(o.type==="toggle"?false:"");return s}),[k,y]=f__namespace.useState({});function D(s,o){N(n=>({...n,[s]:o})),y(n=>{if(!n[s])return n;let v={...n};return delete v[s],v});}h(D,"setValue");async function F(s){s.preventDefault();let o={};for(let n of t){let v=g[n.name];if(n.required&&(v===""||v===null||v===void 0)&&(o[n.name]=`${n.label} is required`),n.validate){let w=n.validate(v);w&&(o[n.name]=w);}}if(Object.keys(o).length>0){y(o);return}await u(g);}return h(F,"handleSubmit"),jsxRuntime.jsxs("form",{onSubmit:F,className:i("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6",a),children:[e&&jsxRuntime.jsx("h3",{className:"mb-4 text-lg font-semibold text-[var(--dash-text)]",children:e}),jsxRuntime.jsx("div",{className:"space-y-4",children:t.map(s=>jsxRuntime.jsx(V,{field:s,value:g[s.name],error:k[s.name],onChange:o=>D(s.name,o)},s.name))}),jsxRuntime.jsxs("div",{className:"mt-6 flex items-center gap-3",children:[jsxRuntime.jsx("button",{type:"submit",disabled:d,className:i("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]","disabled:opacity-50 disabled:cursor-not-allowed"),children:d?"Saving...":b}),l&&jsxRuntime.jsx("button",{type:"button",onClick:l,disabled:d,className:i("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:p})]})]})}h(J,"DashForm");var x=i("w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 py-2 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","disabled:opacity-50 disabled:cursor-not-allowed","transition-colors");function V({field:e,value:t,error:m,onChange:u}){let l=`dash-field-${e.name}`,b=jsxRuntime.jsxs("label",{htmlFor:l,className:"mb-1 block text-sm font-medium text-[var(--dash-text)]",children:[e.label,e.required&&jsxRuntime.jsx("span",{className:"ml-0.5 text-[var(--dash-error)]",children:"*"})]}),p=e.description?jsxRuntime.jsx("p",{className:"mt-1 text-xs text-[var(--dash-text-dim)]",children:e.description}):null,d=m?jsxRuntime.jsx("p",{className:"mt-1 text-xs text-[var(--dash-error)]",children:m}):null;switch(e.type){case "text":case "email":case "password":case "number":return jsxRuntime.jsxs("div",{children:[b,jsxRuntime.jsx("input",{id:l,type:e.type,value:String(t??""),placeholder:e.placeholder,disabled:e.disabled,onChange:a=>u(e.type==="number"?Number(a.target.value):a.target.value),className:i(x,m&&"border-[var(--dash-error)]")}),p,d]});case "textarea":return jsxRuntime.jsxs("div",{children:[b,jsxRuntime.jsx("textarea",{id:l,value:String(t??""),placeholder:e.placeholder,disabled:e.disabled,rows:e.rows??3,onChange:a=>u(a.target.value),className:i(x,"resize-y",m&&"border-[var(--dash-error)]")}),p,d]});case "select":case "relation":return jsxRuntime.jsxs("div",{children:[b,jsxRuntime.jsxs("select",{id:l,value:String(t??""),disabled:e.disabled,onChange:a=>u(a.target.value),className:i(x,m&&"border-[var(--dash-error)]"),children:[jsxRuntime.jsx("option",{value:"",children:e.placeholder??"Select..."}),(e.options??[]).map(a=>jsxRuntime.jsx("option",{value:a.value,children:a.label},a.value))]}),p,d]});case "toggle":return jsxRuntime.jsxs("div",{className:"flex items-center gap-3",children:[jsxRuntime.jsx("button",{id:l,type:"button",role:"switch","aria-checked":!!t,disabled:e.disabled,onClick:()=>u(!t),className:i("relative inline-flex h-5 w-9 flex-shrink-0 rounded-full transition-colors","focus:outline-none focus:ring-2 focus:ring-[var(--dash-primary)] focus:ring-offset-2 focus:ring-offset-[var(--dash-surface)]",t?"bg-[var(--dash-primary)]":"bg-[var(--dash-border)]",e.disabled&&"opacity-50 cursor-not-allowed"),children:jsxRuntime.jsx("span",{className:i("pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",t?"translate-x-4":"translate-x-0.5","mt-0.5")})}),jsxRuntime.jsx("label",{htmlFor:l,className:"text-sm text-[var(--dash-text)]",children:e.label}),p,d]});case "json":return jsxRuntime.jsxs("div",{children:[b,jsxRuntime.jsx("textarea",{id:l,value:typeof t=="string"?t:JSON.stringify(t,null,2),placeholder:e.placeholder??"{}",disabled:e.disabled,rows:e.rows??6,onChange:a=>{try{u(JSON.parse(a.target.value));}catch{u(a.target.value);}},className:i(x,"font-mono text-xs resize-y",m&&"border-[var(--dash-error)]")}),p,d]});case "file":return jsxRuntime.jsxs("div",{children:[b,jsxRuntime.jsx("input",{id:l,type:"file",accept:e.accept,disabled:e.disabled,onChange:a=>{let g=a.target.files?.[0];g&&u(g);},className:i("w-full text-sm text-[var(--dash-text-muted)]","file:mr-3 file:rounded-[var(--dash-radius-sm)] file:border-0 file:bg-[var(--dash-primary)] file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-[var(--dash-primary-text)]","file:cursor-pointer hover:file:bg-[var(--dash-primary-hover)]")}),p,d]});default:return null}}h(V,"FieldRenderer");exports.DashForm=J;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import*as f from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';var S=Object.defineProperty;var h=(e,t)=>S(e,"name",{value:t,configurable:true});function i(...e){return twMerge(clsx(e))}h(i,"cn");function J({title:e,fields:t,values:m,onSubmit:u,onCancel:l,submitLabel:b="Save",cancelLabel:p="Cancel",loading:d=false,className:a}){let[g,N]=f.useState(()=>{let s={};for(let o of t)s[o.name]=m?.[o.name]??o.defaultValue??(o.type==="toggle"?false:"");return s}),[k,y]=f.useState({});function D(s,o){N(n=>({...n,[s]:o})),y(n=>{if(!n[s])return n;let v={...n};return delete v[s],v});}h(D,"setValue");async function F(s){s.preventDefault();let o={};for(let n of t){let v=g[n.name];if(n.required&&(v===""||v===null||v===void 0)&&(o[n.name]=`${n.label} is required`),n.validate){let w=n.validate(v);w&&(o[n.name]=w);}}if(Object.keys(o).length>0){y(o);return}await u(g);}return h(F,"handleSubmit"),jsxs("form",{onSubmit:F,className:i("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6",a),children:[e&&jsx("h3",{className:"mb-4 text-lg font-semibold text-[var(--dash-text)]",children:e}),jsx("div",{className:"space-y-4",children:t.map(s=>jsx(V,{field:s,value:g[s.name],error:k[s.name],onChange:o=>D(s.name,o)},s.name))}),jsxs("div",{className:"mt-6 flex items-center gap-3",children:[jsx("button",{type:"submit",disabled:d,className:i("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]","disabled:opacity-50 disabled:cursor-not-allowed"),children:d?"Saving...":b}),l&&jsx("button",{type:"button",onClick:l,disabled:d,className:i("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:p})]})]})}h(J,"DashForm");var x=i("w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 py-2 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","disabled:opacity-50 disabled:cursor-not-allowed","transition-colors");function V({field:e,value:t,error:m,onChange:u}){let l=`dash-field-${e.name}`,b=jsxs("label",{htmlFor:l,className:"mb-1 block text-sm font-medium text-[var(--dash-text)]",children:[e.label,e.required&&jsx("span",{className:"ml-0.5 text-[var(--dash-error)]",children:"*"})]}),p=e.description?jsx("p",{className:"mt-1 text-xs text-[var(--dash-text-dim)]",children:e.description}):null,d=m?jsx("p",{className:"mt-1 text-xs text-[var(--dash-error)]",children:m}):null;switch(e.type){case "text":case "email":case "password":case "number":return jsxs("div",{children:[b,jsx("input",{id:l,type:e.type,value:String(t??""),placeholder:e.placeholder,disabled:e.disabled,onChange:a=>u(e.type==="number"?Number(a.target.value):a.target.value),className:i(x,m&&"border-[var(--dash-error)]")}),p,d]});case "textarea":return jsxs("div",{children:[b,jsx("textarea",{id:l,value:String(t??""),placeholder:e.placeholder,disabled:e.disabled,rows:e.rows??3,onChange:a=>u(a.target.value),className:i(x,"resize-y",m&&"border-[var(--dash-error)]")}),p,d]});case "select":case "relation":return jsxs("div",{children:[b,jsxs("select",{id:l,value:String(t??""),disabled:e.disabled,onChange:a=>u(a.target.value),className:i(x,m&&"border-[var(--dash-error)]"),children:[jsx("option",{value:"",children:e.placeholder??"Select..."}),(e.options??[]).map(a=>jsx("option",{value:a.value,children:a.label},a.value))]}),p,d]});case "toggle":return jsxs("div",{className:"flex items-center gap-3",children:[jsx("button",{id:l,type:"button",role:"switch","aria-checked":!!t,disabled:e.disabled,onClick:()=>u(!t),className:i("relative inline-flex h-5 w-9 flex-shrink-0 rounded-full transition-colors","focus:outline-none focus:ring-2 focus:ring-[var(--dash-primary)] focus:ring-offset-2 focus:ring-offset-[var(--dash-surface)]",t?"bg-[var(--dash-primary)]":"bg-[var(--dash-border)]",e.disabled&&"opacity-50 cursor-not-allowed"),children:jsx("span",{className:i("pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",t?"translate-x-4":"translate-x-0.5","mt-0.5")})}),jsx("label",{htmlFor:l,className:"text-sm text-[var(--dash-text)]",children:e.label}),p,d]});case "json":return jsxs("div",{children:[b,jsx("textarea",{id:l,value:typeof t=="string"?t:JSON.stringify(t,null,2),placeholder:e.placeholder??"{}",disabled:e.disabled,rows:e.rows??6,onChange:a=>{try{u(JSON.parse(a.target.value));}catch{u(a.target.value);}},className:i(x,"font-mono text-xs resize-y",m&&"border-[var(--dash-error)]")}),p,d]});case "file":return jsxs("div",{children:[b,jsx("input",{id:l,type:"file",accept:e.accept,disabled:e.disabled,onChange:a=>{let g=a.target.files?.[0];g&&u(g);},className:i("w-full text-sm text-[var(--dash-text-muted)]","file:mr-3 file:rounded-[var(--dash-radius-sm)] file:border-0 file:bg-[var(--dash-primary)] file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-[var(--dash-primary-text)]","file:cursor-pointer hover:file:bg-[var(--dash-primary-hover)]")}),p,d]});default:return null}}h(V,"FieldRenderer");export{J as DashForm};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ 'use strict';var r=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var r__namespace=/*#__PURE__*/_interopNamespace(r);var k=Object.defineProperty;var o=(a,n)=>k(a,"name",{value:n,configurable:true});function v(...a){return tailwindMerge.twMerge(clsx.clsx(a))}o(v,"cn");function E({breadcrumbs:a,searchPlaceholder:n="Search...",onSearch:u,avatarUrl:i,userName:l,userDropdown:m,onToggleTheme:p,theme:f="dark",actions:g,className:b}){let[c,x]=r__namespace.useState(false),h=r__namespace.useRef(null);return r__namespace.useEffect(()=>{if(!c)return;function t(d){h.current&&!h.current.contains(d.target)&&x(false);}return o(t,"handleClick"),document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[c]),jsxRuntime.jsxs("div",{className:v("flex h-[var(--dash-header-height)] items-center gap-4 px-4","bg-[var(--dash-surface)] text-[var(--dash-text)]",b),children:[a&&a.length>0&&jsxRuntime.jsx("nav",{className:"flex items-center gap-1 text-sm","aria-label":"Breadcrumb",children:a.map((t,d)=>jsxRuntime.jsxs(r__namespace.Fragment,{children:[d>0&&jsxRuntime.jsx("span",{className:"text-[var(--dash-text-dim)]",children:"/"}),t.href?jsxRuntime.jsx("a",{href:t.href,className:"text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:t.label}):jsxRuntime.jsx("span",{className:"text-[var(--dash-text)]",children:t.label})]},d))}),jsxRuntime.jsx("div",{className:"flex-1"}),u&&jsxRuntime.jsxs("div",{className:"relative hidden sm:block",children:[jsxRuntime.jsxs("svg",{className:"absolute left-2.5 top-1/2 -translate-y-1/2 text-[var(--dash-text-dim)]",width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:[jsxRuntime.jsx("circle",{cx:"7",cy:"7",r:"5.5",stroke:"currentColor",strokeWidth:"1.5"}),jsxRuntime.jsx("path",{d:"M11 11l3 3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}),jsxRuntime.jsx("input",{type:"text",placeholder:n,onChange:t=>u(t.target.value),className:v("h-8 w-56 rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] pl-8 pr-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","transition-colors")})]}),g,p&&jsxRuntime.jsx("button",{type:"button",onClick:p,className:"rounded-[var(--dash-radius-sm)] p-1.5 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors","aria-label":`Switch to ${f==="dark"?"light":"dark"} mode`,children:f==="dark"?jsxRuntime.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:[jsxRuntime.jsx("circle",{cx:"8",cy:"8",r:"3.5",stroke:"currentColor",strokeWidth:"1.5"}),jsxRuntime.jsx("path",{d:"M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}):jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M14 9.5A6.5 6.5 0 016.5 2 5.5 5.5 0 1014 9.5z",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),(i||l)&&jsxRuntime.jsxs("div",{className:"relative",ref:h,children:[jsxRuntime.jsx("button",{type:"button",onClick:()=>x(t=>!t),className:"flex items-center gap-2 rounded-[var(--dash-radius-sm)] p-1 hover:bg-[var(--dash-surface-hover)] transition-colors",children:i?jsxRuntime.jsx("img",{src:i,alt:l??"User",className:"h-7 w-7 rounded-full object-cover"}):jsxRuntime.jsx("div",{className:"flex h-7 w-7 items-center justify-center rounded-full bg-[var(--dash-primary)] text-xs font-medium text-[var(--dash-primary-text)]",children:(l??"?")[0].toUpperCase()})}),c&&m&&jsxRuntime.jsx("div",{className:"absolute right-0 top-full z-50 mt-1 min-w-48 rounded-[var(--dash-radius)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 shadow-lg",children:m})]})]})}o(E,"DashHeader");exports.DashHeader=E;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import*as r from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';var k=Object.defineProperty;var o=(a,n)=>k(a,"name",{value:n,configurable:true});function v(...a){return twMerge(clsx(a))}o(v,"cn");function E({breadcrumbs:a,searchPlaceholder:n="Search...",onSearch:u,avatarUrl:i,userName:l,userDropdown:m,onToggleTheme:p,theme:f="dark",actions:g,className:b}){let[c,x]=r.useState(false),h=r.useRef(null);return r.useEffect(()=>{if(!c)return;function t(d){h.current&&!h.current.contains(d.target)&&x(false);}return o(t,"handleClick"),document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[c]),jsxs("div",{className:v("flex h-[var(--dash-header-height)] items-center gap-4 px-4","bg-[var(--dash-surface)] text-[var(--dash-text)]",b),children:[a&&a.length>0&&jsx("nav",{className:"flex items-center gap-1 text-sm","aria-label":"Breadcrumb",children:a.map((t,d)=>jsxs(r.Fragment,{children:[d>0&&jsx("span",{className:"text-[var(--dash-text-dim)]",children:"/"}),t.href?jsx("a",{href:t.href,className:"text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:t.label}):jsx("span",{className:"text-[var(--dash-text)]",children:t.label})]},d))}),jsx("div",{className:"flex-1"}),u&&jsxs("div",{className:"relative hidden sm:block",children:[jsxs("svg",{className:"absolute left-2.5 top-1/2 -translate-y-1/2 text-[var(--dash-text-dim)]",width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:[jsx("circle",{cx:"7",cy:"7",r:"5.5",stroke:"currentColor",strokeWidth:"1.5"}),jsx("path",{d:"M11 11l3 3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}),jsx("input",{type:"text",placeholder:n,onChange:t=>u(t.target.value),className:v("h-8 w-56 rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] pl-8 pr-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","transition-colors")})]}),g,p&&jsx("button",{type:"button",onClick:p,className:"rounded-[var(--dash-radius-sm)] p-1.5 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors","aria-label":`Switch to ${f==="dark"?"light":"dark"} mode`,children:f==="dark"?jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:[jsx("circle",{cx:"8",cy:"8",r:"3.5",stroke:"currentColor",strokeWidth:"1.5"}),jsx("path",{d:"M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}):jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M14 9.5A6.5 6.5 0 016.5 2 5.5 5.5 0 1014 9.5z",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),(i||l)&&jsxs("div",{className:"relative",ref:h,children:[jsx("button",{type:"button",onClick:()=>x(t=>!t),className:"flex items-center gap-2 rounded-[var(--dash-radius-sm)] p-1 hover:bg-[var(--dash-surface-hover)] transition-colors",children:i?jsx("img",{src:i,alt:l??"User",className:"h-7 w-7 rounded-full object-cover"}):jsx("div",{className:"flex h-7 w-7 items-center justify-center rounded-full bg-[var(--dash-primary)] text-xs font-medium text-[var(--dash-primary-text)]",children:(l??"?")[0].toUpperCase()})}),c&&m&&jsx("div",{className:"absolute right-0 top-full z-50 mt-1 min-w-48 rounded-[var(--dash-radius)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 shadow-lg",children:m})]})]})}o(E,"DashHeader");export{E as DashHeader};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ 'use strict';var clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');var n=Object.defineProperty;var r=(e,a)=>n(e,"name",{value:a,configurable:true});function s(...e){return tailwindMerge.twMerge(clsx.clsx(e))}r(s,"cn");function N({sidebar:e,header:a,children:t,sidebarCollapsed:d=false,onSidebarCollapse:i,className:c}){return jsxRuntime.jsxs("div",{className:s("flex h-screen overflow-hidden","bg-[var(--dash-bg)] text-[var(--dash-text)]",c),children:[jsxRuntime.jsx("aside",{className:s("flex-shrink-0 overflow-y-auto overflow-x-hidden transition-[width] duration-200","border-r border-[var(--dash-border)] bg-[var(--dash-surface)]",d?"w-[var(--dash-sidebar-collapsed-width)]":"w-[var(--dash-sidebar-width)]"),children:e}),jsxRuntime.jsxs("div",{className:"flex flex-1 flex-col overflow-hidden",children:[a&&jsxRuntime.jsx("header",{className:"flex-shrink-0 border-b border-[var(--dash-border)] bg-[var(--dash-surface)]",children:a}),jsxRuntime.jsx("main",{className:"flex-1 overflow-y-auto p-6",children:t})]}),!d&&jsxRuntime.jsx("div",{className:"fixed inset-0 z-40 bg-black/60 lg:hidden",onClick:()=>i?.(true)})]})}r(N,"DashLayout");exports.DashLayout=N;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';var n=Object.defineProperty;var r=(e,a)=>n(e,"name",{value:a,configurable:true});function s(...e){return twMerge(clsx(e))}r(s,"cn");function N({sidebar:e,header:a,children:t,sidebarCollapsed:d=false,onSidebarCollapse:i,className:c}){return jsxs("div",{className:s("flex h-screen overflow-hidden","bg-[var(--dash-bg)] text-[var(--dash-text)]",c),children:[jsx("aside",{className:s("flex-shrink-0 overflow-y-auto overflow-x-hidden transition-[width] duration-200","border-r border-[var(--dash-border)] bg-[var(--dash-surface)]",d?"w-[var(--dash-sidebar-collapsed-width)]":"w-[var(--dash-sidebar-width)]"),children:e}),jsxs("div",{className:"flex flex-1 flex-col overflow-hidden",children:[a&&jsx("header",{className:"flex-shrink-0 border-b border-[var(--dash-border)] bg-[var(--dash-surface)]",children:a}),jsx("main",{className:"flex-1 overflow-y-auto p-6",children:t})]}),!d&&jsx("div",{className:"fixed inset-0 z-40 bg-black/60 lg:hidden",onClick:()=>i?.(true)})]})}r(N,"DashLayout");export{N as DashLayout};
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ 'use strict';var v=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var v__namespace=/*#__PURE__*/_interopNamespace(v);var p=Object.defineProperty;var n=(t,r)=>p(t,"name",{value:r,configurable:true});function i(...t){return tailwindMerge.twMerge(clsx.clsx(t))}n(i,"cn");function b({size:t=28}){return jsxRuntime.jsx("svg",{width:t,height:t,viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsxRuntime.jsx("path",{d:"M4 4h4v6h8V4h4v16h-4v-6H8v6H4V4z",fill:"currentColor"})})}n(b,"HanzoMark");function L({logo:t,groups:r,userMenu:h,collapsed:o=false,onToggleCollapse:s,onNavigate:l,className:a}){return jsxRuntime.jsxs("nav",{className:i("flex h-full flex-col","bg-[var(--dash-surface)] text-[var(--dash-text)]",a),children:[jsxRuntime.jsxs("div",{className:i("flex h-[var(--dash-header-height)] items-center border-b border-[var(--dash-border)]",o?"justify-center px-2":"px-4"),children:[t??jsxRuntime.jsx(b,{}),!o&&s&&jsxRuntime.jsx("button",{type:"button",onClick:s,className:"ml-auto rounded p-1 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]","aria-label":"Collapse sidebar",children:jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),o&&s&&jsxRuntime.jsx("button",{type:"button",onClick:s,className:"absolute -right-3 top-4 z-50 hidden rounded-full border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 text-[var(--dash-text-dim)] hover:text-[var(--dash-text)] lg:flex","aria-label":"Expand sidebar",children:jsxRuntime.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),jsxRuntime.jsx("div",{className:"flex-1 overflow-y-auto py-2",children:r.map((u,c)=>jsxRuntime.jsx(m,{group:u,collapsed:o,onNavigate:l},c))}),h&&jsxRuntime.jsx("div",{className:"border-t border-[var(--dash-border)] p-2",children:h})]})}n(L,"DashSidebar");function m({group:t,collapsed:r,onNavigate:h}){let[o,s]=v__namespace.useState(t.defaultOpen!==false),l=t.collapsible!==false&&!!t.title;return jsxRuntime.jsxs("div",{className:"mb-1",children:[t.title&&!r&&jsxRuntime.jsxs("button",{type:"button",onClick:()=>l&&s(a=>!a),className:i("flex w-full items-center px-4 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-[var(--dash-text-dim)]",l&&"cursor-pointer hover:text-[var(--dash-text-muted)]"),children:[jsxRuntime.jsx("span",{className:"flex-1 text-left",children:t.title}),l&&jsxRuntime.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",className:i("transition-transform",o?"rotate-0":"-rotate-90"),children:jsxRuntime.jsx("path",{d:"M4 6l4 4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})]}),(o||r)&&jsxRuntime.jsx("ul",{className:"space-y-0.5 px-2",children:t.items.map(a=>jsxRuntime.jsx("li",{children:jsxRuntime.jsxs("button",{type:"button",onClick:()=>h?.(a.href),title:r?a.label:void 0,className:i("flex w-full items-center gap-2 rounded-[var(--dash-radius-sm)] px-2 py-1.5 text-sm transition-colors",a.active?"bg-[var(--dash-primary)] text-[var(--dash-primary-text)]":"text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]",r&&"justify-center px-0"),children:[a.icon&&jsxRuntime.jsx("span",{className:"flex h-5 w-5 items-center justify-center flex-shrink-0",children:a.icon}),!r&&jsxRuntime.jsx("span",{className:"flex-1 truncate text-left",children:a.label}),!r&&a.badge!==void 0&&jsxRuntime.jsx("span",{className:"ml-auto rounded-full bg-[var(--dash-primary)] px-1.5 py-0.5 text-[10px] font-medium text-[var(--dash-primary-text)]",children:a.badge})]})},a.href))})]})}n(m,"SidebarGroup");
3
+ exports.DashSidebar=L;
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import*as v from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';var p=Object.defineProperty;var n=(t,r)=>p(t,"name",{value:r,configurable:true});function i(...t){return twMerge(clsx(t))}n(i,"cn");function b({size:t=28}){return jsx("svg",{width:t,height:t,viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsx("path",{d:"M4 4h4v6h8V4h4v16h-4v-6H8v6H4V4z",fill:"currentColor"})})}n(b,"HanzoMark");function L({logo:t,groups:r,userMenu:h,collapsed:o=false,onToggleCollapse:s,onNavigate:l,className:a}){return jsxs("nav",{className:i("flex h-full flex-col","bg-[var(--dash-surface)] text-[var(--dash-text)]",a),children:[jsxs("div",{className:i("flex h-[var(--dash-header-height)] items-center border-b border-[var(--dash-border)]",o?"justify-center px-2":"px-4"),children:[t??jsx(b,{}),!o&&s&&jsx("button",{type:"button",onClick:s,className:"ml-auto rounded p-1 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]","aria-label":"Collapse sidebar",children:jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),o&&s&&jsx("button",{type:"button",onClick:s,className:"absolute -right-3 top-4 z-50 hidden rounded-full border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 text-[var(--dash-text-dim)] hover:text-[var(--dash-text)] lg:flex","aria-label":"Expand sidebar",children:jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),jsx("div",{className:"flex-1 overflow-y-auto py-2",children:r.map((u,c)=>jsx(m,{group:u,collapsed:o,onNavigate:l},c))}),h&&jsx("div",{className:"border-t border-[var(--dash-border)] p-2",children:h})]})}n(L,"DashSidebar");function m({group:t,collapsed:r,onNavigate:h}){let[o,s]=v.useState(t.defaultOpen!==false),l=t.collapsible!==false&&!!t.title;return jsxs("div",{className:"mb-1",children:[t.title&&!r&&jsxs("button",{type:"button",onClick:()=>l&&s(a=>!a),className:i("flex w-full items-center px-4 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-[var(--dash-text-dim)]",l&&"cursor-pointer hover:text-[var(--dash-text-muted)]"),children:[jsx("span",{className:"flex-1 text-left",children:t.title}),l&&jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",className:i("transition-transform",o?"rotate-0":"-rotate-90"),children:jsx("path",{d:"M4 6l4 4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})]}),(o||r)&&jsx("ul",{className:"space-y-0.5 px-2",children:t.items.map(a=>jsx("li",{children:jsxs("button",{type:"button",onClick:()=>h?.(a.href),title:r?a.label:void 0,className:i("flex w-full items-center gap-2 rounded-[var(--dash-radius-sm)] px-2 py-1.5 text-sm transition-colors",a.active?"bg-[var(--dash-primary)] text-[var(--dash-primary-text)]":"text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]",r&&"justify-center px-0"),children:[a.icon&&jsx("span",{className:"flex h-5 w-5 items-center justify-center flex-shrink-0",children:a.icon}),!r&&jsx("span",{className:"flex-1 truncate text-left",children:a.label}),!r&&a.badge!==void 0&&jsx("span",{className:"ml-auto rounded-full bg-[var(--dash-primary)] px-1.5 py-0.5 text-[10px] font-medium text-[var(--dash-primary-text)]",children:a.badge})]})},a.href))})]})}n(m,"SidebarGroup");
3
+ export{L as DashSidebar};
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ 'use strict';var clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime'),q=require('react');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var q__namespace=/*#__PURE__*/_interopNamespace(q);var ie=Object.defineProperty;var i=(e,a)=>ie(e,"name",{value:a,configurable:true});function r(...e){return tailwindMerge.twMerge(clsx.clsx(e))}i(r,"cn");function ce({sidebar:e,header:a,children:l,sidebarCollapsed:s=false,onSidebarCollapse:n,className:c}){return jsxRuntime.jsxs("div",{className:r("flex h-screen overflow-hidden","bg-[var(--dash-bg)] text-[var(--dash-text)]",c),children:[jsxRuntime.jsx("aside",{className:r("flex-shrink-0 overflow-y-auto overflow-x-hidden transition-[width] duration-200","border-r border-[var(--dash-border)] bg-[var(--dash-surface)]",s?"w-[var(--dash-sidebar-collapsed-width)]":"w-[var(--dash-sidebar-width)]"),children:e}),jsxRuntime.jsxs("div",{className:"flex flex-1 flex-col overflow-hidden",children:[a&&jsxRuntime.jsx("header",{className:"flex-shrink-0 border-b border-[var(--dash-border)] bg-[var(--dash-surface)]",children:a}),jsxRuntime.jsx("main",{className:"flex-1 overflow-y-auto p-6",children:l})]}),!s&&jsxRuntime.jsx("div",{className:"fixed inset-0 z-40 bg-black/60 lg:hidden",onClick:()=>n?.(true)})]})}i(ce,"DashLayout");function ue({size:e=28}){return jsxRuntime.jsx("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsxRuntime.jsx("path",{d:"M4 4h4v6h8V4h4v16h-4v-6H8v6H4V4z",fill:"currentColor"})})}i(ue,"HanzoMark");function he({logo:e,groups:a,userMenu:l,collapsed:s=false,onToggleCollapse:n,onNavigate:c,className:o}){return jsxRuntime.jsxs("nav",{className:r("flex h-full flex-col","bg-[var(--dash-surface)] text-[var(--dash-text)]",o),children:[jsxRuntime.jsxs("div",{className:r("flex h-[var(--dash-header-height)] items-center border-b border-[var(--dash-border)]",s?"justify-center px-2":"px-4"),children:[e??jsxRuntime.jsx(ue,{}),!s&&n&&jsxRuntime.jsx("button",{type:"button",onClick:n,className:"ml-auto rounded p-1 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]","aria-label":"Collapse sidebar",children:jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),s&&n&&jsxRuntime.jsx("button",{type:"button",onClick:n,className:"absolute -right-3 top-4 z-50 hidden rounded-full border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 text-[var(--dash-text-dim)] hover:text-[var(--dash-text)] lg:flex","aria-label":"Expand sidebar",children:jsxRuntime.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),jsxRuntime.jsx("div",{className:"flex-1 overflow-y-auto py-2",children:a.map((m,d)=>jsxRuntime.jsx(me,{group:m,collapsed:s,onNavigate:c},d))}),l&&jsxRuntime.jsx("div",{className:"border-t border-[var(--dash-border)] p-2",children:l})]})}i(he,"DashSidebar");function me({group:e,collapsed:a,onNavigate:l}){let[s,n]=q__namespace.useState(e.defaultOpen!==false),c=e.collapsible!==false&&!!e.title;return jsxRuntime.jsxs("div",{className:"mb-1",children:[e.title&&!a&&jsxRuntime.jsxs("button",{type:"button",onClick:()=>c&&n(o=>!o),className:r("flex w-full items-center px-4 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-[var(--dash-text-dim)]",c&&"cursor-pointer hover:text-[var(--dash-text-muted)]"),children:[jsxRuntime.jsx("span",{className:"flex-1 text-left",children:e.title}),c&&jsxRuntime.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",className:r("transition-transform",s?"rotate-0":"-rotate-90"),children:jsxRuntime.jsx("path",{d:"M4 6l4 4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})]}),(s||a)&&jsxRuntime.jsx("ul",{className:"space-y-0.5 px-2",children:e.items.map(o=>jsxRuntime.jsx("li",{children:jsxRuntime.jsxs("button",{type:"button",onClick:()=>l?.(o.href),title:a?o.label:void 0,className:r("flex w-full items-center gap-2 rounded-[var(--dash-radius-sm)] px-2 py-1.5 text-sm transition-colors",o.active?"bg-[var(--dash-primary)] text-[var(--dash-primary-text)]":"text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]",a&&"justify-center px-0"),children:[o.icon&&jsxRuntime.jsx("span",{className:"flex h-5 w-5 items-center justify-center flex-shrink-0",children:o.icon}),!a&&jsxRuntime.jsx("span",{className:"flex-1 truncate text-left",children:o.label}),!a&&o.badge!==void 0&&jsxRuntime.jsx("span",{className:"ml-auto rounded-full bg-[var(--dash-primary)] px-1.5 py-0.5 text-[10px] font-medium text-[var(--dash-primary-text)]",children:o.badge})]})},o.href))})]})}i(me,"SidebarGroup");function ve({breadcrumbs:e,searchPlaceholder:a="Search...",onSearch:l,avatarUrl:s,userName:n,userDropdown:c,onToggleTheme:o,theme:m="dark",actions:d,className:v}){let[D,C]=q__namespace.useState(false),R=q__namespace.useRef(null);return q__namespace.useEffect(()=>{if(!D)return;function b(P){R.current&&!R.current.contains(P.target)&&C(false);}return i(b,"handleClick"),document.addEventListener("mousedown",b),()=>document.removeEventListener("mousedown",b)},[D]),jsxRuntime.jsxs("div",{className:r("flex h-[var(--dash-header-height)] items-center gap-4 px-4","bg-[var(--dash-surface)] text-[var(--dash-text)]",v),children:[e&&e.length>0&&jsxRuntime.jsx("nav",{className:"flex items-center gap-1 text-sm","aria-label":"Breadcrumb",children:e.map((b,P)=>jsxRuntime.jsxs(q__namespace.Fragment,{children:[P>0&&jsxRuntime.jsx("span",{className:"text-[var(--dash-text-dim)]",children:"/"}),b.href?jsxRuntime.jsx("a",{href:b.href,className:"text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:b.label}):jsxRuntime.jsx("span",{className:"text-[var(--dash-text)]",children:b.label})]},P))}),jsxRuntime.jsx("div",{className:"flex-1"}),l&&jsxRuntime.jsxs("div",{className:"relative hidden sm:block",children:[jsxRuntime.jsxs("svg",{className:"absolute left-2.5 top-1/2 -translate-y-1/2 text-[var(--dash-text-dim)]",width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:[jsxRuntime.jsx("circle",{cx:"7",cy:"7",r:"5.5",stroke:"currentColor",strokeWidth:"1.5"}),jsxRuntime.jsx("path",{d:"M11 11l3 3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}),jsxRuntime.jsx("input",{type:"text",placeholder:a,onChange:b=>l(b.target.value),className:r("h-8 w-56 rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] pl-8 pr-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","transition-colors")})]}),d,o&&jsxRuntime.jsx("button",{type:"button",onClick:o,className:"rounded-[var(--dash-radius-sm)] p-1.5 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors","aria-label":`Switch to ${m==="dark"?"light":"dark"} mode`,children:m==="dark"?jsxRuntime.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:[jsxRuntime.jsx("circle",{cx:"8",cy:"8",r:"3.5",stroke:"currentColor",strokeWidth:"1.5"}),jsxRuntime.jsx("path",{d:"M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}):jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M14 9.5A6.5 6.5 0 016.5 2 5.5 5.5 0 1014 9.5z",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),(s||n)&&jsxRuntime.jsxs("div",{className:"relative",ref:R,children:[jsxRuntime.jsx("button",{type:"button",onClick:()=>C(b=>!b),className:"flex items-center gap-2 rounded-[var(--dash-radius-sm)] p-1 hover:bg-[var(--dash-surface-hover)] transition-colors",children:s?jsxRuntime.jsx("img",{src:s,alt:n??"User",className:"h-7 w-7 rounded-full object-cover"}):jsxRuntime.jsx("div",{className:"flex h-7 w-7 items-center justify-center rounded-full bg-[var(--dash-primary)] text-xs font-medium text-[var(--dash-primary-text)]",children:(n??"?")[0].toUpperCase()})}),D&&c&&jsxRuntime.jsx("div",{className:"absolute right-0 top-full z-50 mt-1 min-w-48 rounded-[var(--dash-radius)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 shadow-lg",children:c})]})]})}i(ve,"DashHeader");function te({columns:e,data:a,rowKey:l,selectable:s=false,selectedKeys:n,onSelectionChange:c,searchable:o=false,searchPlaceholder:m="Search...",totalRows:d,page:v=0,pageSize:D=20,onPageChange:C,onPageSizeChange:R,actions:b,loading:P=false,emptyMessage:f="No data",className:x}){let[u,w]=q__namespace.useState(""),[S,A]=q__namespace.useState(null),G=q__namespace.useMemo(()=>{if(!u)return a;let t=u.toLowerCase();return a.filter(k=>e.some(O=>(O.cell?"":String(k[O.id]??"")).toLowerCase().includes(t)))},[a,u,e]),W=q__namespace.useMemo(()=>{if(!S)return G;let{column:t,direction:k}=S;return [...G].sort((O,E)=>{let Z=O[t],ee=E[t];if(Z==null&&ee==null)return 0;if(Z==null)return 1;if(ee==null)return -1;let se=String(Z).localeCompare(String(ee),void 0,{numeric:true});return k==="asc"?se:-se})},[G,S]),I=d??W.length,z=Math.max(1,Math.ceil(I/D)),j=C?W:W.slice(v*D,(v+1)*D),M=n??new Set,J=j.length>0&&j.every(t=>M.has(l(t)));function U(){c&&c(J?new Set:new Set(j.map(l)));}i(U,"toggleAll");function X(t){if(!c)return;let k=new Set(M);k.has(t)?k.delete(t):k.add(t),c(k);}i(X,"toggleRow");function Y(t){A(k=>k?.column===t?k.direction==="asc"?{column:t,direction:"desc"}:null:{column:t,direction:"asc"});}i(Y,"handleSort");let N=b?[...e,{id:"__actions",header:"",width:"auto"}]:e;return jsxRuntime.jsxs("div",{className:r("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)]",x),children:[(o||s)&&jsxRuntime.jsxs("div",{className:"flex items-center gap-3 border-b border-[var(--dash-border)] px-4 py-3",children:[o&&jsxRuntime.jsx("input",{type:"text",placeholder:m,value:u,onChange:t=>w(t.target.value),className:r("h-8 w-64 max-w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]")}),s&&M.size>0&&jsxRuntime.jsxs("span",{className:"text-xs text-[var(--dash-text-muted)]",children:[M.size," selected"]})]}),jsxRuntime.jsx("div",{className:"overflow-x-auto",children:jsxRuntime.jsxs("table",{className:"w-full text-sm",children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{className:"border-b border-[var(--dash-border)]",children:[s&&jsxRuntime.jsx("th",{className:"w-10 px-4 py-2.5",children:jsxRuntime.jsx("input",{type:"checkbox",checked:J,onChange:U,className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),N.map(t=>jsxRuntime.jsx("th",{style:t.width?{width:t.width}:void 0,className:r("px-4 py-2.5 text-[var(--dash-text-dim)] font-medium",t.align==="center"&&"text-center",t.align==="right"&&"text-right",!t.align&&"text-left",t.sortable&&"cursor-pointer select-none hover:text-[var(--dash-text-muted)]"),onClick:t.sortable?()=>Y(t.id):void 0,children:jsxRuntime.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.header,t.sortable&&S?.column===t.id&&jsxRuntime.jsx("span",{className:"text-[10px]",children:S.direction==="asc"?"\u2191":"\u2193"})]})},t.id))]})}),jsxRuntime.jsx("tbody",{children:P?jsxRuntime.jsx("tr",{children:jsxRuntime.jsx("td",{colSpan:N.length+(s?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:"Loading..."})}):j.length===0?jsxRuntime.jsx("tr",{children:jsxRuntime.jsx("td",{colSpan:N.length+(s?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:f})}):j.map(t=>{let k=l(t),O=M.has(k);return jsxRuntime.jsxs("tr",{className:r("border-b border-[var(--dash-border)] transition-colors",O?"bg-[var(--dash-surface-active)]":"hover:bg-[var(--dash-surface-hover)]"),children:[s&&jsxRuntime.jsx("td",{className:"w-10 px-4 py-2.5",children:jsxRuntime.jsx("input",{type:"checkbox",checked:O,onChange:()=>X(k),className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),e.map(E=>jsxRuntime.jsx("td",{className:r("px-4 py-2.5",E.align==="center"&&"text-center",E.align==="right"&&"text-right"),children:E.cell?E.cell(t):String(t[E.id]??"")},E.id)),b&&jsxRuntime.jsx("td",{className:"px-4 py-2.5 text-right",children:b(t)})]},k)})})]})}),z>1&&jsxRuntime.jsxs("div",{className:"flex items-center justify-between border-t border-[var(--dash-border)] px-4 py-2.5 text-xs text-[var(--dash-text-muted)]",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("span",{children:"Rows per page"}),jsxRuntime.jsx("select",{value:D,onChange:t=>R?.(Number(t.target.value)),className:"h-7 rounded border border-[var(--dash-border)] bg-[var(--dash-bg)] px-2 text-xs text-[var(--dash-text)] focus:outline-none",children:[10,20,50,100].map(t=>jsxRuntime.jsx("option",{value:t,children:t},t))})]}),jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsxs("span",{children:["Page ",v+1," of ",z]}),jsxRuntime.jsx("button",{type:"button",disabled:v===0,onClick:()=>C?.(v-1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),jsxRuntime.jsx("button",{type:"button",disabled:v>=z-1,onClick:()=>C?.(v+1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}i(te,"DashDataTable");function re({title:e,fields:a,values:l,onSubmit:s,onCancel:n,submitLabel:c="Save",cancelLabel:o="Cancel",loading:m=false,className:d}){let[v,D]=q__namespace.useState(()=>{let f={};for(let x of a)f[x.name]=l?.[x.name]??x.defaultValue??(x.type==="toggle"?false:"");return f}),[C,R]=q__namespace.useState({});function b(f,x){D(u=>({...u,[f]:x})),R(u=>{if(!u[f])return u;let w={...u};return delete w[f],w});}i(b,"setValue");async function P(f){f.preventDefault();let x={};for(let u of a){let w=v[u.name];if(u.required&&(w===""||w===null||w===void 0)&&(x[u.name]=`${u.label} is required`),u.validate){let S=u.validate(w);S&&(x[u.name]=S);}}if(Object.keys(x).length>0){R(x);return}await s(v);}return i(P,"handleSubmit"),jsxRuntime.jsxs("form",{onSubmit:P,className:r("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6",d),children:[e&&jsxRuntime.jsx("h3",{className:"mb-4 text-lg font-semibold text-[var(--dash-text)]",children:e}),jsxRuntime.jsx("div",{className:"space-y-4",children:a.map(f=>jsxRuntime.jsx(pe,{field:f,value:v[f.name],error:C[f.name],onChange:x=>b(f.name,x)},f.name))}),jsxRuntime.jsxs("div",{className:"mt-6 flex items-center gap-3",children:[jsxRuntime.jsx("button",{type:"submit",disabled:m,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]","disabled:opacity-50 disabled:cursor-not-allowed"),children:m?"Saving...":c}),n&&jsxRuntime.jsx("button",{type:"button",onClick:n,disabled:m,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:o})]})]})}i(re,"DashForm");var Q=r("w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 py-2 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","disabled:opacity-50 disabled:cursor-not-allowed","transition-colors");function pe({field:e,value:a,error:l,onChange:s}){let n=`dash-field-${e.name}`,c=jsxRuntime.jsxs("label",{htmlFor:n,className:"mb-1 block text-sm font-medium text-[var(--dash-text)]",children:[e.label,e.required&&jsxRuntime.jsx("span",{className:"ml-0.5 text-[var(--dash-error)]",children:"*"})]}),o=e.description?jsxRuntime.jsx("p",{className:"mt-1 text-xs text-[var(--dash-text-dim)]",children:e.description}):null,m=l?jsxRuntime.jsx("p",{className:"mt-1 text-xs text-[var(--dash-error)]",children:l}):null;switch(e.type){case "text":case "email":case "password":case "number":return jsxRuntime.jsxs("div",{children:[c,jsxRuntime.jsx("input",{id:n,type:e.type,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,onChange:d=>s(e.type==="number"?Number(d.target.value):d.target.value),className:r(Q,l&&"border-[var(--dash-error)]")}),o,m]});case "textarea":return jsxRuntime.jsxs("div",{children:[c,jsxRuntime.jsx("textarea",{id:n,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,rows:e.rows??3,onChange:d=>s(d.target.value),className:r(Q,"resize-y",l&&"border-[var(--dash-error)]")}),o,m]});case "select":case "relation":return jsxRuntime.jsxs("div",{children:[c,jsxRuntime.jsxs("select",{id:n,value:String(a??""),disabled:e.disabled,onChange:d=>s(d.target.value),className:r(Q,l&&"border-[var(--dash-error)]"),children:[jsxRuntime.jsx("option",{value:"",children:e.placeholder??"Select..."}),(e.options??[]).map(d=>jsxRuntime.jsx("option",{value:d.value,children:d.label},d.value))]}),o,m]});case "toggle":return jsxRuntime.jsxs("div",{className:"flex items-center gap-3",children:[jsxRuntime.jsx("button",{id:n,type:"button",role:"switch","aria-checked":!!a,disabled:e.disabled,onClick:()=>s(!a),className:r("relative inline-flex h-5 w-9 flex-shrink-0 rounded-full transition-colors","focus:outline-none focus:ring-2 focus:ring-[var(--dash-primary)] focus:ring-offset-2 focus:ring-offset-[var(--dash-surface)]",a?"bg-[var(--dash-primary)]":"bg-[var(--dash-border)]",e.disabled&&"opacity-50 cursor-not-allowed"),children:jsxRuntime.jsx("span",{className:r("pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",a?"translate-x-4":"translate-x-0.5","mt-0.5")})}),jsxRuntime.jsx("label",{htmlFor:n,className:"text-sm text-[var(--dash-text)]",children:e.label}),o,m]});case "json":return jsxRuntime.jsxs("div",{children:[c,jsxRuntime.jsx("textarea",{id:n,value:typeof a=="string"?a:JSON.stringify(a,null,2),placeholder:e.placeholder??"{}",disabled:e.disabled,rows:e.rows??6,onChange:d=>{try{s(JSON.parse(d.target.value));}catch{s(d.target.value);}},className:r(Q,"font-mono text-xs resize-y",l&&"border-[var(--dash-error)]")}),o,m]});case "file":return jsxRuntime.jsxs("div",{children:[c,jsxRuntime.jsx("input",{id:n,type:"file",accept:e.accept,disabled:e.disabled,onChange:d=>{let v=d.target.files?.[0];v&&s(v);},className:r("w-full text-sm text-[var(--dash-text-muted)]","file:mr-3 file:rounded-[var(--dash-radius-sm)] file:border-0 file:bg-[var(--dash-primary)] file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-[var(--dash-primary-text)]","file:cursor-pointer hover:file:bg-[var(--dash-primary-hover)]")}),o,m]});default:return null}}i(pe,"FieldRenderer");function be({resourceName:e,resourceNamePlural:a,columns:l,data:s,rowKey:n,fields:c,rowToValues:o,onCreate:m,onUpdate:d,onDelete:v,canCreate:D=true,canEdit:C=true,canDelete:R=true,tableProps:b,loading:P=false,className:f}){let x=a??`${e}s`,[u,w]=q__namespace.useState("list"),[S,A]=q__namespace.useState(null),[G,W]=q__namespace.useState({}),[I,z]=q__namespace.useState(null),[j,M]=q__namespace.useState(false);function J(N){let t=n(N);A(t),W(o?o(N):N),w("edit");}i(J,"handleEdit");function U(N){z(n(N));}i(U,"handleDeleteConfirm");async function X(){if(!(!I||!v)){M(true);try{await v(I);}finally{M(false),z(null);}}}i(X,"confirmDelete");function Y(N){return jsxRuntime.jsxs("div",{className:"flex items-center justify-end gap-1",children:[C&&d&&jsxRuntime.jsx("button",{type:"button",onClick:()=>J(N),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors",children:"Edit"}),R&&v&&jsxRuntime.jsx("button",{type:"button",onClick:()=>U(N),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-error)] hover:bg-[var(--dash-error-dim)] transition-colors",children:"Delete"})]})}return i(Y,"actionsRenderer"),u==="list"?jsxRuntime.jsxs("div",{className:r("space-y-4",f),children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsx("h2",{className:"text-xl font-semibold text-[var(--dash-text)]",children:x}),D&&m&&jsxRuntime.jsxs("button",{type:"button",onClick:()=>{A(null),W({}),w("create");},className:r("rounded-[var(--dash-radius)] px-3 py-1.5 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]"),children:["Create ",e]})]}),jsxRuntime.jsx(te,{columns:l,data:s,rowKey:n,actions:C||R?Y:void 0,loading:P,searchable:true,emptyMessage:`No ${x.toLowerCase()} found`,...b}),I!==null&&jsxRuntime.jsx(fe,{resourceName:e,loading:j,onConfirm:X,onCancel:()=>z(null)})]}):jsxRuntime.jsxs("div",{className:r("space-y-4",f),children:[jsxRuntime.jsxs("button",{type:"button",onClick:()=>w("list"),className:"inline-flex items-center gap-1 text-sm text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:[jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsxRuntime.jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),"Back to ",x]}),jsxRuntime.jsx(re,{title:u==="create"?`Create ${e}`:`Edit ${e}`,fields:c,values:u==="edit"?G:void 0,loading:j,submitLabel:u==="create"?"Create":"Save changes",onCancel:()=>w("list"),onSubmit:async N=>{M(true);try{u==="create"&&m?await m(N):u==="edit"&&S&&d&&await d(S,N),w("list");}finally{M(false);}}})]})}i(be,"DashCrud");function fe({resourceName:e,loading:a,onConfirm:l,onCancel:s}){return jsxRuntime.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:jsxRuntime.jsxs("div",{className:"w-full max-w-sm rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6 shadow-lg",children:[jsxRuntime.jsxs("h3",{className:"text-lg font-semibold text-[var(--dash-text)]",children:["Delete ",e,"?"]}),jsxRuntime.jsxs("p",{className:"mt-2 text-sm text-[var(--dash-text-muted)]",children:["This action cannot be undone. The ",e.toLowerCase()," will be permanently removed."]}),jsxRuntime.jsxs("div",{className:"mt-6 flex items-center justify-end gap-3",children:[jsxRuntime.jsx("button",{type:"button",onClick:s,disabled:a,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:"Cancel"}),jsxRuntime.jsx("button",{type:"button",onClick:l,disabled:a,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-error)] text-white","hover:bg-red-600","disabled:opacity-50 disabled:cursor-not-allowed"),children:a?"Deleting...":"Delete"})]})]})})}i(fe,"DeleteDialog");
3
+ exports.DashCrud=be;exports.DashDataTable=te;exports.DashForm=re;exports.DashHeader=ve;exports.DashLayout=ce;exports.DashSidebar=he;
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsxs,jsx}from'react/jsx-runtime';import*as q from'react';var ie=Object.defineProperty;var i=(e,a)=>ie(e,"name",{value:a,configurable:true});function r(...e){return twMerge(clsx(e))}i(r,"cn");function ce({sidebar:e,header:a,children:l,sidebarCollapsed:s=false,onSidebarCollapse:n,className:c}){return jsxs("div",{className:r("flex h-screen overflow-hidden","bg-[var(--dash-bg)] text-[var(--dash-text)]",c),children:[jsx("aside",{className:r("flex-shrink-0 overflow-y-auto overflow-x-hidden transition-[width] duration-200","border-r border-[var(--dash-border)] bg-[var(--dash-surface)]",s?"w-[var(--dash-sidebar-collapsed-width)]":"w-[var(--dash-sidebar-width)]"),children:e}),jsxs("div",{className:"flex flex-1 flex-col overflow-hidden",children:[a&&jsx("header",{className:"flex-shrink-0 border-b border-[var(--dash-border)] bg-[var(--dash-surface)]",children:a}),jsx("main",{className:"flex-1 overflow-y-auto p-6",children:l})]}),!s&&jsx("div",{className:"fixed inset-0 z-40 bg-black/60 lg:hidden",onClick:()=>n?.(true)})]})}i(ce,"DashLayout");function ue({size:e=28}){return jsx("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsx("path",{d:"M4 4h4v6h8V4h4v16h-4v-6H8v6H4V4z",fill:"currentColor"})})}i(ue,"HanzoMark");function he({logo:e,groups:a,userMenu:l,collapsed:s=false,onToggleCollapse:n,onNavigate:c,className:o}){return jsxs("nav",{className:r("flex h-full flex-col","bg-[var(--dash-surface)] text-[var(--dash-text)]",o),children:[jsxs("div",{className:r("flex h-[var(--dash-header-height)] items-center border-b border-[var(--dash-border)]",s?"justify-center px-2":"px-4"),children:[e??jsx(ue,{}),!s&&n&&jsx("button",{type:"button",onClick:n,className:"ml-auto rounded p-1 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]","aria-label":"Collapse sidebar",children:jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),s&&n&&jsx("button",{type:"button",onClick:n,className:"absolute -right-3 top-4 z-50 hidden rounded-full border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 text-[var(--dash-text-dim)] hover:text-[var(--dash-text)] lg:flex","aria-label":"Expand sidebar",children:jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),jsx("div",{className:"flex-1 overflow-y-auto py-2",children:a.map((m,d)=>jsx(me,{group:m,collapsed:s,onNavigate:c},d))}),l&&jsx("div",{className:"border-t border-[var(--dash-border)] p-2",children:l})]})}i(he,"DashSidebar");function me({group:e,collapsed:a,onNavigate:l}){let[s,n]=q.useState(e.defaultOpen!==false),c=e.collapsible!==false&&!!e.title;return jsxs("div",{className:"mb-1",children:[e.title&&!a&&jsxs("button",{type:"button",onClick:()=>c&&n(o=>!o),className:r("flex w-full items-center px-4 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-[var(--dash-text-dim)]",c&&"cursor-pointer hover:text-[var(--dash-text-muted)]"),children:[jsx("span",{className:"flex-1 text-left",children:e.title}),c&&jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",className:r("transition-transform",s?"rotate-0":"-rotate-90"),children:jsx("path",{d:"M4 6l4 4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})]}),(s||a)&&jsx("ul",{className:"space-y-0.5 px-2",children:e.items.map(o=>jsx("li",{children:jsxs("button",{type:"button",onClick:()=>l?.(o.href),title:a?o.label:void 0,className:r("flex w-full items-center gap-2 rounded-[var(--dash-radius-sm)] px-2 py-1.5 text-sm transition-colors",o.active?"bg-[var(--dash-primary)] text-[var(--dash-primary-text)]":"text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]",a&&"justify-center px-0"),children:[o.icon&&jsx("span",{className:"flex h-5 w-5 items-center justify-center flex-shrink-0",children:o.icon}),!a&&jsx("span",{className:"flex-1 truncate text-left",children:o.label}),!a&&o.badge!==void 0&&jsx("span",{className:"ml-auto rounded-full bg-[var(--dash-primary)] px-1.5 py-0.5 text-[10px] font-medium text-[var(--dash-primary-text)]",children:o.badge})]})},o.href))})]})}i(me,"SidebarGroup");function ve({breadcrumbs:e,searchPlaceholder:a="Search...",onSearch:l,avatarUrl:s,userName:n,userDropdown:c,onToggleTheme:o,theme:m="dark",actions:d,className:v}){let[D,C]=q.useState(false),R=q.useRef(null);return q.useEffect(()=>{if(!D)return;function b(P){R.current&&!R.current.contains(P.target)&&C(false);}return i(b,"handleClick"),document.addEventListener("mousedown",b),()=>document.removeEventListener("mousedown",b)},[D]),jsxs("div",{className:r("flex h-[var(--dash-header-height)] items-center gap-4 px-4","bg-[var(--dash-surface)] text-[var(--dash-text)]",v),children:[e&&e.length>0&&jsx("nav",{className:"flex items-center gap-1 text-sm","aria-label":"Breadcrumb",children:e.map((b,P)=>jsxs(q.Fragment,{children:[P>0&&jsx("span",{className:"text-[var(--dash-text-dim)]",children:"/"}),b.href?jsx("a",{href:b.href,className:"text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:b.label}):jsx("span",{className:"text-[var(--dash-text)]",children:b.label})]},P))}),jsx("div",{className:"flex-1"}),l&&jsxs("div",{className:"relative hidden sm:block",children:[jsxs("svg",{className:"absolute left-2.5 top-1/2 -translate-y-1/2 text-[var(--dash-text-dim)]",width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:[jsx("circle",{cx:"7",cy:"7",r:"5.5",stroke:"currentColor",strokeWidth:"1.5"}),jsx("path",{d:"M11 11l3 3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}),jsx("input",{type:"text",placeholder:a,onChange:b=>l(b.target.value),className:r("h-8 w-56 rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] pl-8 pr-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","transition-colors")})]}),d,o&&jsx("button",{type:"button",onClick:o,className:"rounded-[var(--dash-radius-sm)] p-1.5 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors","aria-label":`Switch to ${m==="dark"?"light":"dark"} mode`,children:m==="dark"?jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:[jsx("circle",{cx:"8",cy:"8",r:"3.5",stroke:"currentColor",strokeWidth:"1.5"}),jsx("path",{d:"M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}):jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M14 9.5A6.5 6.5 0 016.5 2 5.5 5.5 0 1014 9.5z",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),(s||n)&&jsxs("div",{className:"relative",ref:R,children:[jsx("button",{type:"button",onClick:()=>C(b=>!b),className:"flex items-center gap-2 rounded-[var(--dash-radius-sm)] p-1 hover:bg-[var(--dash-surface-hover)] transition-colors",children:s?jsx("img",{src:s,alt:n??"User",className:"h-7 w-7 rounded-full object-cover"}):jsx("div",{className:"flex h-7 w-7 items-center justify-center rounded-full bg-[var(--dash-primary)] text-xs font-medium text-[var(--dash-primary-text)]",children:(n??"?")[0].toUpperCase()})}),D&&c&&jsx("div",{className:"absolute right-0 top-full z-50 mt-1 min-w-48 rounded-[var(--dash-radius)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 shadow-lg",children:c})]})]})}i(ve,"DashHeader");function te({columns:e,data:a,rowKey:l,selectable:s=false,selectedKeys:n,onSelectionChange:c,searchable:o=false,searchPlaceholder:m="Search...",totalRows:d,page:v=0,pageSize:D=20,onPageChange:C,onPageSizeChange:R,actions:b,loading:P=false,emptyMessage:f="No data",className:x}){let[u,w]=q.useState(""),[S,A]=q.useState(null),G=q.useMemo(()=>{if(!u)return a;let t=u.toLowerCase();return a.filter(k=>e.some(O=>(O.cell?"":String(k[O.id]??"")).toLowerCase().includes(t)))},[a,u,e]),W=q.useMemo(()=>{if(!S)return G;let{column:t,direction:k}=S;return [...G].sort((O,E)=>{let Z=O[t],ee=E[t];if(Z==null&&ee==null)return 0;if(Z==null)return 1;if(ee==null)return -1;let se=String(Z).localeCompare(String(ee),void 0,{numeric:true});return k==="asc"?se:-se})},[G,S]),I=d??W.length,z=Math.max(1,Math.ceil(I/D)),j=C?W:W.slice(v*D,(v+1)*D),M=n??new Set,J=j.length>0&&j.every(t=>M.has(l(t)));function U(){c&&c(J?new Set:new Set(j.map(l)));}i(U,"toggleAll");function X(t){if(!c)return;let k=new Set(M);k.has(t)?k.delete(t):k.add(t),c(k);}i(X,"toggleRow");function Y(t){A(k=>k?.column===t?k.direction==="asc"?{column:t,direction:"desc"}:null:{column:t,direction:"asc"});}i(Y,"handleSort");let N=b?[...e,{id:"__actions",header:"",width:"auto"}]:e;return jsxs("div",{className:r("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)]",x),children:[(o||s)&&jsxs("div",{className:"flex items-center gap-3 border-b border-[var(--dash-border)] px-4 py-3",children:[o&&jsx("input",{type:"text",placeholder:m,value:u,onChange:t=>w(t.target.value),className:r("h-8 w-64 max-w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]")}),s&&M.size>0&&jsxs("span",{className:"text-xs text-[var(--dash-text-muted)]",children:[M.size," selected"]})]}),jsx("div",{className:"overflow-x-auto",children:jsxs("table",{className:"w-full text-sm",children:[jsx("thead",{children:jsxs("tr",{className:"border-b border-[var(--dash-border)]",children:[s&&jsx("th",{className:"w-10 px-4 py-2.5",children:jsx("input",{type:"checkbox",checked:J,onChange:U,className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),N.map(t=>jsx("th",{style:t.width?{width:t.width}:void 0,className:r("px-4 py-2.5 text-[var(--dash-text-dim)] font-medium",t.align==="center"&&"text-center",t.align==="right"&&"text-right",!t.align&&"text-left",t.sortable&&"cursor-pointer select-none hover:text-[var(--dash-text-muted)]"),onClick:t.sortable?()=>Y(t.id):void 0,children:jsxs("span",{className:"inline-flex items-center gap-1",children:[t.header,t.sortable&&S?.column===t.id&&jsx("span",{className:"text-[10px]",children:S.direction==="asc"?"\u2191":"\u2193"})]})},t.id))]})}),jsx("tbody",{children:P?jsx("tr",{children:jsx("td",{colSpan:N.length+(s?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:"Loading..."})}):j.length===0?jsx("tr",{children:jsx("td",{colSpan:N.length+(s?1:0),className:"px-4 py-8 text-center text-[var(--dash-text-dim)]",children:f})}):j.map(t=>{let k=l(t),O=M.has(k);return jsxs("tr",{className:r("border-b border-[var(--dash-border)] transition-colors",O?"bg-[var(--dash-surface-active)]":"hover:bg-[var(--dash-surface-hover)]"),children:[s&&jsx("td",{className:"w-10 px-4 py-2.5",children:jsx("input",{type:"checkbox",checked:O,onChange:()=>X(k),className:"h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]"})}),e.map(E=>jsx("td",{className:r("px-4 py-2.5",E.align==="center"&&"text-center",E.align==="right"&&"text-right"),children:E.cell?E.cell(t):String(t[E.id]??"")},E.id)),b&&jsx("td",{className:"px-4 py-2.5 text-right",children:b(t)})]},k)})})]})}),z>1&&jsxs("div",{className:"flex items-center justify-between border-t border-[var(--dash-border)] px-4 py-2.5 text-xs text-[var(--dash-text-muted)]",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsx("span",{children:"Rows per page"}),jsx("select",{value:D,onChange:t=>R?.(Number(t.target.value)),className:"h-7 rounded border border-[var(--dash-border)] bg-[var(--dash-bg)] px-2 text-xs text-[var(--dash-text)] focus:outline-none",children:[10,20,50,100].map(t=>jsx("option",{value:t,children:t},t))})]}),jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{children:["Page ",v+1," of ",z]}),jsx("button",{type:"button",disabled:v===0,onClick:()=>C?.(v-1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),jsx("button",{type:"button",disabled:v>=z-1,onClick:()=>C?.(v+1),className:"rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed",children:jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}i(te,"DashDataTable");function re({title:e,fields:a,values:l,onSubmit:s,onCancel:n,submitLabel:c="Save",cancelLabel:o="Cancel",loading:m=false,className:d}){let[v,D]=q.useState(()=>{let f={};for(let x of a)f[x.name]=l?.[x.name]??x.defaultValue??(x.type==="toggle"?false:"");return f}),[C,R]=q.useState({});function b(f,x){D(u=>({...u,[f]:x})),R(u=>{if(!u[f])return u;let w={...u};return delete w[f],w});}i(b,"setValue");async function P(f){f.preventDefault();let x={};for(let u of a){let w=v[u.name];if(u.required&&(w===""||w===null||w===void 0)&&(x[u.name]=`${u.label} is required`),u.validate){let S=u.validate(w);S&&(x[u.name]=S);}}if(Object.keys(x).length>0){R(x);return}await s(v);}return i(P,"handleSubmit"),jsxs("form",{onSubmit:P,className:r("rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6",d),children:[e&&jsx("h3",{className:"mb-4 text-lg font-semibold text-[var(--dash-text)]",children:e}),jsx("div",{className:"space-y-4",children:a.map(f=>jsx(pe,{field:f,value:v[f.name],error:C[f.name],onChange:x=>b(f.name,x)},f.name))}),jsxs("div",{className:"mt-6 flex items-center gap-3",children:[jsx("button",{type:"submit",disabled:m,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]","disabled:opacity-50 disabled:cursor-not-allowed"),children:m?"Saving...":c}),n&&jsx("button",{type:"button",onClick:n,disabled:m,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:o})]})]})}i(re,"DashForm");var Q=r("w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 py-2 text-sm text-[var(--dash-text)]","placeholder:text-[var(--dash-text-dim)]","focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]","disabled:opacity-50 disabled:cursor-not-allowed","transition-colors");function pe({field:e,value:a,error:l,onChange:s}){let n=`dash-field-${e.name}`,c=jsxs("label",{htmlFor:n,className:"mb-1 block text-sm font-medium text-[var(--dash-text)]",children:[e.label,e.required&&jsx("span",{className:"ml-0.5 text-[var(--dash-error)]",children:"*"})]}),o=e.description?jsx("p",{className:"mt-1 text-xs text-[var(--dash-text-dim)]",children:e.description}):null,m=l?jsx("p",{className:"mt-1 text-xs text-[var(--dash-error)]",children:l}):null;switch(e.type){case "text":case "email":case "password":case "number":return jsxs("div",{children:[c,jsx("input",{id:n,type:e.type,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,onChange:d=>s(e.type==="number"?Number(d.target.value):d.target.value),className:r(Q,l&&"border-[var(--dash-error)]")}),o,m]});case "textarea":return jsxs("div",{children:[c,jsx("textarea",{id:n,value:String(a??""),placeholder:e.placeholder,disabled:e.disabled,rows:e.rows??3,onChange:d=>s(d.target.value),className:r(Q,"resize-y",l&&"border-[var(--dash-error)]")}),o,m]});case "select":case "relation":return jsxs("div",{children:[c,jsxs("select",{id:n,value:String(a??""),disabled:e.disabled,onChange:d=>s(d.target.value),className:r(Q,l&&"border-[var(--dash-error)]"),children:[jsx("option",{value:"",children:e.placeholder??"Select..."}),(e.options??[]).map(d=>jsx("option",{value:d.value,children:d.label},d.value))]}),o,m]});case "toggle":return jsxs("div",{className:"flex items-center gap-3",children:[jsx("button",{id:n,type:"button",role:"switch","aria-checked":!!a,disabled:e.disabled,onClick:()=>s(!a),className:r("relative inline-flex h-5 w-9 flex-shrink-0 rounded-full transition-colors","focus:outline-none focus:ring-2 focus:ring-[var(--dash-primary)] focus:ring-offset-2 focus:ring-offset-[var(--dash-surface)]",a?"bg-[var(--dash-primary)]":"bg-[var(--dash-border)]",e.disabled&&"opacity-50 cursor-not-allowed"),children:jsx("span",{className:r("pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",a?"translate-x-4":"translate-x-0.5","mt-0.5")})}),jsx("label",{htmlFor:n,className:"text-sm text-[var(--dash-text)]",children:e.label}),o,m]});case "json":return jsxs("div",{children:[c,jsx("textarea",{id:n,value:typeof a=="string"?a:JSON.stringify(a,null,2),placeholder:e.placeholder??"{}",disabled:e.disabled,rows:e.rows??6,onChange:d=>{try{s(JSON.parse(d.target.value));}catch{s(d.target.value);}},className:r(Q,"font-mono text-xs resize-y",l&&"border-[var(--dash-error)]")}),o,m]});case "file":return jsxs("div",{children:[c,jsx("input",{id:n,type:"file",accept:e.accept,disabled:e.disabled,onChange:d=>{let v=d.target.files?.[0];v&&s(v);},className:r("w-full text-sm text-[var(--dash-text-muted)]","file:mr-3 file:rounded-[var(--dash-radius-sm)] file:border-0 file:bg-[var(--dash-primary)] file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-[var(--dash-primary-text)]","file:cursor-pointer hover:file:bg-[var(--dash-primary-hover)]")}),o,m]});default:return null}}i(pe,"FieldRenderer");function be({resourceName:e,resourceNamePlural:a,columns:l,data:s,rowKey:n,fields:c,rowToValues:o,onCreate:m,onUpdate:d,onDelete:v,canCreate:D=true,canEdit:C=true,canDelete:R=true,tableProps:b,loading:P=false,className:f}){let x=a??`${e}s`,[u,w]=q.useState("list"),[S,A]=q.useState(null),[G,W]=q.useState({}),[I,z]=q.useState(null),[j,M]=q.useState(false);function J(N){let t=n(N);A(t),W(o?o(N):N),w("edit");}i(J,"handleEdit");function U(N){z(n(N));}i(U,"handleDeleteConfirm");async function X(){if(!(!I||!v)){M(true);try{await v(I);}finally{M(false),z(null);}}}i(X,"confirmDelete");function Y(N){return jsxs("div",{className:"flex items-center justify-end gap-1",children:[C&&d&&jsx("button",{type:"button",onClick:()=>J(N),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors",children:"Edit"}),R&&v&&jsx("button",{type:"button",onClick:()=>U(N),className:"rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-error)] hover:bg-[var(--dash-error-dim)] transition-colors",children:"Delete"})]})}return i(Y,"actionsRenderer"),u==="list"?jsxs("div",{className:r("space-y-4",f),children:[jsxs("div",{className:"flex items-center justify-between",children:[jsx("h2",{className:"text-xl font-semibold text-[var(--dash-text)]",children:x}),D&&m&&jsxs("button",{type:"button",onClick:()=>{A(null),W({}),w("create");},className:r("rounded-[var(--dash-radius)] px-3 py-1.5 text-sm font-medium transition-colors","bg-[var(--dash-primary)] text-[var(--dash-primary-text)]","hover:bg-[var(--dash-primary-hover)]"),children:["Create ",e]})]}),jsx(te,{columns:l,data:s,rowKey:n,actions:C||R?Y:void 0,loading:P,searchable:true,emptyMessage:`No ${x.toLowerCase()} found`,...b}),I!==null&&jsx(fe,{resourceName:e,loading:j,onConfirm:X,onCancel:()=>z(null)})]}):jsxs("div",{className:r("space-y-4",f),children:[jsxs("button",{type:"button",onClick:()=>w("list"),className:"inline-flex items-center gap-1 text-sm text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors",children:[jsx("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",children:jsx("path",{d:"M10 4L6 8l4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),"Back to ",x]}),jsx(re,{title:u==="create"?`Create ${e}`:`Edit ${e}`,fields:c,values:u==="edit"?G:void 0,loading:j,submitLabel:u==="create"?"Create":"Save changes",onCancel:()=>w("list"),onSubmit:async N=>{M(true);try{u==="create"&&m?await m(N):u==="edit"&&S&&d&&await d(S,N),w("list");}finally{M(false);}}})]})}i(be,"DashCrud");function fe({resourceName:e,loading:a,onConfirm:l,onCancel:s}){return jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:jsxs("div",{className:"w-full max-w-sm rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6 shadow-lg",children:[jsxs("h3",{className:"text-lg font-semibold text-[var(--dash-text)]",children:["Delete ",e,"?"]}),jsxs("p",{className:"mt-2 text-sm text-[var(--dash-text-muted)]",children:["This action cannot be undone. The ",e.toLowerCase()," will be permanently removed."]}),jsxs("div",{className:"mt-6 flex items-center justify-end gap-3",children:[jsx("button",{type:"button",onClick:s,disabled:a,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","border border-[var(--dash-border)] text-[var(--dash-text-muted)]","hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]"),children:"Cancel"}),jsx("button",{type:"button",onClick:l,disabled:a,className:r("rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors","bg-[var(--dash-error)] text-white","hover:bg-red-600","disabled:opacity-50 disabled:cursor-not-allowed"),children:a?"Deleting...":"Delete"})]})]})})}i(fe,"DeleteDialog");
3
+ export{be as DashCrud,te as DashDataTable,re as DashForm,ve as DashHeader,ce as DashLayout,he as DashSidebar};
@@ -0,0 +1,37 @@
1
+ import { type DashColumn, type DashDataTableProps } from './dash-data-table';
2
+ import { type DashFieldDef } from './dash-form';
3
+ export interface DashCrudProps<T> {
4
+ /** Resource name (e.g. "User", "API Key") used in UI labels */
5
+ resourceName: string;
6
+ /** Plural resource name (defaults to resourceName + "s") */
7
+ resourceNamePlural?: string;
8
+ /** Column definitions for the list table */
9
+ columns: DashColumn<T>[];
10
+ /** Row data */
11
+ data: T[];
12
+ /** Unique key extractor per row */
13
+ rowKey: (row: T) => string;
14
+ /** Field definitions for create/edit form */
15
+ fields: DashFieldDef[];
16
+ /** Convert a row to form values for editing */
17
+ rowToValues?: (row: T) => Record<string, unknown>;
18
+ /** Called when creating a new record */
19
+ onCreate?: (values: Record<string, unknown>) => Promise<void>;
20
+ /** Called when updating an existing record */
21
+ onUpdate?: (key: string, values: Record<string, unknown>) => Promise<void>;
22
+ /** Called when deleting a record */
23
+ onDelete?: (key: string) => Promise<void>;
24
+ /** Whether create is available */
25
+ canCreate?: boolean;
26
+ /** Whether edit is available */
27
+ canEdit?: boolean;
28
+ /** Whether delete is available */
29
+ canDelete?: boolean;
30
+ /** Pass-through DataTable props */
31
+ tableProps?: Partial<DashDataTableProps<T>>;
32
+ /** Loading state */
33
+ loading?: boolean;
34
+ className?: string;
35
+ }
36
+ export declare function DashCrud<T>({ resourceName, resourceNamePlural, columns, data, rowKey, fields, rowToValues, onCreate, onUpdate, onDelete, canCreate, canEdit, canDelete, tableProps, loading, className, }: DashCrudProps<T>): import("react/jsx-runtime").JSX.Element;
37
+ //# sourceMappingURL=dash-crud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dash-crud.d.ts","sourceRoot":"","sources":["../../../src/dash/dash-crud.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3F,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAMzD,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,4CAA4C;IAC5C,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB,eAAe;IACf,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,mCAAmC;IACnC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAC1B,6CAA6C;IAC7C,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjD,wCAAwC;IACxC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1E,oCAAoC;IACpC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzC,kCAAkC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,kCAAkC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,mCAAmC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3C,oBAAoB;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAQD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAC1B,YAAY,EACZ,kBAAkB,EAClB,OAAO,EACP,IAAI,EACJ,MAAM,EACN,MAAM,EACN,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAgB,EAChB,OAAc,EACd,SAAgB,EAChB,UAAU,EACV,OAAe,EACf,SAAS,GACV,EAAE,aAAa,CAAC,CAAC,CAAC,2CAgJlB"}
@@ -0,0 +1,74 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from '../../utils';
5
+ import { DashDataTable } from './dash-data-table';
6
+ import { DashForm } from './dash-form';
7
+ /* ------------------------------------------------------------------ */
8
+ /* Component */
9
+ /* ------------------------------------------------------------------ */
10
+ export function DashCrud({ resourceName, resourceNamePlural, columns, data, rowKey, fields, rowToValues, onCreate, onUpdate, onDelete, canCreate = true, canEdit = true, canDelete = true, tableProps, loading = false, className, }) {
11
+ const plural = resourceNamePlural ?? `${resourceName}s`;
12
+ const [view, setView] = React.useState('list');
13
+ const [editingKey, setEditingKey] = React.useState(null);
14
+ const [editValues, setEditValues] = React.useState({});
15
+ const [deleteKey, setDeleteKey] = React.useState(null);
16
+ const [submitting, setSubmitting] = React.useState(false);
17
+ /* ------ edit ------ */
18
+ function handleEdit(row) {
19
+ const key = rowKey(row);
20
+ setEditingKey(key);
21
+ setEditValues(rowToValues ? rowToValues(row) : row);
22
+ setView('edit');
23
+ }
24
+ /* ------ delete confirm ------ */
25
+ function handleDeleteConfirm(row) {
26
+ setDeleteKey(rowKey(row));
27
+ }
28
+ async function confirmDelete() {
29
+ if (!deleteKey || !onDelete)
30
+ return;
31
+ setSubmitting(true);
32
+ try {
33
+ await onDelete(deleteKey);
34
+ }
35
+ finally {
36
+ setSubmitting(false);
37
+ setDeleteKey(null);
38
+ }
39
+ }
40
+ /* ------ actions column ------ */
41
+ function actionsRenderer(row) {
42
+ return (_jsxs("div", { className: "flex items-center justify-end gap-1", children: [canEdit && onUpdate && (_jsx("button", { type: "button", onClick: () => handleEdit(row), className: "rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors", children: "Edit" })), canDelete && onDelete && (_jsx("button", { type: "button", onClick: () => handleDeleteConfirm(row), className: "rounded-[var(--dash-radius-sm)] px-2 py-1 text-xs text-[var(--dash-error)] hover:bg-[var(--dash-error-dim)] transition-colors", children: "Delete" }))] }));
43
+ }
44
+ /* ------ list view ------ */
45
+ if (view === 'list') {
46
+ return (_jsxs("div", { className: cn('space-y-4', className), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h2", { className: "text-xl font-semibold text-[var(--dash-text)]", children: plural }), canCreate && onCreate && (_jsxs("button", { type: "button", onClick: () => {
47
+ setEditingKey(null);
48
+ setEditValues({});
49
+ setView('create');
50
+ }, className: cn('rounded-[var(--dash-radius)] px-3 py-1.5 text-sm font-medium transition-colors', 'bg-[var(--dash-primary)] text-[var(--dash-primary-text)]', 'hover:bg-[var(--dash-primary-hover)]'), children: ["Create ", resourceName] }))] }), _jsx(DashDataTable, { columns: columns, data: data, rowKey: rowKey, actions: (canEdit || canDelete) ? actionsRenderer : undefined, loading: loading, searchable: true, emptyMessage: `No ${plural.toLowerCase()} found`, ...tableProps }), deleteKey !== null && (_jsx(DeleteDialog, { resourceName: resourceName, loading: submitting, onConfirm: confirmDelete, onCancel: () => setDeleteKey(null) }))] }));
51
+ }
52
+ /* ------ create / edit view ------ */
53
+ return (_jsxs("div", { className: cn('space-y-4', className), children: [_jsxs("button", { type: "button", onClick: () => setView('list'), className: "inline-flex items-center gap-1 text-sm text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors", children: [_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M10 4L6 8l4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }), "Back to ", plural] }), _jsx(DashForm, { title: view === 'create' ? `Create ${resourceName}` : `Edit ${resourceName}`, fields: fields, values: view === 'edit' ? editValues : undefined, loading: submitting, submitLabel: view === 'create' ? 'Create' : 'Save changes', onCancel: () => setView('list'), onSubmit: async (vals) => {
54
+ setSubmitting(true);
55
+ try {
56
+ if (view === 'create' && onCreate) {
57
+ await onCreate(vals);
58
+ }
59
+ else if (view === 'edit' && editingKey && onUpdate) {
60
+ await onUpdate(editingKey, vals);
61
+ }
62
+ setView('list');
63
+ }
64
+ finally {
65
+ setSubmitting(false);
66
+ }
67
+ } })] }));
68
+ }
69
+ /* ------------------------------------------------------------------ */
70
+ /* DeleteDialog (internal) */
71
+ /* ------------------------------------------------------------------ */
72
+ function DeleteDialog({ resourceName, loading, onConfirm, onCancel, }) {
73
+ return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60", children: _jsxs("div", { className: "w-full max-w-sm rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6 shadow-lg", children: [_jsxs("h3", { className: "text-lg font-semibold text-[var(--dash-text)]", children: ["Delete ", resourceName, "?"] }), _jsxs("p", { className: "mt-2 text-sm text-[var(--dash-text-muted)]", children: ["This action cannot be undone. The ", resourceName.toLowerCase(), " will be permanently removed."] }), _jsxs("div", { className: "mt-6 flex items-center justify-end gap-3", children: [_jsx("button", { type: "button", onClick: onCancel, disabled: loading, className: cn('rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors', 'border border-[var(--dash-border)] text-[var(--dash-text-muted)]', 'hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]'), children: "Cancel" }), _jsx("button", { type: "button", onClick: onConfirm, disabled: loading, className: cn('rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors', 'bg-[var(--dash-error)] text-white', 'hover:bg-red-600', 'disabled:opacity-50 disabled:cursor-not-allowed'), children: loading ? 'Deleting...' : 'Delete' })] })] }) }));
74
+ }
@@ -0,0 +1,50 @@
1
+ import * as React from 'react';
2
+ export interface DashColumn<T> {
3
+ id: string;
4
+ header: string;
5
+ /** Render cell content. Falls back to (row as any)[id]. */
6
+ cell?: (row: T) => React.ReactNode;
7
+ /** Enable sorting on this column */
8
+ sortable?: boolean;
9
+ /** Width hint (CSS value) */
10
+ width?: string;
11
+ /** Alignment */
12
+ align?: 'left' | 'center' | 'right';
13
+ }
14
+ export interface DashDataTableProps<T> {
15
+ /** Column definitions */
16
+ columns: DashColumn<T>[];
17
+ /** Row data */
18
+ data: T[];
19
+ /** Unique key extractor per row */
20
+ rowKey: (row: T) => string;
21
+ /** Enable row selection checkboxes */
22
+ selectable?: boolean;
23
+ /** Currently selected row keys */
24
+ selectedKeys?: Set<string>;
25
+ /** Called when selection changes */
26
+ onSelectionChange?: (keys: Set<string>) => void;
27
+ /** Searchable - shows search input above table */
28
+ searchable?: boolean;
29
+ /** Search placeholder */
30
+ searchPlaceholder?: string;
31
+ /** Pagination: total rows available (may exceed data.length for server pagination) */
32
+ totalRows?: number;
33
+ /** Current page (0-indexed) */
34
+ page?: number;
35
+ /** Rows per page */
36
+ pageSize?: number;
37
+ /** Called when page changes */
38
+ onPageChange?: (page: number) => void;
39
+ /** Called when page size changes */
40
+ onPageSizeChange?: (size: number) => void;
41
+ /** Actions column renderer (edit, delete buttons etc.) */
42
+ actions?: (row: T) => React.ReactNode;
43
+ /** Loading state */
44
+ loading?: boolean;
45
+ /** Empty state message */
46
+ emptyMessage?: string;
47
+ className?: string;
48
+ }
49
+ export declare function DashDataTable<T>({ columns, data, rowKey, selectable, selectedKeys, onSelectionChange, searchable, searchPlaceholder, totalRows, page, pageSize, onPageChange, onPageSizeChange, actions, loading, emptyMessage, className, }: DashDataTableProps<T>): import("react/jsx-runtime").JSX.Element;
50
+ //# sourceMappingURL=dash-data-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dash-data-table.d.ts","sourceRoot":"","sources":["../../../src/dash/dash-data-table.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAA;IAClC,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gBAAgB;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;CACpC;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,yBAAyB;IACzB,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB,eAAe;IACf,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,mCAAmC;IACnC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAC1B,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,kCAAkC;IAClC,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,oCAAoC;IACpC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,CAAA;IAC/C,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,yBAAyB;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAA;IACrC,oBAAoB;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAQD,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAC/B,OAAO,EACP,IAAI,EACJ,MAAM,EACN,UAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAkB,EAClB,iBAA+B,EAC/B,SAAS,EACT,IAAQ,EACR,QAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,OAAO,EACP,OAAe,EACf,YAAwB,EACxB,SAAS,GACV,EAAE,kBAAkB,CAAC,CAAC,CAAC,2CAyPvB"}
@@ -0,0 +1,88 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from '../../utils';
5
+ /* ------------------------------------------------------------------ */
6
+ /* Component */
7
+ /* ------------------------------------------------------------------ */
8
+ export function DashDataTable({ columns, data, rowKey, selectable = false, selectedKeys, onSelectionChange, searchable = false, searchPlaceholder = 'Search...', totalRows, page = 0, pageSize = 20, onPageChange, onPageSizeChange, actions, loading = false, emptyMessage = 'No data', className, }) {
9
+ const [search, setSearch] = React.useState('');
10
+ const [sort, setSort] = React.useState(null);
11
+ /* ---------- filtering ---------- */
12
+ const filtered = React.useMemo(() => {
13
+ if (!search)
14
+ return data;
15
+ const q = search.toLowerCase();
16
+ return data.filter((row) => columns.some((col) => {
17
+ const val = col.cell ? '' : String(row[col.id] ?? '');
18
+ return val.toLowerCase().includes(q);
19
+ }));
20
+ }, [data, search, columns]);
21
+ /* ---------- sorting ---------- */
22
+ const sorted = React.useMemo(() => {
23
+ if (!sort)
24
+ return filtered;
25
+ const { column, direction } = sort;
26
+ return [...filtered].sort((a, b) => {
27
+ const av = a[column];
28
+ const bv = b[column];
29
+ if (av == null && bv == null)
30
+ return 0;
31
+ if (av == null)
32
+ return 1;
33
+ if (bv == null)
34
+ return -1;
35
+ const cmp = String(av).localeCompare(String(bv), undefined, { numeric: true });
36
+ return direction === 'asc' ? cmp : -cmp;
37
+ });
38
+ }, [filtered, sort]);
39
+ /* ---------- pagination ---------- */
40
+ const total = totalRows ?? sorted.length;
41
+ const totalPages = Math.max(1, Math.ceil(total / pageSize));
42
+ const rows = onPageChange ? sorted : sorted.slice(page * pageSize, (page + 1) * pageSize);
43
+ /* ---------- selection ---------- */
44
+ const selected = selectedKeys ?? new Set();
45
+ const allSelected = rows.length > 0 && rows.every((r) => selected.has(rowKey(r)));
46
+ function toggleAll() {
47
+ if (!onSelectionChange)
48
+ return;
49
+ if (allSelected) {
50
+ onSelectionChange(new Set());
51
+ }
52
+ else {
53
+ onSelectionChange(new Set(rows.map(rowKey)));
54
+ }
55
+ }
56
+ function toggleRow(key) {
57
+ if (!onSelectionChange)
58
+ return;
59
+ const next = new Set(selected);
60
+ if (next.has(key)) {
61
+ next.delete(key);
62
+ }
63
+ else {
64
+ next.add(key);
65
+ }
66
+ onSelectionChange(next);
67
+ }
68
+ function handleSort(colId) {
69
+ setSort((prev) => {
70
+ if (prev?.column === colId) {
71
+ return prev.direction === 'asc' ? { column: colId, direction: 'desc' } : null;
72
+ }
73
+ return { column: colId, direction: 'asc' };
74
+ });
75
+ }
76
+ const allColumns = actions
77
+ ? [...columns, { id: '__actions', header: '', width: 'auto' }]
78
+ : columns;
79
+ return (_jsxs("div", { className: cn('rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)]', className), children: [(searchable || selectable) && (_jsxs("div", { className: "flex items-center gap-3 border-b border-[var(--dash-border)] px-4 py-3", children: [searchable && (_jsx("input", { type: "text", placeholder: searchPlaceholder, value: search, onChange: (e) => setSearch(e.target.value), className: cn('h-8 w-64 max-w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 text-sm text-[var(--dash-text)]', 'placeholder:text-[var(--dash-text-dim)]', 'focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]') })), selectable && selected.size > 0 && (_jsxs("span", { className: "text-xs text-[var(--dash-text-muted)]", children: [selected.size, " selected"] }))] })), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-[var(--dash-border)]", children: [selectable && (_jsx("th", { className: "w-10 px-4 py-2.5", children: _jsx("input", { type: "checkbox", checked: allSelected, onChange: toggleAll, className: "h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]" }) })), allColumns.map((col) => (_jsx("th", { style: col.width ? { width: col.width } : undefined, className: cn('px-4 py-2.5 text-[var(--dash-text-dim)] font-medium', col.align === 'center' && 'text-center', col.align === 'right' && 'text-right', !col.align && 'text-left', col.sortable && 'cursor-pointer select-none hover:text-[var(--dash-text-muted)]'), onClick: col.sortable ? () => handleSort(col.id) : undefined, children: _jsxs("span", { className: "inline-flex items-center gap-1", children: [col.header, col.sortable && sort?.column === col.id && (_jsx("span", { className: "text-[10px]", children: sort.direction === 'asc' ? '\u2191' : '\u2193' }))] }) }, col.id)))] }) }), _jsx("tbody", { children: loading ? (_jsx("tr", { children: _jsx("td", { colSpan: allColumns.length + (selectable ? 1 : 0), className: "px-4 py-8 text-center text-[var(--dash-text-dim)]", children: "Loading..." }) })) : rows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: allColumns.length + (selectable ? 1 : 0), className: "px-4 py-8 text-center text-[var(--dash-text-dim)]", children: emptyMessage }) })) : (rows.map((row) => {
80
+ const key = rowKey(row);
81
+ const isSelected = selected.has(key);
82
+ return (_jsxs("tr", { className: cn('border-b border-[var(--dash-border)] transition-colors', isSelected
83
+ ? 'bg-[var(--dash-surface-active)]'
84
+ : 'hover:bg-[var(--dash-surface-hover)]'), children: [selectable && (_jsx("td", { className: "w-10 px-4 py-2.5", children: _jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggleRow(key), className: "h-4 w-4 rounded border-[var(--dash-border)] accent-[var(--dash-primary)]" }) })), columns.map((col) => (_jsx("td", { className: cn('px-4 py-2.5', col.align === 'center' && 'text-center', col.align === 'right' && 'text-right'), children: col.cell
85
+ ? col.cell(row)
86
+ : String(row[col.id] ?? '') }, col.id))), actions && (_jsx("td", { className: "px-4 py-2.5 text-right", children: actions(row) }))] }, key));
87
+ })) })] }) }), totalPages > 1 && (_jsxs("div", { className: "flex items-center justify-between border-t border-[var(--dash-border)] px-4 py-2.5 text-xs text-[var(--dash-text-muted)]", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { children: "Rows per page" }), _jsx("select", { value: pageSize, onChange: (e) => onPageSizeChange?.(Number(e.target.value)), className: "h-7 rounded border border-[var(--dash-border)] bg-[var(--dash-bg)] px-2 text-xs text-[var(--dash-text)] focus:outline-none", children: [10, 20, 50, 100].map((n) => (_jsx("option", { value: n, children: n }, n))) })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("span", { children: ["Page ", page + 1, " of ", totalPages] }), _jsx("button", { type: "button", disabled: page === 0, onClick: () => onPageChange?.(page - 1), className: "rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed", children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M10 4L6 8l4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsx("button", { type: "button", disabled: page >= totalPages - 1, onClick: () => onPageChange?.(page + 1), className: "rounded p-1 hover:bg-[var(--dash-surface-hover)] disabled:opacity-30 disabled:cursor-not-allowed", children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }))] }));
88
+ }
@@ -0,0 +1,52 @@
1
+ export type DashFieldType = 'text' | 'number' | 'email' | 'password' | 'select' | 'toggle' | 'textarea' | 'json' | 'relation' | 'file';
2
+ export interface DashFieldOption {
3
+ label: string;
4
+ value: string;
5
+ }
6
+ export interface DashFieldDef {
7
+ /** Field key (maps to form value key) */
8
+ name: string;
9
+ /** Display label */
10
+ label: string;
11
+ /** Field type */
12
+ type: DashFieldType;
13
+ /** Placeholder text */
14
+ placeholder?: string;
15
+ /** Description shown below field */
16
+ description?: string;
17
+ /** Whether the field is required */
18
+ required?: boolean;
19
+ /** Select options (for type=select or type=relation) */
20
+ options?: DashFieldOption[];
21
+ /** Default value */
22
+ defaultValue?: unknown;
23
+ /** Disabled */
24
+ disabled?: boolean;
25
+ /** File accept pattern (for type=file) */
26
+ accept?: string;
27
+ /** Number of textarea rows */
28
+ rows?: number;
29
+ /** Zod-style validation function. Return error string or null. */
30
+ validate?: (value: unknown) => string | null;
31
+ }
32
+ export interface DashFormProps {
33
+ /** Form title */
34
+ title?: string;
35
+ /** Field definitions */
36
+ fields: DashFieldDef[];
37
+ /** Initial values */
38
+ values?: Record<string, unknown>;
39
+ /** Called on submit with validated values */
40
+ onSubmit: (values: Record<string, unknown>) => void | Promise<void>;
41
+ /** Called on cancel */
42
+ onCancel?: () => void;
43
+ /** Submit button label */
44
+ submitLabel?: string;
45
+ /** Cancel button label */
46
+ cancelLabel?: string;
47
+ /** Loading state */
48
+ loading?: boolean;
49
+ className?: string;
50
+ }
51
+ export declare function DashForm({ title, fields, values: initialValues, onSubmit, onCancel, submitLabel, cancelLabel, loading, className, }: DashFormProps): import("react/jsx-runtime").JSX.Element;
52
+ //# sourceMappingURL=dash-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dash-form.d.ts","sourceRoot":"","sources":["../../../src/dash/dash-form.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,MAAM,GACN,UAAU,GACV,MAAM,CAAA;AAEV,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,IAAI,EAAE,aAAa,CAAA;IACnB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wDAAwD;IACxD,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;IAC3B,oBAAoB;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,eAAe;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAA;CAC7C;AAED,MAAM,WAAW,aAAa;IAC5B,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wBAAwB;IACxB,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,6CAA6C;IAC7C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oBAAoB;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAMD,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,MAAM,EACN,MAAM,EAAE,aAAa,EACrB,QAAQ,EACR,QAAQ,EACR,WAAoB,EACpB,WAAsB,EACtB,OAAe,EACf,SAAS,GACV,EAAE,aAAa,2CAmGf"}
@@ -0,0 +1,90 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from '../../utils';
5
+ /* ------------------------------------------------------------------ */
6
+ /* Component */
7
+ /* ------------------------------------------------------------------ */
8
+ export function DashForm({ title, fields, values: initialValues, onSubmit, onCancel, submitLabel = 'Save', cancelLabel = 'Cancel', loading = false, className, }) {
9
+ const [values, setValues] = React.useState(() => {
10
+ const init = {};
11
+ for (const f of fields) {
12
+ init[f.name] = initialValues?.[f.name] ?? f.defaultValue ?? (f.type === 'toggle' ? false : '');
13
+ }
14
+ return init;
15
+ });
16
+ const [errors, setErrors] = React.useState({});
17
+ function setValue(name, value) {
18
+ setValues((prev) => ({ ...prev, [name]: value }));
19
+ setErrors((prev) => {
20
+ if (!prev[name])
21
+ return prev;
22
+ const next = { ...prev };
23
+ delete next[name];
24
+ return next;
25
+ });
26
+ }
27
+ async function handleSubmit(e) {
28
+ e.preventDefault();
29
+ // Validate
30
+ const errs = {};
31
+ for (const f of fields) {
32
+ const v = values[f.name];
33
+ if (f.required && (v === '' || v === null || v === undefined)) {
34
+ errs[f.name] = `${f.label} is required`;
35
+ }
36
+ if (f.validate) {
37
+ const err = f.validate(v);
38
+ if (err)
39
+ errs[f.name] = err;
40
+ }
41
+ }
42
+ if (Object.keys(errs).length > 0) {
43
+ setErrors(errs);
44
+ return;
45
+ }
46
+ await onSubmit(values);
47
+ }
48
+ return (_jsxs("form", { onSubmit: handleSubmit, className: cn('rounded-[var(--dash-radius-lg)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-6', className), children: [title && (_jsx("h3", { className: "mb-4 text-lg font-semibold text-[var(--dash-text)]", children: title })), _jsx("div", { className: "space-y-4", children: fields.map((field) => (_jsx(FieldRenderer, { field: field, value: values[field.name], error: errors[field.name], onChange: (v) => setValue(field.name, v) }, field.name))) }), _jsxs("div", { className: "mt-6 flex items-center gap-3", children: [_jsx("button", { type: "submit", disabled: loading, className: cn('rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors', 'bg-[var(--dash-primary)] text-[var(--dash-primary-text)]', 'hover:bg-[var(--dash-primary-hover)]', 'disabled:opacity-50 disabled:cursor-not-allowed'), children: loading ? 'Saving...' : submitLabel }), onCancel && (_jsx("button", { type: "button", onClick: onCancel, disabled: loading, className: cn('rounded-[var(--dash-radius)] px-4 py-2 text-sm font-medium transition-colors', 'border border-[var(--dash-border)] text-[var(--dash-text-muted)]', 'hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]'), children: cancelLabel }))] })] }));
49
+ }
50
+ /* ------------------------------------------------------------------ */
51
+ /* FieldRenderer (internal) */
52
+ /* ------------------------------------------------------------------ */
53
+ const inputBase = cn('w-full rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] px-3 py-2 text-sm text-[var(--dash-text)]', 'placeholder:text-[var(--dash-text-dim)]', 'focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]', 'disabled:opacity-50 disabled:cursor-not-allowed', 'transition-colors');
54
+ function FieldRenderer({ field, value, error, onChange, }) {
55
+ const id = `dash-field-${field.name}`;
56
+ const labelEl = (_jsxs("label", { htmlFor: id, className: "mb-1 block text-sm font-medium text-[var(--dash-text)]", children: [field.label, field.required && _jsx("span", { className: "ml-0.5 text-[var(--dash-error)]", children: "*" })] }));
57
+ const descEl = field.description ? (_jsx("p", { className: "mt-1 text-xs text-[var(--dash-text-dim)]", children: field.description })) : null;
58
+ const errEl = error ? (_jsx("p", { className: "mt-1 text-xs text-[var(--dash-error)]", children: error })) : null;
59
+ switch (field.type) {
60
+ case 'text':
61
+ case 'email':
62
+ case 'password':
63
+ case 'number':
64
+ return (_jsxs("div", { children: [labelEl, _jsx("input", { id: id, type: field.type, value: String(value ?? ''), placeholder: field.placeholder, disabled: field.disabled, onChange: (e) => onChange(field.type === 'number' ? Number(e.target.value) : e.target.value), className: cn(inputBase, error && 'border-[var(--dash-error)]') }), descEl, errEl] }));
65
+ case 'textarea':
66
+ return (_jsxs("div", { children: [labelEl, _jsx("textarea", { id: id, value: String(value ?? ''), placeholder: field.placeholder, disabled: field.disabled, rows: field.rows ?? 3, onChange: (e) => onChange(e.target.value), className: cn(inputBase, 'resize-y', error && 'border-[var(--dash-error)]') }), descEl, errEl] }));
67
+ case 'select':
68
+ case 'relation':
69
+ return (_jsxs("div", { children: [labelEl, _jsxs("select", { id: id, value: String(value ?? ''), disabled: field.disabled, onChange: (e) => onChange(e.target.value), className: cn(inputBase, error && 'border-[var(--dash-error)]'), children: [_jsx("option", { value: "", children: field.placeholder ?? 'Select...' }), (field.options ?? []).map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }), descEl, errEl] }));
70
+ case 'toggle':
71
+ return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("button", { id: id, type: "button", role: "switch", "aria-checked": Boolean(value), disabled: field.disabled, onClick: () => onChange(!value), className: cn('relative inline-flex h-5 w-9 flex-shrink-0 rounded-full transition-colors', 'focus:outline-none focus:ring-2 focus:ring-[var(--dash-primary)] focus:ring-offset-2 focus:ring-offset-[var(--dash-surface)]', value ? 'bg-[var(--dash-primary)]' : 'bg-[var(--dash-border)]', field.disabled && 'opacity-50 cursor-not-allowed'), children: _jsx("span", { className: cn('pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transition-transform', value ? 'translate-x-4' : 'translate-x-0.5', 'mt-0.5') }) }), _jsx("label", { htmlFor: id, className: "text-sm text-[var(--dash-text)]", children: field.label }), descEl, errEl] }));
72
+ case 'json':
73
+ return (_jsxs("div", { children: [labelEl, _jsx("textarea", { id: id, value: typeof value === 'string' ? value : JSON.stringify(value, null, 2), placeholder: field.placeholder ?? '{}', disabled: field.disabled, rows: field.rows ?? 6, onChange: (e) => {
74
+ try {
75
+ onChange(JSON.parse(e.target.value));
76
+ }
77
+ catch {
78
+ onChange(e.target.value);
79
+ }
80
+ }, className: cn(inputBase, 'font-mono text-xs resize-y', error && 'border-[var(--dash-error)]') }), descEl, errEl] }));
81
+ case 'file':
82
+ return (_jsxs("div", { children: [labelEl, _jsx("input", { id: id, type: "file", accept: field.accept, disabled: field.disabled, onChange: (e) => {
83
+ const file = e.target.files?.[0];
84
+ if (file)
85
+ onChange(file);
86
+ }, className: cn('w-full text-sm text-[var(--dash-text-muted)]', 'file:mr-3 file:rounded-[var(--dash-radius-sm)] file:border-0 file:bg-[var(--dash-primary)] file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-[var(--dash-primary-text)]', 'file:cursor-pointer hover:file:bg-[var(--dash-primary-hover)]') }), descEl, errEl] }));
87
+ default:
88
+ return null;
89
+ }
90
+ }
@@ -0,0 +1,28 @@
1
+ import * as React from 'react';
2
+ export interface BreadcrumbItem {
3
+ label: string;
4
+ href?: string;
5
+ }
6
+ export interface DashHeaderProps {
7
+ /** Breadcrumb trail */
8
+ breadcrumbs?: BreadcrumbItem[];
9
+ /** Search input placeholder */
10
+ searchPlaceholder?: string;
11
+ /** Called when search query changes */
12
+ onSearch?: (query: string) => void;
13
+ /** User avatar URL */
14
+ avatarUrl?: string;
15
+ /** User display name */
16
+ userName?: string;
17
+ /** Dropdown menu rendered on avatar click */
18
+ userDropdown?: React.ReactNode;
19
+ /** Toggle dark/light theme */
20
+ onToggleTheme?: () => void;
21
+ /** Current theme */
22
+ theme?: 'dark' | 'light';
23
+ /** Extra actions (buttons, etc.) rendered right of search */
24
+ actions?: React.ReactNode;
25
+ className?: string;
26
+ }
27
+ export declare function DashHeader({ breadcrumbs, searchPlaceholder, onSearch, avatarUrl, userName, userDropdown, onToggleTheme, theme, actions, className, }: DashHeaderProps): import("react/jsx-runtime").JSX.Element;
28
+ //# sourceMappingURL=dash-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dash-header.d.ts","sourceRoot":"","sources":["../../../src/dash/dash-header.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,WAAW,CAAC,EAAE,cAAc,EAAE,CAAA;IAC9B,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAMD,wBAAgB,UAAU,CAAC,EACzB,WAAW,EACX,iBAA+B,EAC/B,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,KAAc,EACd,OAAO,EACP,SAAS,GACV,EAAE,eAAe,2CAmIjB"}
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from '../../utils';
5
+ /* ------------------------------------------------------------------ */
6
+ /* Component */
7
+ /* ------------------------------------------------------------------ */
8
+ export function DashHeader({ breadcrumbs, searchPlaceholder = 'Search...', onSearch, avatarUrl, userName, userDropdown, onToggleTheme, theme = 'dark', actions, className, }) {
9
+ const [dropdownOpen, setDropdownOpen] = React.useState(false);
10
+ const dropdownRef = React.useRef(null);
11
+ // Close dropdown on outside click
12
+ React.useEffect(() => {
13
+ if (!dropdownOpen)
14
+ return;
15
+ function handleClick(e) {
16
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
17
+ setDropdownOpen(false);
18
+ }
19
+ }
20
+ document.addEventListener('mousedown', handleClick);
21
+ return () => document.removeEventListener('mousedown', handleClick);
22
+ }, [dropdownOpen]);
23
+ return (_jsxs("div", { className: cn('flex h-[var(--dash-header-height)] items-center gap-4 px-4', 'bg-[var(--dash-surface)] text-[var(--dash-text)]', className), children: [breadcrumbs && breadcrumbs.length > 0 && (_jsx("nav", { className: "flex items-center gap-1 text-sm", "aria-label": "Breadcrumb", children: breadcrumbs.map((crumb, i) => (_jsxs(React.Fragment, { children: [i > 0 && (_jsx("span", { className: "text-[var(--dash-text-dim)]", children: "/" })), crumb.href ? (_jsx("a", { href: crumb.href, className: "text-[var(--dash-text-muted)] hover:text-[var(--dash-text)] transition-colors", children: crumb.label })) : (_jsx("span", { className: "text-[var(--dash-text)]", children: crumb.label }))] }, i))) })), _jsx("div", { className: "flex-1" }), onSearch && (_jsxs("div", { className: "relative hidden sm:block", children: [_jsxs("svg", { className: "absolute left-2.5 top-1/2 -translate-y-1/2 text-[var(--dash-text-dim)]", width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: [_jsx("circle", { cx: "7", cy: "7", r: "5.5", stroke: "currentColor", strokeWidth: "1.5" }), _jsx("path", { d: "M11 11l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })] }), _jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch(e.target.value), className: cn('h-8 w-56 rounded-[var(--dash-radius-sm)] border border-[var(--dash-border)] bg-[var(--dash-bg)] pl-8 pr-3 text-sm text-[var(--dash-text)]', 'placeholder:text-[var(--dash-text-dim)]', 'focus:border-[var(--dash-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--dash-primary)]', 'transition-colors') })] })), actions, onToggleTheme && (_jsx("button", { type: "button", onClick: onToggleTheme, className: "rounded-[var(--dash-radius-sm)] p-1.5 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)] transition-colors", "aria-label": `Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`, children: theme === 'dark' ? (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [_jsx("circle", { cx: "8", cy: "8", r: "3.5", stroke: "currentColor", strokeWidth: "1.5" }), _jsx("path", { d: "M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })] })) : (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M14 9.5A6.5 6.5 0 016.5 2 5.5 5.5 0 1014 9.5z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })) })), (avatarUrl || userName) && (_jsxs("div", { className: "relative", ref: dropdownRef, children: [_jsx("button", { type: "button", onClick: () => setDropdownOpen((o) => !o), className: "flex items-center gap-2 rounded-[var(--dash-radius-sm)] p-1 hover:bg-[var(--dash-surface-hover)] transition-colors", children: avatarUrl ? (_jsx("img", { src: avatarUrl, alt: userName ?? 'User', className: "h-7 w-7 rounded-full object-cover" })) : (_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-full bg-[var(--dash-primary)] text-xs font-medium text-[var(--dash-primary-text)]", children: (userName ?? '?')[0].toUpperCase() })) }), dropdownOpen && userDropdown && (_jsx("div", { className: "absolute right-0 top-full z-50 mt-1 min-w-48 rounded-[var(--dash-radius)] border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 shadow-lg", children: userDropdown }))] }))] }));
24
+ }
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ export interface DashLayoutProps {
3
+ /** Sidebar element (use DashSidebar) */
4
+ sidebar: React.ReactNode;
5
+ /** Top header element (use DashHeader) */
6
+ header?: React.ReactNode;
7
+ /** Main content */
8
+ children: React.ReactNode;
9
+ /** Whether the sidebar is collapsed */
10
+ sidebarCollapsed?: boolean;
11
+ /** Callback when sidebar collapse state changes */
12
+ onSidebarCollapse?: (collapsed: boolean) => void;
13
+ className?: string;
14
+ }
15
+ export declare function DashLayout({ sidebar, header, children, sidebarCollapsed, onSidebarCollapse, className, }: DashLayoutProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=dash-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dash-layout.d.ts","sourceRoot":"","sources":["../../../src/dash/dash-layout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,mBAAmB;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,uCAAuC;IACvC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,mDAAmD;IACnD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IAChD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,gBAAwB,EACxB,iBAAiB,EACjB,SAAS,GACV,EAAE,eAAe,2CAyCjB"}
@@ -0,0 +1,8 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { cn } from '../../utils';
4
+ export function DashLayout({ sidebar, header, children, sidebarCollapsed = false, onSidebarCollapse, className, }) {
5
+ return (_jsxs("div", { className: cn('flex h-screen overflow-hidden', 'bg-[var(--dash-bg)] text-[var(--dash-text)]', className), children: [_jsx("aside", { className: cn('flex-shrink-0 overflow-y-auto overflow-x-hidden transition-[width] duration-200', 'border-r border-[var(--dash-border)] bg-[var(--dash-surface)]', sidebarCollapsed
6
+ ? 'w-[var(--dash-sidebar-collapsed-width)]'
7
+ : 'w-[var(--dash-sidebar-width)]'), children: sidebar }), _jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [header && (_jsx("header", { className: "flex-shrink-0 border-b border-[var(--dash-border)] bg-[var(--dash-surface)]", children: header })), _jsx("main", { className: "flex-1 overflow-y-auto p-6", children: children })] }), !sidebarCollapsed && (_jsx("div", { className: "fixed inset-0 z-40 bg-black/60 lg:hidden", onClick: () => onSidebarCollapse?.(true) }))] }));
8
+ }
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+ export interface NavItem {
3
+ label: string;
4
+ href: string;
5
+ icon?: React.ReactNode;
6
+ badge?: string | number;
7
+ active?: boolean;
8
+ }
9
+ export interface NavGroup {
10
+ title?: string;
11
+ items: NavItem[];
12
+ collapsible?: boolean;
13
+ defaultOpen?: boolean;
14
+ }
15
+ export interface DashSidebarProps {
16
+ /** Logo or brand element rendered at the top */
17
+ logo?: React.ReactNode;
18
+ /** Navigation groups */
19
+ groups: NavGroup[];
20
+ /** User menu rendered at the bottom */
21
+ userMenu?: React.ReactNode;
22
+ /** Whether the sidebar is collapsed (icon-only mode) */
23
+ collapsed?: boolean;
24
+ /** Toggle collapse */
25
+ onToggleCollapse?: () => void;
26
+ /** Called when a nav item is clicked */
27
+ onNavigate?: (href: string) => void;
28
+ className?: string;
29
+ }
30
+ export declare function DashSidebar({ logo, groups, userMenu, collapsed, onToggleCollapse, onNavigate, className, }: DashSidebarProps): import("react/jsx-runtime").JSX.Element;
31
+ //# sourceMappingURL=dash-sidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dash-sidebar.d.ts","sourceRoot":"","sources":["../../../src/dash/dash-sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,OAAO,EAAE,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,wBAAwB;IACxB,MAAM,EAAE,QAAQ,EAAE,CAAA;IAClB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,sBAAsB;IACtB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,wCAAwC;IACxC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA2BD,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,SAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,SAAS,GACV,EAAE,gBAAgB,2CA+DlB"}
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from '../../utils';
5
+ /* ------------------------------------------------------------------ */
6
+ /* Hanzo H mark (default logo) */
7
+ /* ------------------------------------------------------------------ */
8
+ function HanzoMark({ size = 28 }) {
9
+ return (_jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M4 4h4v6h8V4h4v16h-4v-6H8v6H4V4z", fill: "currentColor" }) }));
10
+ }
11
+ /* ------------------------------------------------------------------ */
12
+ /* Component */
13
+ /* ------------------------------------------------------------------ */
14
+ export function DashSidebar({ logo, groups, userMenu, collapsed = false, onToggleCollapse, onNavigate, className, }) {
15
+ return (_jsxs("nav", { className: cn('flex h-full flex-col', 'bg-[var(--dash-surface)] text-[var(--dash-text)]', className), children: [_jsxs("div", { className: cn('flex h-[var(--dash-header-height)] items-center border-b border-[var(--dash-border)]', collapsed ? 'justify-center px-2' : 'px-4'), children: [logo ?? _jsx(HanzoMark, {}), !collapsed && onToggleCollapse && (_jsx("button", { type: "button", onClick: onToggleCollapse, className: "ml-auto rounded p-1 text-[var(--dash-text-dim)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]", "aria-label": "Collapse sidebar", children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M10 4L6 8l4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })), collapsed && onToggleCollapse && (_jsx("button", { type: "button", onClick: onToggleCollapse, className: "absolute -right-3 top-4 z-50 hidden rounded-full border border-[var(--dash-border)] bg-[var(--dash-surface)] p-1 text-[var(--dash-text-dim)] hover:text-[var(--dash-text)] lg:flex", "aria-label": "Expand sidebar", children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", children: _jsx("path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }))] }), _jsx("div", { className: "flex-1 overflow-y-auto py-2", children: groups.map((group, gi) => (_jsx(SidebarGroup, { group: group, collapsed: collapsed, onNavigate: onNavigate }, gi))) }), userMenu && (_jsx("div", { className: "border-t border-[var(--dash-border)] p-2", children: userMenu }))] }));
16
+ }
17
+ /* ------------------------------------------------------------------ */
18
+ /* SidebarGroup (internal) */
19
+ /* ------------------------------------------------------------------ */
20
+ function SidebarGroup({ group, collapsed, onNavigate, }) {
21
+ const [open, setOpen] = React.useState(group.defaultOpen !== false);
22
+ const isCollapsible = group.collapsible !== false && !!group.title;
23
+ return (_jsxs("div", { className: "mb-1", children: [group.title && !collapsed && (_jsxs("button", { type: "button", onClick: () => isCollapsible && setOpen((o) => !o), className: cn('flex w-full items-center px-4 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-[var(--dash-text-dim)]', isCollapsible && 'cursor-pointer hover:text-[var(--dash-text-muted)]'), children: [_jsx("span", { className: "flex-1 text-left", children: group.title }), isCollapsible && (_jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", className: cn('transition-transform', open ? 'rotate-0' : '-rotate-90'), children: _jsx("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }))] })), (open || collapsed) && (_jsx("ul", { className: "space-y-0.5 px-2", children: group.items.map((item) => (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => onNavigate?.(item.href), title: collapsed ? item.label : undefined, className: cn('flex w-full items-center gap-2 rounded-[var(--dash-radius-sm)] px-2 py-1.5 text-sm transition-colors', item.active
24
+ ? 'bg-[var(--dash-primary)] text-[var(--dash-primary-text)]'
25
+ : 'text-[var(--dash-text-muted)] hover:bg-[var(--dash-surface-hover)] hover:text-[var(--dash-text)]', collapsed && 'justify-center px-0'), children: [item.icon && (_jsx("span", { className: "flex h-5 w-5 items-center justify-center flex-shrink-0", children: item.icon })), !collapsed && _jsx("span", { className: "flex-1 truncate text-left", children: item.label }), !collapsed && item.badge !== undefined && (_jsx("span", { className: "ml-auto rounded-full bg-[var(--dash-primary)] px-1.5 py-0.5 text-[10px] font-medium text-[var(--dash-primary-text)]", children: item.badge }))] }) }, item.href))) }))] }));
26
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @hanzo/ui/dash
3
+ *
4
+ * Shared dash UI foundation. Dark-themed layout, navigation,
5
+ * data table, form builder, and CRUD components.
6
+ *
7
+ * Design tokens in tokens.css work in both React and Svelte.
8
+ */
9
+ export { DashLayout } from './dash-layout';
10
+ export type { DashLayoutProps } from './dash-layout';
11
+ export { DashSidebar } from './dash-sidebar';
12
+ export type { DashSidebarProps, NavItem, NavGroup } from './dash-sidebar';
13
+ export { DashHeader } from './dash-header';
14
+ export type { DashHeaderProps, BreadcrumbItem } from './dash-header';
15
+ export { DashDataTable } from './dash-data-table';
16
+ export type { DashDataTableProps, DashColumn } from './dash-data-table';
17
+ export { DashForm } from './dash-form';
18
+ export type { DashFormProps, DashFieldDef, DashFieldType, DashFieldOption } from './dash-form';
19
+ export { DashCrud } from './dash-crud';
20
+ export type { DashCrudProps } from './dash-crud';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dash/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAGzE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAGpE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAGvE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAG9F,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @hanzo/ui/dash
3
+ *
4
+ * Shared dash UI foundation. Dark-themed layout, navigation,
5
+ * data table, form builder, and CRUD components.
6
+ *
7
+ * Design tokens in tokens.css work in both React and Svelte.
8
+ */
9
+ // Layout
10
+ export { DashLayout } from './dash-layout';
11
+ // Sidebar
12
+ export { DashSidebar } from './dash-sidebar';
13
+ // Header
14
+ export { DashHeader } from './dash-header';
15
+ // Data Table
16
+ export { DashDataTable } from './dash-data-table';
17
+ // Form
18
+ export { DashForm } from './dash-form';
19
+ // CRUD
20
+ export { DashCrud } from './dash-crud';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "5.3.43",
3
+ "version": "5.4.1",
4
4
  "description": "Multi-framework UI library with React, Vue, Svelte, and React Native support. Based on shadcn/ui with comprehensive framework coverage.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -255,6 +255,17 @@
255
255
  "import": "./dist/drawer.mjs",
256
256
  "require": "./dist/drawer.js"
257
257
  },
258
+ "./dash": {
259
+ "types": "./dist/dash/index.d.ts",
260
+ "import": "./dist/dash/index.mjs",
261
+ "require": "./dist/dash/index.js"
262
+ },
263
+ "./dash/tokens.css": "./src/dash/tokens.css",
264
+ "./dash/*": {
265
+ "types": "./dist/dash/*.d.ts",
266
+ "import": "./dist/dash/*.mjs",
267
+ "require": "./dist/dash/*.js"
268
+ },
258
269
  "./billing": {
259
270
  "types": "./dist/billing/index.d.ts",
260
271
  "import": "./dist/billing/index.mjs",