@stackwright-pro/display-components 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/charles/git/peraspera/stackwright-pro/packages/display-components/dist/index.js","../src/components/MetricCard.tsx","../src/types/index.ts","../src/components/StatusBadge.tsx","../src/components/StatBar.tsx","../src/components/Sparkline.tsx","../src/components/ActivityFeed.tsx","../src/components/DashboardGrid.tsx","../src/components/DataTable.tsx","../src/components/JsonViewer.tsx"],"names":["jsxs","jsx","useState"],"mappings":"AAAA;ACAA,qCAAuB;ADEvB;AACA;AEsFO,IAAM,aAAA,EAAe;AAAA,EAC1B,OAAA,EAAS,SAAA;AAAA,EACT,OAAA,EAAS,SAAA;AAAA,EACT,OAAA,EAAS,SAAA;AAAA,EACT,KAAA,EAAO,SAAA;AAAA,EACP,IAAA,EAAM,SAAA;AAAA,EACN,UAAA,EAAY,SAAA;AAAA,EACZ,OAAA,EAAS,SAAA;AAAA,EACT,IAAA,EAAM,SAAA;AAAA,EACN,aAAA,EAAe;AACjB,CAAA;AAGO,IAAM,cAAA,EAA+C;AAAA,EAC1D,WAAA,EAAa,SAAA;AAAA,EACb,QAAA,EAAU,SAAA;AAAA,EACV,MAAA,EAAQ,SAAA;AAAA,EACR,WAAA,EAAa;AACf,CAAA;AFtFA;AACA;ACKM,+CAAA;AAtBN,IAAM,WAAA,EAAa,CAAC,EAAE,UAAU,CAAA,EAAA,GAAqC;AACnE,EAAA,MAAM,MAAA,EACJ,UAAA,IAAc,KAAA,EACV,YAAA,CAAa,QAAA,EACb,UAAA,IAAc,OAAA,EACd,YAAA,CAAa,MAAA,EACb,YAAA,CAAa,aAAA;AAEnB,EAAA,uBACE,6BAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,IAAA;AAAA,MACN,MAAA,EAAO,IAAA;AAAA,MACP,OAAA,EAAQ,WAAA;AAAA,MACR,IAAA,EAAK,MAAA;AAAA,MACL,MAAA,EAAQ,KAAA;AAAA,MACR,WAAA,EAAY,GAAA;AAAA,MACZ,aAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAe,OAAA;AAAA,MACf,KAAA,EAAO;AAAA,QACL,SAAA,EAAW,UAAA,IAAc,OAAA,EAAS,iBAAA,EAAmB,KAAA;AAAA,MACvD,CAAA;AAAA,MAEA,QAAA,kBAAA,6BAAA,MAAC,EAAA,EAAK,CAAA,EAAE,wBAAA,CAAwB;AAAA,IAAA;AAAA,EAClC,CAAA;AAEJ,CAAA;AAGA,IAAM,eAAA,EAAiB,CAAC,EAAE,MAAM,CAAA,EAAA,GAAyB;AACvD,EAAA,uBACE,6BAAA;AAAA,IAAC,aAAA,CAAO,IAAA;AAAA,IAAP;AAAA,MACC,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA;AAAA,MAC7B,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,CAAA,EAAG,EAAE,CAAA;AAAA,MAC5B,UAAA,EAAY,EAAE,QAAA,EAAU,GAAA,EAAK,IAAA,EAAM,UAAU,CAAA;AAAA,MAE5C,QAAA,EAAA,KAAA,CAAM,cAAA,CAAe;AAAA,IAAA;AAAA,EACxB,CAAA;AAEJ,CAAA;AAEO,IAAM,WAAA,EAAa,CAAC;AAAA,EACzB,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA,EAAQ,YAAA,CAAa,OAAA;AAAA,EACrB;AACF,CAAA,EAAA,GAAuB;AACrB,EAAA,uBACE,8BAAA;AAAA,IAAC,aAAA,CAAO,GAAA;AAAA,IAAP;AAAA,MACC,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,KAAK,CAAA;AAAA,MACnC,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,EAAE,CAAA;AAAA,MAChC,UAAA,EAAY,EAAE,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,6BAA6B,CAAA;AAAA,MACnE,UAAA,EAAY,EAAE,QAAA,EAAU,IAAI,CAAA;AAAA,MAC5B,KAAA,EAAO;AAAA,QACL,eAAA,EAAiB,OAAA;AAAA,QACjB,YAAA,EAAc,MAAA;AAAA,QACd,OAAA,EAAS,MAAA;AAAA,QACT,SAAA,EAAW,2BAAA;AAAA,QACX,MAAA,EAAQ,mBAAA;AAAA,QACR,QAAA,EAAU,UAAA;AAAA,QACV,QAAA,EAAU;AAAA,MACZ,CAAA;AAAA,MAGA,QAAA,EAAA;AAAA,wBAAA,6BAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,GAAA,EAAK,CAAA;AAAA,cACL,IAAA,EAAM,CAAA;AAAA,cACN,KAAA,EAAO,CAAA;AAAA,cACP,MAAA,EAAQ,KAAA;AAAA,cACR,eAAA,EAAiB;AAAA,YACnB;AAAA,UAAA;AAAA,QACF,CAAA;AAAA,wBAEA,8BAAA,KAAC,EAAA,EAAI,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAY,YAAA,EAAc,cAAA,EAAgB,gBAAgB,CAAA,EACvF,QAAA,EAAA;AAAA,0BAAA,8BAAA,KAAC,EAAA,EAAI,KAAA,EAAO,EAAE,IAAA,EAAM,EAAE,CAAA,EAEpB,QAAA,EAAA;AAAA,4BAAA,6BAAA;AAAA,cAAC,GAAA;AAAA,cAAA;AAAA,gBACC,KAAA,EAAO;AAAA,kBACL,QAAA,EAAU,MAAA;AAAA,kBACV,KAAA,EAAO,YAAA,CAAa,aAAA;AAAA,kBACpB,MAAA,EAAQ,WAAA;AAAA,kBACR,UAAA,EAAY;AAAA,gBACd,CAAA;AAAA,gBAEC,QAAA,EAAA;AAAA,cAAA;AAAA,YACH,CAAA;AAAA,4BAGA,6BAAA;AAAA,cAAC,GAAA;AAAA,cAAA;AAAA,gBACC,KAAA,EAAO;AAAA,kBACL,QAAA,EAAU,MAAA;AAAA,kBACV,UAAA,EAAY,GAAA;AAAA,kBACZ,KAAA,EAAO,YAAA,CAAa,IAAA;AAAA,kBACpB,MAAA,EAAQ,CAAA;AAAA,kBACR,UAAA,EAAY;AAAA,gBACd,CAAA;AAAA,gBAEA,QAAA,kBAAA,6BAAA,cAAC,EAAA,EAAe,MAAA,CAAc;AAAA,cAAA;AAAA,YAChC,CAAA;AAAA,YAGC,MAAA,GAAS,WAAA,mBACR,8BAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,KAAA,EAAO;AAAA,kBACL,OAAA,EAAS,MAAA;AAAA,kBACT,UAAA,EAAY,QAAA;AAAA,kBACZ,GAAA,EAAK,KAAA;AAAA,kBACL,SAAA,EAAW;AAAA,gBACb,CAAA;AAAA,gBAEA,QAAA,EAAA;AAAA,kCAAA,6BAAA,UAAC,EAAA,EAAW,SAAA,EAAW,MAAA,CAAO,CAAA;AAAA,kCAC9B,6BAAA;AAAA,oBAAC,MAAA;AAAA,oBAAA;AAAA,sBACC,KAAA,EAAO;AAAA,wBACL,QAAA,EAAU,MAAA;AAAA,wBACV,KAAA,EAAO,YAAA,CAAa;AAAA,sBACtB,CAAA;AAAA,sBAEC,QAAA,EAAA;AAAA,oBAAA;AAAA,kBACH;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF;AAAA,UAAA,EAAA,CAEJ,CAAA;AAAA,UAGC,KAAA,mBACC,6BAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAO;AAAA,gBACL,KAAA,EAAO,MAAA;AAAA,gBACP,MAAA,EAAQ,MAAA;AAAA,gBACR,YAAA,EAAc,MAAA;AAAA,gBACd,eAAA,EAAiB,CAAA,EAAA;AACR,gBAAA;AACG,gBAAA;AACI,gBAAA;AAChB,gBAAA;AACF,cAAA;AAEC,cAAA;AAAA,YAAA;AACH,UAAA;AAEJ,QAAA;AAAA,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;ADekC;AACA;AGvKX;AAQnBA;AAJkC;AACR,EAAA;AAG1BA,EAAAA;AAAC,IAAA;AAAA,IAAA;AACQ,MAAA;AACI,QAAA;AACG,QAAA;AACP,QAAA;AACI,QAAA;AACK,QAAA;AACW,QAAA;AACC,QAAA;AAC5B,MAAA;AAGC,MAAA;AACCC,QAAAA;AAAQ,UAAA;AAAP,UAAA;AACU,YAAA;AACU,cAAA;AACE,cAAA;AACrB,YAAA;AACY,YAAA;AACA,cAAA;AACF,cAAA;AACF,cAAA;AACR,YAAA;AACO,YAAA;AACE,cAAA;AACC,cAAA;AACM,cAAA;AACG,cAAA;AACN,cAAA;AACb,YAAA;AAAA,UAAA;AACF,QAAA;AAKAA,QAAAA;AAAC,UAAA;AAAA,UAAA;AACQ,YAAA;AACE,cAAA;AACC,cAAA;AACM,cAAA;AACG,cAAA;AACnB,YAAA;AAAA,UAAA;AACF,QAAA;AAIFA,wBAAAA;AAAC,UAAA;AAAA,UAAA;AACQ,YAAA;AACK,cAAA;AACE,cAAA;AACZ,cAAA;AACe,cAAA;AACjB,YAAA;AAEC,YAAA;AAAA,UAAA;AACH,QAAA;AAAA,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;AHuKkC;AACA;AI1OX;AAoCXD;AAhCY;AACtB,EAAA;AACA,EAAA;AACA,EAAA;AACqB,EAAA;AACJ,EAAA;AACC;AACU,EAAA;AAGzB,EAAA;AAGG,IAAA;AAAC,MAAA;AAAA,MAAA;AACQ,QAAA;AACI,UAAA;AACO,UAAA;AACF,UAAA;AAChB,QAAA;AAEC,QAAA;AACC,UAAA;AAAC,YAAA;AAAA,YAAA;AACQ,cAAA;AACK,gBAAA;AACH,gBAAA;AACK,gBAAA;AACd,cAAA;AAEC,cAAA;AAAA,YAAA;AACH,UAAA;AAGA,UAAA;AAAC,YAAA;AAAA,YAAA;AACQ,cAAA;AACK,gBAAA;AACH,gBAAA;AACK,gBAAA;AACd,cAAA;AAEC,cAAA;AAAA,gBAAA;AAAW,gBAAA;AAAA,cAAA;AAAA,YAAA;AACd,UAAA;AAAA,QAAA;AAAA,MAAA;AAEJ,IAAA;AAIFC,oBAAAA;AAAC,MAAA;AAAA,MAAA;AACQ,QAAA;AACE,UAAA;AACC,UAAA;AACY,UAAA;AACN,UAAA;AACJ,UAAA;AACZ,QAAA;AAEAA,QAAAA;AAAQ,UAAA;AAAP,UAAA;AACqB,YAAA;AACC,YAAA;AACP,YAAA;AACP,YAAA;AACG,cAAA;AACS,cAAA;AACH,cAAA;AAChB,YAAA;AAAA,UAAA;AACF,QAAA;AAAA,MAAA;AACF,IAAA;AAGAD,oBAAAA;AAAC,MAAA;AAAA,MAAA;AACQ,QAAA;AACI,UAAA;AACO,UAAA;AACL,UAAA;AACD,UAAA;AACU,UAAA;AACtB,QAAA;AAEA,QAAA;AAAC,0BAAA;AACA,0BAAA;AAA2B,QAAA;AAAA,MAAA;AAC9B,IAAA;AACF,EAAA;AAEJ;AJgPkC;AACA;AKvUX;AAqCfA;AAjCkB;AACxB,EAAA;AACQ,EAAA;AACC,EAAA;AACY,EAAA;AACd,EAAA;AACa;AACU,EAAA;AACrB,IAAA;AACT,EAAA;AAE4B,EAAA;AACA,EAAA;AACD,EAAA;AAGK,EAAA;AACL,IAAA;AACI,IAAA;AACb,IAAA;AACjB,EAAA;AAE8B,EAAA;AACA,EAAA;AAG7BA,EAAAA;AAAC,IAAA;AAAA,IAAA;AACC,MAAA;AACA,MAAA;AACyB,MAAA;AACN,MAAA;AAEnB,MAAA;AAAC,wBAAA;AAEI,0BAAA;AACA,0BAAA;AAEL,QAAA;AAIEC,QAAAA;AAAQ,UAAA;AAAP,UAAA;AACI,YAAA;AACG,YAAA;AACgB,YAAA;AACA,YAAA;AACR,YAAA;AAAc,UAAA;AAC9B,QAAA;AAIFA,wBAAAA;AAAQ,UAAA;AAAP,UAAA;AACI,YAAA;AACE,YAAA;AACG,YAAA;AACI,YAAA;AACE,YAAA;AACC,YAAA;AACJ,YAAA;AACA,YAAA;AACG,YAAA;AAA6B,UAAA;AAC7C,QAAA;AAGAA,wBAAAA;AAAQ,UAAA;AAAP,UAAA;AACK,YAAA;AACgB,YAAA;AAClB,YAAA;AACI,YAAA;AACc,YAAA;AACA,YAAA;AACC,YAAA;AAAmB,UAAA;AAC1C,QAAA;AAAA,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;ALmUkC;AACA;AMnZX;AAkCjBD;AA7B6D;AAEtD,EAAA;AAQ6C,EAAA;AAC7C,IAAA;AACA,IAAA;AACF,IAAA;AACD,IAAA;AACR,EAAA;AAGEC,EAAAA;AAAC,IAAA;AAAA,IAAA;AACQ,MAAA;AACE,QAAA;AACC,QAAA;AACM,QAAA;AACW,QAAA;AAChB,QAAA;AACG,QAAA;AACI,QAAA;AAClB,MAAA;AAEAD,MAAAA;AAAC,QAAA;AAAA,QAAA;AACO,UAAA;AACC,UAAA;AACC,UAAA;AACH,UAAA;AACG,UAAA;AACI,UAAA;AACE,UAAA;AACC,UAAA;AAEf,UAAA;AAAC,4BAAA;AACA,4BAAA;AAAyB,UAAA;AAAA,QAAA;AAC5B,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;AAGyB;AACH,EAAA;AACJ,EAAA;AACe,EAAA;AACH,EAAA;AACC,EAAA;AACD,EAAA;AAEH,EAAA;AACI,EAAA;AACC,EAAA;AACF,EAAA;AACG,EAAA;AACjC;AAG0B;AACxB,EAAA;AACA,EAAA;AAII;AAEFA,EAAAA;AAAQ,IAAA;AAAP,IAAA;AAC2B,MAAA;AACE,MAAA;AACP,MAAA;AACd,MAAA;AACI,QAAA;AACJ,QAAA;AACI,QAAA;AACK,QAAA;AAChB,MAAA;AAEA,MAAA;AAAC,wBAAA;AACA,wBAAA;AACCC,0BAAAA;AAAC,YAAA;AAAA,YAAA;AACQ,cAAA;AACK,gBAAA;AACE,gBAAA;AACL,gBAAA;AACC,gBAAA;AACV,cAAA;AAEM,cAAA;AAAA,YAAA;AACR,UAAA;AAEE,UAAA;AAAC,YAAA;AAAA,YAAA;AACQ,cAAA;AACK,gBAAA;AACH,gBAAA;AACC,gBAAA;AACV,cAAA;AAEM,cAAA;AAAA,YAAA;AACR,UAAA;AAEJ,QAAA;AACAA,wBAAAA;AAAC,UAAA;AAAA,UAAA;AACQ,YAAA;AACK,cAAA;AACU,cAAA;AACR,cAAA;AACd,YAAA;AAEC,YAAA;AAA8B,UAAA;AACjC,QAAA;AAAA,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;AAEsC;AACJ,EAAA;AAG9BD,EAAAA;AAAC,IAAA;AAAA,IAAA;AACQ,MAAA;AACY,QAAA;AACH,QAAA;AACL,QAAA;AACE,QAAA;AACH,QAAA;AACV,MAAA;AAEA,MAAA;AAAAC,wBAAAA;AAAC,UAAA;AAAA,UAAA;AACQ,YAAA;AACK,cAAA;AACE,cAAA;AACQ,cAAA;AACZ,cAAA;AACV,YAAA;AACD,YAAA;AAAA,UAAA;AAED,QAAA;AACC,wBAAA;AAID,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;ANyYkC;AACA;AOpiBX;AAkBf;AAfsB;AAClB,EAAA;AACV,EAAA;AACM,EAAA;AACkB;AAEtBA,EAAAA;AAAC,IAAA;AAAA,IAAA;AACQ,MAAA;AACI,QAAA;AACY,QAAA;AACV,QAAA;AACJ,QAAA;AACT,MAAA;AAEkB,MAAA;AACR,QAAA;AAAP,QAAA;AAEwB,UAAA;AACA,UAAA;AACF,UAAA;AAEpB,UAAA;AAAA,QAAA;AALI,QAAA;AAOR,MAAA;AAAA,IAAA;AACH,EAAA;AAEJ;APqiBkC;AACA;AQnkBlC;AAEE;AACA;AACA;AACA;AAGK;AACgB;AACE;AAsILD;AAlIwB;AAC1C,EAAA;AACA,EAAA;AACU,EAAA;AACK,EAAA;AACf,EAAA;AACoB;AACU,EAAA;AAGuB,EAAA;AAC/B,IAAA;AACS,IAAA;AACjB,IAAA;AACI,IAAA;AACc,MAAA;AAGD,MAAA;AACe,QAAA;AAC1C,MAAA;AAC2B,MAAA;AACA,QAAA;AAC3B,MAAA;AAC0B,MAAA;AAEtB,QAAA;AAMAC,QAAAA;AAAC,UAAA;AAAA,UAAA;AACQ,YAAA;AACI,cAAA;AACK,cAAA;AACM,cAAA;AACb,cAAA;AACG,cAAA;AACE,cAAA;AACd,YAAA;AAEa,YAAA;AAAA,UAAA;AACf,QAAA;AAEJ,MAAA;AACyB,MAAA;AAC3B,IAAA;AAC0B,IAAA;AACP,IAAA;AACnB,EAAA;AAE0B,EAAA;AAC1B,IAAA;AACS,IAAA;AACQ,IAAA;AACA,IAAA;AACA,IAAA;AACE,IAAA;AACpB,EAAA;AAEY,EAAA;AAETA,IAAAA;AAAC,MAAA;AAAA,MAAA;AACQ,QAAA;AACI,UAAA;AACG,UAAA;AACI,UAAA;AACP,UAAA;AACW,UAAA;AACtB,QAAA;AAEAA,QAAAA;AAAQ,UAAA;AAAP,UAAA;AACoB,YAAA;AACL,YAAA;AACE,YAAA;AAA+G,UAAA;AACjI,QAAA;AAAA,MAAA;AACF,IAAA;AAEJ,EAAA;AAEuB,EAAA;AAEnBA,IAAAA;AAAC,MAAA;AAAA,MAAA;AACQ,QAAA;AACI,UAAA;AACG,UAAA;AACI,UAAA;AACP,UAAA;AACW,UAAA;AACtB,QAAA;AAEC,QAAA;AAAA,MAAA;AACH,IAAA;AAEJ,EAAA;AAGEA,EAAAA;AAAC,IAAA;AAAA,IAAA;AACQ,MAAA;AACY,QAAA;AACH,QAAA;AACJ,QAAA;AACC,QAAA;AACH,QAAA;AACV,MAAA;AAEAA,MAAAA;AAEK,wBAAA;AAIQ,UAAA;AAAA,UAAA;AAEiB,YAAA;AACT,YAAA;AACI,cAAA;AACE,cAAA;AACD,cAAA;AACE,cAAA;AACQ,cAAA;AACL,cAAA;AACA,cAAA;AACE,cAAA;AACH,cAAA;AACE,cAAA;AACJ,cAAA;AACd,YAAA;AAEA,YAAA;AACqB,cAAA;AACJ,cAAA;AAGjB,YAAA;AAAA,UAAA;AArBY,UAAA;AA0BtB,QAAA;AACC,wBAAA;AAEW,UAAA;AAAP,UAAA;AAEe,YAAA;AACC,YAAA;AACR,YAAA;AACG,cAAA;AACI,cAAA;AACd,YAAA;AAEK,YAAA;AACF,cAAA;AAAA,cAAA;AAEQ,gBAAA;AACI,kBAAA;AACC,kBAAA;AACH,kBAAA;AACO,kBAAA;AAChB,gBAAA;AAEC,gBAAA;AAAwD,cAAA;AAR/C,cAAA;AAUb,YAAA;AAAA,UAAA;AApBQ,UAAA;AAuBf,QAAA;AAEJ,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;AR0iBkC;AACA;ASruBjB;AACRC;AAyCI;AApCQ;AACd,EAAA;AACG,EAAA;AACA,EAAA;AACC,EAAA;AACH,EAAA;AACG,EAAA;AACX;AAGkB;AAChB,EAAA;AACQ,EAAA;AACR,EAAA;AACA,EAAA;AAMI;AAC4BA,EAAAA;AAET,EAAA;AAEc,EAAA;AACf,IAAA;AACV,MAAA;AACV,IAAA;AACqB,IAAA;AACX,MAAA;AACV,IAAA;AACqB,IAAA;AACX,MAAA;AACV,IAAA;AACqB,IAAA;AACZF,MAAAA;AAA6C,QAAA;AAAE,QAAA;AAAM,QAAA;AAAC,MAAA;AAC/D,IAAA;AAC0B,IAAA;AACA,MAAA;AAEtBA,MAAAA;AAA8C,QAAA;AAC1C,QAAA;AAEA,QAAA;AAGuB,UAAA;AACQ,UAAA;AAK/B,QAAA;AAA2C,UAAA;AAAU,UAAA;AAAO,UAAA;AAAM,QAAA;AACjE,QAAA;AAAI,QAAA;AAET,MAAA;AAEJ,IAAA;AACqB,IAAA;AACI,MAAA;AACG,MAAA;AAExBA,MAAAA;AACqB,QAAA;AAEjB,QAAA;AAAQ,UAAA;AAAP,UAAA;AACU,YAAA;AACU,YAAA;AACG,YAAA;AAET,YAAA;AAETA,8BAAAA;AAA0C,gBAAA;AAAE,gBAAA;AAAE,gBAAA;AAAC,cAAA;AAAO,cAAA;AAAmB,cAAA;AAC5D,cAAA;AAEhB,YAAA;AAAA,UAAA;AACH,QAAA;AAEgB,QAAA;AACpB,MAAA;AAEJ,IAAA;AACQ,IAAA;AACV,EAAA;AAEgC,EAAA;AACP,IAAA;AACM,IAAA;AAG1B,IAAA;AACCA,sBAAAA;AAAQ,QAAA;AAAP,QAAA;AACgB,UAAA;AACM,UAAA;AACd,UAAA;AACO,YAAA;AACJ,YAAA;AACA,YAAA;AACC,YAAA;AACG,YAAA;AACF,YAAA;AACU,YAAA;AACX,YAAA;AACG,YAAA;AACP,YAAA;AACP,UAAA;AAEA,UAAA;AAAC,4BAAA;AAGW,YAAA;AAAa,UAAA;AAAA,QAAA;AAC3B,MAAA;AACC,sBAAA;AAEW,QAAA;AAAP,QAAA;AACuB,UAAA;AACH,UAAA;AACA,UAAA;AACA,UAAA;AAEN,UAAA;AAAI,QAAA;AAGvB,MAAA;AACF,IAAA;AAEJ,EAAA;AAEQ,EAAA;AACV;AAGoD;AACtBE,EAAAA;AAEG,EAAA;AACH,IAAA;AACZ,IAAA;AACa,IAAA;AAC7B,EAAA;AAGED,EAAAA;AAAQ,IAAA;AAAP,IAAA;AACU,MAAA;AACiB,MAAA;AACF,MAAA;AACjB,MAAA;AACK,QAAA;AACL,QAAA;AACE,QAAA;AACE,QAAA;AACiB,QAAA;AACA,QAAA;AAClB,QAAA;AACM,QAAA;AACJ,QAAA;AACE,QAAA;AACJ,QAAA;AACI,QAAA;AACd,MAAA;AAEU,MAAA;AAAY,IAAA;AACxB,EAAA;AAEJ;AAEmC;AAE/BD,EAAAA;AAAC,IAAA;AAAA,IAAA;AACQ,MAAA;AACK,QAAA;AACO,QAAA;AACH,QAAA;AACL,QAAA;AACG,QAAA;AACF,QAAA;AACE,QAAA;AACU,QAAA;AACtB,QAAA;AACF,MAAA;AAEA,MAAA;AAAC,wBAAA;AACA,wBAAA;AAAqE,MAAA;AAAA,IAAA;AACxE,EAAA;AAEJ;ATqtBkC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/charles/git/peraspera/stackwright-pro/packages/display-components/dist/index.js","sourcesContent":[null,"import { motion } from 'motion/react';\nimport { THEME_COLORS } from '../types';\nimport type { MetricCardProps, TrendDirection } from '../types';\n\n// Trend arrow icons\nconst TrendArrow = ({ direction }: { direction: TrendDirection }) => {\n const color =\n direction === 'up'\n ? THEME_COLORS.success\n : direction === 'down'\n ? THEME_COLORS.error\n : THEME_COLORS.textSecondary;\n\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{\n transform: direction === 'down' ? 'rotate(180deg)' : undefined,\n }}\n >\n <path d=\"M12 19V5M5 12l7-7 7 7\" />\n </svg>\n );\n};\n\n// Animated number counter\nconst AnimatedNumber = ({ value }: { value: number }) => {\n return (\n <motion.span\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.5, ease: 'easeOut' }}\n >\n {value.toLocaleString()}\n </motion.span>\n );\n};\n\nexport const MetricCard = ({\n label,\n value,\n trend,\n trendValue,\n color = THEME_COLORS.primary,\n icon,\n}: MetricCardProps) => {\n return (\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n whileHover={{ scale: 1.02, boxShadow: '0 4px 20px rgba(0,0,0,0.1)' }}\n transition={{ duration: 0.3 }}\n style={{\n backgroundColor: 'white',\n borderRadius: '12px',\n padding: '24px',\n boxShadow: '0 1px 3px rgba(0,0,0,0.1)',\n border: '1px solid #E5E7EB',\n position: 'relative',\n overflow: 'hidden',\n }}\n >\n {/* Accent bar */}\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '4px',\n backgroundColor: color,\n }}\n />\n\n <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>\n <div style={{ flex: 1 }}>\n {/* Label */}\n <p\n style={{\n fontSize: '14px',\n color: THEME_COLORS.textSecondary,\n margin: '0 0 8px 0',\n fontWeight: 500,\n }}\n >\n {label}\n </p>\n\n {/* Value */}\n <p\n style={{\n fontSize: '36px',\n fontWeight: 700,\n color: THEME_COLORS.text,\n margin: 0,\n lineHeight: 1,\n }}\n >\n <AnimatedNumber value={value} />\n </p>\n\n {/* Trend */}\n {trend && trendValue && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n marginTop: '12px',\n }}\n >\n <TrendArrow direction={trend} />\n <span\n style={{\n fontSize: '13px',\n color: THEME_COLORS.textSecondary,\n }}\n >\n {trendValue}\n </span>\n </div>\n )}\n </div>\n\n {/* Icon */}\n {icon && (\n <div\n style={{\n width: '48px',\n height: '48px',\n borderRadius: '12px',\n backgroundColor: `${color}15`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: color,\n }}\n >\n {icon}\n </div>\n )}\n </div>\n </motion.div>\n );\n};\n\nexport default MetricCard;\n","// Trend direction for metrics\nexport type TrendDirection = 'up' | 'down' | 'stable';\n\n// Status badge variants\nexport type StatusVariant = 'operational' | 'degraded' | 'outage' | 'maintenance';\n\n// Metric card props\nexport interface MetricCardProps {\n label: string;\n value: number;\n trend?: TrendDirection;\n trendValue?: string;\n color?: string;\n icon?: React.ReactNode;\n}\n\n// Status badge props\nexport interface StatusBadgeProps {\n status: StatusVariant;\n label: string;\n pulse?: boolean;\n}\n\n// Stat bar props\nexport interface StatBarProps {\n current: number;\n max: number;\n label?: string;\n color?: string;\n showPercentage?: boolean;\n}\n\n// Sparkline props\nexport interface SparklineProps {\n data: number[];\n width?: number;\n height?: number;\n color?: string;\n fill?: boolean;\n}\n\n// Activity feed item\nexport interface ActivityItem {\n id: string;\n type: 'success' | 'warning' | 'error' | 'info';\n title: string;\n description?: string;\n timestamp: Date | string;\n}\n\n// Activity feed props\nexport interface ActivityFeedProps {\n items: ActivityItem[];\n maxItems?: number;\n}\n\n// Dashboard grid props\nexport interface DashboardGridProps {\n columns?: 1 | 2 | 3 | 4;\n cards: React.ReactNode[];\n gap?: number;\n}\n\n// Column definition for data table\nexport interface ColumnDef<T> {\n field: keyof T;\n header: string;\n type?: 'text' | 'badge' | 'date' | 'number';\n sortable?: boolean;\n filterable?: boolean;\n}\n\n// Data table props\nexport interface DataTableProps<T> {\n data: T[];\n columns: ColumnDef<T>[];\n loading?: boolean;\n emptyMessage?: string;\n onRowClick?: (row: T) => void;\n}\n\n// JSON viewer props\nexport interface JsonViewerProps {\n data: unknown;\n collapsible?: boolean;\n maxHeight?: string;\n}\n\n// Theme colors for Stackwright Pro\nexport const THEME_COLORS = {\n primary: '#0066CC',\n success: '#10B981',\n warning: '#F59E0B',\n error: '#EF4444',\n info: '#3B82F6',\n background: '#FFFFFF',\n surface: '#F3F4F6',\n text: '#111827',\n textSecondary: '#6B7280',\n} as const;\n\n// Status colors\nexport const STATUS_COLORS: Record<StatusVariant, string> = {\n operational: '#10B981',\n degraded: '#F59E0B',\n outage: '#EF4444',\n maintenance: '#6B7280',\n};\n","import { motion } from 'motion/react';\nimport { STATUS_COLORS } from '../types';\nimport type { StatusBadgeProps } from '../types';\n\nexport const StatusBadge = ({ status, label, pulse = false }: StatusBadgeProps) => {\n const color = STATUS_COLORS[status];\n\n return (\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 12px',\n borderRadius: '9999px',\n backgroundColor: `${color}15`,\n border: `1px solid ${color}30`,\n }}\n >\n {/* Pulsing dot */}\n {pulse && (\n <motion.div\n animate={{\n scale: [1, 1.2, 1],\n opacity: [1, 0.6, 1],\n }}\n transition={{\n duration: 1.5,\n repeat: Infinity,\n ease: 'easeInOut',\n }}\n style={{\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: color,\n boxShadow: `0 0 8px ${color}`,\n }}\n />\n )}\n\n {/* Static dot */}\n {!pulse && (\n <div\n style={{\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: color,\n }}\n />\n )}\n\n {/* Label */}\n <span\n style={{\n fontSize: '13px',\n fontWeight: 600,\n color: color,\n textTransform: 'capitalize',\n }}\n >\n {label}\n </span>\n </div>\n );\n};\n\nexport default StatusBadge;\n","import { motion } from 'motion/react';\nimport { THEME_COLORS } from '../types';\nimport type { StatBarProps } from '../types';\n\nexport const StatBar = ({\n current,\n max,\n label,\n color = THEME_COLORS.primary,\n showPercentage = true,\n}: StatBarProps) => {\n const percentage = Math.min(100, Math.round((current / max) * 100));\n\n return (\n <div style={{ width: '100%' }}>\n {/* Label and percentage */}\n {(label || showPercentage) && (\n <div\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n marginBottom: '8px',\n }}\n >\n {label && (\n <span\n style={{\n fontSize: '14px',\n color: THEME_COLORS.text,\n fontWeight: 500,\n }}\n >\n {label}\n </span>\n )}\n {showPercentage && (\n <span\n style={{\n fontSize: '14px',\n color: THEME_COLORS.textSecondary,\n fontWeight: 600,\n }}\n >\n {percentage}%\n </span>\n )}\n </div>\n )}\n\n {/* Progress bar */}\n <div\n style={{\n width: '100%',\n height: '8px',\n backgroundColor: `${color}20`,\n borderRadius: '4px',\n overflow: 'hidden',\n }}\n >\n <motion.div\n initial={{ width: 0 }}\n animate={{ width: `${percentage}%` }}\n transition={{ duration: 0.8, ease: 'easeOut' }}\n style={{\n height: '100%',\n backgroundColor: color,\n borderRadius: '4px',\n }}\n />\n </div>\n\n {/* Current/Max values */}\n <div\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n marginTop: '4px',\n fontSize: '12px',\n color: THEME_COLORS.textSecondary,\n }}\n >\n <span>{current.toLocaleString()}</span>\n <span>{max.toLocaleString()}</span>\n </div>\n </div>\n );\n};\n\nexport default StatBar;\n","import { motion } from 'motion/react';\nimport { THEME_COLORS } from '../types';\nimport type { SparklineProps } from '../types';\n\nexport const Sparkline = ({\n data,\n width = 100,\n height = 30,\n color = THEME_COLORS.primary,\n fill = false,\n}: SparklineProps) => {\n if (!data || data.length < 2) {\n return null;\n }\n\n const min = Math.min(...data);\n const max = Math.max(...data);\n const range = max - min || 1;\n\n // Generate points\n const points = data.map((value, index) => {\n const x = (index / (data.length - 1)) * width;\n const y = height - ((value - min) / range) * height;\n return `${x},${y}`;\n });\n\n const pathD = `M ${points.join(' L ')}`;\n const fillPath = `${pathD} L ${width},${height} L 0,${height} Z`;\n\n return (\n <svg\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n style={{ overflow: 'visible' }}\n >\n <defs>\n <linearGradient id={`gradient-${color.replace('#', '')}`} x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stopColor={color} stopOpacity={0.3} />\n <stop offset=\"100%\" stopColor={color} stopOpacity={0} />\n </linearGradient>\n </defs>\n\n {/* Fill area */}\n {fill && (\n <motion.path\n d={fillPath}\n fill={`url(#gradient-${color.replace('#', '')})`}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.5 }}\n />\n )}\n\n {/* Line */}\n <motion.path\n d={pathD}\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={{ duration: 1, ease: 'easeOut' }}\n />\n\n {/* End dot */}\n <motion.circle\n cx={width}\n cy={height - ((data[data.length - 1] - min) / range) * height}\n r=\"3\"\n fill={color}\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={{ delay: 0.9, duration: 0.2 }}\n />\n </svg>\n );\n};\n\nexport default Sparkline;\n","import { motion } from 'motion/react';\nimport { THEME_COLORS } from '../types';\nimport type { ActivityFeedProps, ActivityItem } from '../types';\n\n// Icon components for each activity type\nconst ActivityIcon = ({ type }: { type: ActivityItem['type'] }) => {\n const color =\n type === 'success'\n ? THEME_COLORS.success\n : type === 'warning'\n ? THEME_COLORS.warning\n : type === 'error'\n ? THEME_COLORS.error\n : THEME_COLORS.info;\n\n const iconPaths: Record<ActivityItem['type'], string> = {\n success: 'M20 6L9 17l-5-5',\n warning: 'M12 9v4M12 17h.01',\n error: 'M18 6L6 18M6 6l12 12',\n info: 'M12 16v-4M12 8h.01',\n };\n\n return (\n <div\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n backgroundColor: `${color}15`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d={iconPaths[type]} />\n </svg>\n </div>\n );\n};\n\n// Format timestamp to relative time\nconst formatTimestamp = (timestamp: Date | string): string => {\n const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return 'Just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n return date.toLocaleDateString();\n};\n\n// Single activity item\nconst ActivityFeedItem = ({\n item,\n index,\n}: {\n item: ActivityItem;\n index: number;\n}) => {\n return (\n <motion.div\n initial={{ opacity: 0, x: -20 }}\n animate={{ opacity: 1, x: 0 }}\n transition={{ delay: index * 0.1, duration: 0.3 }}\n style={{\n display: 'flex',\n gap: '12px',\n padding: '12px 0',\n borderBottom: '1px solid #E5E7EB',\n }}\n >\n <ActivityIcon type={item.type} />\n <div style={{ flex: 1 }}>\n <p\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: THEME_COLORS.text,\n margin: 0,\n }}\n >\n {item.title}\n </p>\n {item.description && (\n <p\n style={{\n fontSize: '13px',\n color: THEME_COLORS.textSecondary,\n margin: '4px 0 0 0',\n }}\n >\n {item.description}\n </p>\n )}\n </div>\n <span\n style={{\n fontSize: '12px',\n color: THEME_COLORS.textSecondary,\n whiteSpace: 'nowrap',\n }}\n >\n {formatTimestamp(item.timestamp)}\n </span>\n </motion.div>\n );\n};\n\nexport const ActivityFeed = ({ items, maxItems }: ActivityFeedProps) => {\n const displayItems = maxItems ? items.slice(0, maxItems) : items;\n\n return (\n <div\n style={{\n backgroundColor: 'white',\n borderRadius: '12px',\n padding: '20px',\n boxShadow: '0 1px 3px rgba(0,0,0,0.1)',\n border: '1px solid #E5E7EB',\n }}\n >\n <h3\n style={{\n fontSize: '16px',\n fontWeight: 600,\n color: THEME_COLORS.text,\n margin: '0 0 16px 0',\n }}\n >\n Recent Activity\n </h3>\n <div>\n {displayItems.map((item, index) => (\n <ActivityFeedItem key={item.id} item={item} index={index} />\n ))}\n </div>\n </div>\n );\n};\n\nexport default ActivityFeed;\n","import { motion } from 'motion/react';\nimport type { DashboardGridProps } from '../types';\n\nexport const DashboardGrid = ({\n columns = 3,\n cards,\n gap = 24,\n}: DashboardGridProps) => {\n return (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(${columns}, 1fr)`,\n gap: `${gap}px`,\n width: '100%',\n }}\n >\n {cards.map((card, index) => (\n <motion.div\n key={index}\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: index * 0.1, duration: 0.4 }}\n >\n {card}\n </motion.div>\n ))}\n </div>\n );\n};\n\nexport default DashboardGrid;\n","import {\n createColumnHelper,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable,\n type SortingState,\n type ColumnDef as TanstackColumnDef,\n} from '@tanstack/react-table';\nimport { motion } from 'motion/react';\nimport { useState } from 'react';\nimport { THEME_COLORS } from '../types';\nimport type { DataTableProps, ColumnDef } from '../types';\n\nexport function DataTable<T extends object>({\n data,\n columns,\n loading = false,\n emptyMessage = 'No data available',\n onRowClick,\n}: DataTableProps<T>) {\n const [sorting, setSorting] = useState<SortingState>([]);\n\n // Convert ColumnDef to tanstack columns using accessors\n const tableColumns: TanstackColumnDef<T>[] = columns.map((col) => ({\n id: String(col.field),\n accessorKey: String(col.field) as keyof T,\n header: col.header,\n cell: (info) => {\n const value = info.getValue();\n \n // Format based on type\n if (col.type === 'date' && value) {\n return new Date(value as string | Date).toLocaleDateString();\n }\n if (col.type === 'number') {\n return (value as number).toLocaleString();\n }\n if (col.type === 'badge') {\n const badgeColor =\n value === 'available' || value === 'operational'\n ? THEME_COLORS.success\n : value === 'pending'\n ? THEME_COLORS.warning\n : THEME_COLORS.error;\n return (\n <span\n style={{\n padding: '4px 8px',\n borderRadius: '4px',\n backgroundColor: `${badgeColor}15`,\n color: badgeColor,\n fontSize: '12px',\n fontWeight: 500,\n }}\n >\n {String(value)}\n </span>\n );\n }\n return String(value ?? '');\n },\n sortingFn: col.sortable ? 'alphanumeric' : undefined,\n enableSorting: col.sortable ?? false,\n }));\n\n const table = useReactTable({\n data,\n columns: tableColumns,\n state: { sorting },\n onSortingChange: setSorting,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n });\n\n if (loading) {\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px',\n color: THEME_COLORS.textSecondary,\n }}\n >\n <motion.div\n animate={{ rotate: 360 }}\n transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}\n style={{ width: '24px', height: '24px', border: '3px solid #E5E7EB', borderTopColor: THEME_COLORS.primary, borderRadius: '50%' }}\n />\n </div>\n );\n }\n\n if (data.length === 0) {\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px',\n color: THEME_COLORS.textSecondary,\n }}\n >\n {emptyMessage}\n </div>\n );\n }\n\n return (\n <div\n style={{\n backgroundColor: 'white',\n borderRadius: '12px',\n overflow: 'hidden',\n boxShadow: '0 1px 3px rgba(0,0,0,0.1)',\n border: '1px solid #E5E7EB',\n }}\n >\n <div style={{ overflowX: 'auto' }}>\n <table style={{ width: '100%', borderCollapse: 'collapse' }}>\n <thead>\n {table.getHeaderGroups().map((headerGroup) => (\n <tr key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <th\n key={header.id}\n onClick={header.column.getToggleSortingHandler()}\n style={{\n padding: '12px 16px',\n textAlign: 'left',\n fontSize: '12px',\n fontWeight: 600,\n color: THEME_COLORS.textSecondary,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n backgroundColor: THEME_COLORS.surface,\n borderBottom: '1px solid #E5E7EB',\n cursor: columns.find(c => c.field === header.column.id)?.sortable ? 'pointer' : 'default',\n userSelect: 'none',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>\n {flexRender(header.column.columnDef.header, header.getContext())}\n {header.column.getIsSorted() && (\n <span>{header.column.getIsSorted() === 'asc' ? '↑' : '↓'}</span>\n )}\n </div>\n </th>\n ))}\n </tr>\n ))}\n </thead>\n <tbody>\n {table.getRowModel().rows.map((row) => (\n <motion.tr\n key={row.id}\n whileHover={{ backgroundColor: '#F9FAFB' }}\n onClick={() => onRowClick?.(row.original)}\n style={{\n cursor: onRowClick ? 'pointer' : 'default',\n transition: 'background-color 0.15s',\n }}\n >\n {row.getVisibleCells().map((cell) => (\n <td\n key={cell.id}\n style={{\n padding: '12px 16px',\n fontSize: '14px',\n color: THEME_COLORS.text,\n borderBottom: '1px solid #E5E7EB',\n }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </td>\n ))}\n </motion.tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nexport default DataTable;\n","import { motion, AnimatePresence } from 'motion/react';\nimport { useState } from 'react';\nimport { THEME_COLORS } from '../types';\nimport type { JsonViewerProps } from '../types';\n\n// Syntax highlighting colors\nconst syntaxColors = {\n key: '#0066CC',\n string: '#10B981',\n number: '#F59E0B',\n boolean: '#8B5CF6',\n null: '#6B7280',\n bracket: '#111827',\n};\n\n// Recursive renderer for JSON\nconst JsonNode = ({\n data,\n depth = 0,\n collapsible,\n maxHeight,\n}: {\n data: unknown;\n depth?: number;\n collapsible?: boolean;\n maxHeight?: string;\n}) => {\n const [expanded, setExpanded] = useState(depth < 2);\n\n const indent = depth * 16;\n\n const renderValue = (value: unknown, key?: string): JSX.Element => {\n if (value === null) {\n return <span style={{ color: syntaxColors.null }}>null</span>;\n }\n if (typeof value === 'boolean') {\n return <span style={{ color: syntaxColors.boolean }}>{String(value)}</span>;\n }\n if (typeof value === 'number') {\n return <span style={{ color: syntaxColors.number }}>{value}</span>;\n }\n if (typeof value === 'string') {\n return <span style={{ color: syntaxColors.string }}>\"{value}\"</span>;\n }\n if (Array.isArray(value)) {\n if (value.length === 0) return <span style={{ color: syntaxColors.bracket }}>[]</span>;\n return (\n <span style={{ color: syntaxColors.bracket }}>\n [{' '}\n {expanded ? (\n <>\n {value.map((item, i) => (\n <span key={i}>\n {renderValue(item)}\n {i < value.length - 1 && ', '}\n </span>\n ))}\n </>\n ) : (\n <span style={{ color: syntaxColors.null }}>...{value.length} items</span>\n )}{' '}\n ]\n </span>\n );\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>);\n if (entries.length === 0) return <span style={{ color: syntaxColors.bracket }}>{'{}'}</span>;\n return (\n <span style={{ color: syntaxColors.bracket }}>\n {expanded ? '{ ' : '{ ... '}\n {expanded && (\n <motion.div\n initial={false}\n animate={{ height: 'auto', opacity: 1 }}\n style={{ paddingLeft: 16 }}\n >\n {entries.map(([k, v], i) => (\n <div key={k}>\n <span style={{ color: syntaxColors.key }}>\"{k}\"</span>: {renderValue(v, k)}\n {i < entries.length - 1 && ','}\n </div>\n ))}\n </motion.div>\n )}\n {expanded ? '}' : '}'}\n </span>\n );\n }\n return <span>{String(value)}</span>;\n };\n\n if (collapsible && depth > 0 && typeof data === 'object' && data !== null) {\n const entries = Object.entries(data as Record<string, unknown>);\n const isExpandable = entries.length > 0 || Array.isArray(data);\n\n return (\n <div style={{ marginLeft: indent }}>\n <motion.button\n onClick={() => setExpanded(!expanded)}\n whileHover={{ scale: 1.02 }}\n style={{\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n padding: '2px 4px',\n fontFamily: 'monospace',\n fontSize: '13px',\n color: THEME_COLORS.textSecondary,\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n }}\n >\n <span style={{ transition: 'transform 0.2s', transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)' }}>\n ▶\n </span>\n {expanded ? 'collapse' : 'expand'}\n </motion.button>\n <AnimatePresence>\n {expanded && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n style={{ overflow: maxHeight ? (expanded ? 'auto' : 'hidden') : undefined, maxHeight }}\n >\n {renderValue(data)}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n }\n\n return <div style={{ marginLeft: indent }}>{renderValue(data)}</div>;\n};\n\n// Copy to clipboard\nconst CopyButton = ({ data }: { data: unknown }) => {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n await navigator.clipboard.writeText(JSON.stringify(data, null, 2));\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n return (\n <motion.button\n onClick={handleCopy}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n style={{\n position: 'absolute',\n top: '12px',\n right: '12px',\n padding: '6px 12px',\n backgroundColor: copied ? THEME_COLORS.success : THEME_COLORS.surface,\n color: copied ? 'white' : THEME_COLORS.text,\n border: 'none',\n borderRadius: '6px',\n fontSize: '12px',\n fontWeight: 500,\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n >\n {copied ? 'Copied!' : 'Copy'}\n </motion.button>\n );\n};\n\nexport const JsonViewer = ({ data, collapsible = true, maxHeight }: JsonViewerProps) => {\n return (\n <div\n style={{\n position: 'relative',\n backgroundColor: '#F8FAFC',\n borderRadius: '8px',\n padding: '16px',\n fontFamily: 'monospace',\n fontSize: '13px',\n lineHeight: 1.6,\n overflow: maxHeight ? 'hidden' : undefined,\n maxHeight: maxHeight,\n }}\n >\n <CopyButton data={data} />\n <JsonNode data={data} collapsible={collapsible} maxHeight={maxHeight} />\n </div>\n );\n};\n\nexport default JsonViewer;\n"]}