gridsmith-ui 0.29.1 → 0.30.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.
- package/CHANGELOG.md +54 -0
- package/README.md +5 -1
- package/dist/DropdownMenu-DqT7ZQ0D.d.ts +39 -0
- package/dist/charts.js +4 -2
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +4 -4
- package/dist/{chunk-OYNUU346.js → chunk-7QLXYRPD.js} +3 -12
- package/dist/chunk-7QLXYRPD.js.map +1 -0
- package/dist/chunk-F2BNJSON.js +1348 -0
- package/dist/chunk-F2BNJSON.js.map +1 -0
- package/dist/{chunk-37WOC7F7.js → chunk-GQVBZ4GW.js} +29 -8
- package/dist/chunk-GQVBZ4GW.js.map +1 -0
- package/dist/{chunk-MFAWJSMJ.js → chunk-INGF2CPW.js} +3 -22
- package/dist/chunk-INGF2CPW.js.map +1 -0
- package/dist/{chunk-I3MTQ3CS.js → chunk-KTPGMJUK.js} +5 -5
- package/dist/{chunk-I3MTQ3CS.js.map → chunk-KTPGMJUK.js.map} +1 -1
- package/dist/{chunk-MKFWHWBK.js → chunk-L6HWACK7.js} +7 -7
- package/dist/chunk-L6HWACK7.js.map +1 -0
- package/dist/chunk-LJYSVZMI.js +25 -0
- package/dist/chunk-LJYSVZMI.js.map +1 -0
- package/dist/{chunk-FUKSLQ77.js → chunk-NI5542ZM.js} +39 -35
- package/dist/chunk-NI5542ZM.js.map +1 -0
- package/dist/chunk-NKUCS67T.js +13 -0
- package/dist/chunk-NKUCS67T.js.map +1 -0
- package/dist/{chunk-RECCCA7Z.js → chunk-NLXQ323J.js} +4 -4
- package/dist/{chunk-RECCCA7Z.js.map → chunk-NLXQ323J.js.map} +1 -1
- package/dist/{chunk-ZI3OQDET.js → chunk-OIOII5L6.js} +93 -4
- package/dist/chunk-OIOII5L6.js.map +1 -0
- package/dist/{chunk-RJEUQ7RL.js → chunk-Q36JVJX4.js} +46 -89
- package/dist/chunk-Q36JVJX4.js.map +1 -0
- package/dist/{chunk-FD4YED7O.js → chunk-RHWTMTU5.js} +3 -3
- package/dist/{chunk-FD4YED7O.js.map → chunk-RHWTMTU5.js.map} +1 -1
- package/dist/chunk-TYNDXMBV.js +105 -0
- package/dist/chunk-TYNDXMBV.js.map +1 -0
- package/dist/{chunk-4TUJXDRU.js → chunk-UNS4TGGK.js} +20 -11
- package/dist/chunk-UNS4TGGK.js.map +1 -0
- package/dist/chunk-Z4MCD73B.js +316 -0
- package/dist/chunk-Z4MCD73B.js.map +1 -0
- package/dist/data-grid.d.ts +25 -6
- package/dist/data-grid.js +177 -55
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +1 -1
- package/dist/editor.js +3 -3
- package/dist/{feather-FNBQ74RR.js → feather-XFFEFLTV.js} +5 -3
- package/dist/feather-XFFEFLTV.js.map +1 -0
- package/dist/{heroicons-DODCSYWD.js → heroicons-L6DOHBEA.js} +5 -3
- package/dist/heroicons-L6DOHBEA.js.map +1 -0
- package/dist/icons.d.ts +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +138 -39
- package/dist/index.js +660 -1568
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +26 -8
- package/dist/kanban.js +200 -76
- package/dist/kanban.js.map +1 -1
- package/dist/{lucide-ZWE3EPGP.js → lucide-JOORDTO6.js} +5 -3
- package/dist/lucide-JOORDTO6.js.map +1 -0
- package/dist/{phosphor-DIHPA4AJ.js → phosphor-TKGDYNGR.js} +5 -3
- package/dist/phosphor-TKGDYNGR.js.map +1 -0
- package/dist/resizable.js +10 -9
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +12 -8
- package/dist/{table-utils-CxnpFHRF.d.ts → table-utils-BXkP-2Hx.d.ts} +3 -1
- package/dist/{tabler-D3VYTSGI.js → tabler-YGETLYRU.js} +5 -3
- package/dist/tabler-YGETLYRU.js.map +1 -0
- package/dist/tokens.css +14 -0
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.js +8 -7
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +14 -0
- package/package.json +1 -1
- package/dist/chunk-37WOC7F7.js.map +0 -1
- package/dist/chunk-4TUJXDRU.js.map +0 -1
- package/dist/chunk-FUKSLQ77.js.map +0 -1
- package/dist/chunk-MFAWJSMJ.js.map +0 -1
- package/dist/chunk-MKFWHWBK.js.map +0 -1
- package/dist/chunk-OYNUU346.js.map +0 -1
- package/dist/chunk-QM4SJKWV.js +0 -51
- package/dist/chunk-QM4SJKWV.js.map +0 -1
- package/dist/chunk-QNHVPE2B.js +0 -117
- package/dist/chunk-QNHVPE2B.js.map +0 -1
- package/dist/chunk-RJEUQ7RL.js.map +0 -1
- package/dist/chunk-ZI3OQDET.js.map +0 -1
- package/dist/feather-FNBQ74RR.js.map +0 -1
- package/dist/heroicons-DODCSYWD.js.map +0 -1
- package/dist/lucide-ZWE3EPGP.js.map +0 -1
- package/dist/phosphor-DIHPA4AJ.js.map +0 -1
- package/dist/tabler-D3VYTSGI.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/control-looks.ts","../../../showcase/src/lib/filter-row.ts","../../../showcase/src/components/Input.tsx","../../../showcase/src/components/InlineFieldError.tsx","../../../showcase/src/components/Field.tsx","../../../showcase/src/components/Dropdown.tsx","../../../showcase/src/components/NumberInput.tsx","../../../showcase/src/components/Popover.tsx","../../../showcase/src/components/Pagination.tsx","../../../showcase/src/lib/use-pagination.ts"],"names":["jsxs","jsx","createContext","useContext","useCallback","useEffect","useRef","useId","useState","createPortal"],"mappings":";;;;;;;;;;;;;;;;;;AAOO,IAAM,UAAA,GAAa;AAGnB,IAAM,eAAA,GAAkB;AAMxB,IAAM,gBAAA,GAAmB;AAMzB,IAAM,cAAA,GAAiB;AAGvB,IAAM,eAAA,GAAkB;AAGxB,IAAM,kBAAA,GAAqB;ACrB3B,IAAM,gBAAA,GAAmB,cAAc,KAAK;AAO5C,IAAM,kBAAA,GAAqB,sBAAA;ACHlC,IAAM,YAAA,0BAAsB,cAAc,CAAA;AAC1C,IAAM,OAAA,GAAU,CAAC,CAAA,KAAsC;AACrD,EAAA,MAAM,IAAI,CAAA,CAAE,MAAA;AACZ,EAAA,IAAI,CAAC,GAAG,OAAO,MAAA;AACf,EAAA,OAAO,CAAA,YAAa,gBAAA,KAAqB,CAAA,CAAE,IAAA,KAAS,UAAA,IAAc,EAAE,IAAA,KAAS,OAAA,CAAA,GAAW,CAAA,CAAE,OAAA,GAAU,CAAA,CAAE,KAAA;AACxG,CAAA;AAOA,IAAM,YAAA,GAA0C;AAAA,EAC9C,EAAA,EAAI,iCAAA;AAAA,EACJ,EAAA,EAAI,iCAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,IAAM,UAAA,GAAwC;AAAA,EAC5C,EAAA,EAAI,yBAAA;AAAA,EACJ,EAAA,EAAI,yBAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEO,SAAS,KAAA,CAAM,EAAE,SAAA,EAAW,IAAA,EAAM,QAAA,EAAU,KAAA,GAAQ,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,GAAG,KAAA,EAAM,EAAmJ;AAE5O,EAAA,gBAAA,EAAiB;AACjB,EAAA,MAAM,WAAA,GAAc,WAAW,kBAAkB,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,YAAY,WAAA,IAAe,IAAA;AAExC,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,gBAAgB,CAAA,GAAI,kBAAA,GAAqB,QAAA;AAGlE,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,UAAU,MAAA,GAAY,YAAA,GAAe,KAAA,CAAM,KAAA,EAAO,OAAO,CAAA;AAClH,EAAA,MAAM,WAAA,GAAc,QAAQ,iCAAA,GAAoC,iCAAA;AAChE,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,IAAS,CAAC,MAAM,QAAA,IAAY,CAAC,KAAA,CAAM,QAAA,GAAW,6CAAA,GAAgD,EAAA;AAEnH,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA;AAAA,UACT,mBAAA;AAAA,UAAqB,KAAA;AAAA,UACrB,aAAa,IAAI,CAAA;AAAA,UACjB,yBAAA;AAAA,UACA,wCAAA;AAAA,UAA0C,WAAA;AAAA,UAC1C,+BAAA;AAAA,UACA,iCAAA;AAAA,UACA,WAAA;AAAA,UACA,QAAQ,oBAAA,GAAuB,oBAAA;AAAA,UAC/B,yDAAA;AAAA,UACA,MAAM,QAAA,IAAY,qCAAA;AAAA,UAClB,MAAM,QAAA,IAAY,wCAAA;AAAA,UAClB;AAAA,SACF;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,MAAA,oBAAU,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gEAAA,EAAkE,QAAA,EAAA,MAAA,EAAO,CAAA;AAAA,0BACpG,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,gBAAc,KAAA,IAAS,MAAA;AAAA,cACvB,SAAA,EAAW,EAAA;AAAA,gBACT,4CAAA;AAAA,gBACA,WAAW,IAAI,CAAA;AAAA,gBACf,+BAAA;AAAA,gBACA,yCAAA;AAAA,gBACA,6BAAA;AAAA,gBACA;AAAA,eACF;AAAA,cACC,GAAG,KAAA;AAAA,cACJ,UAAU,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,KAAA,KAAU,SAAY,QAAA,GAAW;AAAA;AAAA,WACrE;AAAA,UACC,MAAA,oBAAU,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kEAAkE,QAAA,EAAA,MAAA,EAAO;AAAA;AAAA;AAAA,KACtG;AAAA,EAEJ;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,gBAAc,KAAA,IAAS,MAAA;AAAA,MACvB,SAAA,EAAW,EAAA;AAAA,QACT,MAAA;AAAA,QAAQ,KAAA;AAAA,QACR,WAAW,IAAI,CAAA;AAAA,QAAG,aAAa,IAAI,CAAA;AAAA,QACnC,uDAAA;AAAA,QACA,wCAAA;AAAA,QAA0C,WAAA;AAAA,QAC1C,+BAAA;AAAA,QACA,iCAAA;AAAA,QACA,yCAAA;AAAA,QACA,WAAA;AAAA,QACA,QAAQ,gBAAA,GAAmB,gBAAA;AAAA,QAC3B,uDAAA;AAAA,QACA,sGAAA;AAAA,QACA,yDAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MACJ,UAAU,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,KAAA,KAAU,SAAY,QAAA,GAAW;AAAA;AAAA,GACrE;AAEJ;AASO,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,UAAA,EAAY,OAAA,EAAS,QAAQ,KAAA,EAAO,GAAA,EAAK,GAAG,KAAA,EAAM,EAAkB;AAExG,EAAA,gBAAA,EAAiB;AAEjB,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,UAAU,MAAA,GAAY,YAAA,GAAe,KAAA,CAAM,KAAA,EAAO,OAAO,CAAA;AAClH,EAAA,MAAM,WAAA,GAAc,OAA4B,IAAI,CAAA;AACpD,EAAA,MAAM,cAAe,GAAA,IAAO,WAAA;AAE5B,EAAA,MAAM,MAAA,GAAS,YAAY,MAAM;AAC/B,IAAA,MAAM,KAAK,WAAA,CAAY,OAAA;AACvB,IAAA,IAAI,CAAC,EAAA,IAAM,CAAC,UAAA,EAAY;AACxB,IAAA,EAAA,CAAG,MAAM,MAAA,GAAS,MAAA;AAClB,IAAA,IAAI,SAAS,EAAA,CAAG,YAAA;AAChB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,aAAa,UAAA,CAAW,gBAAA,CAAiB,EAAE,CAAA,CAAE,UAAU,CAAA,IAAK,EAAA;AAClE,MAAA,MAAM,SAAA,GAAY,UAAA,GAAa,OAAA,GAAU,UAAA,CAAW,gBAAA,CAAiB,EAAE,CAAA,CAAE,UAAU,CAAA,GAAI,UAAA,CAAW,gBAAA,CAAiB,EAAE,EAAE,aAAa,CAAA;AACpI,MAAA,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,SAAS,CAAA;AAAA,IACrC;AACA,IAAA,EAAA,CAAG,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,EAAA,CAAA;AAAA,EAC7B,CAAA,EAAG,CAAC,UAAA,EAAY,OAAA,EAAS,WAAW,CAAC,CAAA;AAErC,EAAA,SAAA,CAAU,MAAM;AAAE,IAAA,MAAA,EAAO;AAAA,EAAG,GAAG,CAAC,MAAA,EAAQ,MAAM,KAAA,EAAO,KAAA,CAAM,YAAY,CAAC,CAAA;AAExE,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,WAAA;AAAA,MACL,gBAAc,KAAA,IAAS,MAAA;AAAA,MACvB,SAAA,EAAW,EAAA;AAAA,QACT,yEAAA;AAAA,QACA,uDAAA;AAAA,QACA,wCAAA;AAAA,QACA,QAAQ,iCAAA,GAAoC,6EAAA;AAAA,QAC5C,+BAAA;AAAA,QACA,iCAAA;AAAA,QACA,yCAAA;AAAA,QACA,QAAQ,gBAAA,GAAmB,gBAAA;AAAA,QAC3B,sGAAA;AAAA,QACA,sJAAA;AAAA,QACA,yDAAA;AAAA,QACA,UAAA,IAAc,6BAAA;AAAA,QACd;AAAA,OACF;AAAA,MACA,OAAA,EAAS,aAAa,MAAA,GAAS,MAAA;AAAA,MAC9B,GAAG,KAAA;AAAA,MACJ,UAAU,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,KAAA,KAAU,SAAY,QAAA,GAAW;AAAA;AAAA,GACrE;AAEJ;AAEO,SAAS,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,GAAG,OAAM,EAA0C;AAC9F,EAAA,uBACE,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,kEAAA;AAAA,QACA,iEAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEH;AAAA;AAAA,GACH;AAEJ;AAMA,IAAM,YAAA,GAA4E;AAAA,EAChF,IAAI,EAAE,CAAA,EAAG,IAAI,CAAA,EAAG,EAAA,EAAI,OAAO,EAAA,EAAG;AAAA,EAC9B,IAAI,EAAE,CAAA,EAAG,IAAI,CAAA,EAAG,EAAA,EAAI,OAAO,EAAA;AAC7B,CAAA;AAEO,SAAS,OAAO,EAAE,OAAA,EAAS,QAAA,EAAU,KAAA,EAAO,UAAU,KAAA,GAAQ,KAAA,EAAO,MAAA,GAAS,MAAA,EAAQ,OAAO,IAAA,EAAM,iBAAA,EAAmB,cAAA,EAAgB,GAAG,MAAK,EAAsP;AAEzY,EAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,QAAA,EAAU,OAAO,CAAA;AAClD,EAAA,MAAM,IAAA,GAAO,aAAa,IAAI,CAAA;AAC9B,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,CAAA,GAAI,IAAA,CAAK,KAAA,GAAQ,CAAA;AACrC,EAAA,MAAM,YAAA,mBACJ,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MAAO,IAAA,EAAK,QAAA;AAAA,MACX,IAAA,EAAK,QAAA;AAAA,MACL,cAAA,EAAc,OAAA;AAAA,MACd,YAAA,EAAY,CAAC,KAAA,IAAS,CAAC,iBAAiB,QAAA,GAAW,MAAA;AAAA,MACnD,iBAAA,EAAiB,cAAA;AAAA,MACjB,gBAAc,KAAA,IAAS,MAAA;AAAA,MACvB,QAAA;AAAA,MACA,SAAS,MAAM,CAAC,QAAA,IAAY,MAAA,CAAO,CAAC,OAAO,CAAA;AAAA,MAC1C,GAAG,IAAA;AAAA,MACJ,SAAA,EAAW,EAAA;AAAA,QACT,4DAAA;AAAA,QACA,wCAAA;AAAA,QACA,iCAAA;AAAA,QACA,yDAAA;AAAA,QACA,UAAA;AAAA,QACA,WAAW,oBAAA,GAAuB,gBAAA;AAAA;AAAA,QAElC,UAAU,eAAA,GAAkB,gBAAA;AAAA,QAC5B,KAAA,IAAS;AAAA,OACX;AAAA,MACA,OAAO,EAAE,KAAA,EAAO,KAAK,CAAA,EAAG,MAAA,EAAQ,KAAK,CAAA,EAAE;AAAA,MAEvC,QAAA,kBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,EAAA;AAAA,YACT,2CAAA;AAAA;AAAA,YAEA,UAAU,cAAA,GAAiB,eAAA;AAAA,YAC3B,2DAAA;AAAA,YACA,iCAAA;AAAA,YACA;AAAA,WACF;AAAA,UACA,KAAA,EAAO;AAAA,YACL,OAAO,IAAA,CAAK,KAAA;AAAA,YACZ,QAAQ,IAAA,CAAK,KAAA;AAAA,YACb,SAAA,EAAW,OAAA,GACP,CAAA,gBAAA,EAAmB,MAAM,CAAA,6BAAA,CAAA,GACzB;AAAA;AACN;AAAA;AACF;AAAA,GACF;AAGF,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,2BAAQ,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,QAAA,IAAY,kBAAkB,GAAI,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,EAC3E;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,MAAA,KAAW,SACP,4CAAA,GACA,mCAAA;AAAA,QACJ,WAAW,qCAAA,GAAwC;AAAA,OACrD;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mDAAA,EAAqD,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,QAC1E;AAAA;AAAA;AAAA,GACH;AAEJ;ACrPO,SAAS,gBAAA,CAAiB,EAAE,OAAA,EAAS,EAAA,EAAI,WAAU,EAA0B;AAClF,EAAA,uBACEA,IAAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,IAAA,EAAK,OAAA;AAAA,MACL,SAAA,EAAW,EAAA;AAAA,QACT,yEAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OACF;AAAA,MAGA,QAAA,EAAA;AAAA,wBAAAC,IAAC,IAAA,EAAA,EAAK,IAAA,EAAK,SAAQ,IAAA,EAAM,EAAA,EAAI,WAAU,wCAAA,EAAyC,CAAA;AAAA,wBAChFA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,OAAA,EAAQ;AAAA;AAAA;AAAA,GACjB;AAEJ;ACKA,IAAM,YAAA,GAAeC,cAAwC,IAAI,CAAA;AAG1D,SAAS,QAAA,GAAqC;AACnD,EAAA,OAAOC,WAAW,YAAY,CAAA;AAChC;AAMO,SAAS,YAAA,CAAa,EAAE,QAAA,EAAS,EAA4B;AAClE,EAAA,uBAAOF,GAAAA,CAAC,YAAA,CAAa,UAAb,EAAsB,KAAA,EAAO,MAAO,QAAA,EAAS,CAAA;AACvD;AAwBO,SAAS,eAAA,CAAgB,GAAA,EAAyB,OAAA,GAA+C,EAAC,EAOvG;AACA,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,EAAA,GAAK,GAAA,CAAI,EAAA,IAAM,KAAA,EAAO,SAAA;AAC5B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,GAAA,CAAI,SAAS,GAAA,CAAI,cAAc,CAAA,KAAM,IAAA,IAAQ,IAAI,cAAc,CAAA,KAAM,MAAA,IAAU,CAAC,CAAC,KAAA,EAAO,OAAA;AAC1G,EAAA,MAAM,QAAA,GAAW,CAAC,CAAC,GAAA,CAAI,YAAY,GAAA,CAAI,eAAe,CAAA,KAAM,IAAA,IAAQ,IAAI,eAAe,CAAA,KAAM,MAAA,IAAU,CAAC,CAAC,KAAA,EAAO,QAAA;AAChH,EAAA,MAAM,SAAS,OAAA,CAAQ,qBAAA,IAAyB,YAAY,EAAA,GAAK,CAAA,EAAG,EAAE,CAAA,SAAA,CAAA,GAAc,MAAA;AACpF,EAAA,MAAM,MAAM,CAAC,GAAA,CAAI,kBAAkB,CAAA,EAAG,KAAA,EAAO,aAAa,MAAM,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA,CAAE,MAAM,KAAK,CAAA,CAAE,OAAO,OAAO,CAAA;AACvH,EAAA,OAAO;AAAA,IACL,EAAA;AAAA,IACA,OAAA,EAAS,GAAA,CAAI,iBAAiB,CAAA,IAAK,KAAA,EAAO,OAAA;AAAA,IAC1C,WAAA,EAAa,CAAC,GAAG,IAAI,GAAA,CAAI,GAAG,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,IAAK,MAAA;AAAA,IAC5C,OAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA,EAAc,MAAA,mBAASA,GAAAA,CAAC,MAAA,EAAA,EAAK,IAAI,MAAA,EAAQ,MAAA,EAAM,IAAA,EAAC,QAAA,EAAA,UAAA,EAAQ,CAAA,GAAU;AAAA,GACpE;AACF;AAUO,IAAM,gBAAA,GAAmBC,cAAc,KAAK;AAgD5C,SAAS,KAAA,CAAM,EAAE,KAAA,EAAO,QAAA,EAAU,MAAM,KAAA,EAAO,QAAA,EAAU,WAAA,EAAa,SAAA,GAAY,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,QAAA,EAAU,WAAU,EAAe;AAC7I,EAAA,MAAM,UAAA,GAAaC,WAAW,gBAAgB,CAAA;AAC9C,EAAA,MAAM,YAAY,KAAA,EAAM;AACxB,EAAA,MAAM,EAAA,GAAK,MAAA,IAAU,CAAA,MAAA,EAAS,SAAS,CAAA,CAAA;AACvC,EAAA,MAAM,MAAA,GAAS,GAAG,EAAE,CAAA,KAAA,CAAA;AACpB,EAAA,MAAM,OAAA,GAAU,GAAG,EAAE,CAAA,MAAA,CAAA;AAGrB,EAAA,MAAM,OAAO,sBAAA,EAAuB;AAEpC,EAAA,MAAM,IAAA,GAAO,MAAM,cAAA,IAAkB,QAAA;AACrC,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAA6B,MAAS,CAAA;AAC1E,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,KAAK,CAAA;AACtC,EAAA,MAAM,aAAa,QAAA,GAAY,IAAA,GAAO,KAAK,MAAA,CAAO,EAAE,IAAI,UAAA,GAAc,MAAA;AACtE,EAAA,MAAM,QAAQ,OAAO,QAAA,KAAa,aAAa,IAAA,GAAO,QAAA,CAAS,KAAK,QAAQ,CAAA;AAC5E,EAAA,MAAM,aAAa,KAAA,IAAS,cAAA,CAAe,KAAK,CAAA,GAAK,MAAM,KAAA,GAAoC,IAAA;AAC/F,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,EAAE,QAAA,EAAU,UAAA,EAAY,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,OAAA,EAAS,CAAC,CAAC,UAAA,EAAY,MAAM,CAAA;AAC9F,EAAA,MAAM,KAAA,GAAQC,YAAY,MAA0B;AAClD,IAAA,MAAM,EAAE,UAAU,EAAA,EAAI,UAAA,EAAY,OAAO,EAAA,EAAI,SAAA,KAAc,MAAA,CAAO,OAAA;AAClE,IAAA,IAAI,CAAC,IAAI,OAAO,MAAA;AAChB,IAAA,MAAM,KAAA,GAAQ,KAAA,IAAS,OAAA,IAAW,KAAA,GAAQ,MAAM,KAAA,GAAQ,KAAA,IAAS,SAAA,IAAa,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAW,QAAA,CAAS,cAAA,CAAe,SAAS,CAAA,EAA+B,KAAA;AACvK,IAAA,MAAM,OAAA,GAAU,GAAG,KAAK,CAAA;AACxB,IAAA,OAAO,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,CAAQ,MAAA,GAAS,IAAI,OAAA,GAAU,MAAA;AAAA,EACvE,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACX,EAAA,MAAM,IAAA,GAAOA,WAAAA,CAAY,CAAC,OAAA,KAAgC;AACxD,IAAA,MAAM,EAAE,IAAA,EAAM,CAAA,EAAG,EAAA,EAAI,SAAA,KAAc,MAAA,CAAO,OAAA;AAC1C,IAAA,IAAI,CAAA,EAAG,CAAA,CAAE,QAAA,CAAS,SAAA,EAAW,OAAO,CAAA;AAAA,uBACjB,OAAO,CAAA;AAAA,EAC5B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,MAAM,WAAW,IAAA,EAAM,QAAA;AACvB,EAAA,MAAM,MAAA,GAAS,CAAC,CAAC,QAAA;AACjB,EAAAC,SAAAA,CAAU,MAAO,QAAA,IAAY,MAAA,GAAS,SAAS,EAAA,EAAI,KAAK,CAAA,GAAI,MAAA,EAAY,CAAC,QAAA,EAAU,MAAA,EAAQ,EAAA,EAAI,KAAK,CAAC,CAAA;AAGrG,EAAA,MAAM,OAAA,GAAUC,OAA6C,IAAI,CAAA;AACjE,EAAAD,SAAAA,CAAU,MAAM,MAAM;AAAE,IAAA,IAAI,OAAA,CAAQ,OAAA,EAAS,YAAA,CAAa,OAAA,CAAQ,OAAO,CAAA;AAAA,EAAG,CAAA,EAAG,EAAE,CAAA;AACjF,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAA,IAAI,QAAQ,OAAA,EAAS;AAAE,MAAA,YAAA,CAAa,QAAQ,OAAO,CAAA;AAAG,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,IAAM;AAAA,EAChF,CAAA;AACA,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IAAA,IAAI,CAAC,QAAA,EAAU;AACf,IAAA,IAAI,OAAA,CAAQ,OAAA,EAAS,YAAA,CAAa,OAAA,CAAQ,OAAO,CAAA;AACjD,IAAA,OAAA,CAAQ,OAAA,GAAU,WAAW,MAAM;AACjC,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,MAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,MAAA,IAAI,MAAA,CAAO,QAAQ,IAAA,KAAS,UAAA,IAAc,OAAO,OAAA,CAAQ,OAAA,EAAS,IAAA,CAAK,KAAA,EAAO,CAAA;AAAA,IAChF,GAAG,CAAC,CAAA;AAAA,EACN,CAAA;AAGA,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,IAAI,CAAC,QAAA,EAAU;AACf,IAAA,UAAA,CAAW,MAAM;AACf,MAAA,MAAM,EAAE,IAAA,EAAM,CAAA,EAAG,MAAM,OAAA,EAAS,OAAA,KAAY,MAAA,CAAO,OAAA;AACnD,MAAA,IAAK,MAAM,UAAA,IAAc,OAAA,IAAY,OAAA,EAAS,IAAA,CAAK,OAAO,CAAA;AAAA,IAC5D,GAAG,CAAC,CAAA;AAAA,EACN,CAAA;AAEA,EAAA,MAAM,aAAa,OAAO,KAAA,KAAU,YAAY,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,GAAQ,UAAA;AAC3E,EAAA,MAAM,QAAA,GAAW,OAAO,UAAA,KAAe,QAAA,IAAY,WAAW,MAAA,GAAS,CAAA;AACvE,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,GAAO,MAAA,GAAS,MAAM,QAAA,GAAW,OAAA,GAAU,IAAI,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,IAAK,MAAA;AACnG,EAAA,MAAM,OAAA,GAAU,GAAG,EAAE,CAAA,MAAA,CAAA;AACrB,EAAA,MAAM,YAAA,GAAe,QAA2B,OAAO,EAAE,WAAW,EAAA,EAAI,OAAA,EAAS,aAAa,OAAA,EAAS,QAAA,EAAU,UAAU,CAAC,CAAC,UAAS,CAAA,EAAI,CAAC,IAAI,OAAA,EAAS,WAAA,EAAa,QAAA,EAAU,QAAQ,CAAC,CAAA;AAExL,EAAA,MAAM,YAAA,GAAkC;AAAA,IACtC,EAAA;AAAA,IACA,kBAAA,EAAoB,WAAA;AAAA,IACpB,GAAI,WAAW,EAAE,cAAA,EAAgB,MAAe,KAAA,EAAO,IAAA,KAAS,EAAC;AAAA,IACjE,GAAI,WAAW,EAAE,eAAA,EAAiB,MAAe,QAAA,EAAU,IAAA,KAAS;AAAC,GACvE;AAEA,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAClC,IAAA,OAAA,GAAU,SAAS,YAAY,CAAA;AAAA,EACjC,CAAA,MAAO;AACL,IAAA,IAAI,CAAC,SAAS,CAAC,cAAA,CAAe,KAAK,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,kDAAkD,CAAA;AACxG,IAAA,MAAM,QAAA,GAAW,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA;AACvC,IAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAW,GAAG,UAAS,GAAI,YAAA;AAG1C,IAAA,MAAM,cAAc,UAAA,EAAY,QAAA;AAChC,IAAA,MAAM,WAAW,QAAA,IAAY,CAAC,WAAW,EAAE,QAAA,EAAU,IAAI,IAAA,KAAoB;AAAE,MAAA,WAAA,GAAc,GAAG,IAAI,CAAA;AAAG,MAAA,OAAA,EAAQ;AAAA,IAAG,CAAA,KAAM,EAAC;AAGzH,IAAA,OAAA,GAAU,aAAa,KAAA,EAAgD,QAAA,GAAW,QAAA,GAAW,EAAE,GAAG,QAAA,EAAU,GAAI,SAAA,GAAY,EAAE,OAAO,IAAA,EAAK,GAAI,EAAC,EAAI,GAAG,UAAU,CAAA;AAAA,EAClK;AAEA,EAAA,MAAM,SAAA,mBACJL,IAAAA,CAAC,KAAA,EAAA,EAAM,IAAI,OAAA,EAAS,OAAA,EAAS,EAAA,EAAI,SAAA,EAAW,GAAG,SAAA,IAAa,SAAA,EAAW,SAAA,IAAa,UAAA,IAAc,0BAA0B,CAAA,EACzH,QAAA,EAAA;AAAA,IAAA,KAAA;AAAA,IACA,QAAA,oBAAYC,GAAAA,CAAC,MAAA,EAAA,EAAK,eAAY,MAAA,EAAO,SAAA,EAAU,2CAA0C,QAAA,EAAA,GAAA,EAAC;AAAA,GAAA,EAC7F,CAAA;AAGF,EAAA;AAAA;AAAA,oBAEED,IAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA,CAAG,0DAAA,EAA4D,SAAS,CAAA;AAAA,QAClF,GAAI,WAAW,EAAE,cAAA,EAAgB,eAAe,cAAA,EAAgB,OAAA,KAAY,EAAC;AAAA,QAI7E,QAAA,EAAA;AAAA,UAAA,SAAA,IAAa,CAAC,WAAA,GAAc,SAAA,mBAC3BA,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4CAAA,EACZ,QAAA,EAAA;AAAA,YAAA,SAAA;AAAA,YACA;AAAA,WAAA,EACH,CAAA;AAAA,0BAEFC,GAAAA,CAAC,YAAA,CAAa,UAAb,EAAsB,KAAA,EAAO,cAAe,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,UACpD,IAAA,oBACCA,GAAAA,CAAC,GAAA,EAAA,EAAE,IAAI,MAAA,EAAQ,SAAA,EAAU,uCAAuC,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,UAEtE,QAAA,oBAAYA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,IAAI,OAAA,EAAS,OAAA,EAAS,UAAA,EAAY,SAAA,EAAU,MAAA,EAAO;AAAA;AAAA;AAAA;AACpF;AAEJ;AClPA,IAAM,eAAA,GAAgD;AAAA,EACpD,EAAA,EAAI,yDAAA;AAAA,EACJ,EAAA,EAAI,yDAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAsBO,SAAS,QAAA,CAAS;AAAA,EACvB,OAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA,EAAU,YAAA;AAAA,EACV,KAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc,WAAA;AAAA,EACd,QAAA;AAAA,EACA,UAAA;AAAA,EACA,IAAA,EAAM,QAAA;AAAA,EACN,SAAA;AAAA,EACA,GAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA,GAAQ,KAAA;AAAA,EACR,SAAA,GAAY,IAAA;AAAA,EACZ,YAAA,EAAc,SAAA;AAAA,EACd,GAAG;AACL,CAAA,EAAkB;AAEhB,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,YAAA,EAAc,KAAK,CAAA;AAGtD,EAAA,gBAAA,EAAiB;AACjB,EAAA,MAAM,WAAA,GAAcE,WAAW,kBAAkB,CAAA;AAGjD,EAAA,MAAM,cAAcI,KAAAA,EAAM;AAC1B,EAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,EAAE,GAAG,MAAA,EAAQ,KAAA,EAAO,KAAA,IAAS,MAAA,EAAU,EAAG,EAAE,qBAAA,EAAuB,IAAA,EAAM,CAAA;AACzG,EAAA,MAAM,SAAA,GAAY,QAAQ,EAAA,IAAM,WAAA;AAChC,EAAA,MAAM,WAAA,GAAc,GAAG,SAAS,CAAA,MAAA,CAAA;AAChC,EAAA,MAAM,aAAa,OAAA,CAAQ,OAAA,GAAU,CAAA,EAAG,OAAA,CAAQ,OAAO,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GAAK,KAAA,IAAS,CAAC,SAAA,GAAY,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GAAK,MAAA;AAC/H,EAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,EAAA,MAAM,IAAA,GAAO,YAAY,WAAA,IAAe,IAAA;AACxC,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,SAAS,KAAK,CAAA;AACtC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIA,SAAS,EAAE,CAAA;AACvC,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIA,SAAS,KAAK,CAAA;AAClD,EAAA,MAAM,UAAA,GAAaF,OAA0B,IAAI,CAAA;AAEjD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIE,SAAgC,IAAI,CAAA;AAClE,EAAA,cAAA,CAAe,OAAO,CAAA;AACtB,EAAA,MAAM,OAAA,GAAUF,OAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,SAAA,GAAYA,OAAyB,IAAI,CAAA;AAC/C,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAIE,QAAAA,CAAS,EAAE,GAAA,EAAK,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,KAAA,EAAO,CAAA,EAAG,CAAA;AAE5D,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAQ,CAAC,KAAK,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA;AAE5E,EAAA,MAAM,SAAA,GAAYJ,YAAY,MAAM;AAClC,IAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AACzB,IAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,qBAAA,EAAsB;AACtD,IAAA,IAAI,GAAA,GAAM,KAAK,MAAA,GAAS,CAAA;AACxB,IAAA,IAAI,OAAO,IAAA,CAAK,IAAA;AAChB,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AAEnB,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,OAAA,CAAQ,qBAAA,EAAsB;AACvD,MAAA,MAAM,KAAK,MAAA,CAAO,UAAA;AAClB,MAAA,MAAM,KAAK,MAAA,CAAO,WAAA;AAClB,MAAA,IAAI,IAAA,GAAO,QAAA,CAAS,KAAA,GAAQ,EAAA,EAAI,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAA,GAAK,QAAA,CAAS,KAAA,GAAQ,CAAC,CAAA;AAC1E,MAAA,IAAI,GAAA,GAAM,QAAA,CAAS,MAAA,GAAS,EAAA,EAAI;AAC9B,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,GAAM,CAAA,GAAI,QAAA,CAAS,MAAA;AACtC,QAAA,IAAI,KAAA,IAAS,GAAG,GAAA,GAAM,KAAA;AAAA,mBACX,IAAA,CAAK,GAAA,CAAI,GAAG,EAAA,GAAK,QAAA,CAAS,SAAS,CAAC,CAAA;AAAA,MACjD;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,EAAE,GAAA,EAAK,IAAA,EAAM,KAAA,EAAO,CAAA;AAAA,EAC7B,CAAA,EAAG,EAAE,CAAA;AAIL,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAII,SAAS,IAAI,CAAA;AAC7C,EAAA,IAAI,SAAS,QAAA,EAAU;AACrB,IAAA,WAAA,CAAY,IAAI,CAAA;AAChB,IAAA,IAAI,IAAA,YAAgB,EAAE,CAAA;AAAA,uBACH,KAAK,CAAA;AAAA,EAC1B;AAEA,EAAAH,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,SAAA,EAAU;AACV,IAAA,MAAM,GAAA,GAAM,sBAAsB,MAAM;AACtC,MAAA,SAAA,EAAU;AACV,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA,IACpB,CAAC,CAAA;AACD,IAAA,MAAM,QAAA,GAAW,MAAM,SAAA,EAAU;AACjC,IAAA,MAAA,CAAO,gBAAA,CAAiB,QAAA,EAAU,QAAA,EAAU,IAAI,CAAA;AAChD,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,SAAS,CAAA;AAC3C,IAAA,OAAO,MAAM;AACX,MAAA,oBAAA,CAAqB,GAAG,CAAA;AACxB,MAAA,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,QAAA,EAAU,IAAI,CAAA;AACnD,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,SAAS,CAAA;AAAA,IAChD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,SAAS,CAAC,CAAA;AAGpB,EAAA,MAAM,KAAA,GAAQC,OAAO,KAAK,CAAA;AAI1B,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,UAAA,EAAY;AAC1B,IAAA,KAAA,CAAM,OAAA,GAAU,KAAA;AAChB,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,SAAA,CAAU,QAAQ,KAAA,EAAM;AACxB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAS,gBAAA,CAAoC,iBAAiB,CAAA,IAAK,EAAE,CAAA;AACpG,IAAA,CAAC,GAAA,CAAI,IAAA,CAAK,CAAC,EAAA,KAAO,EAAA,CAAG,YAAA,CAAa,eAAe,CAAA,KAAM,MAAM,CAAA,IAAK,GAAA,CAAI,CAAC,IAAI,KAAA,EAAM;AAAA,EACnF,CAAA,EAAG,CAAC,IAAA,EAAM,UAAU,CAAC,CAAA;AAErB,EAAAD,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAAkB;AACjC,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,IAAI,UAAA,CAAW,SAAS,QAAA,CAAS,MAAM,KAAK,OAAA,CAAQ,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AAC/E,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,OAAO,CAAA;AAC9C,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,WAAA,EAAa,OAAO,CAAA;AAAA,EAChE,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAGT,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,IAAI,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,EAAS;AAChC,IAAA,MAAM,KAAK,QAAA,CAAS,aAAA;AACpB,IAAA,MAAM,EAAA,GAAK,EAAA,YAAc,WAAA,IAAe,OAAA,CAAQ,OAAA,EAAS,QAAA,CAAS,EAAE,CAAA,GAAI,EAAA,CAAG,YAAA,CAAa,gBAAgB,CAAA,GAAI,IAAA;AAC5G,IAAA,IAAI,EAAA,WAAa,EAAE,CAAA;AAAA,EACrB,CAAA;AAEA,EAAA,MAAM,EAAE,OAAO,UAAA,EAAY,WAAA,KAAgB,aAAA,CAAc,IAAA,EAAM,EAAE,OAAA,EAAS,UAAA,EAAY,OAAO,OAAA,EAAS,KAAA,EAAO,MAAM,OAAA,CAAQ,KAAK,GAAG,QAAA,EAAU,KAAA,EAAO,QAAA,EAAU,WAAA,EAAa,CAAA;AAM3K,EAAA,MAAM,YAAYC,MAAAA,CAAO,EAAE,QAAQ,EAAA,EAAI,EAAA,EAAI,GAAG,CAAA;AAC9C,EAAAD,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,aAAA,GAAgB,MAAM,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,SAAS,gBAAA,CAAoC,iBAAiB,CAAA,IAAK,EAAE,CAAA;AACpH,IAAA,MAAM,WAAA,GAAc,CAAC,GAAA,KAAgB;AACnC,MAAA,MAAM,MAAM,aAAA,EAAc;AAC1B,MAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACtB,MAAA,GAAA,CAAA,CAAM,GAAA,GAAM,IAAI,MAAA,GAAU,GAAA,CAAI,UAAU,GAAA,CAAI,MAAM,EAAE,KAAA,EAAM;AAC1D,MAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAAA,IAClB,CAAA;AACA,IAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAAqB;AAClC,MAAA,MAAM,MAAA,GAAS,QAAQ,OAAA,EAAS,QAAA,CAAS,SAAS,aAAa,CAAA,IAAK,UAAA,CAAW,OAAA,KAAY,QAAA,CAAS,aAAA;AACpG,MAAA,IAAI,CAAC,MAAA,EAAQ;AACb,MAAA,MAAM,MAAM,aAAA,EAAc;AAC1B,MAAA,MAAM,UAAU,GAAA,CAAI,SAAA,CAAU,CAAC,EAAA,KAAO,EAAA,KAAO,SAAS,aAAa,CAAA;AACnE,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AAAE,QAAA,IAAI,CAAA,CAAE,gBAAA,IAAoB,CAAC,UAAA,EAAW,EAAG;AAAQ,QAAA,CAAA,CAAE,cAAA,EAAe;AAAG,QAAA,WAAA,EAAY;AAAG,QAAA,OAAA,CAAQ,KAAK,CAAA;AAAG,QAAA;AAAA,MAAQ;AACtI,MAAA,IAAI,CAAA,CAAE,QAAQ,WAAA,EAAa;AAAE,QAAA,CAAA,CAAE,cAAA,EAAe;AAAG,QAAA,WAAA,CAAY,OAAA,GAAU,CAAA,GAAI,CAAA,GAAI,OAAA,GAAU,CAAC,CAAA;AAAG,QAAA;AAAA,MAAQ;AACrG,MAAA,IAAI,CAAA,CAAE,QAAQ,SAAA,EAAW;AAAE,QAAA,CAAA,CAAE,cAAA,EAAe;AAAG,QAAA,WAAA,CAAY,UAAU,CAAA,GAAI,GAAA,CAAI,MAAA,GAAS,CAAA,GAAI,UAAU,CAAC,CAAA;AAAG,QAAA;AAAA,MAAQ;AAChH,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,KAAkB,SAAA,CAAU,OAAA;AACtD,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,MAAA,IAAU,CAAC,QAAA,EAAU;AAAE,QAAA,CAAA,CAAE,cAAA,EAAe;AAAG,QAAA,WAAA,CAAY,CAAC,CAAA;AAAG,QAAA;AAAA,MAAQ;AACjF,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,KAAA,IAAS,CAAC,QAAA,EAAU;AAAE,QAAA,CAAA,CAAE,cAAA,EAAe;AAAG,QAAA,WAAA,CAAY,GAAA,CAAI,SAAS,CAAC,CAAA;AAAG,QAAA;AAAA,MAAQ;AAC7F,MAAA,IAAI,CAAC,UAAA,IAAc,CAAA,CAAE,GAAA,CAAI,WAAW,CAAA,IAAK,CAAC,CAAA,CAAE,OAAA,IAAW,CAAC,CAAA,CAAE,OAAA,IAAW,CAAC,EAAE,MAAA,EAAQ;AAC9E,QAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,QAAA,SAAA,CAAU,OAAA,CAAQ,MAAA,GAAS,GAAA,GAAM,SAAA,CAAU,OAAA,CAAQ,EAAA,GAAK,GAAA,GAAM,CAAA,CAAE,GAAA,GAAM,SAAA,CAAU,OAAA,CAAQ,MAAA,GAAS,CAAA,CAAE,GAAA;AACnG,QAAA,SAAA,CAAU,QAAQ,EAAA,GAAK,GAAA;AACvB,QAAA,MAAM,CAAA,GAAI,SAAA,CAAU,OAAA,CAAQ,MAAA,CAAO,WAAA,EAAY;AAC/C,QAAA,MAAM,GAAA,GAAM,GAAA,CAAI,SAAA,CAAU,CAAC,QAAQ,EAAA,CAAG,WAAA,IAAe,EAAA,EAAI,IAAA,EAAK,CAAE,WAAA,EAAY,CAAE,UAAA,CAAW,CAAC,CAAC,CAAA;AAC3F,QAAA,IAAI,OAAO,CAAA,EAAG;AAAE,UAAA,CAAA,CAAE,cAAA,EAAe;AAAG,UAAA,WAAA,CAAY,GAAG,CAAA;AAAA,QAAG;AAAA,MACxD;AAAA,IACF,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,KAAK,CAAA;AAC1C,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,KAAK,CAAA;AAAA,EAC5D,GAAG,CAAC,IAAA,EAAM,UAAA,EAAY,UAAA,EAAY,WAAW,CAAC,CAAA;AAE9C,EAAA,MAAM,WAAW,UAAA,IAAc,MAAA,GAC3B,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,CAAM,WAAA,GAAc,QAAA,CAAS,MAAA,CAAO,WAAA,EAAa,CAAC,CAAA,GAC1E,OAAA;AAEJ,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAsB;AACzC,EAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,IAAA,MAAM,CAAA,GAAI,IAAI,KAAA,IAAS,EAAA;AACvB,IAAA,IAAI,CAAC,OAAO,GAAA,CAAI,CAAC,GAAG,MAAA,CAAO,GAAA,CAAI,CAAA,EAAG,EAAE,CAAA;AACpC,IAAA,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,CAAG,IAAA,CAAK,GAAG,CAAA;AAAA,EACzB;AACA,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,KAAM,EAAE,CAAA;AAEhE,EAAA,MAAM,YAAA,GAAe,CAAC,EAAA,KAAe;AACnC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,GAAA,GAAM,cAAA,CAAe,QAAA,CAAS,EAAE,IAClC,cAAA,CAAe,MAAA,CAAO,CAAC,CAAA,KAAM,MAAM,EAAE,CAAA,GACrC,CAAC,GAAG,gBAAgB,EAAE,CAAA;AAC1B,MAAA,QAAA,CAAS,GAAG,CAAA;AAAA,IACd,CAAA,MAAO;AAEL,MAAA,WAAA,EAAY;AACZ,MAAA,QAAA,CAAS,EAAE,CAAA;AACX,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf;AAAA,EACF,CAAA;AAKA,EAAA,MAAM,QAAA,GAAWC,OAAuB,IAAI,CAAA;AAC5C,EAAA,MAAM,gBAAA,GAAmBA,OAAgD,IAAI,CAAA;AAC7E,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,UAAU,gBAAA,CAAiB,OAAA;AACjC,IAAA,IAAI,YAAY,IAAA,EAAM;AACtB,IAAA,gBAAA,CAAiB,OAAA,GAAU,IAAA;AAC3B,IAAA,IAAI,cAAA,CAAe,QAAA,CAAS,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC5C,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,QAAA,CAAS,SAAS,gBAAA,CAA8B,oBAAoB,CAAA,IAAK,EAAE,CAAA;AACpG,IAAA,iBAAA,CAAkB,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,UAAA,CAAW,OAAO,CAAA;AAAA,EAC5D,CAAC,CAAA;AAED,EAAA,MAAM,YAAA,GAAe,WACjB,cAAA,CAAe,MAAA,GAAS,IACtB,CAAA,EAAG,cAAA,CAAe,MAAM,CAAA,SAAA,CAAA,GACxB,WAAA,GACF,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,EAAA,KAAO,eAAe,CAAC,CAAC,GAAG,KAAA,IAAS,WAAA;AAE9D,EAAA,MAAM,EAAE,GAAA,EAAK,WAAA,EAAa,WAAA,EAAY,GAAI,eAAA,CAAgB,EAAE,KAAA,EAAO,CAAA,EAAG,OAAA,EAAS,YAAA,EAAc,CAAA;AAE7F,EAAA,uBACEN,KAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAC/C,QAAA,EAAA;AAAA,IAAA,KAAA,oBACCC,GAAAA,CAAC,MAAA,EAAA,EAAK,IAAI,WAAA,EAAa,SAAA,EAAU,uEAAuE,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IAE/G,OAAA,CAAQ,YAAA;AAAA,oBACTD,IAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,UAAA;AAAA,QACL,EAAA,EAAI,SAAA;AAAA,QACJ,IAAA,EAAK,QAAA;AAAA,QACL,SAAS,MAAM,CAAC,QAAA,IAAY,OAAA,CAAQ,CAAC,IAAI,CAAA;AAAA,QACzC,SAAA,EAAW,CAAC,CAAA,KAAM;AAChB,UAAA,IAAI,YAAY,IAAA,EAAM;AACtB,UAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,WAAA,IAAe,CAAA,CAAE,QAAQ,SAAA,EAAW;AAAE,YAAA,CAAA,CAAE,cAAA,EAAe;AAAG,YAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,UAAG;AAAA,QACzF,CAAA;AAAA,QACA,QAAA;AAAA,QACA,gBAAc,OAAA,IAAW,MAAA;AAAA,QACzB,eAAA,EAAc,SAAA;AAAA,QACd,eAAA,EAAe,IAAA;AAAA,QACf,YAAA,EAAY,aAAa,MAAA,GAAY,SAAA;AAAA,QACrC,iBAAA,EAAiB,UAAA;AAAA,QACjB,oBAAkB,OAAA,CAAQ,WAAA;AAAA,QAC1B,SAAA,EAAW,EAAA;AAAA,UACT,mDAAA;AAAA,UACA,gBAAgB,IAAI,CAAA;AAAA,UACpB,uDAAA;AAAA,UACA,wCAAA;AAAA,UACA,UAAU,iCAAA,GAAoC,iCAAA;AAAA,UAC9C,+BAAA;AAAA,UACA,iCAAA;AAAA,UACA,mBAAA;AAAA,UACA,CAAC,OAAA,IAAW,CAAC,QAAA,IAAY,CAAC,IAAA,IAAQ,6CAAA;AAAA,UAClC,IAAA,KAAS,UAAU,iBAAA,GAAoB,WAAA,CAAA;AAAA,UACvC,UAAU,gBAAA,GAAmB,gBAAA;AAAA,UAC7B,sEAAA;AAAA,UACA,CAAC,eAAe,MAAA,IAAU;AAAA,SAC5B;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,WAAA,mBACCC,IAAC,WAAA,EAAA,EAAY,OAAA,EAAS,cAAc,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAK,WAAA,EAAa,SAAA,EAAU,YAAY,QAAA,EAAA,YAAA,EAAa,CAAA,EAAO,oBAEtGA,GAAAA,CAAC,UAAK,GAAA,EAAK,WAAA,EAAa,SAAA,EAAU,UAAA,EAAY,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,0BAE7DA,GAAAA,CAAC,MAAA,EAAA,EAAK,WAAW,EAAA,CAAG,sBAAA,EAAwB,QAAQ,YAAY,CAAA,EAC9D,QAAA,kBAAAA,GAAAA,CAAC,QAAK,IAAA,EAAK,eAAA,EAAgB,MAAM,EAAA,EAAI,SAAA,EAAU,aAAY,CAAA,EAC7D;AAAA;AAAA;AAAA,KACF;AAAA,IAEC,IAAA,IAAQ,YAAA;AAAA,sBACPD,IAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,OAAA;AAAA,UAGL,QAAA,EAAU,EAAA;AAAA,UAEV,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA,EAAgB;AAAA,UAClC,SAAA,EAAW,EAAA;AAAA,YACT,4CAAA;AAAA,YACA,oCAAA;AAAA,YACA,2FAAA;AAAA,YACA,0EAAA;AAAA,YACA,+CAAA;AAAA,YACA;AAAA,WACF;AAAA,UACA,OAAO,EAAE,GAAA,EAAK,IAAI,GAAA,EAAK,IAAA,EAAM,IAAI,IAAA,EAAM,QAAA,EAAU,GAAA,CAAI,KAAA,EAAO,OAAO,aAAA,EAAe,QAAA,EAAU,sBAAsB,UAAA,EAAY,UAAA,GAAa,YAAY,QAAA,EAAS;AAAA,UAE/J,QAAA,EAAA;AAAA,YAAA,UAAA,oBACCC,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2EAAA,EAA4E,OAAO,EAAE,OAAA,EAAS,mBAAA,EAAoB,EAC/H,QAAA,kBAAAA,GAAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,GAAA,EAAK,SAAA;AAAA,gBACL,IAAA,EAAK,MAAA;AAAA,gBACL,KAAA,EAAO,MAAA;AAAA,gBACP,UAAU,CAAC,CAAA,KAAM,SAAA,CAAU,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,gBACzC,WAAA,EAAY,cAAA;AAAA,gBAEZ,mBAAA,EAAkB,EAAA;AAAA,gBAClB,WAAW,EAAA,CAAG,0GAAA,EAA4G,IAAA,KAAS,IAAA,GAAO,YAAY,SAAS;AAAA;AAAA,aACjK,EACF,CAAA;AAAA,4BAGFA,IAAC,KAAA,EAAA,EAAI,GAAA,EAAK,YAAY,IAAA,EAAK,SAAA,EAAU,WAAU,gCAAA,EAAiC,KAAA,EAAO,EAAE,OAAA,EAAS,6BAAA,EAA+B,WAAW,+BAAA,EAAgC,EACzK,mBAAS,MAAA,KAAW,CAAA,mBACnBA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,GAAG,iDAAA,EAAmD,IAAA,KAAS,OAAO,SAAA,GAAY,SAAS,GAAG,QAAA,EAAA,kBAAA,EAAgB,CAAA,GAC1H,SAAA,GACF,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,SAAS,CAAA,CAAE,IAAI,CAAC,CAAC,OAAO,IAAI,CAAA,qBAC5CD,IAAAA,CAAC,KAAA,EAAA,EACE,QAAA,EAAA;AAAA,cAAA,KAAA,oBACCC,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,qGACV,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,cAED,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACTA,GAAAA;AAAA,gBAAC,YAAA;AAAA,gBAAA;AAAA,kBAEC,GAAA;AAAA,kBACA,UAAA,EAAY,cAAA,CAAe,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAAA,kBAC1C,QAAA;AAAA,kBACA,QAAA,EAAU,YAAA;AAAA,kBACV;AAAA,iBAAA;AAAA,gBALK,GAAA,CAAI;AAAA,eAOZ;AAAA,aAAA,EAAA,EAfO,KAgBV,CACD,CAAA,GAED,SAAS,GAAA,CAAI,CAAC,wBACZA,GAAAA;AAAA,cAAC,YAAA;AAAA,cAAA;AAAA,gBAEC,GAAA;AAAA,gBACA,UAAA,EAAY,cAAA,CAAe,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAAA,gBAC1C,QAAA;AAAA,gBACA,QAAA,EAAU,YAAA;AAAA,gBACV;AAAA,eAAA;AAAA,cALK,GAAA,CAAI;AAAA,aAOZ,CAAA,EAEL;AAAA;AAAA;AAAA,OACF;AAAA,MACA,aAAa,QAAA,CAAS;AAAA,KACxB;AAAA,IAEC,YAAY,SAAA,IAAa,cAAA,CAAe,MAAA,GAAS,CAAA,oBAChDA,GAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,QAAA,EAAU,WAAU,mCAAA,EAC3B,QAAA,EAAA,cAAA,CAAe,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AAC5B,MAAA,MAAM,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAC,CAAA;AAC1C,MAAA,OAAO,sBACLD,IAAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAU,qJAAA;AAAA,UAET,QAAA,EAAA;AAAA,YAAA,GAAA,CAAI,KAAA;AAAA,4BACLC,GAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBAAO,IAAA,EAAK,QAAA;AAAA,gBACX,kBAAA,EAAiB,EAAA;AAAA,gBACjB,SAAS,MAAM;AAAE,kBAAA,gBAAA,CAAiB,OAAA,GAAU,EAAE,KAAA,EAAO,CAAA,EAAG,OAAO,CAAA,EAAE;AAAG,kBAAA,YAAA,CAAa,CAAC,CAAA;AAAA,gBAAG,CAAA;AAAA,gBACrF,SAAA,EAAW,EAAA,CAAG,oDAAA,EAAsD,UAAU,CAAA;AAAA,gBAC9E,YAAA,EAAY,CAAA,OAAA,EAAU,GAAA,CAAI,KAAK,CAAA,CAAA;AAAA,gBAE/B,0BAAAA,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,MAAM,EAAA,EAAI;AAAA;AAAA;AAC/B;AAAA,SAAA;AAAA,QAXK;AAAA,OAYP,GACE,IAAA;AAAA,IACN,CAAC,CAAA,EACH;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAEA,SAAS,YAAA,CAAa;AAAA,EACpB,GAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA,GAAO;AACT,CAAA,EAMG;AACD,EAAA,uBACED,IAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,IAAA,EAAK,QAAA;AAAA,MACL,kBAAgB,GAAA,CAAI,EAAA;AAAA,MACpB,eAAA,EAAe,UAAA;AAAA,MACf,QAAA,EAAU,EAAA;AAAA,MACV,OAAA,EAAS,MAAM,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAAA,MAC9B,SAAA,EAAW,EAAA;AAAA,QACT,+DAAA;AAAA,QACA,8CAAA;AAAA;AAAA,QAEA,UAAA;AAAA,QACA,IAAA,KAAS,OAAO,yBAAA,GAA4B,2BAAA;AAAA,QAC5C,UAAA,IAAc,CAAC,QAAA,GACX,gEAAA,GACA;AAAA,OACN;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,QAAA,oBACCC,GAAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA;AAAA,cACT,sKAAA;AAAA,cACA,aACI,iEAAA,GACA;AAAA,aACN;AAAA,YAEC,QAAA,EAAA,UAAA,oBAAcA,GAAAA,CAAC,IAAA,EAAA,EAAK,MAAK,OAAA,EAAQ,IAAA,EAAM,EAAA,EAAI,SAAA,EAAU,kCAAA,EAAmC;AAAA;AAAA,SAC3F;AAAA,wBAEFA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,QAAA,EAAU,cAAI,KAAA,EAAM,CAAA;AAAA,QACnC,UAAA,IAAc,CAAC,QAAA,oBAAYA,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,IAAA,EAAM,IAAA,KAAS,IAAA,GAAO,EAAA,GAAK,EAAA,EAAI;AAAA;AAAA;AAAA,GAChF;AAEJ;AChbA,IAAM,KAAA,GAAQ;AAAA,EACZ,IAAI,EAAE,GAAA,EAAK,mCAAmC,KAAA,EAAO,sBAAA,EAAwB,KAAK,aAAA,EAAc;AAAA,EAChG,IAAI,EAAE,GAAA,EAAK,mCAAmC,KAAA,EAAO,sBAAA,EAAwB,KAAK,aAAA,EAAc;AAAA,EAChG,IAAI,EAAE,GAAA,EAAK,mCAAmC,KAAA,EAAO,wBAAA,EAA0B,KAAK,gBAAA;AACtF,CAAA;AAEO,SAAS,WAAA,CAAY;AAAA,EAC1B,KAAA;AAAA,EACA,QAAA,EAAU,YAAA;AAAA,EACV,GAAA,GAAM,CAAA,QAAA;AAAA,EACN,GAAA,GAAM,QAAA;AAAA,EACN,IAAA,GAAO,CAAA;AAAA,EACP,QAAA,GAAW,KAAA;AAAA,EACX,WAAA,GAAc,GAAA;AAAA,EACd,MAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA,EAAM,QAAA;AAAA,EACN,SAAA;AAAA,EACA,KAAA,GAAQ,KAAA;AAAA,EACR,aAAA;AAAA,EACA;AACF,CAAA,EAAqB;AAEnB,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,YAAA,EAAc,KAAK,CAAA;AAEtD,EAAA,gBAAA,EAAiB;AACjB,EAAA,MAAM,WAAA,GAAcE,WAAW,kBAAkB,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,YAAY,WAAA,IAAe,IAAA;AACxC,EAAA,MAAM,WAAA,GAAcG,OAAuC,MAAS,CAAA;AACpE,EAAA,MAAM,UAAA,GAAaA,OAAsC,MAAS,CAAA;AAClE,EAAA,MAAM,QAAA,GAAWA,OAAyB,IAAI,CAAA;AAC9C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIE,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAIA,QAAAA,CAAS,MAAA,CAAO,KAAK,CAAC,CAAA;AAEhD,EAAA,MAAM,QAAA,GAAW,aAAA,IAAkB,IAAA,GAAO,CAAA,KAAM,CAAA;AAIhD,EAAA,MAAM,CAAC,UAAU,WAAW,CAAA,GAAIA,SAAS,EAAE,KAAA,EAAO,SAAS,CAAA;AAC3D,EAAA,IAAI,KAAA,KAAU,QAAA,CAAS,KAAA,IAAS,OAAA,KAAY,SAAS,OAAA,EAAS;AAC5D,IAAA,WAAA,CAAY,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA;AAC9B,IAAA,IAAI,CAAC,OAAA,EAAS,QAAA,CAAS,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EACtC;AAEA,EAAA,MAAM,KAAA,GAAQJ,WAAAA;AAAA,IACZ,CAAC,MAAc,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,CAAC,CAAC,CAAA;AAAA,IAC7C,CAAC,KAAK,GAAG;AAAA,GACX;AAMA,EAAA,MAAM,QAAA,GAAW,UAAU,KAAK,CAAA;AAQhC,EAAA,MAAM,WAAA,GAAcA,WAAAA,CAAY,CAAC,CAAA,EAAW,MAAM,KAAA,KAAU;AAC1D,IAAA,MAAM,OAAA,GAAU,MAAM,CAAC,CAAA;AAGvB,IAAA,QAAA,CAAS,OAAA,GAAU,OAAA;AACnB,IAAA,QAAA,CAAS,MAAA,CAAO,OAAO,CAAC,CAAA;AACxB,IAAA,CAAC,GAAA,GAAM,YAAA,GAAe,QAAA,EAAU,OAAO,CAAA;AACvC,IAAA,OAAO,OAAA;AAAA,EACT,GAAG,CAAC,QAAA,EAAU,YAAA,EAAc,KAAA,EAAO,QAAQ,CAAC,CAAA;AAE5C,EAAA,MAAM,SAAA,GAAYA,WAAAA,CAAY,MAAM,WAAA,CAAY,QAAA,CAAS,OAAA,GAAU,IAAI,CAAA,EAAG,CAAC,WAAA,EAAa,IAAA,EAAM,QAAQ,CAAC,CAAA;AACvG,EAAA,MAAM,SAAA,GAAYA,WAAAA,CAAY,MAAM,WAAA,CAAY,QAAA,CAAS,OAAA,GAAU,IAAI,CAAA,EAAG,CAAC,WAAA,EAAa,IAAA,EAAM,QAAQ,CAAC,CAAA;AAEvG,EAAA,MAAM,WAAA,GAAcA,WAAAA;AAAA,IAClB,CAAC,EAAA,KAAmB;AAClB,MAAA,EAAA,EAAG;AACH,MAAA,UAAA,CAAW,OAAA,GAAU,WAAW,MAAM;AACpC,QAAA,WAAA,CAAY,OAAA,GAAU,WAAA,CAAY,EAAA,EAAI,EAAE,CAAA;AAAA,MAC1C,GAAG,GAAG,CAAA;AAAA,IACR,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,UAAA,GAAaA,YAAY,MAAM;AACnC,IAAA,YAAA,CAAa,WAAW,OAAO,CAAA;AAC/B,IAAA,aAAA,CAAc,YAAY,OAAO,CAAA;AAAA,EACnC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GAAcA,WAAAA;AAAA,IAClB,CAAC,CAAA,KAA2C;AAC1C,MAAA,MAAM,GAAA,GAAM,EAAE,MAAA,CAAO,KAAA;AAErB,MAAA,IAAI,GAAA,KAAQ,EAAA,IAAM,GAAA,KAAQ,GAAA,EAAK;AAC7B,QAAA,QAAA,CAAS,GAAG,CAAA;AACZ,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,QAAA,IAAY,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AAEpC,MAAA,MAAM,YAAA,GAAe,WAAW,eAAA,GAAkB,SAAA;AAClD,MAAA,IAAI,CAAC,YAAA,CAAa,IAAA,CAAK,GAAG,CAAA,EAAG;AAE7B,MAAA,QAAA,CAAS,GAAG,CAAA;AAEZ,MAAA,MAAM,MAAA,GAAS,WAAW,GAAG,CAAA;AAC7B,MAAA,IAAI,CAAC,KAAA,CAAM,MAAM,CAAA,IAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACtC,QAAA,QAAA,CAAS,KAAA,CAAM,MAAM,CAAC,CAAA;AAAA,MACxB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAA,EAAU,KAAA,EAAO,QAAQ;AAAA,GAC5B;AAEA,EAAA,MAAM,UAAA,GAAaA,YAAY,MAAM;AACnC,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,MAAM,MAAA,GAAS,WAAW,KAAK,CAAA;AAC/B,IAAA,IAAI,CAAC,KAAA,CAAM,MAAM,CAAA,IAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAEtC,MAAA,MAAM,YAAY,WAAA,CAAY,MAAA,EAAQ,KAAA,KAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAC7D,MAAA,QAAA,CAAS,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,IAC5B,CAAA,MAAO;AACL,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAG,CAAA,GAAI,GAAA,GAAM,CAAA;AACvC,MAAA,MAAM,YAAY,WAAA,CAAY,KAAA,KAAU,MAAA,GAAY,KAAA,GAAQ,UAAU,IAAI,CAAA;AAC1E,MAAA,QAAA,CAAS,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,KAAA,EAAO,WAAA,EAAa,GAAA,EAAK,KAAK,CAAC,CAAA;AAEnC,EAAA,MAAM,WAAA,GAAcA,YAAY,MAAM;AACpC,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgBA,WAAAA;AAAA,IACpB,CAAC,CAAA,KAA2B;AAC1B,MAAA,IAAI,CAAA,CAAE,QAAQ,SAAA,EAAW;AAAE,QAAA,CAAA,CAAE,cAAA,EAAe;AAAG,QAAA,SAAA,EAAU;AAAA,MAAG;AAC5D,MAAA,IAAI,CAAA,CAAE,QAAQ,WAAA,EAAa;AAAE,QAAA,CAAA,CAAE,cAAA,EAAe;AAAG,QAAA,SAAA,EAAU;AAAA,MAAG;AAAA,IAChE,CAAA;AAAA,IACA,CAAC,WAAW,SAAS;AAAA,GACvB;AAEA,EAAA,MAAM,CAAA,GAAI,MAAM,IAAI,CAAA;AACpB,EAAA,MAAM,QAAQ,KAAA,IAAS,GAAA;AACvB,EAAA,MAAM,QAAQ,KAAA,IAAS,GAAA;AAEvB,EAAA,uBACEJ,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,0BAAA;AAAA,QACA,CAAA,CAAE,GAAA;AAAA,QACF,wCAAA;AAAA,QACA,QAAQ,iCAAA,GAAoC,iCAAA;AAAA,QAC5C,+BAAA;AAAA,QACA,iCAAA;AAAA,QACA,yBAAA;AAAA,QACA,yDAAA;AAAA,QACA,CAAC,KAAA,IAAS,CAAC,QAAA,IAAY,6CAAA;AAAA,QACvB,QAAQ,uBAAA,GAA0B,uBAAA;AAAA,QAClC,QAAA,IAAY,qCAAA;AAAA,QACZ;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,GAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,QAAA,EAAU,EAAA;AAAA,YACV,UAAU,QAAA,IAAY,KAAA;AAAA,YACtB,WAAA,EAAa,CAAC,CAAA,KAAM;AAAE,cAAA,CAAA,CAAE,cAAA,EAAe;AAAG,cAAA,QAAA,CAAS,SAAS,KAAA,EAAM;AAAG,cAAA,IAAI,CAAC,QAAA,IAAY,CAAC,KAAA,cAAmB,SAAS,CAAA;AAAA,YAAG,CAAA;AAAA,YACtH,SAAA,EAAW,UAAA;AAAA,YACX,YAAA,EAAc,UAAA;AAAA,YACd,SAAA,EAAW,EAAA;AAAA,cACT,kDAAA;AAAA,cACA,4EAAA;AAAA,cACA,+FAAA;AAAA,cACA,kCAAA;AAAA,cACA,iCAAA;AAAA;AAAA;AAAA,cAGA,UAAA;AAAA,cACA,CAAA,CAAE,GAAA;AAAA,cAAK,CAAA,CAAE,KAAA;AAAA,cAAA,CACR,YAAY,KAAA,KAAU;AAAA,aACzB;AAAA,YACA,YAAA,EAAW,UAAA;AAAA,YACZ,QAAA,EAAA;AAAA;AAAA,SAED;AAAA,wBAEAD,KAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,mDAAA,EAAqD,CAAA,CAAE,KAAK,CAAA,EAC5E,QAAA,EAAA;AAAA,UAAA,MAAA,oBAAUC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gDAAgD,QAAA,EAAA,MAAA,EAAO,CAAA;AAAA,0BAClFA,GAAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,QAAA;AAAA,cACL,EAAA;AAAA,cACA,IAAA,EAAK,MAAA;AAAA,cACL,SAAA,EAAW,WAAW,SAAA,GAAY,SAAA;AAAA,cAClC,gBAAc,KAAA,IAAS,MAAA;AAAA,cACvB,KAAA,EAAO,OAAA,GAAU,KAAA,GAAQ,MAAA,CAAO,KAAK,CAAA;AAAA,cACrC,QAAA,EAAU,WAAA;AAAA,cACV,OAAA,EAAS,WAAA;AAAA,cACT,MAAA,EAAQ,UAAA;AAAA,cACR,SAAA,EAAW,aAAA;AAAA,cACX,QAAA;AAAA,cACA,WAAA;AAAA,cACA,SAAA,EAAW,EAAA;AAAA,gBACT,wDAAA;AAAA,gBACA,+BAAA;AAAA,gBACA,yCAAA;AAAA,gBACA,wCAAA;AAAA,gBACA,CAAA,CAAE,KAAA;AAAA,gBACF,QAAA,IAAY;AAAA;AACd;AAAA,WACF;AAAA,UACC,0BAAUA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gDAAgD,QAAA,EAAA,MAAA,EAAO;AAAA,SAAA,EACpF,CAAA;AAAA,wBAEAA,GAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,QAAA,EAAU,EAAA;AAAA,YACV,UAAU,QAAA,IAAY,KAAA;AAAA,YACtB,WAAA,EAAa,CAAC,CAAA,KAAM;AAAE,cAAA,CAAA,CAAE,cAAA,EAAe;AAAG,cAAA,QAAA,CAAS,SAAS,KAAA,EAAM;AAAG,cAAA,IAAI,CAAC,QAAA,IAAY,CAAC,KAAA,cAAmB,SAAS,CAAA;AAAA,YAAG,CAAA;AAAA,YACtH,SAAA,EAAW,UAAA;AAAA,YACX,YAAA,EAAc,UAAA;AAAA,YACd,SAAA,EAAW,EAAA;AAAA,cACT,kDAAA;AAAA,cACA,4EAAA;AAAA,cACA,+FAAA;AAAA,cACA,kCAAA;AAAA,cACA,iCAAA;AAAA,cACA,UAAA;AAAA,cACA,CAAA,CAAE,GAAA;AAAA,cAAK,CAAA,CAAE,KAAA;AAAA,cAAA,CACR,YAAY,KAAA,KAAU;AAAA,aACzB;AAAA,YACA,YAAA,EAAW,UAAA;AAAA,YACZ,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA,GACF;AAEJ;AChPO,SAAS,OAAA,CAAQ,EAAE,IAAA,EAAM,YAAA,EAAc,OAAA,EAAS,QAAA,EAAU,IAAA,GAAO,QAAA,EAAU,KAAA,GAAQ,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,WAAU,EAAiB;AAC/I,EAAA,MAAM,UAAA,GAAaK,OAAoB,IAAI,CAAA;AAC3C,EAAA,MAAM,WAAA,GAAcA,OAAuB,IAAI,CAAA;AAE/C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIE,SAA6B,MAAS,CAAA;AAC9E,EAAA,MAAM,cAAA,GAAiBJ,WAAAA,CAAY,CAAC,IAAA,KAA6B;AAC/D,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,IAAA,eAAA,CAAgB,MAAM,WAAW,CAAA;AAAA,EACnC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,UAAA,EAAY,WAAA,EAAa,IAAA,EAAM,EAAE,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,CAAA,EAAG,IAAA,EAAM,IAAA,EAAM,CAAA;AAG7F,EAAA,MAAM,eAAA,GAAkB,UAAU,YAAY,CAAA;AAE9C,EAAA,MAAM,EAAE,KAAA,EAAO,UAAA,EAAY,MAAA,KAAW,aAAA,EAAc;AAIpD,EAAA,MAAM,EAAE,OAAO,UAAA,EAAY,WAAA,KAAgB,aAAA,CAAc,IAAA,EAAM,EAAE,OAAA,EAAS,UAAA,EAAY,OAAO,WAAA,EAAa,KAAA,EAAO,MAAM,eAAA,CAAgB,OAAA,CAAQ,KAAK,CAAA,EAAG,QAAA,EAAU,OAAA,EAAS,MAAA,EAAQ,CAAA;AAElL,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AAKX,IAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAqB;AACtC,MAAA,IAAI,EAAE,GAAA,KAAQ,QAAA,IAAY,EAAE,gBAAA,IAAoB,CAAC,YAAW,EAAG;AAC/D,MAAA,MAAM,SAAS,QAAA,CAAS,aAAA;AACxB,MAAA,IAAI,MAAA,IAAU,MAAA,KAAW,QAAA,CAAS,IAAA,IAAQ,CAAC,UAAA,CAAW,OAAA,EAAS,QAAA,CAAS,MAAM,KAAK,CAAC,WAAA,CAAY,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AAC3H,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,WAAA,EAAY;AACZ,MAAA,eAAA,CAAgB,QAAQ,KAAK,CAAA;AAAA,IAC/B,CAAA;AAIA,IAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAAkB;AACjC,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,IAAI,MAAA,CAAO,CAAC,CAAA,IAAK,UAAA,CAAW,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA,IAAK,WAAA,CAAY,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AAChG,MAAA,eAAA,CAAgB,QAAQ,KAAK,CAAA;AAAA,IAC/B,CAAA;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,OAAO,CAAA;AAC9C,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,SAAS,CAAA;AACjD,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAa,OAAO,CAAA;AAAA,IACnD,CAAA;AAAA,EACF,GAAG,CAAC,IAAA,EAAM,iBAAiB,UAAA,EAAY,WAAA,EAAa,MAAM,CAAC,CAAA;AAE3D,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,IAAA,EAAM,YAAA,CAAa,WAAA,CAAY,OAAO,CAAA;AAAA,EAC5C,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,uBACEL,KAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAC,GAAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACE,GAAG,YAAY,OAAO,CAAA;AAAA,QACvB,GAAA,EAAK,cAAA;AAAA,QACL,SAAS,MAAM;AAAE,UAAA,eAAA,CAAgB,UAAA,CAAW,SAAS,WAAW,CAAA;AAAG,UAAA,YAAA,CAAa,CAAC,IAAI,CAAA;AAAA,QAAG,CAAA;AAAA,QAEvF,QAAA,EAAA;AAAA;AAAA,KACH;AAAA,IACC,IAAA,IAAQQ,YAAAA;AAAA,sBACPR,GAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,WAAA;AAAA,UACL,SAAA,EAAQ,SAAA;AAAA,UACP,GAAG,UAAA;AAAA,UAEJ,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA,EAAgB;AAAA,UAClC,SAAA,EAAW,EAAA;AAAA,YACT,+BAAA;AAAA,YACA,oCAAA;AAAA,YACA,cAAA;AAAA,YACA,0EAAA;AAAA,YACA,+BAAA;AAAA,YACA;AAAA,WACF;AAAA,UACA,KAAA,EAAO;AAAA,YACL,KAAK,GAAA,CAAI,GAAA;AAAA,YACT,MAAM,GAAA,CAAI,IAAA;AAAA,YACV,OAAO,KAAA,KAAU,SAAA,GAAY,YAAA,GAAe,KAAA,KAAU,SAAS,MAAA,GAAY;AAAA,WAC7E;AAAA,UAGA,QAAA,kBAAAA,GAAAA,CAAC,OAAA,EAAA,EAAQ,KAAA,EAAO,OAAQ,QAAA,EAAS;AAAA;AAAA,OACnC;AAAA,MACA,aAAa,QAAA,CAAS;AAAA;AACxB,GAAA,EACF,CAAA;AAEJ;AC9EA,IAAM,aAAA,uBAAoB,OAAA,EAAwB;AAE3C,SAAS,WAAW,KAAA,EAAwB;AACjD,EAAA,MAAM,EAAE,YAAW,GAAI,KAAA;AACvB,EAAAI,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,UAAA,EAAY;AACjB,IAAA,MAAM,KAAA,GAAA,CAAS,aAAA,CAAc,GAAA,CAAI,UAAU,KAAK,CAAA,IAAK,CAAA;AACrD,IAAA,aAAA,CAAc,GAAA,CAAI,YAAY,KAAK,CAAA;AACnC,IAAA,IAAI,KAAA,GAAQ,CAAA,EAAG,QAAA,CAAS,YAAA,EAAc,gLAAgL,CAAA;AACtN,IAAA,OAAO,MAAM;AAAE,MAAA,aAAA,CAAc,IAAI,UAAA,EAAA,CAAa,aAAA,CAAc,IAAI,UAAU,CAAA,IAAK,KAAK,CAAC,CAAA;AAAA,IAAG,CAAA;AAAA,EAC1F,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AACf,EAAA,IAAA,CAAK,KAAA,CAAM,SAAS,WAAA,IAAe,KAAA,CAAM,SAAS,iBAAA,KAAsB,KAAA,CAAM,YAAY,uBAAOJ,IAAC,QAAA,EAAA,EAAU,GAAG,OAAO,UAAA,EAAY,KAAA,CAAM,YAAY,MAAA,EAAQ,KAAA,CAAM,SAAS,iBAAA,EAAmB,CAAA;AAC9L,EAAA,uBAAOA,GAAAA,CAAC,WAAA,EAAA,EAAa,GAAG,KAAA,EAAO,CAAA;AACjC;AAOA,SAAS,WAAW,EAAA,EAAqC;AACvD,EAAA,KAAA,IAAS,CAAA,GAAI,EAAA,CAAG,aAAA,EAAe,CAAA,IAAK,CAAA,KAAM,QAAA,CAAS,IAAA,IAAQ,CAAA,KAAM,QAAA,CAAS,eAAA,EAAiB,CAAA,GAAI,CAAA,CAAE,aAAA,EAAe;AAC9G,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,gBAAA,CAAiB,CAAC,CAAA;AACxC,IAAA,IAAA,CAAK,SAAA,KAAc,UAAU,SAAA,KAAc,QAAA,KAAa,EAAE,YAAA,GAAe,CAAA,CAAE,cAAc,OAAO,CAAA;AAAA,EAClG;AACA,EAAA,OAAO,IAAA;AACT;AAMA,SAAS,WAAW,EAAA,EAAyB;AAC3C,EAAA,IAAI,GAAA,GAAM,EAAA,CAAG,qBAAA,EAAsB,CAAE,MAAM,MAAA,CAAO,OAAA;AAClD,EAAA,KAAA,IAAS,CAAA,GAAI,EAAA,CAAG,aAAA,EAAe,CAAA,IAAK,CAAA,KAAM,QAAA,CAAS,eAAA,EAAiB,CAAA,GAAI,CAAA,CAAE,aAAA,EAAe,GAAA,IAAO,CAAA,CAAE,SAAA;AAClG,EAAA,OAAO,GAAA;AACT;AASA,SAAS,QAAA,CAAS,EAAE,OAAA,EAAS,UAAA,EAAY,eAAe,WAAA,EAAa,MAAA,EAAQ,WAAU,EAAkE;AACvJ,EAAA,MAAM,MAAA,GAASK,OAAuB,IAAI,CAAA;AAC1C,EAAA,MAAM,IAAA,GAAO,UAAU,UAAU,CAAA;AACjC,EAAA,MAAM,QAAA,GAAWA,OAAsB,IAAI,CAAA;AAC3C,EAAAD,UAAU,MAAM;AACd,IAAA,MAAM,KAAK,MAAA,CAAO,OAAA;AAClB,IAAA,IAAI,CAAC,UAAU,CAAC,OAAA,IAAW,CAAC,EAAA,IAAM,OAAO,yBAAyB,WAAA,EAAa;AAC/E,IAAA,MAAM,QAAA,GAAW,IAAI,oBAAA,CAAqB,CAAC,OAAA,KAAY;AACrD,MAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,CAAA,EAAG;AAC5C,MAAA,MAAM,EAAA,GAAK,WAAW,EAAE,CAAA;AACxB,MAAA,IAAI,QAAA,CAAS,YAAY,IAAA,IAAQ,IAAA,CAAK,IAAI,EAAA,GAAK,QAAA,CAAS,OAAO,CAAA,GAAI,CAAA,EAAG;AACtE,MAAA,QAAA,CAAS,OAAA,GAAU,EAAA;AACnB,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf,CAAA,EAAG,EAAE,IAAA,EAAM,UAAA,CAAW,EAAE,CAAA,EAAG,UAAA,EAAY,aAAa,CAAA;AACpD,IAAA,QAAA,CAAS,QAAQ,EAAE,CAAA;AACnB,IAAA,MAAM,QAAQ,MAAM;AAAE,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IAAM,CAAA;AAC/C,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,KAAA,EAAO,EAAE,SAAS,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AACzE,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,UAAA,EAAW;AACpB,MAAA,MAAA,CAAO,oBAAoB,QAAA,EAAU,KAAA,EAAO,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,IAC/D,CAAA;AAAA,EACF,GAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,WAAA,EAAa,IAAI,CAAC,CAAA;AACvC,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,EAAA,uBACEL,IAAAA,CAAC,KAAA,EAAA,EAAI,eAAA,EAAc,EAAA,EAAG,sBAAA,EAAsB,MAAA,GAAS,iBAAA,GAAoB,WAAA,EAAa,SAAA,EAAW,EAAA,CAAG,4BAAA,EAA8B,SAAS,CAAA,EACxI,QAAA,EAAA;AAAA,IAAA,MAAA,oBAAUC,GAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,MAAA,EAAQ,0BAAuB,EAAA,EAAG,aAAA,EAAY,MAAA,EAAO,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,oBAClGA,GAAAA,CAAC,MAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,SAAQ,WAAA,EAAY,OAAA,EAAS,UAAA,EAAa,QAAA,EAAA,aAAA,IAAiB,WAAA,EAAY;AAAA,GAAA,EAC/F,CAAA;AAEJ;AAEA,SAAS,WAAA,CAAY,EAAE,WAAA,EAAa,UAAA,EAAY,YAAA,EAAc,UAAU,YAAA,EAAc,eAAA,EAAiB,gBAAA,EAAkB,SAAA,EAAU,EAAoB;AACrJ,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,WAAA,EAAa,UAAU,CAAA;AAGpD,EAAA,MAAM,cAAc,mBAAA,EAAoB;AACxC,EAAA,MAAM,QAAA,GAAW,gBAAgB,WAAA,CAAY,YAAA;AAI7C,EAAA,MAAM,UAAA,GAAa,CAAC,EAAE,eAAA,IAAmB,YAAY,IAAA,IAAQ,gBAAA,CAAA;AAC7D,EAAA,IAAI,UAAA,IAAc,CAAA,IAAK,CAAC,UAAA,EAAY,OAAO,IAAA;AAE3C,EAAA,uBACED,IAAAA,CAAC,KAAA,EAAA,EAAI,YAAA,EAAW,YAAA,EAAa,eAAA,EAAc,EAAA,EAAG,SAAA,EAAW,EAAA,CAAG,sCAAA,EAAwC,SAAS,CAAA,EAC1G,QAAA,EAAA;AAAA,IAAA,UAAA,IAAc,eAAA,IAAmB,YAAY,IAAA,IAAQ,gBAAA,oBACpDA,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4BAAA,EACb,QAAA,EAAA;AAAA,sBAAAC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uDAAA,EAAwD,QAAA,EAAA,eAAA,EAAa,CAAA;AAAA,sBAErFA,GAAAA,CAAC,aAAA,EAAA,EAAc,KAAA,EAAO,MAEpB,QAAA,kBAAAA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,YAAA,EAAY,kBAAkB,QAAQ,CAAA,CAAA;AAAA,UACtC,OAAA,EAAS,eAAA,CAAgB,GAAA,CAAI,CAAC,OAAO,EAAE,EAAA,EAAI,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA,EAAO,MAAA,CAAO,CAAC,GAAE,CAAE,CAAA;AAAA,UACzE,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,UACtB,UAAU,CAAC,CAAA,KAAM,gBAAA,CAAiB,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,UAC3C,IAAA,EAAK,IAAA;AAAA,UACL,SAAA,EAAU;AAAA;AAAA,OACZ,EACF;AAAA,KAAA,EACF,CAAA;AAAA,IAGD,aAAa,CAAA,oBAAKD,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4BAAA,EAClC,QAAA,EAAA;AAAA,sBAAAC,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAAO,IAAA,EAAK,QAAA;AAAA,UACX,OAAA,EAAS,MAAM,YAAA,CAAa,WAAA,GAAc,CAAC,CAAA;AAAA,UAC3C,UAAU,WAAA,IAAe,CAAA;AAAA,UACzB,YAAA,EAAW,eAAA;AAAA,UACX,SAAA,EAAW,EAAA;AAAA,YACT,gIAAA;AAAA,YACA,+BAAA;AAAA,YACA,0EAAA;AAAA,YACA,2DAAA;AAAA,YACA,yDAAA;AAAA,YACA,mEAAA;AAAA,YACA,uDAAA;AAAA,YACA;AAAA,WACF;AAAA,UAEA,QAAA,kBAAAA,IAAC,IAAA,EAAA,EAAK,IAAA,EAAK,iBAAgB,IAAA,EAAM,EAAA,EAAI,WAAU,YAAA,EAAa;AAAA;AAAA,OAC9D;AAAA,MAEC,KAAA,CAAM,GAAA;AAAA,QAAI,CAAC,CAAA,EAAG,CAAA,KACb,CAAA,KAAM,wBACJA,GAAAA,CAAC,cAAA,EAAA,EAAqC,UAAA,EAAwB,YAAA,EAAA,EAAzC,CAAA,SAAA,EAAY,CAAC,CAAA,CAAwD,oBAE1FA,GAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YAAO,IAAA,EAAK,QAAA;AAAA,YAEX,OAAA,EAAS,MAAM,YAAA,CAAa,CAAW,CAAA;AAAA,YACvC,cAAA,EAAc,CAAA,KAAM,WAAA,GAAc,MAAA,GAAS,MAAA;AAAA,YAC3C,SAAA,EAAW,EAAA;AAAA,cACT,4IAAA;AAAA,cACA,+BAAA;AAAA,cACA,wCAAA;AAAA,cACA,yDAAA;AAAA,cACA,UAAA;AAAA,cACA,CAAA,KAAM,cACF,wIAAA,GACA;AAAA,aACN;AAAA,YAEC,QAAA,EAAA;AAAA,WAAA;AAAA,UAdI;AAAA;AAeP,OAEJ;AAAA,sBAEAA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAAO,IAAA,EAAK,QAAA;AAAA,UACX,OAAA,EAAS,MAAM,YAAA,CAAa,WAAA,GAAc,CAAC,CAAA;AAAA,UAC3C,UAAU,WAAA,IAAe,UAAA;AAAA,UACzB,YAAA,EAAW,WAAA;AAAA,UACX,SAAA,EAAW,EAAA;AAAA,YACT,gIAAA;AAAA,YACA,+BAAA;AAAA,YACA,0EAAA;AAAA,YACA,2DAAA;AAAA,YACA,yDAAA;AAAA,YACA,mEAAA;AAAA,YACA,uDAAA;AAAA,YACA;AAAA,WACF;AAAA,UAEA,0BAAAA,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,eAAA,EAAgB,MAAM,EAAA,EAAI;AAAA;AAAA;AACvC,KAAA,EACA;AAAA,GAAA,EACF,CAAA;AAEJ;AAEA,SAAS,cAAA,CAAe,SAAiB,KAAA,EAAmC;AAC1E,EAAA,IAAI,KAAA,IAAS,CAAA,EAAG,OAAO,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,KAAA,EAAM,EAAG,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AAEpE,EAAA,MAAM,KAAA,GAA4B,CAAC,CAAC,CAAA;AAEpC,EAAA,IAAI,OAAA,GAAU,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,KAAK,CAAA;AAEjC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAC,CAAA;AACrC,EAAA,MAAM,MAAM,IAAA,CAAK,GAAA,CAAI,KAAA,GAAQ,CAAA,EAAG,UAAU,CAAC,CAAA;AAC3C,EAAA,KAAA,IAAS,IAAI,KAAA,EAAO,CAAA,IAAK,KAAK,CAAA,EAAA,EAAK,KAAA,CAAM,KAAK,CAAC,CAAA;AAE/C,EAAA,IAAI,OAAA,GAAU,KAAA,GAAQ,CAAA,EAAG,KAAA,CAAM,KAAK,KAAK,CAAA;AAEzC,EAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAChB,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,cAAA,CAAe,EAAE,UAAA,EAAY,YAAA,EAAa,EAAiE;AAClH,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIO,SAAS,KAAK,CAAA;AACtC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,SAAS,CAAC,CAAA;AAE1C,EAAA,MAAM,gBAAA,GAAmB,CAAC,IAAA,KAAkB;AAC1C,IAAA,IAAI,IAAA,cAAkB,CAAC,CAAA;AACvB,IAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,EACd,CAAA;AAEA,EAAA,MAAM,WAAW,MAAM;AACrB,IAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,UAAA,EAAY,KAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,CAAC,CAAA;AAC1D,IAAA,YAAA,CAAa,OAAO,CAAA;AACpB,IAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,EACf,CAAA;AAEA,EAAA,uBACEP,GAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA,EAAc,gBAAA;AAAA,MACd,yBACEA,GAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,YAAA,EAAW,YAAA;AAAA,UACX,OAAA,EAAS,MAAM,gBAAA,CAAiB,IAAI,CAAA;AAAA,UACpC,SAAA,EAAW,EAAA;AAAA,YACT,gIAAA;AAAA,YACA,+BAAA;AAAA,YACA,6BAAA;AAAA,YACA,yDAAA;AAAA,YACA,mEAAA;AAAA,YACA;AAAA,WACF;AAAA,UACD,QAAA,EAAA;AAAA;AAAA,OAED;AAAA,MAGF,QAAA,kBAAAD,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+BAAA,EACb,QAAA,EAAA;AAAA,wBAAAC,GAAAA,CAAC,OAAA,EAAA,EAAM,SAAA,EAAU,qDAAA,EAAsD,QAAA,EAAA,YAAA,EAAU,CAAA;AAAA,wBACjFD,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EACb,QAAA,EAAA;AAAA,0BAAAC,GAAAA;AAAA,YAAC,WAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAO,QAAA;AAAA,cACP,QAAA,EAAU,WAAA;AAAA,cACV,GAAA,EAAK,CAAA;AAAA,cACL,GAAA,EAAK,UAAA;AAAA,cACL,IAAA,EAAM,CAAA;AAAA,cACN,IAAA,EAAK,IAAA;AAAA,cACL,SAAA,EAAU;AAAA;AAAA,WACZ;AAAA,0BACAA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,OAAA,EAAS,QAAA;AAAA,cACT,SAAA,EAAW,EAAA;AAAA,gBACT,8EAAA;AAAA,gBACA,+BAAA;AAAA,gBACA,gEAAA;AAAA,gBACA,yDAAA;AAAA,gBACA,kBAAA;AAAA,gBACA;AAAA,eACF;AAAA,cACD,QAAA,EAAA;AAAA;AAAA;AAED,SAAA,EACF;AAAA,OAAA,EACF;AAAA;AAAA,GACF;AAEJ;AClNA,SAAS,SAAS,IAAA,EAAwB;AACxC,EAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA,KAAS,UAAU,OAAO,IAAA,IAAQ,IAAA,GAAQ,IAAA,CAAyB,EAAA,GAAK,MAAA;AACpG,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,SAAS,OAAA,EAA0B;AAC1C,EAAA,IAAI;AAAE,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,OAAA,IAAW,IAAI,CAAA;AAAA,EAAG,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,OAAO,OAAO,CAAA;AAAA,EAAG;AAClF;AAEA,SAAS,SAAA,CAAU,MAA0B,OAAA,EAA0B;AACrE,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,IAAI;AAAE,IAAA,KAAA,GAAQ,KAAK,SAAA,CAAU,QAAA,CAAS,KAAK,CAAC,CAAC,KAAK,IAAI,CAAA;AAAA,EAAG,CAAA,CAAA,MAAQ;AAAE,IAAA,KAAA,GAAQ,EAAA;AAAA,EAAI;AAC/E,EAAA,OAAO,CAAA,EAAG,KAAK,MAAM,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,EAAI,QAAA,CAAS,OAAO,CAAC,CAAA,CAAA;AACrD;AASA,SAAS,WAAA,CAAY,IAAA,EAAY,IAAA,EAA0B,KAAA,EAAwB;AACjF,EAAA,IAAI,KAAA,KAAU,IAAA,CAAK,KAAA,IAAS,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,KAAA,KAAU,MAAA,IAAa,IAAA,CAAK,MAAA,KAAW,GAAG,OAAO,KAAA;AAChH,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,CAAC,CAAC,MAAM,IAAA,CAAK,KAAA,IAAS,QAAA,CAAS,IAAA,CAAK,KAAK,MAAA,GAAS,IAAA,CAAK,MAAM,CAAC,MAAM,IAAA,CAAK,KAAA;AAChG;AASO,SAAS,aAAA,CAAiB,IAAA,EAAoB,OAAA,GAA6B,EAAC,EAAa;AAC9F,EAAA,MAAM,QAAQ,mBAAA,EAAoB;AAClC,EAAA,MAAM,KAAA,GAAmC,OAAA,CAAQ,KAAA,IAAS,KAAA,CAAM,mBAAmB,yBAAA,CAA0B,eAAA;AAC7G,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIO,SAAwB,IAAI,CAAA;AAChE,EAAA,MAAM,CAAC,UAAU,CAAA,GAAIA,QAAAA,CAAS,OAAO,EAAC,CAAE,CAAA;AACxC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,UAAA,IAAc,OAAA,CAAQ,QAAA,IAAY,KAAA,CAAM,YAAA,IAAgB,yBAAA,CAA0B,YAAY,CAAC,CAAA;AACvI,EAAA,MAAM,CAAC,IAAA,EAAM,YAAY,CAAA,GAAIA,SAAS,CAAC,CAAA;AAMvC,EAAA,MAAM,GAAA,GAAM,SAAA,CAAU,IAAA,EAAM,OAAA,CAAQ,OAAO,CAAA;AAC3C,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA;AACtC,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,IAAIA,QAAAA,CAAe,OAAO,EAAE,GAAA,EAAK,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,OAAO,QAAA,CAAS,IAAA,CAAK,CAAC,CAAC,CAAA,EAAG,OAAM,CAAE,CAAA;AAC5G,EAAA,MAAM,OAAA,GAAU,KAAK,GAAA,KAAQ,GAAA;AAC7B,EAAA,MAAM,cAAc,OAAA,IAAW,CAAC,WAAA,CAAY,IAAA,EAAM,MAAM,KAAK,CAAA;AAC7D,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,EAAE,GAAA,EAAK,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,QAAA,CAAS,IAAA,CAAK,CAAC,CAAC,CAAA,EAAG,KAAA,EAAO,CAAA;AACrE,IAAA,IAAI,WAAA,IAAe,IAAA,KAAS,CAAA,EAAG,YAAA,CAAa,CAAC,CAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,aAAa,IAAA,CAAK,MAAA;AACxB,EAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,IAAA,CAAK,UAAA,GAAa,QAAQ,CAAC,CAAA;AAC/D,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,CAAA,GAAI,IAAI,CAAA,EAAG,UAAU,CAAA;AACxE,EAAA,MAAM,QAAQ,KAAA,KAAU,YAAA;AAExB,EAAA,MAAM,KAAA,GAAQ,KAAA,GAAQ,CAAA,GAAA,CAAK,OAAA,GAAU,CAAA,IAAK,QAAA;AAC1C,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,UAAU,QAAQ,CAAA;AAClD,EAAA,MAAM,KAAA,GAA0B,KAAA,CAAM,MAAA,KAAW,CAAA,GAAI,CAAC,CAAA,EAAG,CAAC,CAAA,GAAI,CAAC,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,MAAM,MAAM,CAAA;AAC9F,EAAA,MAAM,UAAU,OAAA,GAAU,UAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,IAAA,KAAiB,YAAA,CAAa,KAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAI,CAAC,CAAA,EAAG,UAAU,CAAC,CAAA;AAClG,EAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,CAAC,CAAA,KAAM,KAAK,GAAA,CAAI,CAAA,GAAI,CAAA,EAAG,UAAU,CAAC,CAAA;AACtE,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,KAAiB;AAAE,IAAA,aAAA,CAAc,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAI,CAAC,CAAC,CAAA;AAAG,IAAA,YAAA,CAAa,CAAC,CAAA;AAAA,EAAG,CAAA;AAEvG,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IAAO,KAAA;AAAA,IAAO,IAAA,EAAM,OAAA;AAAA,IAAS,QAAA;AAAA,IAAU,UAAA;AAAA,IAAY,UAAA;AAAA,IAAY,KAAA;AAAA,IAAO,OAAO,KAAA,CAAM,MAAA;AAAA,IAAQ,OAAA;AAAA,IAAS,QAAA;AAAA,IAAU,OAAA;AAAA,IAAS,WAAA;AAAA,IACvH,KAAA,EAAO,EAAE,WAAA,EAAa,OAAA,EAAS,UAAA,EAAY,cAAc,OAAA,EAAS,QAAA,EAAU,gBAAA,EAAkB,WAAA,EAAa,IAAA,EAAM,KAAA,EAAO,SAAS,UAAA,EAAY,QAAA,EAAU,UAAA,EAAY,GAAI,OAAA,CAAQ,eAAA,GAAkB,EAAE,eAAA,EAAiB,OAAA,CAAQ,eAAA,EAAgB,GAAI,EAAC;AAAG,GACtP;AACF;AAMO,SAAS,SAAA,CAAa,MAAoB,KAAA,EAA6B;AAC5E,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,OAAO,MAAM,KAAA,CAAM,CAAC,CAAA,KAAM,CAAA,GAAI,EAAC,GAAI,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,MAAM,CAAC,CAAA,GAAI,GAAG,KAAA,CAAM,KAAA,CAAM,CAAC,CAAC,CAAA;AAClF;AAGO,SAAS,iBAAA,CAAkB,SAAA,EAAmB,MAAA,EAAgB,KAAA,EAA8B;AACjG,EAAA,MAAM,QAAQ,KAAA,EAAO,UAAA;AACrB,EAAAH,UAAU,MAAM;AAGd,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,MAAA,KAAW,KAAA,EAAO,QAAA,CAAS,WAAW,CAAA,iBAAA,EAAoB,KAAK,CAAA,0BAAA,EAA6B,MAAM,CAAA,gIAAA,CAAkI,CAAA;AAAA,EACjQ,CAAA,EAAG,CAAC,SAAA,EAAW,MAAA,EAAQ,KAAK,CAAC,CAAA;AAC/B","file":"chunk-FUKSLQ77.js","sourcesContent":["/**\n * Sprint 25.14 A20: the checked and switched looks, shared by the controls (Checkbox, RadioGroup, Toggle) and the Card's\n * selection indicators, so the two never drift apart (the review of 30 September: the Card kept the old switch, the\n * accent's gradient and the accent dot after the controls moved).\n */\n\n/** A checked box's fill and a selected radio's dot: the check colour, with the theme's check gradient (by default the accent's) over it. */\nexport const CHECK_FILL = \"bg-[var(--ds-check-bg)] [background-image:var(--ds-check-gradient,var(--ds-gradient))]\";\n\n/** A switch's track when on: the check colour, as a checked box's. */\nexport const SWITCH_TRACK_ON = \"bg-[var(--ds-check-bg)] border-transparent\";\n\n/**\n * A switch's track when off: from tokens only a regenerated stylesheet has (the theme writers emit them), falling back\n * to the switch as it was, so an app that hasn't regenerated never gets an outline in its old, fainter edge colour.\n */\nexport const SWITCH_TRACK_OFF = \"bg-[var(--ds-switch-off-fill,var(--ds-bg-muted))] border-[var(--ds-switch-off-edge,var(--ds-border-default))]\";\n\n/**\n * A switch's knob when on: the surface made opaque (a glass theme's half-white surface would show the track through it),\n * as pinned table cells are (D31); a surface that is wholly transparent stays so.\n */\nexport const SWITCH_KNOB_ON = \"bg-[var(--ds-bg-surface)] supports-[color:oklch(from_red_l_c_h)]:bg-[oklch(from_var(--ds-bg-surface)_l_c_h_/_max(alpha,min(1,alpha*1000)))]\";\n\n/** A switch's knob when off: the edge colour, beside the outline (the same fallback as the track). */\nexport const SWITCH_KNOB_OFF = \"bg-[var(--ds-switch-off-knob,var(--ds-bg-surface))]\";\n\n/** The knob moves and changes colour together with its track, so it never shows before the track does. */\nexport const SWITCH_KNOB_MOTION = \"transition-[transform,background-color] duration-[var(--ds-transition-speed)]\";\n","import { createContext } from \"react\";\n\n/**\n * A row of filters (PageHeader's filters slot) tells the controls in it that they are in one, so a text field takes a\n * search field's width, the table toolbar's (280 px), instead of a line of its own (the owner's\n * look at a bold header with content overlap, 30 September 2026: the search box filled a whole line).\n */\nexport const FilterRowContext = createContext(false);\n\n/**\n * A text field's width in a filter row: the toolbar search's 280 px, never wider than the row. A set width, not a flex\n * basis: a row that hugs its controls (the strip on a bold band) sizes itself from their widths, and a basis it doesn't\n * count pushed the field onto a line of its own.\n */\nexport const FILTER_FIELD_WIDTH = \"w-[280px] max-w-full\";\n","import { useCallback, useContext, useEffect, useRef, type Ref } from \"react\";\nimport { cn, FIELD_FOCUS_RING, FIELD_HAS_FOCUS_RING, ERROR_FOCUS_RING, ERROR_HAS_FOCUS_RING, FOCUS_RING } from \"../lib/utils\";\nimport { useInputModality } from \"../lib/input-modality\";\nimport type { ReactNode, InputHTMLAttributes, TextareaHTMLAttributes, LabelHTMLAttributes } from \"react\";\nimport { ControlSizeContext } from \"./Button\";\nimport { useReportedChange } from \"../lib/form-context\";\nimport { SWITCH_KNOB_MOTION, SWITCH_KNOB_OFF, SWITCH_KNOB_ON, SWITCH_TRACK_OFF, SWITCH_TRACK_ON } from \"../lib/control-looks\";\nimport { FILTER_FIELD_WIDTH, FilterRowContext } from \"../lib/filter-row\";\n\n/** A native field's new value from its change event: `checked` for a box, `value` for the rest (Sprint 25.12 A15). */\n/** An uncontrolled field's value, which no edit equals: the field holds its value itself. */\nconst UNCONTROLLED = Symbol(\"uncontrolled\");\nconst valueOf = (e: { target: EventTarget | null }) => {\n const t = e.target as HTMLInputElement | HTMLTextAreaElement | null;\n if (!t) return undefined;\n return t instanceof HTMLInputElement && (t.type === \"checkbox\" || t.type === \"radio\") ? t.checked : t.value;\n};\n\ntype InputSize = \"sm\" | \"md\" | \"lg\";\n\n// \"prefix\" must be omitted from the inherited attributes: React's HTMLAttributes\n// declares the RDFa attribute `prefix?: string`, and intersecting it with\n// `prefix?: ReactNode` collapses the prop to string-only at use sites.\nconst INPUT_HEIGHT: Record<InputSize, string> = {\n sm: \"h-[var(--ds-control-height-sm)]\",\n md: \"h-[var(--ds-control-height-md)]\",\n lg: \"h-[var(--ds-control-height-lg)]\",\n};\n\nconst INPUT_TEXT: Record<InputSize, string> = {\n sm: \"px-ds-2 py-ds-1 text-xs\",\n md: \"px-ds-3 py-ds-2 text-sm\",\n lg: \"px-ds-4 py-ds-3 text-base\",\n};\n\nexport function Input({ className, size: sizeProp, error = false, prefix, suffix, ...props }: Omit<InputHTMLAttributes<HTMLInputElement>, \"size\" | \"prefix\"> & { size?: InputSize; error?: boolean; prefix?: ReactNode; suffix?: ReactNode }) {\n // a field: clicked into, the active look; reached with Tab, the outline (Sprint 30, lib/input-modality.ts)\n useInputModality();\n const contextSize = useContext(ControlSizeContext);\n const size = sizeProp ?? contextSize ?? \"md\";\n // in a row of filters, a search field's width rather than a line of its own (the owner, 30 September)\n const width = useContext(FilterRowContext) ? FILTER_FIELD_WIDTH : \"w-full\";\n // Sprint 25.12 A15: the user's typing marks the form's overlay (only a new value); the page's onChange runs as given.\n // Uncontrolled (defaultValue), every edit is new: clearing a prefilled field compared \"\" with no value (0.21.0).\n const onChange = useReportedChange(props.onChange, props.value === undefined ? UNCONTROLLED : props.value, valueOf);\n const borderColor = error ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)]\";\n const hoverBorder = !error && !props.disabled && !props.readOnly ? \"hover:border-[var(--ds-input-border-hover)]\" : \"\";\n\n if (prefix || suffix) {\n return (\n <div\n className={cn(\n \"flex items-center\", width,\n INPUT_HEIGHT[size],\n \"bg-[var(--ds-input-bg)]\",\n \"border-[length:var(--ds-border-width)]\", borderColor,\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n hoverBorder,\n error ? ERROR_HAS_FOCUS_RING : FIELD_HAS_FOCUS_RING,\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n props.disabled && \"cursor-not-allowed opacity-disabled\",\n props.readOnly && \"bg-[var(--ds-bg-muted)] cursor-default\",\n className\n )}\n >\n {prefix && <span className=\"shrink-0 pl-ds-3 text-[var(--ds-text-muted)] flex items-center\">{prefix}</span>}\n <input\n aria-invalid={error || undefined}\n className={cn(\n \"flex-1 min-w-0 bg-transparent outline-none\",\n INPUT_TEXT[size],\n \"text-[var(--ds-text-primary)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n \"disabled:cursor-not-allowed\",\n \"read-only:text-[var(--ds-text-secondary)] read-only:cursor-default\",\n )}\n {...props}\n onChange={props.onChange || props.value === undefined ? onChange : undefined}\n />\n {suffix && <span className=\"shrink-0 pr-ds-3 text-[var(--ds-text-muted)] flex items-center\">{suffix}</span>}\n </div>\n );\n }\n\n return (\n <input\n aria-invalid={error || undefined}\n className={cn(\n \"flex\", width,\n INPUT_TEXT[size], INPUT_HEIGHT[size],\n \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)]\", borderColor,\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n hoverBorder,\n error ? ERROR_FOCUS_RING : FIELD_FOCUS_RING,\n \"disabled:cursor-not-allowed disabled:opacity-disabled\",\n \"read-only:bg-[var(--ds-bg-muted)] read-only:text-[var(--ds-text-secondary)] read-only:cursor-default\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n className\n )}\n {...props}\n onChange={props.onChange || props.value === undefined ? onChange : undefined}\n />\n );\n}\n\ninterface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n autoResize?: boolean;\n maxRows?: number;\n error?: boolean;\n ref?: Ref<HTMLTextAreaElement>;\n}\n\nexport function Textarea({ className, autoResize, maxRows, error = false, ref, ...props }: TextareaProps) {\n // a field, as Input (Sprint 30)\n useInputModality();\n // Sprint 25.12 A15: as Input\n const onChange = useReportedChange(props.onChange, props.value === undefined ? UNCONTROLLED : props.value, valueOf);\n const internalRef = useRef<HTMLTextAreaElement>(null);\n const textareaRef = (ref ?? internalRef) as React.RefObject<HTMLTextAreaElement>;\n\n const resize = useCallback(() => {\n const el = textareaRef.current;\n if (!el || !autoResize) return;\n el.style.height = \"auto\";\n let target = el.scrollHeight;\n if (maxRows) {\n const lineHeight = parseFloat(getComputedStyle(el).lineHeight) || 20;\n const maxHeight = lineHeight * maxRows + parseFloat(getComputedStyle(el).paddingTop) + parseFloat(getComputedStyle(el).paddingBottom);\n target = Math.min(target, maxHeight);\n }\n el.style.height = `${target}px`;\n }, [autoResize, maxRows, textareaRef]);\n\n useEffect(() => { resize(); }, [resize, props.value, props.defaultValue]);\n\n return (\n <textarea\n ref={textareaRef}\n aria-invalid={error || undefined}\n className={cn(\n \"flex min-h-[var(--ds-control-height-md)] w-full px-ds-3 py-ds-2 text-sm\",\n \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)]\",\n error ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)] hover:border-[var(--ds-input-border-hover)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n error ? ERROR_FOCUS_RING : FIELD_FOCUS_RING,\n \"disabled:cursor-not-allowed disabled:opacity-disabled disabled:hover:border-[var(--ds-input-border)]\",\n \"read-only:bg-[var(--ds-bg-muted)] read-only:text-[var(--ds-text-secondary)] read-only:cursor-default read-only:hover:border-[var(--ds-input-border)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n autoResize && \"resize-none overflow-hidden\",\n className\n )}\n onInput={autoResize ? resize : undefined}\n {...props}\n onChange={props.onChange || props.value === undefined ? onChange : undefined}\n />\n );\n}\n\nexport function Label({ className, children, ...props }: LabelHTMLAttributes<HTMLLabelElement>) {\n return (\n <label\n className={cn(\n \"text-sm font-medium leading-none text-[var(--ds-text-secondary)]\",\n \"peer-disabled:cursor-not-allowed peer-disabled:opacity-disabled\",\n className\n )}\n {...props}\n >\n {children}\n </label>\n );\n}\n\nexport type ToggleLayout = \"full\" | \"compact\";\nexport type ToggleSize = \"sm\" | \"md\";\n\n// Track width/height and thumb diameter; the thumb sits 1px inside the border.\nconst TOGGLE_SIZES: Record<ToggleSize, { w: number; h: number; thumb: number }> = {\n sm: { w: 32, h: 18, thumb: 12 },\n md: { w: 44, h: 24, thumb: 16 },\n};\n\nexport function Toggle({ checked, onChange, label, disabled, error = false, layout = \"full\", size = \"md\", \"aria-labelledby\": ariaLabelledBy, ...rest }: { checked: boolean; onChange: (v: boolean) => void; label?: string; disabled?: boolean; error?: boolean; layout?: ToggleLayout; size?: ToggleSize; \"aria-labelledby\"?: string } & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onChange\">) {\n // Sprint 25.12 A15: a flip is a change, reported to the form's overlay\n const change = useReportedChange(onChange, checked);\n const dims = TOGGLE_SIZES[size];\n const travel = dims.w - dims.thumb - 3;\n const switchButton = (\n <button type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={!label && !ariaLabelledBy ? \"Toggle\" : undefined}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={error || undefined}\n disabled={disabled}\n onClick={() => !disabled && change(!checked)}\n {...rest}\n className={cn(\n \"relative inline-flex shrink-0 items-center overflow-hidden\",\n \"border-[length:var(--ds-border-width)]\",\n \"rounded-[var(--ds-radius-full)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n FOCUS_RING,\n disabled ? \"cursor-not-allowed\" : \"cursor-pointer\",\n // Sprint 25.14 A20: on, the checked colour, as a checkbox's; off, the outline in the edge colour (lib/control-looks.ts)\n checked ? SWITCH_TRACK_ON : SWITCH_TRACK_OFF,\n error && \"border-[var(--ds-status-error)]\"\n )}\n style={{ width: dims.w, height: dims.h }}\n >\n <span\n className={cn(\n \"pointer-events-none inline-block shrink-0\",\n // on: the surface made opaque; off: the edge colour, beside the outline\n checked ? SWITCH_KNOB_ON : SWITCH_KNOB_OFF,\n \"border-[length:var(--ds-border-width)] border-transparent\",\n \"rounded-[var(--ds-radius-full)]\",\n SWITCH_KNOB_MOTION\n )}\n style={{\n width: dims.thumb,\n height: dims.thumb,\n transform: checked\n ? `translateX(calc(${travel}px - var(--ds-border-width)))`\n : \"translateX(calc(1px + var(--ds-border-width)))\",\n }}\n />\n </button>\n );\n\n if (!label) {\n return <div className={cn(disabled && \"opacity-disabled\")}>{switchButton}</div>;\n }\n\n return (\n <label\n className={cn(\n layout === \"full\"\n ? \"flex items-center justify-between gap-ds-4\"\n : \"inline-flex items-center gap-ds-3\",\n disabled ? \"cursor-not-allowed opacity-disabled\" : \"cursor-pointer\",\n )}\n >\n <span className=\"text-sm font-medium text-[var(--ds-text-primary)]\">{label}</span>\n {switchButton}\n </label>\n );\n}\n","import { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\n\ninterface InlineFieldErrorProps {\n message: string;\n id: string;\n className?: string;\n}\n\nexport function InlineFieldError({ message, id, className }: InlineFieldErrorProps) {\n return (\n <p\n id={id}\n role=\"alert\"\n className={cn(\n \"flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error-text)]\",\n \"mt-ds-1.5\",\n className\n )}\n >\n {/* the words take the status's words colour (Sprint 30, P10); the icon, a mark, keeps the status colour */}\n <Icon name=\"error\" size={14} className=\"shrink-0 text-[var(--ds-status-error)]\" />\n <span>{message}</span>\n </p>\n );\n}\n","import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, type ReactElement, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { useOptionalFormContext } from \"../lib/form-context\";\nimport { Label } from \"./Input\";\nimport { InlineFieldError } from \"./InlineFieldError\";\n\nexport interface FieldControlProps {\n id: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: true;\n \"aria-required\"?: true;\n required?: boolean;\n /** Set on Gridsmith form components (Input, Textarea, Dropdown, DatePicker, …). */\n error?: boolean;\n}\n\n/**\n * What a control inside a Field knows about it (Sprint 25.7, C5): the label's id, for a control that `<label for>`\n * cannot name (a slider is a div with role=\"slider\") to take it with aria-labelledby, and the hint and error ids.\n */\nexport interface FieldContextValue {\n controlId: string;\n labelId: string;\n describedBy?: string;\n /** The Field shows an error. */\n invalid?: boolean;\n required?: boolean;\n}\n\nconst FieldContext = createContext<FieldContextValue | null>(null);\n\n/** The Field a control sits in, or null. */\nexport function useField(): FieldContextValue | null {\n return useContext(FieldContext);\n}\n\n/**\n * The parts of a control that has several (Sprint 25.19 R2: RecurrencePicker's custom repeat), each with a label of its\n * own: inside, no control takes the Field's id, label, description or error, which name the control's main part only.\n */\nexport function OutsideField({ children }: { children: ReactNode }) {\n return <FieldContext.Provider value={null}>{children}</FieldContext.Provider>;\n}\n\n/** The wiring a control may be given as props: by a Field's clone, or by a page that labels it itself. */\nexport interface FieldControlWiring {\n id?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: boolean | \"true\" | \"false\";\n \"aria-required\"?: boolean | \"true\" | \"false\";\n required?: boolean;\n error?: boolean;\n}\n\n/**\n * What a Gridsmith control that is not a native input takes from the Field it sits in, merged with its own props, which\n * win (round 27 review: Dropdown, DatePicker and SegmentedControl dropped the Field's id and description, so the error\n * summary read \"A field: Needs attention\" with no link, and a screen reader heard the placeholder as the name):\n * - `id`, for the Field's `<label for>`, the summary's link and the focus after a submit;\n * - `labelId`, the label that names it by aria-labelledby, which reaches a button, a group or a radiogroup alike;\n * - `describedBy`, the hint and the error, each id once;\n * - `invalid` and `required`. A role that cannot carry aria-required (a button, a group) says it in its description\n * instead: `requiredNote` is the hidden text, already in `describedBy`, for the control to render.\n * Outside a Field a control gets its own props back.\n */\nexport function useFieldControl(own: FieldControlWiring, options: { requiredInDescription?: boolean } = {}): {\n id?: string;\n labelId?: string;\n describedBy?: string;\n invalid: boolean;\n required: boolean;\n requiredNote: ReactNode;\n} {\n const field = useField();\n const id = own.id ?? field?.controlId;\n const invalid = !!own.error || own[\"aria-invalid\"] === true || own[\"aria-invalid\"] === \"true\" || !!field?.invalid;\n const required = !!own.required || own[\"aria-required\"] === true || own[\"aria-required\"] === \"true\" || !!field?.required;\n const noteId = options.requiredInDescription && required && id ? `${id}-required` : undefined;\n const ids = [own[\"aria-describedby\"], field?.describedBy, noteId].filter(Boolean).join(\" \").split(/\\s+/).filter(Boolean);\n return {\n id,\n labelId: own[\"aria-labelledby\"] ?? field?.labelId,\n describedBy: [...new Set(ids)].join(\" \") || undefined,\n invalid,\n required,\n requiredNote: noteId ? <span id={noteId} hidden>Required</span> : null,\n };\n}\n\n/**\n * A field's label: any text or element, never nothing. Sprint 25.12 A31 (R28-59): run 75 labelled only the first of its\n * repeated rows (`label={index === 0 ? … : undefined}`), and every other row's fields had no name. A label that\n * shouldn't show takes `hideLabel`; repeated rows use AddAnother, which shows each label once.\n */\nexport type FieldLabel = Exclude<ReactNode, null | undefined | boolean>;\n\n/** Set by AddAnother around each row: a hidden label shows again when the group is too narrow for its headings. */\nexport const AddAnotherRowCtx = createContext(false);\n\nexport interface FieldProps {\n label: FieldLabel;\n /**\n * The label is read out but not shown (Sprint 25.12 A31): for a field whose purpose the page shows another way, such\n * as a column heading above repeated rows. In an AddAnother group it shows again when the group stacks its rows.\n */\n hideLabel?: boolean;\n /** The single form control. Receives id, aria-describedby, aria-invalid/error and required automatically. */\n children: ReactElement | ((props: FieldControlProps) => ReactNode);\n /** Persistent help text (format requirements, why a field is disabled). Shown below the control, above any error. */\n hint?: ReactNode;\n /** Current validation error. Rendered as InlineFieldError (role=\"alert\") and linked via aria-describedby. Wins over `validate`. */\n error?: string | null | false;\n /**\n * The field's check: the message for what is wrong with its value, or nothing (`validate={(v) => v ? undefined :\n * \"Enter a title\"}`). It gets the control's `value` (or `checked`); a closure over your own state works as well.\n * Inside a FormWrapper it runs at the project's validation timing (forms.validationTiming, through the form):\n * - `onBlur`: when the field is left;\n * - `onChange`: as the value changes, once the field has been left;\n * - `onSubmit`: on submit only.\n *\n * Whatever the timing, it runs on every submit, and FormWrapper's `onSubmit` gets its message under this Field's\n * `id`, or no key at all when the value passes, so an empty `errors` means the form is valid. A message that shows is\n * checked again as the value changes, so it goes as soon as the value is right. Focus\n * moving into the control's own popup (a Dropdown's list, a DatePicker's calendar) is not leaving the field. Outside\n * a FormWrapper it runs when the field is left (round 26, R26-2).\n */\n validate?: (value: unknown) => string | undefined | null | false;\n required?: boolean;\n /** Slot to the right of the label, e.g. a \"Forgot password?\" Link. */\n labelAction?: ReactNode;\n /** Explicit id for the control; generated when omitted. */\n id?: string;\n className?: string;\n}\n\n/**\n * Label + control + hint + error, wired together. Guarantees the label is\n * associated (htmlFor/id), that hint and error are announced\n * (aria-describedby), that the control is marked invalid, and that the error\n * sits directly below the field (forms-002/006/009/010). Use one Field per\n * control; do not add a separate <Label> or a label prop on the child.\n *\n * In a SettingsLayout panel a Field keeps the narrow page's reading width however wide the page is (the panel's\n * --ds-form-max, Sprint 25.9); a `max-w-*` class of your own wins.\n */\nexport function Field({ label, children, hint, error, required, labelAction, hideLabel = false, id: idProp, validate, className }: FieldProps) {\n const inGroupRow = useContext(AddAnotherRowCtx);\n const generated = useId();\n const id = idProp ?? `field-${generated}`;\n const hintId = `${id}-hint`;\n const errorId = `${id}-error`;\n\n // ── The field's own check (round 26, R26-2) ──\n const form = useOptionalFormContext();\n // outside a form, the only moment a field can check itself is when it is left\n const mode = form?.validationMode ?? \"onBlur\";\n const [localError, setLocalError] = useState<string | undefined>(undefined);\n const [left, setLeft] = useState(false);\n const checkError = validate ? (form ? form.errors[id] : localError) : undefined;\n const child = typeof children === \"function\" ? null : Children.only(children);\n const childProps = child && isValidElement(child) ? (child.props as Record<string, unknown>) : null;\n const latest = useLatest({ validate, childProps, id, mode, left, showing: !!checkError, form });\n const check = useCallback((): string | undefined => {\n const { validate: fn, childProps: props, id: controlId } = latest.current;\n if (!fn) return undefined;\n const value = props && \"value\" in props ? props.value : props && \"checked\" in props ? props.checked : (document.getElementById(controlId) as HTMLInputElement | null)?.value;\n const message = fn(value);\n return typeof message === \"string\" && message.length > 0 ? message : undefined;\n }, [latest]);\n const show = useCallback((message: string | undefined) => {\n const { form: f, id: controlId } = latest.current;\n if (f) f.setError(controlId, message);\n else setLocalError(message);\n }, [latest]);\n // every submit runs the check, whatever the timing\n const register = form?.register;\n const checks = !!validate;\n useEffect(() => (register && checks ? register(id, check) : undefined), [register, checks, id, check]);\n // Left: focus goes out of the field's React tree and doesn't come back straight away. React carries focus events\n // through portals, so moving into the control's own popup comes back in, and cancels the check.\n const leaving = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => () => { if (leaving.current) clearTimeout(leaving.current); }, []);\n const onFocusCapture = () => {\n if (leaving.current) { clearTimeout(leaving.current); leaving.current = null; }\n };\n const onBlurCapture = () => {\n if (!validate) return;\n if (leaving.current) clearTimeout(leaving.current);\n leaving.current = setTimeout(() => {\n leaving.current = null;\n setLeft(true);\n if (latest.current.mode !== \"onSubmit\" || latest.current.showing) show(check());\n }, 0);\n };\n // Changed: checked again once the page has the new value, if the timing is onChange and the field has been left,\n // or if its message shows, so it goes as soon as the value is right\n const recheck = () => {\n if (!validate) return;\n setTimeout(() => {\n const { mode: m, left: wasLeft, showing } = latest.current;\n if ((m === \"onChange\" && wasLeft) || showing) show(check());\n }, 0);\n };\n\n const shownError = typeof error === \"string\" && error.length > 0 ? error : checkError;\n const hasError = typeof shownError === \"string\" && shownError.length > 0;\n const describedBy = [hint ? hintId : null, hasError ? errorId : null].filter(Boolean).join(\" \") || undefined;\n const labelId = `${id}-label`;\n const fieldContext = useMemo<FieldContextValue>(() => ({ controlId: id, labelId, describedBy, invalid: hasError, required: !!required }), [id, labelId, describedBy, hasError, required]);\n\n const controlProps: FieldControlProps = {\n id,\n \"aria-describedby\": describedBy,\n ...(hasError ? { \"aria-invalid\": true as const, error: true } : {}),\n ...(required ? { \"aria-required\": true as const, required: true } : {}),\n };\n\n let control: ReactNode;\n if (typeof children === \"function\") {\n control = children(controlProps);\n } else {\n if (!child || !isValidElement(child)) throw new Error(\"Field expects a single form control as its child\");\n const isNative = typeof child.type === \"string\";\n const { error: errorFlag, ...ariaOnly } = controlProps;\n // with a check, the control's own onChange is kept and the check follows it (a Gridsmith control calls onChange\n // with its value; a native one's input event reaches the wrapper too)\n const ownOnChange = childProps?.onChange as ((...args: unknown[]) => void) | undefined;\n const onChange = validate && !isNative ? { onChange: (...args: unknown[]) => { ownOnChange?.(...args); recheck(); } } : {};\n // Native elements get ARIA only (an unknown `error` attribute would warn);\n // Gridsmith components get `error` so they render their error styling.\n control = cloneElement(child as ReactElement<Record<string, unknown>>, isNative ? ariaOnly : { ...ariaOnly, ...(errorFlag ? { error: true } : {}), ...onChange });\n }\n\n const labelNode = (\n <Label id={labelId} htmlFor={id} className={cn(hideLabel && \"sr-only\", hideLabel && inGroupRow && \"@max-[30rem]:not-sr-only\")}>\n {label}\n {required && <span aria-hidden=\"true\" className=\"ml-ds-0.5 text-[var(--ds-status-error)]\">*</span>}\n </Label>\n );\n\n return (\n // In a settings panel a field keeps the narrow reading width however wide the page is (--ds-form-max, Sprint 25.9 A4)\n <div\n className={cn(\"flex flex-col gap-ds-1.5 max-w-[var(--ds-form-max,none)]\", className)}\n {...(validate ? { onFocusCapture, onBlurCapture, onInputCapture: recheck } : {})}\n >\n {/* A hidden label with no action beside it takes no row of its own, so the field keeps its height (A31); in an\n AddAnother row it shows again once the group stacks its rows and hides its headings. */}\n {hideLabel && !labelAction ? labelNode : (\n <div className=\"flex items-center justify-between gap-ds-2\">\n {labelNode}\n {labelAction}\n </div>\n )}\n <FieldContext.Provider value={fieldContext}>{control}</FieldContext.Provider>\n {hint && (\n <p id={hintId} className=\"text-xs text-[var(--ds-text-muted)]\">{hint}</p>\n )}\n {hasError && <InlineFieldError id={errorId} message={shownError} className=\"mt-0\" />}\n </div>\n );\n}\n","import { cn, ACTIVE_RING, FIELD_FOCUS_RING, ERROR_ACTIVE_RING, ERROR_FOCUS_RING, FOCUS_RING } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { focusAfterRemoval, usePopupFocus } from \"../lib/focus\";\nimport { useInputModality } from \"../lib/input-modality\";\nimport { useRevealFocus } from \"../lib/reveal-focus\";\nimport { AutoTooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useState, useRef, useEffect, useLayoutEffect, useCallback, useContext, useId, type Ref } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { ControlSizeContext } from \"./Button\";\nimport { useFieldControl, type FieldControlWiring } from \"./Field\";\nimport { useReportedChange } from \"../lib/form-context\";\n\ninterface Option {\n id: string;\n label: string;\n group?: string;\n}\n\ntype DropdownSize = \"sm\" | \"md\" | \"lg\";\n\nconst DROPDOWN_HEIGHT: Record<DropdownSize, string> = {\n sm: \"px-ds-2 py-ds-1 text-xs h-[var(--ds-control-height-sm)]\",\n md: \"px-ds-3 py-ds-2 text-sm h-[var(--ds-control-height-md)]\",\n lg: \"px-ds-4 py-ds-3 text-base h-[var(--ds-control-height-lg)]\",\n};\n\ninterface DropdownProps extends FieldControlWiring {\n options: Option[];\n value: string | string[];\n onChange: (value: string | string[]) => void;\n label?: string;\n disabled?: boolean;\n placeholder?: string;\n multiple?: boolean;\n searchable?: boolean;\n size?: DropdownSize;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n container?: Element | DocumentFragment;\n error?: boolean;\n /** When multiple, show removable chips below the trigger. Defaults to true. Set false in toolbar contexts where chips are shown elsewhere. */\n showChips?: boolean;\n /** Accessible name for the trigger, for when there is no visible `label` (e.g. in a toolbar). */\n \"aria-label\"?: string;\n}\n\nexport function Dropdown({\n options,\n value,\n onChange: onChangeProp,\n label,\n disabled,\n placeholder = \"Select...\",\n multiple,\n searchable,\n size: sizeProp,\n className,\n ref,\n container,\n error = false,\n showChips = true,\n \"aria-label\": ariaLabel,\n ...wiring\n}: DropdownProps) {\n // Sprint 25.12 A15: a choice the user makes marks the form's overlay; the list's search box doesn't (its own state)\n const onChange = useReportedChange(onChangeProp, value);\n // A field (Sprint 30, P13): from the keyboard the trigger and the list's search box show the outline; after a pointer\n // press the search box shows the active look, and while the list is open the trigger keeps it (ACTIVE_RING)\n useInputModality();\n const contextSize = useContext(ControlSizeContext);\n // Inside a Field the trigger takes the Field's id, label, hint, error and required state (round 27 review): the label\n // and then the trigger's own text name it, the list-box button pattern's \"Plan, Starter\" (APG collapsible listbox).\n const generatedId = useId();\n const control = useFieldControl({ ...wiring, error: error || undefined }, { requiredInDescription: true });\n const triggerId = control.id ?? generatedId;\n const labelSpanId = `${triggerId}-label`;\n const labelledBy = control.labelId ? `${control.labelId} ${triggerId}` : label && !ariaLabel ? `${labelSpanId} ${triggerId}` : undefined;\n const invalid = control.invalid;\n const size = sizeProp ?? contextSize ?? \"md\";\n const [open, setOpen] = useState(false);\n const [search, setSearch] = useState(\"\");\n const [positioned, setPositioned] = useState(false);\n const triggerRef = useRef<HTMLButtonElement>(null);\n // the arrows' option comes into view whole, with its outline (Sprint 30, P3): the list shows part of one at its foot\n const [listbox, setListbox] = useState<HTMLDivElement | null>(null);\n useRevealFocus(listbox);\n const menuRef = useRef<HTMLDivElement>(null);\n const searchRef = useRef<HTMLInputElement>(null);\n const [pos, setPos] = useState({ top: 0, left: 0, width: 0 });\n\n const selectedValues = Array.isArray(value) ? value : [value].filter(Boolean);\n\n const updatePos = useCallback(() => {\n if (!triggerRef.current) return;\n const rect = triggerRef.current.getBoundingClientRect();\n let top = rect.bottom + 4;\n let left = rect.left;\n const width = rect.width;\n\n if (menuRef.current) {\n const menuRect = menuRef.current.getBoundingClientRect();\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n if (left + menuRect.width > vw) left = Math.max(0, vw - menuRect.width - 8);\n if (top + menuRect.height > vh) {\n const above = rect.top - 4 - menuRect.height;\n if (above >= 0) top = above;\n else top = Math.max(0, vh - menuRect.height - 8);\n }\n }\n\n setPos({ top, left, width });\n }, []);\n\n // Opening clears the search; closing forgets the last position (render-time\n // state adjustment, so the menu never paints with stale values).\n const [prevOpen, setPrevOpen] = useState(open);\n if (open !== prevOpen) {\n setPrevOpen(open);\n if (open) setSearch(\"\");\n else setPositioned(false);\n }\n\n useEffect(() => {\n if (!open) return;\n updatePos();\n const raf = requestAnimationFrame(() => {\n updatePos();\n setPositioned(true);\n });\n const onScroll = () => updatePos();\n window.addEventListener(\"scroll\", onScroll, true);\n window.addEventListener(\"resize\", updatePos);\n return () => {\n cancelAnimationFrame(raf);\n window.removeEventListener(\"scroll\", onScroll, true);\n window.removeEventListener(\"resize\", updatePos);\n };\n }, [open, updatePos]);\n\n // Sprint 25.7: the user moved to an option since the list opened (arrows, Home/End, type-ahead). Tab then picks it (D14(a)).\n const moved = useRef(false);\n\n // Focus moves in once the panel is visible: it opens with visibility hidden until positioned, and a hidden element\n // cannot take focus (focusing it in the same frame used to leave focus on the trigger in real browsers).\n useLayoutEffect(() => {\n if (!open || !positioned) return;\n moved.current = false;\n if (searchRef.current) {\n searchRef.current.focus();\n return;\n }\n const els = Array.from(menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"option\"]') ?? []);\n (els.find((el) => el.getAttribute(\"aria-selected\") === \"true\") ?? els[0])?.focus();\n }, [open, positioned]);\n\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n if (triggerRef.current?.contains(target) || menuRef.current?.contains(target)) return;\n setOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n // Tab while open (D14(a)): a single-select list picks the option the user moved to; opened and left, nothing changes.\n const commitMoved = () => {\n if (multiple || !moved.current) return;\n const el = document.activeElement;\n const id = el instanceof HTMLElement && menuRef.current?.contains(el) ? el.getAttribute(\"data-option-id\") : null;\n if (id) onChange(id);\n };\n // Sprint 25.7: focus hands back on close, and Tab out carries on from the trigger (lib/focus usePopupFocus).\n const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: menuRef, close: () => setOpen(false), tabExits: \"any\", onTabOut: commitMoved });\n\n // Keyboard while open: Escape closes (focus returns to the trigger); arrows,\n // Home/End move focus through the options; typing jumps to the first option\n // starting with those letters (when there is no search box); Enter/Space\n // activate the focused option natively.\n const typeahead = useRef({ buffer: \"\", at: 0 });\n useEffect(() => {\n if (!open) return;\n const optionButtons = () => Array.from(menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"option\"]') ?? []);\n const focusOption = (idx: number) => {\n const els = optionButtons();\n if (els.length === 0) return;\n els[((idx % els.length) + els.length) % els.length].focus();\n moved.current = true;\n };\n const onKey = (e: KeyboardEvent) => {\n const inMenu = menuRef.current?.contains(document.activeElement) || triggerRef.current === document.activeElement;\n if (!inMenu) return;\n const els = optionButtons();\n const current = els.findIndex((el) => el === document.activeElement);\n if (e.key === \"Escape\") { if (e.defaultPrevented || !isTopLayer()) return; e.preventDefault(); returnFocus(); setOpen(false); return; }\n if (e.key === \"ArrowDown\") { e.preventDefault(); focusOption(current < 0 ? 0 : current + 1); return; }\n if (e.key === \"ArrowUp\") { e.preventDefault(); focusOption(current < 0 ? els.length - 1 : current - 1); return; }\n const inSearch = document.activeElement === searchRef.current;\n if (e.key === \"Home\" && !inSearch) { e.preventDefault(); focusOption(0); return; }\n if (e.key === \"End\" && !inSearch) { e.preventDefault(); focusOption(els.length - 1); return; }\n if (!searchable && e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {\n const now = Date.now();\n typeahead.current.buffer = now - typeahead.current.at > 700 ? e.key : typeahead.current.buffer + e.key;\n typeahead.current.at = now;\n const q = typeahead.current.buffer.toLowerCase();\n const hit = els.findIndex((el) => (el.textContent ?? \"\").trim().toLowerCase().startsWith(q));\n if (hit >= 0) { e.preventDefault(); focusOption(hit); }\n }\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, searchable, isTopLayer, returnFocus]);\n\n const filtered = searchable && search\n ? options.filter((o) => o.label.toLowerCase().includes(search.toLowerCase()))\n : options;\n\n const groups = new Map<string, Option[]>();\n for (const opt of filtered) {\n const g = opt.group ?? \"\";\n if (!groups.has(g)) groups.set(g, []);\n groups.get(g)!.push(opt);\n }\n const hasGroups = Array.from(groups.keys()).some((k) => k !== \"\");\n\n const handleSelect = (id: string) => {\n if (multiple) {\n const arr = selectedValues.includes(id)\n ? selectedValues.filter((v) => v !== id)\n : [...selectedValues, id];\n onChange(arr);\n } else {\n // Focus back on the trigger before the consumer runs, so a dialog it opens records the trigger (Sprint 25.7).\n returnFocus();\n onChange(id);\n setOpen(false);\n }\n };\n\n // Removing a chip moves focus to the chip before it, else the one after, else the trigger (D14(c)), once the value\n // no longer holds it. The next render drops the request either way, so a removal the consumer refused never moves\n // focus later.\n const chipsRef = useRef<HTMLDivElement>(null);\n const pendingChipFocus = useRef<{ index: number; value: string } | null>(null);\n useLayoutEffect(() => {\n const pending = pendingChipFocus.current;\n if (pending === null) return;\n pendingChipFocus.current = null;\n if (selectedValues.includes(pending.value)) return;\n const chips = Array.from(chipsRef.current?.querySelectorAll<HTMLElement>(\"[data-chip-remove]\") ?? []);\n focusAfterRemoval(chips, pending.index, triggerRef.current);\n });\n\n const displayLabel = multiple\n ? selectedValues.length > 0\n ? `${selectedValues.length} selected`\n : placeholder\n : options.find((o) => o.id === selectedValues[0])?.label ?? placeholder;\n\n const { ref: overflowRef, isTruncated } = useTextOverflow({ lines: 1, content: displayLabel });\n\n return (\n <div ref={ref} className={cn(\"relative\", className)}>\n {label && (\n <span id={labelSpanId} className=\"block mb-ds-1.5 text-sm font-medium text-[var(--ds-text-secondary)]\">{label}</span>\n )}\n {control.requiredNote}\n <button\n ref={triggerRef}\n id={triggerId}\n type=\"button\"\n onClick={() => !disabled && setOpen(!open)}\n onKeyDown={(e) => {\n if (disabled || open) return;\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") { e.preventDefault(); setOpen(true); }\n }}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-label={labelledBy ? undefined : ariaLabel}\n aria-labelledby={labelledBy}\n aria-describedby={control.describedBy}\n className={cn(\n \"w-full flex items-center justify-between gap-ds-2\",\n DROPDOWN_HEIGHT[size],\n \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)]\",\n invalid ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"transition-colors\",\n !invalid && !disabled && !open && \"hover:border-[var(--ds-input-border-hover)]\",\n open && (invalid ? ERROR_ACTIVE_RING : ACTIVE_RING),\n invalid ? ERROR_FOCUS_RING : FIELD_FOCUS_RING,\n \"cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled\",\n !selectedValues.length && \"text-[var(--ds-text-muted)]\"\n )}\n >\n {isTruncated ? (\n <AutoTooltip content={displayLabel}><span ref={overflowRef} className=\"truncate\">{displayLabel}</span></AutoTooltip>\n ) : (\n <span ref={overflowRef} className=\"truncate\">{displayLabel}</span>\n )}\n <span className={cn(\"transition-transform\", open && \"rotate-180\")}>\n <Icon name=\"chevron-right\" size={14} className=\"rotate-90\" />\n </span>\n </button>\n\n {open && createPortal(\n <div\n ref={menuRef}\n // Safari focuses no button on a mousedown and drops focus to the body; a panel that can take focus keeps it\n // inside the control's React tree, so a Field's leave check never fires mid-choice (round 27 review)\n tabIndex={-1}\n // A choice is the list's own: its click must not also reach a clickable row or card around the Dropdown.\n onClick={(e) => e.stopPropagation()}\n className={cn(\n \"fixed z-[var(--ds-z-popover)] outline-none\",\n \"bg-[var(--ds-bg-surface-elevated)]\",\n \"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"rounded-[var(--ds-radius-md)] overflow-hidden\",\n \"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]\",\n )}\n style={{ top: pos.top, left: pos.left, minWidth: pos.width, width: \"max-content\", maxWidth: \"calc(100vw - 16px)\", visibility: positioned ? \"visible\" : \"hidden\" }}\n >\n {searchable && (\n <div className=\"border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\" style={{ padding: \"var(--ds-space-2)\" }}>\n <input\n ref={searchRef}\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search…\"\n // the list's own search field, its first row: no look of its own (Sprint 30, the owner's decision B)\n data-popup-search=\"\"\n className={cn(\"w-full bg-transparent text-[var(--ds-text-primary)] placeholder:text-[var(--ds-text-muted)] outline-none\", size === \"sm\" ? \"text-xs\" : \"text-sm\")}\n />\n </div>\n )}\n {/* its padding is room for the options' outline, never under its 4 px reach (Sprint 30, P3) */}\n <div ref={setListbox} role=\"listbox\" className=\"overflow-y-auto scroll-p-[4px]\" style={{ padding: \"max(var(--ds-space-1), 4px)\", maxHeight: \"var(--ds-dropdown-max-height)\" }}>\n {filtered.length === 0 ? (\n <p className={cn(\"text-[var(--ds-text-muted)] text-center py-ds-4\", size === \"sm\" ? \"text-xs\" : \"text-sm\")}>No options found</p>\n ) : hasGroups ? (\n Array.from(groups.entries()).map(([group, opts]) => (\n <div key={group}>\n {group && (\n <p className=\"text-2xs font-medium uppercase tracking-wider text-[var(--ds-text-muted)] px-ds-2 pt-ds-2 pb-ds-1\">\n {group}\n </p>\n )}\n {opts.map((opt) => (\n <OptionButton\n key={opt.id}\n opt={opt}\n isSelected={selectedValues.includes(opt.id)}\n multiple={multiple}\n onSelect={handleSelect}\n size={size}\n />\n ))}\n </div>\n ))\n ) : (\n filtered.map((opt) => (\n <OptionButton\n key={opt.id}\n opt={opt}\n isSelected={selectedValues.includes(opt.id)}\n multiple={multiple}\n onSelect={handleSelect}\n size={size}\n />\n ))\n )}\n </div>\n </div>,\n container ?? document.body\n )}\n\n {multiple && showChips && selectedValues.length > 0 && (\n <div ref={chipsRef} className=\"flex flex-wrap gap-ds-1 mt-ds-1.5\">\n {selectedValues.map((v, i) => {\n const opt = options.find((o) => o.id === v);\n return opt ? (\n <span\n key={v}\n className=\"inline-flex items-center gap-ds-1 text-xs rounded-[var(--ds-radius-sm)] bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)] px-ds-1.5 py-ds-0.5\"\n >\n {opt.label}\n <button type=\"button\"\n data-chip-remove=\"\"\n onClick={() => { pendingChipFocus.current = { index: i, value: v }; handleSelect(v); }}\n className={cn(\"hover:text-[var(--ds-text-primary)] cursor-pointer\", FOCUS_RING)}\n aria-label={`Remove ${opt.label}`}\n >\n <Icon name=\"close\" size={10} />\n </button>\n </span>\n ) : null;\n })}\n </div>\n )}\n </div>\n );\n}\n\nfunction OptionButton({\n opt,\n isSelected,\n multiple,\n onSelect,\n size = \"md\",\n}: {\n opt: Option;\n isSelected: boolean;\n multiple?: boolean;\n onSelect: (id: string) => void;\n size?: DropdownSize;\n}) {\n return (\n <button\n type=\"button\"\n role=\"option\"\n data-option-id={opt.id}\n aria-selected={isSelected}\n tabIndex={-1}\n onClick={() => onSelect(opt.id)}\n className={cn(\n \"w-full text-left cursor-pointer rounded-[var(--ds-radius-sm)]\",\n \"transition-colors flex items-center gap-ds-2\",\n // the arrows move DOM focus here, so the option draws the outline; outside it, clear of the chosen one's fill\n FOCUS_RING,\n size === \"sm\" ? \"px-ds-2 py-ds-1 text-xs\" : \"px-ds-2 py-ds-1.5 text-sm\",\n isSelected && !multiple\n ? \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\"\n : \"text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-emphasis)]\"\n )}\n >\n {multiple && (\n <span\n className={cn(\n \"w-[var(--ds-icon-size-sm)] h-[var(--ds-icon-size-sm)] rounded-[var(--ds-radius-sm)] border-[length:var(--ds-border-width)] shrink-0 flex items-center justify-center\",\n isSelected\n ? \"bg-[var(--ds-accent-primary)] border-[var(--ds-accent-primary)]\"\n : \"border-[var(--ds-border-default)]\"\n )}\n >\n {isSelected && <Icon name=\"check\" size={10} className=\"text-[var(--ds-text-on-primary)]\" />}\n </span>\n )}\n <span className=\"flex-1\">{opt.label}</span>\n {isSelected && !multiple && <Icon name=\"check\" size={size === \"sm\" ? 12 : 14} />}\n </button>\n );\n}\n","import { useCallback, useContext, useRef, useState } from \"react\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { cn, FIELD_FOCUS_WITHIN_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_RING } from \"../lib/utils\";\nimport { useInputModality } from \"../lib/input-modality\";\nimport { ControlSizeContext } from \"./Button\";\nimport { useReportedChange } from \"../lib/form-context\";\n\ninterface NumberInputProps {\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n placeholder?: string;\n prefix?: string;\n suffix?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n error?: boolean;\n /** Allow decimal input. Default: true when step is not an integer, false otherwise. */\n allowDecimals?: boolean;\n /** Forwarded to the inner input element so a Label htmlFor can be associated. */\n id?: string;\n}\n\n// The height is the bordered box's (box-sizing: border-box), so the control measures exactly the token beside an\n// Input or a Button; the buttons and the field stretch to it.\nconst sizes = {\n sm: { box: \"h-[var(--ds-control-height-sm)]\", input: \"text-xs self-stretch\", btn: \"w-7 text-xs\" },\n md: { box: \"h-[var(--ds-control-height-md)]\", input: \"text-sm self-stretch\", btn: \"w-9 text-sm\" },\n lg: { box: \"h-[var(--ds-control-height-lg)]\", input: \"text-base self-stretch\", btn: \"w-10 text-base\" },\n};\n\nexport function NumberInput({\n value,\n onChange: onChangeProp,\n min = -Infinity,\n max = Infinity,\n step = 1,\n disabled = false,\n placeholder = \"0\",\n prefix,\n suffix,\n size: sizeProp,\n className,\n error = false,\n allowDecimals,\n id,\n}: NumberInputProps) {\n // Sprint 25.12 A15: a new value the user gives this control marks the form's overlay; the page's onChange runs as given\n const onChange = useReportedChange(onChangeProp, value);\n // a field: clicked into, the active look; reached with Tab, the outline (Sprint 30, lib/input-modality.ts)\n useInputModality();\n const contextSize = useContext(ControlSizeContext);\n const size = sizeProp ?? contextSize ?? \"md\";\n const intervalRef = useRef<ReturnType<typeof setInterval>>(undefined);\n const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n const inputRef = useRef<HTMLInputElement>(null);\n const [focused, setFocused] = useState(false);\n const [draft, setDraft] = useState(String(value));\n\n const decimals = allowDecimals ?? (step % 1 !== 0);\n\n // While not focused the draft mirrors the controlled value; on blur it\n // re-syncs (render-time state adjustment).\n const [prevSync, setPrevSync] = useState({ value, focused });\n if (value !== prevSync.value || focused !== prevSync.focused) {\n setPrevSync({ value, focused });\n if (!focused) setDraft(String(value));\n }\n\n const clamp = useCallback(\n (v: number) => Math.min(max, Math.max(min, v)),\n [min, max],\n );\n\n // Stepping reads the latest committed value through a ref so a held button\n // (setInterval in startRepeat) keeps counting instead of re-adding one step\n // to the value captured at mousedown. useLatest syncs it to the prop in a\n // layout effect (never during render); commitValue advances it in the handler.\n const valueRef = useLatest(value);\n\n // Commit a stepped or blurred value. The draft is updated too: the input\n // shows the draft while focused, and stepping happens while focused (the\n // buttons focus the input), so without this the text never moved and the\n // stale draft was committed back over the new value on blur.\n // `own`: the control settles on a value by itself (a blur with nothing typed falls back to the minimum), which is\n // not the user's change and doesn't mark the form's overlay (Sprint 25.12 A15).\n const commitValue = useCallback((v: number, own = false) => {\n const clamped = clamp(v);\n // Advance the ref now, not on the next render: repeat ticks can land\n // before React re-renders, and each must build on the previous one.\n valueRef.current = clamped;\n setDraft(String(clamped));\n (own ? onChangeProp : onChange)(clamped);\n return clamped;\n }, [onChange, onChangeProp, clamp, valueRef]);\n\n const increment = useCallback(() => commitValue(valueRef.current + step), [commitValue, step, valueRef]);\n const decrement = useCallback(() => commitValue(valueRef.current - step), [commitValue, step, valueRef]);\n\n const startRepeat = useCallback(\n (fn: () => void) => {\n fn();\n timeoutRef.current = setTimeout(() => {\n intervalRef.current = setInterval(fn, 75);\n }, 400);\n },\n [],\n );\n\n const stopRepeat = useCallback(() => {\n clearTimeout(timeoutRef.current);\n clearInterval(intervalRef.current);\n }, []);\n\n const handleInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value;\n\n if (raw === \"\" || raw === \"-\") {\n setDraft(raw);\n return;\n }\n\n if (!decimals && raw.includes(\".\")) return;\n\n const validPattern = decimals ? /^-?\\d*\\.?\\d*$/ : /^-?\\d*$/;\n if (!validPattern.test(raw)) return;\n\n setDraft(raw);\n\n const parsed = parseFloat(raw);\n if (!isNaN(parsed) && isFinite(parsed)) {\n onChange(clamp(parsed));\n }\n },\n [onChange, clamp, decimals],\n );\n\n const handleBlur = useCallback(() => {\n setFocused(false);\n const parsed = parseFloat(draft);\n if (!isNaN(parsed) && isFinite(parsed)) {\n // nothing typed: a value outside min and max clamped on the way through is the control's own (0.21.0)\n const committed = commitValue(parsed, draft === String(value));\n setDraft(String(committed));\n } else {\n const fallback = isFinite(min) ? min : 0;\n const committed = commitValue(value !== undefined ? value : fallback, true);\n setDraft(String(committed));\n }\n }, [draft, commitValue, min, value]);\n\n const handleFocus = useCallback(() => {\n setFocused(true);\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowUp\") { e.preventDefault(); increment(); }\n if (e.key === \"ArrowDown\") { e.preventDefault(); decrement(); }\n },\n [increment, decrement],\n );\n\n const s = sizes[size];\n const atMin = value <= min;\n const atMax = value >= max;\n\n return (\n <div\n className={cn(\n \"flex items-center w-full\",\n s.box,\n \"border-[length:var(--ds-border-width)]\",\n error ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"bg-[var(--ds-input-bg)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n !error && !disabled && \"hover:border-[var(--ds-input-border-hover)]\",\n error ? ERROR_FOCUS_WITHIN_RING : FIELD_FOCUS_WITHIN_RING,\n disabled && \"opacity-disabled cursor-not-allowed\",\n className,\n )}\n >\n <button\n type=\"button\"\n tabIndex={-1}\n disabled={disabled || atMin}\n onMouseDown={(e) => { e.preventDefault(); inputRef.current?.focus(); if (!disabled && !atMin) startRepeat(decrement); }}\n onMouseUp={stopRepeat}\n onMouseLeave={stopRepeat}\n className={cn(\n \"inline-flex items-center justify-center shrink-0\",\n \"border-r-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]\",\n \"transition-colors cursor-pointer\",\n \"rounded-l-[var(--ds-radius-md)]\",\n // kept out of the Tab order (the field's arrows step it) and never focused by a press: the outline all the same\n // if anything focuses it (Sprint 30)\n FOCUS_RING,\n s.btn, s.input,\n (disabled || atMin) && \"opacity-disabled cursor-not-allowed hover:bg-transparent hover:text-[var(--ds-text-muted)]\",\n )}\n aria-label=\"Decrease\"\n >\n −\n </button>\n\n <div className={cn(\"flex items-center flex-1 min-w-0 px-ds-2 gap-ds-1\", s.input)}>\n {prefix && <span className=\"text-[var(--ds-text-muted)] shrink-0 text-xs\">{prefix}</span>}\n <input\n ref={inputRef}\n id={id}\n type=\"text\"\n inputMode={decimals ? \"decimal\" : \"numeric\"}\n aria-invalid={error || undefined}\n value={focused ? draft : String(value)}\n onChange={handleInput}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n placeholder={placeholder}\n className={cn(\n \"w-full min-w-0 bg-transparent text-center outline-none\",\n \"text-[var(--ds-text-primary)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n \"font-[family-name:var(--ds-font-mono)]\",\n s.input,\n disabled && \"cursor-not-allowed\",\n )}\n />\n {suffix && <span className=\"text-[var(--ds-text-muted)] shrink-0 text-xs\">{suffix}</span>}\n </div>\n\n <button\n type=\"button\"\n tabIndex={-1}\n disabled={disabled || atMax}\n onMouseDown={(e) => { e.preventDefault(); inputRef.current?.focus(); if (!disabled && !atMax) startRepeat(increment); }}\n onMouseUp={stopRepeat}\n onMouseLeave={stopRepeat}\n className={cn(\n \"inline-flex items-center justify-center shrink-0\",\n \"border-l-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]\",\n \"transition-colors cursor-pointer\",\n \"rounded-r-[var(--ds-radius-md)]\",\n FOCUS_RING,\n s.btn, s.input,\n (disabled || atMax) && \"opacity-disabled cursor-not-allowed hover:bg-transparent hover:text-[var(--ds-text-muted)]\",\n )}\n aria-label=\"Increase\"\n >\n +\n </button>\n </div>\n );\n}\n","import { useRef, useEffect, type ReactNode, useState, useCallback } from \"react\";\nimport { RowsCtx } from \"../lib/surface-context\";\nimport { createPortal } from \"react-dom\";\nimport { cn, GLASS_DROPDOWN } from \"../lib/utils\";\nimport { Slot } from \"../lib/slot\";\nimport { triggerType } from \"./Button\";\nimport { usePosition, type Side, type Align } from \"../lib/use-position\";\nimport { focusInitial, usePopupFocus, usePressMarks } from \"../lib/focus\";\nimport { useLatest } from \"../lib/use-latest\";\n\ninterface PopoverProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n trigger: ReactNode;\n children: ReactNode;\n side?: Side;\n align?: Align;\n width?: \"trigger\" | \"auto\" | (string & {});\n className?: string;\n container?: Element | DocumentFragment;\n}\n\nexport function Popover({ open, onOpenChange, trigger, children, side = \"bottom\", align = \"center\", width, className, container }: PopoverProps) {\n const triggerRef = useRef<HTMLElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n // Measured in commit-phase code (ref callback, click handler), never read from the ref during render.\n const [triggerWidth, setTriggerWidth] = useState<number | undefined>(undefined);\n const setTriggerNode = useCallback((node: HTMLElement | null) => {\n triggerRef.current = node;\n setTriggerWidth(node?.offsetWidth);\n }, []);\n\n const pos = usePosition(triggerRef, floatingRef, open, { side, align, offset: 8, flip: true });\n // Read from the listeners below, so a new onOpenChange each render never re-registers them (an inner list's Escape\n // listener would then run first, and this popover would see itself on top after the list closed).\n const onOpenChangeRef = useLatest(onOpenChange);\n // A press in a popup the content opens elsewhere in the page (a Dropdown's list) passes through this tree first.\n const { props: pressMarks, marked } = usePressMarks();\n\n // Sprint 25.7: Tab from the panel's last control (or Shift+Tab from its first) closes it and carries on from the\n // trigger; content that closes it (an Apply button) hands focus back through the safety net.\n const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: floatingRef, close: () => onOpenChangeRef.current(false), tabExits: \"edges\", marked });\n\n useEffect(() => {\n if (!open) return;\n\n // Bubble phase on document, after the content's own handlers: content that stops or handles Escape (a draft\n // field going back a step, a list inside closing) keeps the popover open. It acts only with focus in it, or\n // nowhere, so an Escape meant for a field elsewhere never closes it.\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || e.defaultPrevented || !isTopLayer()) return;\n const active = document.activeElement;\n if (active && active !== document.body && !triggerRef.current?.contains(active) && !floatingRef.current?.contains(active)) return;\n e.preventDefault();\n returnFocus();\n onOpenChangeRef.current(false);\n };\n\n // A press outside the popover's React tree closes it, whatever is open inside it (Radix's dismissable layer). A\n // press in a popup opened from it (a Dropdown's list) is inside, so its click lands.\n const onPress = (e: MouseEvent) => {\n const target = e.target as Node;\n if (marked(e) || triggerRef.current?.contains(target) || floatingRef.current?.contains(target)) return;\n onOpenChangeRef.current(false);\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"mousedown\", onPress);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"mousedown\", onPress);\n };\n }, [open, onOpenChangeRef, isTopLayer, returnFocus, marked]);\n\n useEffect(() => {\n if (open) focusInitial(floatingRef.current);\n }, [open]);\n\n return (\n <>\n <Slot\n {...triggerType(trigger)}\n ref={setTriggerNode}\n onClick={() => { setTriggerWidth(triggerRef.current?.offsetWidth); onOpenChange(!open); }}\n >\n {trigger}\n </Slot>\n {open && createPortal(\n <div\n ref={floatingRef}\n data-gs=\"popover\"\n {...pressMarks}\n // Clicks inside are the panel's own, not a click on a row or card the trigger sits in.\n onClick={(e) => e.stopPropagation()}\n className={cn(\n \"fixed z-[var(--ds-z-popover)]\",\n \"bg-[var(--ds-bg-surface-elevated)]\",\n GLASS_DROPDOWN,\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"rounded-[var(--ds-radius-md)]\",\n className\n )}\n style={{\n top: pos.top,\n left: pos.left,\n width: width === \"trigger\" ? triggerWidth : width === \"auto\" ? undefined : width,\n }}\n >\n {/* an overlay's content is no collection's row, wherever it was opened from */}\n <RowsCtx value={false}>{children}</RowsCtx>\n </div>,\n container ?? document.body\n )}\n </>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { cn, FOCUS_RING } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { Dropdown } from \"./Dropdown\";\nimport { Popover } from \"./Popover\";\nimport { NumberInput } from \"./NumberInput\";\nimport { Button } from \"./Button\";\nimport { useShellPreferences } from \"../lib/preferences\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { FormChangeCtx } from \"../lib/form-context\";\nimport { warnOnce } from \"../lib/dev-warn\";\n\ninterface PaginationProps {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n pageSize?: number;\n pageSizeOptions?: number[];\n onPageSizeChange?: (size: number) => void;\n /**\n * How the list shows more (round 22): page numbers, a Load more button, or loading as the user scrolls (with the\n * button kept for keyboard users). `usePagination` passes the project's dataDisplay.paginationStyle here in\n * `pager.props`, so `<Pagination {...pager.props} />` follows the project's style with nothing written on the page.\n */\n mode?: \"pagination\" | \"load-more\" | \"infinite-scroll\";\n /** Rows left to load (load-more and infinite-scroll). */\n hasMore?: boolean;\n /** Load the next rows (load-more and infinite-scroll). */\n onLoadMore?: () => void;\n /** The Load more button's label (default \"Load more\"). */\n loadMoreLabel?: string;\n className?: string;\n /** Set by `usePagination` in `pager.props`: which list the control belongs to (Sprint 25.13 A3). */\n pagerToken?: object;\n}\n\n/** The controls drawn for each pager: a list given the pager draws one, so a <Pagination> of the page's is a second. */\nconst controlsDrawn = new WeakMap<object, number>();\n\nexport function Pagination(props: PaginationProps) {\n const { pagerToken } = props;\n useEffect(() => {\n if (!pagerToken) return;\n const count = (controlsDrawn.get(pagerToken) ?? 0) + 1;\n controlsDrawn.set(pagerToken, count);\n if (count > 1) warnOnce(\"Pagination\", \"this list's pager already draws its control: a list given the pager (<Table pager={pager}>) draws it beneath the rows, so remove the separate <Pagination {...pager.props} />.\");\n return () => { controlsDrawn.set(pagerToken, (controlsDrawn.get(pagerToken) ?? 1) - 1); };\n }, [pagerToken]);\n if ((props.mode === \"load-more\" || props.mode === \"infinite-scroll\") && props.onLoadMore) return <LoadMore {...props} onLoadMore={props.onLoadMore} scroll={props.mode === \"infinite-scroll\"} />;\n return <PageNumbers {...props} />;\n}\n\n/**\n * The box that scrolls the marker into view: the nearest ancestor that scrolls up and down, else the page (null, the\n * viewport). A list in a fixed-height scroller loads more as that scroller moves (Sprint 25.13 A49: the trigger watched\n * the viewport, so scrolling inside the list never loaded more).\n */\nfunction scrollerOf(el: HTMLElement): HTMLElement | null {\n for (let n = el.parentElement; n && n !== document.body && n !== document.documentElement; n = n.parentElement) {\n const { overflowY } = getComputedStyle(n);\n if ((overflowY === \"auto\" || overflowY === \"scroll\") && n.scrollHeight > n.clientHeight) return n;\n }\n return null;\n}\n\n/**\n * An element's top in content coordinates: where it sits in the page, however far anything is scrolled. The window's\n * scroll is the document element's, so the walk stops below it (the review of 23 September: it was counted twice).\n */\nfunction contentTop(el: HTMLElement): number {\n let top = el.getBoundingClientRect().top + window.scrollY;\n for (let n = el.parentElement; n && n !== document.documentElement; n = n.parentElement) top += n.scrollTop;\n return top;\n}\n\n/**\n * Load more, by button or by scrolling (round 22). The scroll trigger is an observed marker above the button: when it\n * comes within 200 px of view the next rows load, and the observer is renewed after each load so a short list keeps\n * filling the window. It loads again only when the last load moved it — the list grew — or the user has scrolled since:\n * a list shown as a loading skeleton does not grow, and a Team page whose table showed one for half a second loaded\n * all 120 rows before its first row appeared. The button stays for keyboard users and for anyone who stops short.\n */\nfunction LoadMore({ hasMore, onLoadMore, loadMoreLabel, currentPage, scroll, className }: PaginationProps & { onLoadMore: () => void; scroll: boolean }) {\n const marker = useRef<HTMLDivElement>(null);\n const load = useLatest(onLoadMore);\n const loadedAt = useRef<number | null>(null);\n useEffect(() => {\n const el = marker.current;\n if (!scroll || !hasMore || !el || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver((entries) => {\n if (!entries.some((e) => e.isIntersecting)) return;\n const at = contentTop(el);\n if (loadedAt.current !== null && Math.abs(at - loadedAt.current) < 1) return;\n loadedAt.current = at;\n load.current();\n }, { root: scrollerOf(el), rootMargin: \"200px 0px\" });\n observer.observe(el);\n const rearm = () => { loadedAt.current = null; };\n window.addEventListener(\"scroll\", rearm, { capture: true, passive: true });\n return () => {\n observer.disconnect();\n window.removeEventListener(\"scroll\", rearm, { capture: true });\n };\n }, [scroll, hasMore, currentPage, load]);\n if (!hasMore) return null;\n return (\n <div data-ds-pager=\"\" data-pagination-mode={scroll ? \"infinite-scroll\" : \"load-more\"} className={cn(\"flex flex-col items-center\", className)}>\n {scroll && <div ref={marker} data-load-more-trigger=\"\" aria-hidden=\"true\" className=\"h-px w-full\" />}\n <Button type=\"button\" variant=\"secondary\" onClick={onLoadMore}>{loadMoreLabel ?? \"Load more\"}</Button>\n </div>\n );\n}\n\nfunction PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }: PaginationProps) {\n const pages = buildPageRange(currentPage, totalPages);\n // Sprint 25.6 (B9): dataDisplay.itemsPerPage reaches the selector through the shell; a prop wins. App code pages its\n // list with usePagination, which reads the same value and passes it here in `pager.props` (round 21).\n const preferences = useShellPreferences();\n const pageSize = pageSizeProp ?? preferences.itemsPerPage;\n // A list that fits on one page shows no page numbers (GOV.UK: \"Do not show pagination if there's only one page of\n // content\"; the review of 30 September found \"‹ 1 ›\" under every short list). A size choice stays, so a user who\n // picked a larger size can pick a smaller one again.\n const sizeChoice = !!(pageSizeOptions && pageSize != null && onPageSizeChange);\n if (totalPages <= 1 && !sizeChoice) return null;\n\n return (\n <nav aria-label=\"Pagination\" data-ds-pager=\"\" className={cn(\"flex flex-wrap items-center gap-ds-3\", className)}>\n {sizeChoice && pageSizeOptions && pageSize != null && onPageSizeChange && (\n <div className=\"flex items-center gap-ds-2\">\n <span className=\"text-sm text-[var(--ds-text-muted)] whitespace-nowrap\">Rows per page</span>\n {/* the page size is how the list is viewed: it never marks an overlay's form (0.21.0) */}\n <FormChangeCtx value={null}>\n {/* named by the visible label, then the size chosen (WCAG 4.1.2, 2.5.3) */}\n <Dropdown\n aria-label={`Rows per page, ${pageSize}`}\n options={pageSizeOptions.map((n) => ({ id: String(n), label: String(n) }))}\n value={String(pageSize)}\n onChange={(v) => onPageSizeChange(Number(v))}\n size=\"sm\"\n className=\"w-[4.5rem]\"\n />\n </FormChangeCtx>\n </div>\n )}\n\n {totalPages > 1 && <div className=\"flex items-center gap-ds-1\">\n <button type=\"button\"\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage <= 1}\n aria-label=\"Previous page\"\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n \"disabled:opacity-disabled disabled:cursor-not-allowed\",\n FOCUS_RING,\n )}\n >\n <Icon name=\"chevron-right\" size={16} className=\"rotate-180\" />\n </button>\n\n {pages.map((p, i) =>\n p === \"...\" ? (\n <EllipsisJumper key={`ellipsis-${i}`} totalPages={totalPages} onPageChange={onPageChange} />\n ) : (\n <button type=\"button\"\n key={p}\n onClick={() => onPageChange(p as number)}\n aria-current={p === currentPage ? \"page\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm font-medium cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n FOCUS_RING,\n p === currentPage\n ? \"bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)] border-[var(--ds-accent-primary)]\"\n : \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\"\n )}\n >\n {p}\n </button>\n )\n )}\n\n <button type=\"button\"\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage >= totalPages}\n aria-label=\"Next page\"\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n \"disabled:opacity-disabled disabled:cursor-not-allowed\",\n FOCUS_RING,\n )}\n >\n <Icon name=\"chevron-right\" size={16} />\n </button>\n </div>}\n </nav>\n );\n}\n\nfunction buildPageRange(current: number, total: number): (number | \"...\")[] {\n if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);\n\n const pages: (number | \"...\")[] = [1];\n\n if (current > 3) pages.push(\"...\");\n\n const start = Math.max(2, current - 1);\n const end = Math.min(total - 1, current + 1);\n for (let i = start; i <= end; i++) pages.push(i);\n\n if (current < total - 2) pages.push(\"...\");\n\n pages.push(total);\n return pages;\n}\n\nfunction EllipsisJumper({ totalPages, onPageChange }: { totalPages: number; onPageChange: (page: number) => void }) {\n const [open, setOpen] = useState(false);\n const [jumpPage, setJumpPage] = useState(1);\n\n const handleOpenChange = (next: boolean) => {\n if (next) setJumpPage(1);\n setOpen(next);\n };\n\n const handleGo = () => {\n const clamped = Math.min(totalPages, Math.max(1, jumpPage));\n onPageChange(clamped);\n setOpen(false);\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={handleOpenChange}\n trigger={\n <button\n type=\"button\"\n aria-label=\"Go to page\"\n onClick={() => handleOpenChange(true)}\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"text-[var(--ds-text-muted)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n FOCUS_RING,\n )}\n >\n …\n </button>\n }\n >\n <div className=\"flex flex-col gap-ds-2 p-ds-3\">\n <label className=\"text-xs font-medium text-[var(--ds-text-secondary)]\">Go to page</label>\n <div className=\"flex items-center gap-ds-2\">\n <NumberInput\n value={jumpPage}\n onChange={setJumpPage}\n min={1}\n max={totalPages}\n step={1}\n size=\"sm\"\n className=\"w-[5rem]\"\n />\n <button\n type=\"button\"\n onClick={handleGo}\n className={cn(\n \"px-ds-2.5 h-[var(--ds-control-height-sm)] text-xs font-medium cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:opacity-90\",\n FOCUS_RING,\n )}\n >\n Go\n </button>\n </div>\n </div>\n </Popover>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { warnOnce } from \"./dev-warn\";\nimport { PREFERENCE_HOUSE_DEFAULTS, useShellPreferences, type PreferencePaginationStyle } from \"./preferences\";\n\n/**\n * A long list in one hook (round 21; all three list styles since round 22). The page size and the list style are the\n * project's `dataDisplay.itemsPerPage` and `dataDisplay.paginationStyle`, read from the shell, so a mid-build\n * `update_rule` on either reaches every list with no page edited. The page gets what to show, the props for\n * `<Pagination>` — page numbers, a Load more button or loading on scroll, whichever the project's style is — and the\n * numbers the count line needs (\"Showing 51–100 of 200 events\", or \"Showing 40 of 120 members\" while a list grows).\n *\n * Run 58 hand-wrote the paging; runs 59 and 60 hand-wrote load-more and scroll loading — an IntersectionObserver, a\n * visible count and a page size copied in as a constant, twice in one app — because the library had no way to.\n *\n * const rows = events.map(toRow)\n * const pager = usePagination(rows)\n * <TableToolbar resultCount={rows.length} resultNoun={[\"event\", \"events\"]} pagination={pager} />\n * <Table columns={columns} data={rows} pager={pager} />\n *\n * The list takes the whole pager (Sprint 25.13 A3): Table, DataGrid, StackedList, Timeline and VirtualizedList draw the\n * pager's part of every row and its control beneath, and a sortable Table sorts every row, not one page. For anything\n * else, draw the page's items and the control yourself: `pager.items.map(…)` then `<Pagination {...pager.props} />`.\n *\n * A long page that must mount only the rows on screen (logs, a feed) still pages: the size the user asked for goes to\n * the hook, with its override note, and the list mounts only what is on screen of each page (A49):\n *\n * // @gridsmith-override dataDisplay.itemsPerPage: <the user's words>\n * const pager = usePagination(entries, { pageSize: 100 })\n * <VirtualizedList items={entries} pager={pager} estimateSize={() => 40} renderItem={(entry) => <LogLine entry={entry} />} />\n */\nexport interface Pager<T> {\n /** The list style this list follows: the project's, unless `style` was passed. */\n style: PreferencePaginationStyle;\n /** What to show: the current page's rows, or every row loaded so far on a list that grows. */\n items: T[];\n /** The current page, from 1; on a growing list, how many pages are loaded. */\n page: number;\n pageSize: number;\n totalItems: number;\n totalPages: number;\n /** The first and last row numbers on screen, from 1 (\"Showing 51–100\"); [0, 0] for an empty list. */\n range: [number, number];\n /** How many rows are on screen. */\n shown: number;\n /** Rows left to show: a next page, or more to load. */\n hasMore: boolean;\n /** The next page, or the next `pageSize` rows on a growing list. */\n loadMore: () => void;\n setPage: (page: number) => void;\n /** A page-size selector's choice; it wins over the project's page size and starts again at page 1. */\n setPageSize: (size: number) => void;\n /**\n * Spread onto <Pagination>: it renders page numbers, a Load more button or the scroll trigger, as `style` says. A list\n * given the whole pager (`<Table pager={pager}>`, Sprint 25.13 A3) draws this control itself.\n */\n props: {\n currentPage: number; totalPages: number; onPageChange: (page: number) => void; pageSize: number; onPageSizeChange: (size: number) => void;\n mode: PreferencePaginationStyle; hasMore: boolean; onLoadMore: () => void;\n /** The page sizes the user may choose between, when the page offers the choice (`pageSizeOptions` below). */\n pageSizeOptions?: number[];\n /** Which pager the control belongs to, so a second control for the same list is caught in development (A3). */\n pagerToken: object;\n };\n}\n\nexport interface PaginationOptions {\n /** A fixed page size for this list, over the project's. Leave it out: the project's page size is the rule. */\n pageSize?: number;\n /** Values that start the list again at page 1 when they change — the sort column and direction, a search query. */\n resetOn?: unknown;\n /**\n * A list style for this list only, over the project's. Leave it out: the project's style is the rule. Passing one that\n * differs is overriding a rule in force — ask the user first, and put `// @gridsmith-override\n * dataDisplay.paginationStyle: <their reason>` above the call.\n */\n style?: PreferencePaginationStyle;\n /**\n * The page sizes the user may choose between, beside the page numbers (`[10, 25, 50]`). The choice goes with the\n * control, so a list given the pager (A3) offers it too. Leave it out for the project's page size alone.\n */\n pageSizeOptions?: number[];\n}\n\n/** What identifies a list's first item across renders: its id, or the value itself; objects without an id are not compared. */\nfunction firstKey(item: unknown): unknown {\n if (item !== null && typeof item === \"object\") return \"id\" in item ? (item as { id: unknown }).id : undefined;\n return item;\n}\n\nfunction resetKey(resetOn: unknown): string {\n try { return JSON.stringify(resetOn ?? null); } catch { return String(resetOn); }\n}\n\nfunction signature(list: readonly unknown[], resetOn: unknown): string {\n let first = \"\";\n try { first = JSON.stringify(firstKey(list[0]) ?? null); } catch { first = \"\"; }\n return `${list.length}|${first}|${resetKey(resetOn)}`;\n}\n\n/** What a list was when last seen: whether a new one is the same list with items added at either end. */\ninterface Seen { sig: string; length: number; first: unknown; reset: string }\n\n/**\n * The same list with items added at its start or its end, and the caller's resetOn unchanged: a live log's new entry,\n * a feed's newest. Its first item, which has an id or is a value, is still first, or has moved down by what was added.\n */\nfunction grewAtAnEnd(seen: Seen, list: readonly unknown[], reset: string): boolean {\n if (reset !== seen.reset || list.length <= seen.length || seen.first === undefined || seen.length === 0) return false;\n return firstKey(list[0]) === seen.first || firstKey(list[list.length - seen.length]) === seen.first;\n}\n\n/**\n * Pages a list in the project's list style (pagination, load more or infinite scroll) and page size, both from the\n * shell. It returns the pager: the rows to show now (`items`), the page and the counts, and the control's state, which a\n * Table, DataGrid, StackedList, Timeline or VirtualizedList takes as its `pager` prop to draw the rows and the control.\n * `resetOn` starts the list again at page 1 when its value changes (a sort, a search); `pageSize` and `style` set this\n * list apart from the project's.\n */\nexport function usePagination<T>(list: readonly T[], options: PaginationOptions = {}): Pager<T> {\n const shell = useShellPreferences();\n const style: PreferencePaginationStyle = options.style ?? shell.paginationStyle ?? PREFERENCE_HOUSE_DEFAULTS.paginationStyle;\n const [chosenSize, setChosenSize] = useState<number | null>(null);\n const [pagerToken] = useState(() => ({}));\n const pageSize = Math.max(1, Math.floor(chosenSize ?? options.pageSize ?? shell.itemsPerPage ?? PREFERENCE_HOUSE_DEFAULTS.itemsPerPage));\n const [page, setPageState] = useState(1);\n\n // A different list — filtered, searched, sorted another way — starts again at page 1: its length, its first item's\n // id or the caller's resetOn values changed. The same list with items added at an end keeps its page, and a growing\n // list its depth (the review of 30 September: a live log's new entry collapsed a list grown to 200 back to 100).\n // Adjusted during render, so the stale page never paints.\n const sig = signature(list, options.resetOn);\n const reset = resetKey(options.resetOn);\n const [seen, setSeen] = useState<Seen>(() => ({ sig, length: list.length, first: firstKey(list[0]), reset }));\n const changed = seen.sig !== sig;\n const startsAgain = changed && !grewAtAnEnd(seen, list, reset);\n if (changed) {\n setSeen({ sig, length: list.length, first: firstKey(list[0]), reset });\n if (startsAgain && page !== 1) setPageState(1);\n }\n\n const totalItems = list.length;\n const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));\n const current = Math.min(Math.max(1, startsAgain ? 1 : page), totalPages);\n const grows = style !== \"pagination\";\n // page numbers show one page; a growing list shows every page loaded so far\n const start = grows ? 0 : (current - 1) * pageSize;\n const items = list.slice(start, current * pageSize);\n const range: [number, number] = items.length === 0 ? [0, 0] : [start + 1, start + items.length];\n const hasMore = current < totalPages;\n const setPage = (next: number) => setPageState(Math.min(Math.max(1, Math.floor(next)), totalPages));\n const loadMore = () => setPageState((p) => Math.min(p + 1, totalPages));\n const setPageSize = (size: number) => { setChosenSize(Math.max(1, Math.floor(size))); setPageState(1); };\n\n return {\n style, items, page: current, pageSize, totalItems, totalPages, range, shown: items.length, hasMore, loadMore, setPage, setPageSize,\n props: { currentPage: current, totalPages, onPageChange: setPage, pageSize, onPageSizeChange: setPageSize, mode: style, hasMore, onLoadMore: loadMore, pagerToken, ...(options.pageSizeOptions ? { pageSizeOptions: options.pageSizeOptions } : {}) },\n };\n}\n\n/**\n * The part of a whole list a pager shows (Sprint 25.13 A3): its page, or every page loaded so far on a list that grows.\n * A list given the pager draws this, then the pager's control.\n */\nexport function pagerPart<T>(list: readonly T[], pager?: Pager<unknown>): T[] {\n if (!pager) return list as T[];\n return pager.range[0] === 0 ? [] : list.slice(pager.range[0] - 1, pager.range[1]);\n}\n\n/** In development, a list handed one page with the pager: it needs every item, since it draws the pager's part itself. */\nexport function useWholeListCheck(component: string, length: number, pager?: Pager<unknown>): void {\n const total = pager?.totalItems;\n useEffect(() => {\n // the same items, either way: more than the pager counts leave the last ones where no page reaches them (the review\n // of 30 September)\n if (total !== undefined && length !== total) warnOnce(component, `the pager counts ${total} items but the list holds ${length}: give the list and usePagination the same items, every item of the list, and the list draws the pager's part (Sprint 25.13 A3).`);\n }, [component, length, total]);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/hydrated.ts","../../../showcase/src/lib/locale.ts","../../../showcase/src/components/Skeleton.tsx","../../../showcase/src/lib/title-text.ts"],"names":[],"mappings":"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","file":"chunk-MFAWJSMJ.js","sourcesContent":["import { useSyncExternalStore } from \"react\";\n\nconst noSubscription = () => () => {};\nconst inBrowser = () => true;\nconst onServer = () => false;\n\n/**\n * Whether the browser has taken the page over (Sprint 25.20 D3): false on a server, and in the render that hydrates the\n * server's HTML (it must draw what the server drew), true straight after. A render with no server HTML (a Vite app, a\n * component mounted later) is true from its first render. What depends on the visitor's clock or time zone, which no\n * server knows, waits for it.\n */\nexport function useHydrated(): boolean {\n return useSyncExternalStore(noSubscription, inBrowser, onServer);\n}\n\n/**\n * Today on the visitor's device, once the browser has the page (null on a server and while hydrating): the day a date\n * grid marks and starts its keyboard on. Read on each render, so a grid drawn again after midnight marks the new day.\n */\nexport function useToday(): Date | null {\n return useHydrated() ? new Date() : null;\n}\n","import { createContext, useContext } from \"react\";\nimport { browserLanguages, formatLocale, localeFor, FIXED_FORM, type LocaleChoice } from \"./format-locale\";\nimport { useHydrated } from \"./hydrated\";\n\n// the choice itself needs no React, so server code can make it too (Sprint 25.22's review: requestLocale, on utils)\nexport { localeChoice, FIXED_FORM, type LocaleChoice } from \"./format-locale\";\n\nexport const LocaleContext = createContext<LocaleChoice | null>(null);\n\n/**\n * The locale a component writes its dates and numbers in (Sprint 25.20 L1). On a server, and while the browser hydrates\n * the server's HTML, the one the server chose: LocaleProvider's (the visitor's form of the page's language, from the\n * request), else \"en\", never a machine's own default, so both sides write the same. Once the page has loaded, the\n * browser's own reading (the visitor's form of the page's `lang`, as formatLocale() reads it), usually the same. A render\n * with no server HTML reads the browser's from its first render. Undefined is the browser's own language.\n */\nexport function useFormatLocale(): string | undefined {\n const choice = useContext(LocaleContext);\n const hydrated = useHydrated();\n if (!hydrated) return choice ? choice.server : FIXED_FORM;\n return choice ? localeFor(choice.lang, browserLanguages()) ?? choice.server : formatLocale();\n}\n","import { cn } from \"../lib/utils\";\n\ninterface SkeletonProps {\n variant?: \"text\" | \"avatar\" | \"card\" | \"table-row\" | \"custom\";\n lines?: number;\n width?: string;\n height?: string;\n className?: string;\n}\n\nfunction Bone({ className, style, \"data-gs\": marker }: { className?: string; style?: React.CSSProperties; \"data-gs\"?: string }) {\n return (\n <div\n data-gs={marker}\n className={cn(\"rounded-[var(--ds-radius-sm)] bg-[var(--ds-bg-emphasis)] animate-pulse\", className)}\n style={style}\n />\n );\n}\n\nexport function Skeleton({ variant = \"text\", lines = 3, width, height, className }: SkeletonProps) {\n if (variant === \"custom\") {\n return <Bone data-gs=\"skeleton\" className={className} style={{ width, height }} />;\n }\n\n if (variant === \"avatar\") {\n return <Bone data-gs=\"skeleton\" className={cn(\"h-10 w-10 rounded-[var(--ds-radius-full)]\", className)} />;\n }\n\n if (variant === \"card\") {\n return (\n <div data-gs=\"skeleton\" className={cn(\"space-y-ds-3\", className)}>\n <Bone className=\"h-32 w-full rounded-[var(--ds-radius-md)]\" />\n <Bone className=\"h-4 w-3/4\" />\n <Bone className=\"h-4 w-1/2\" />\n </div>\n );\n }\n\n if (variant === \"table-row\") {\n return (\n <div data-gs=\"skeleton\" className={cn(\"flex gap-ds-4\", className)}>\n <Bone className=\"h-4 flex-[3]\" />\n <Bone className=\"h-4 flex-[2]\" />\n <Bone className=\"h-4 flex-1\" />\n <Bone className=\"h-4 flex-1\" />\n </div>\n );\n }\n\n // text variant\n const widths = [\"w-3/4\", \"w-1/2\", \"w-5/6\", \"w-2/3\", \"w-4/5\"];\n return (\n <div data-gs=\"skeleton\" className={cn(\"space-y-ds-3\", className)}>\n {Array.from({ length: lines }, (_, i) => (\n <Bone key={i} className={cn(\"h-4\", widths[i % widths.length])} />\n ))}\n </div>\n );\n}\n","/**\n * A title's text classes: CardTitle's, which a titled Table's band and a ChartContainer's title share (Sprint 25.9, A1),\n * one definition so they cannot drift. A word or a name longer than its line breaks at the line's edge (round 27,\n * R27-16: run 70's \"primary-logo-navy.svg\" ran out of its card); break-word, not anywhere, so a title's words still\n * set its minimum and the actions beside it wrap under it before a word is broken (HEADER_LAYOUT.floor).\n */\nexport const TITLE_TEXT = \"font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] break-words\";\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/dev-warn.ts","../../../showcase/src/lib/icon-pack-imports.ts","../../../showcase/src/lib/icons.tsx"],"names":[],"mappings":"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","file":"chunk-MKFWHWBK.js","sourcesContent":["// Bundlers set process.env.NODE_ENV. Where none did (a page with no build step), reading it throws and warnings stay off.\ndeclare const process: { env: { NODE_ENV?: string } };\nconst warned = new Set<string>();\n\n/** A mistake in a component's props, told to the developer once a page, in a development build. */\nexport function warnOnce(component: string, message: string): void {\n let dev = false;\n try {\n dev = process.env.NODE_ENV !== \"production\";\n } catch {\n dev = false;\n }\n const text = `${component}: ${message}`;\n if (!dev || warned.has(text)) return;\n warned.add(text);\n console.warn(text);\n}\n","/**\n * The import each icon pack takes, as an app writes it when it registers its theme's pack (Sprint 25.21 P1:\n * `registerIconPack('feather', () => import('react-icons/fi'))`). One table for the library's warning, the shells\n * `get_app_shell` writes and the engine's fix. Lucide is the library's own: every app installs it, as the fallback.\n * No React here, so the platform reads it as it reads the other showcase modules.\n */\nexport const ICON_PACK_IMPORTS = {\n feather: \"react-icons/fi\",\n heroicons: \"@heroicons/react/24/outline\",\n phosphor: \"@phosphor-icons/react\",\n tabler: \"@tabler/icons-react\",\n} as const;\n\n/** A pack an app registers: every pack but Lucide. */\nexport type RegisteredIconPack = keyof typeof ICON_PACK_IMPORTS;\n\n/** The two lines that register a pack, at the top of an app's shell, before any preloadPack. */\nexport function iconPackRegistration(pack: RegisteredIconPack): { importLine: string; call: string } {\n return {\n importLine: \"import { registerIconPack } from 'gridsmith-ui/icons'\",\n call: `registerIconPack('${pack}', () => import('${ICON_PACK_IMPORTS[pack]}'))`,\n };\n}\n","import { createContext, useContext, useEffect, useSyncExternalStore, type ReactElement, type ReactNode, type ComponentType } from \"react\";\nimport { warnOnce } from \"./dev-warn\";\nimport { iconPackRegistration, type RegisteredIconPack } from \"./icon-pack-imports\";\nimport type { PackLoad } from \"./icon-packs/types\";\n\n/* ── Types ────────────────────────────────────────────────────── */\n\n/**\n * Runtime list of curated icon names. The CuratedIconName type derives from\n * this array, so adding a name here extends autocomplete automatically.\n * Every name must have an alias (or auto-kebab match) in ALL five packs —\n * icon-completeness.test.tsx enforces this.\n */\nexport const CURATED_ICON_NAMES = [\n \"home\", \"folder\", \"chart\", \"settings\",\n \"chevron-right\", \"close\", \"plus\", \"search\",\n \"bell\", \"user\", \"check\", \"warning\", \"info\", \"error\",\n \"clock\", \"calendar\",\n \"bold\", \"italic\", \"underline\", \"strikethrough\",\n \"align-left\", \"align-center\", \"align-right\",\n \"list\", \"list-ordered\", \"list-checks\",\n \"link\", \"image\", \"table\", \"code\", \"quote\", \"minus\",\n \"superscript\", \"subscript\", \"highlight\", \"type\",\n \"chevron-up\", \"chevron-down\", \"chevron-left\", \"trash\",\n \"undo\", \"redo\",\n \"arrow-left\", \"grip-vertical\",\n \"mic\", \"paperclip\", \"send\",\n \"log-out\", \"edit\", \"menu\", \"more-horizontal\",\n \"star\", \"bookmark\", \"download\", \"upload\", \"sparkles\",\n \"file\", \"file-text\", \"eye\", \"eye-off\", \"copy\", \"external-link\", \"filter\", \"lock\",\n \"map-pin\",\n] as const;\n\ntype CuratedIconName = (typeof CURATED_ICON_NAMES)[number];\n\n/**\n * Curated names provide autocomplete and work identically across all 5 packs.\n * Any kebab-case string is also accepted — it resolves directly against the\n * active pack's native exports (e.g. \"clipboard-copy\" → Lucide's ClipboardCopy).\n */\nexport type IconName = CuratedIconName | (string & {});\n\nexport type IconPack = \"lucide\" | \"phosphor\" | \"heroicons\" | \"tabler\" | \"feather\";\n\ntype IconComponent = ComponentType<Record<string, unknown>>;\ntype IconMap = Record<string, IconComponent>;\n\n/* ── External store ──────────────────────────────────────────── */\n\ntype Subscriber = () => void;\nconst subscribers = new Set<Subscriber>();\nfunction notifySubscribers() {\n subscribers.forEach((fn) => fn());\n}\nfunction subscribe(cb: Subscriber): () => void {\n subscribers.add(cb);\n return () => { subscribers.delete(cb); };\n}\n\nconst curatedCache = new Map<IconPack, IconMap>();\nconst extendedCache = new Map<IconPack, IconMap>();\n\nfunction useCuratedMap(pack: IconPack): IconMap | null {\n return useSyncExternalStore(\n subscribe,\n () => curatedCache.get(pack) ?? null,\n () => null,\n );\n}\n\nfunction useExtendedMap(pack: IconPack): IconMap | null {\n return useSyncExternalStore(\n subscribe,\n () => extendedCache.get(pack) ?? null,\n () => null,\n );\n}\n\n/* ── Pack loading ────────────────────────────────────────────────\n Each pack is isolated in its own file under ./icon-packs/, and reads\n its package through an import handed to it: the app's own for its\n theme's pack (registerIconPack, Sprint 25.21 P1), the library's own\n for Lucide. No file the library publishes names a pack the app may\n not have installed, so no bundler looks for one: Next.js's webpack\n resolved every pack the library named, and failed the build.\n\n Loading is two-phase:\n 1. Curated map (50 static named imports) — available as soon as\n the pack chunk loads, cached and notified immediately.\n 2. Extended map (full barrel import + kebab-case iteration) —\n loaded in the background, cached and notified when ready. */\n\nconst loadingPacks = new Set<IconPack>();\nconst failedPacks = new Set<IconPack>();\n\ntype PackModule = {\n loadCurated(load: PackLoad): Promise<IconMap>;\n loadExtended(load: PackLoad): Promise<IconMap>;\n};\n\n/** Each pack's import: Lucide's is the library's own (every app installs it); the others are the app's, registered. */\nconst packImports = new Map<IconPack, PackLoad>([[\"lucide\", () => import(\"lucide-react\")]]);\n\n/**\n * The theme's icon pack, as the app's own import (Sprint 25.21 P1): `registerIconPack('feather', () =>\n * import('react-icons/fi'))` at the top of the shell, before any preloadPack. The library names no pack itself, so an\n * app's bundler only ever meets the pack the app installed. A pack drawn before it is registered draws Lucide's icons,\n * and draws its own once registered. Lucide needs no line.\n */\nexport function registerIconPack(pack: RegisteredIconPack, load: PackLoad): void {\n packImports.set(pack, load);\n // a draw that met the pack unregistered loads it now: its icons redraw once the pack's map arrives (a notice alone\n // changes no snapshot, so nothing would redraw to ask)\n if (failedPacks.delete(pack)) void loadPack(pack);\n}\n\n/** The npm package each pack needs — named in the error when a pack is missing. */\nconst PEER_PACKAGE: Record<IconPack, string> = {\n lucide: \"lucide-react\",\n phosphor: \"@phosphor-icons/react\",\n heroicons: \"@heroicons/react\",\n tabler: \"@tabler/icons-react\",\n feather: \"react-icons\",\n};\n\nasync function loadPack(pack: IconPack): Promise<void> {\n if (curatedCache.has(pack) || loadingPacks.has(pack) || failedPacks.has(pack)) return;\n loadingPacks.add(pack);\n\n // Each pack module reaches its package only through the import handed to it\n // (see icon-packs/*.ts), so the chunk import below always succeeds and it is\n // loadCurated() that rejects when the package is not installed.\n const load = packImports.get(pack);\n if (!load) {\n // not registered: Lucide's icons stand in (Icon's third tier), and the developer is told the line to add\n failedPacks.add(pack);\n loadingPacks.delete(pack);\n const lines = iconPackRegistration(pack as RegisteredIconPack);\n warnOnce(\"IconProvider\", `the ${pack} icon pack isn't registered, so its icons are drawn from Lucide. At the top of the shell, before any preloadPack: ${lines.importLine}; ${lines.call}`);\n return;\n }\n let mod: PackModule;\n let curated: IconMap;\n try {\n switch (pack) {\n case \"lucide\": mod = await import(\"./icon-packs/lucide\"); break;\n case \"phosphor\": mod = await import(\"./icon-packs/phosphor\"); break;\n case \"heroicons\": mod = await import(\"./icon-packs/heroicons\"); break;\n case \"tabler\": mod = await import(\"./icon-packs/tabler\"); break;\n case \"feather\": mod = await import(\"./icon-packs/feather\"); break;\n }\n curated = await mod!.loadCurated(load);\n } catch {\n loadingPacks.delete(pack);\n failedPacks.add(pack);\n console.error(`gridsmith-ui: ${PEER_PACKAGE[pack]} is not installed. Run: npm install ${PEER_PACKAGE[pack]}`);\n return;\n }\n\n curatedCache.set(pack, curated);\n notifySubscribers();\n\n mod!.loadExtended(load).then((extended) => {\n extendedCache.set(pack, extended);\n notifySubscribers();\n }).catch(() => {\n // Extended map failed (e.g. network error loading the full barrel).\n // Curated icons still work; extended names will not resolve.\n });\n}\n\n/** A pack's registered import, for the tests that load the packs directly; they register them first. */\nfunction importOf(pack: IconPack): PackLoad {\n const load = packImports.get(pack);\n if (!load) throw new Error(`gridsmith-ui: register the ${pack} icon pack first (registerIconPack)`);\n return load;\n}\n\n/** Exported for the icon-completeness test — not part of the public API. */\nexport const packLoaders: Record<IconPack, {\n curated: () => Promise<IconMap>;\n extended: () => Promise<IconMap>;\n}> = {\n lucide: { curated: () => import(\"./icon-packs/lucide\").then((m) => m.loadCurated(importOf(\"lucide\"))), extended: () => import(\"./icon-packs/lucide\").then((m) => m.loadExtended(importOf(\"lucide\"))) },\n phosphor: { curated: () => import(\"./icon-packs/phosphor\").then((m) => m.loadCurated(importOf(\"phosphor\"))), extended: () => import(\"./icon-packs/phosphor\").then((m) => m.loadExtended(importOf(\"phosphor\"))) },\n heroicons: { curated: () => import(\"./icon-packs/heroicons\").then((m) => m.loadCurated(importOf(\"heroicons\"))), extended: () => import(\"./icon-packs/heroicons\").then((m) => m.loadExtended(importOf(\"heroicons\"))) },\n tabler: { curated: () => import(\"./icon-packs/tabler\").then((m) => m.loadCurated(importOf(\"tabler\"))), extended: () => import(\"./icon-packs/tabler\").then((m) => m.loadExtended(importOf(\"tabler\"))) },\n feather: { curated: () => import(\"./icon-packs/feather\").then((m) => m.loadCurated(importOf(\"feather\"))), extended: () => import(\"./icon-packs/feather\").then((m) => m.loadExtended(importOf(\"feather\"))) },\n};\n\n/* ── Context ──────────────────────────────────────────────────── */\n\ninterface IconContextValue {\n pack: IconPack;\n weight: number;\n}\n\nconst IconCtx = createContext<IconContextValue>({ pack: \"lucide\", weight: 1.5 });\n\n/**\n * Sets the icon pack and stroke weight for every Icon inside it, and starts loading the pack. The app shell's generated\n * code puts it around the app with the theme's pack, so a page doesn't add its own.\n */\nexport function IconProvider({ pack, weight, children }: { pack: IconPack; weight: number; children: ReactNode }) {\n useEffect(() => {\n loadPack(pack);\n if (pack !== \"lucide\") loadPack(\"lucide\");\n }, [pack]);\n\n return <IconCtx.Provider value={{ pack, weight }}>{children}</IconCtx.Provider>;\n}\n\n/**\n * Start loading a pack's icon chunk before React mounts. Call this in your\n * app's entry point or shell for the fastest possible cold start, after the\n * pack is registered (every pack but Lucide, Sprint 25.21 P1):\n *\n * import { preloadPack, registerIconPack } from 'gridsmith-ui/icons'\n * registerIconPack('feather', () => import('react-icons/fi'))\n * preloadPack('feather')\n */\nexport function preloadPack(pack: IconPack): void {\n loadPack(pack);\n}\n\n/* ── Phosphor weight mapping ──────────────────────────────────── */\n\n/**\n * A stroke weight maps to a stroke weight only. `fill` and `duotone` change the\n * glyph itself (Phosphor's filled Check is a check inside a filled square), so\n * a theme's heaviest stroke must never reach them — the Sprint 22 bench found\n * every tick on a 2.5-weight theme rendered as a filled box (14 Sep 2026).\n */\nexport function getPhosphorWeight(numericWeight: number): \"thin\" | \"light\" | \"regular\" | \"bold\" {\n if (numericWeight <= 0.75) return \"thin\";\n if (numericWeight <= 1.25) return \"light\";\n if (numericWeight <= 1.75) return \"regular\";\n return \"bold\";\n}\n\n/* ── Icon component ───────────────────────────────────────────── */\n\n/**\n * `from`: the component slot that drew the icon (\"Button's iconLeft\"), named in the development warning when the theme's\n * pack has no icon by that name. A name no pack has draws nothing (Sprint 25.17 A26: an arrow or a word passed as an\n * icon was printed as text before slots took names).\n */\n/**\n * Whether a map holds an icon of its own by this name, never one its prototype lends: a slot now takes any string, and\n * \"constructor\", \"toString\" or \"__proto__\" read off a plain object drew junk or threw (Sprint 25.17's review). The icon\n * is then read off the map itself, so the compiler sees a component the map holds, not one made while rendering.\n */\nfunction owns(map: Record<string, IconComponent> | null | undefined, name: string): map is Record<string, IconComponent> {\n return !!map && Object.prototype.hasOwnProperty.call(map, name);\n}\n\n/**\n * An icon by name, drawn from the pack the IconProvider around it sets (the theme's, through the app shell), with Lucide\n * as the fallback when the pack lacks the name; `size` in pixels, 16 by default. A name neither has draws nothing and\n * warns once in development, where `from` names the caller.\n */\nexport function Icon({ name, size = 16, className, from }: { name: IconName; size?: number; className?: string; from?: string }) {\n const { pack, weight } = useContext(IconCtx);\n\n const curatedMap = useCuratedMap(pack);\n const extendedMap = useExtendedMap(pack);\n const lucideCurated = useCuratedMap(\"lucide\");\n const lucideExtended = useExtendedMap(\"lucide\");\n\n // Ensure the active pack is loading (covers cases where Icon mounts\n // before IconProvider's useEffect fires, e.g. during SSR hydration)\n if (!curatedCache.has(pack) && !loadingPacks.has(pack)) {\n loadPack(pack);\n }\n\n let Comp: IconComponent | undefined | null = null;\n let renderPack: IconPack = pack;\n\n // Tier 1: curated map (available once pack chunk has loaded)\n if (owns(curatedMap, name)) {\n Comp = curatedMap[name];\n }\n\n // Tier 2: extended map (available after barrel import completes)\n if (!Comp && owns(extendedMap, name)) {\n Comp = extendedMap[name];\n }\n\n // Tier 3: lucide fallback (curated first, then extended)\n if (!Comp && pack !== \"lucide\") {\n const fallback = owns(lucideCurated, name) ? lucideCurated[name] : owns(lucideExtended, name) ? lucideExtended[name] : undefined;\n if (fallback) {\n Comp = fallback;\n renderPack = \"lucide\";\n }\n }\n\n const allMapsLoaded = !!(curatedMap && extendedMap && (pack === \"lucide\" || (lucideCurated && lucideExtended)));\n const missing = !Comp && allMapsLoaded;\n useEffect(() => {\n if (missing) warnOnce(\"Icon\", `\"${name}\" is not an icon name in the ${pack} pack${pack === \"lucide\" ? \"\" : \" or Lucide\"}, so ${from ?? \"it\"} draws nothing. Pass an icon name, or an element.`);\n }, [missing, name, pack, from]);\n\n if (!Comp) {\n if (allMapsLoaded) return null;\n return <span style={{ display: \"inline-block\", width: size, height: size }} className={className} />;\n }\n\n if (renderPack === \"phosphor\") {\n return <Comp size={size} weight={getPhosphorWeight(weight)} className={className} />;\n }\n\n if (renderPack === \"heroicons\") {\n return <Comp className={className} style={{ width: size, height: size, strokeWidth: weight }} />;\n }\n\n if (renderPack === \"tabler\") {\n return <Comp size={size} stroke={weight} className={className} />;\n }\n\n if (renderPack === \"feather\") {\n return <Comp size={size} className={className} strokeWidth={weight} />;\n }\n\n return <Comp size={size} strokeWidth={weight} className={className} />;\n}\n\n/* ── Icon slots ───────────────────────────────────────────────── */\n\n/**\n * What an icon slot takes (Sprint 25.17 A26): an icon name, drawn as the theme's icon at the slot's size, or an element,\n * drawn as given. `IconName` accepts any string, so text type-checks: in development a name the theme's pack lacks warns,\n * naming the slot, and draws nothing; the engine flags a literal that is no icon name (gs:icon-slot-not-an-icon).\n */\nexport type IconSlot = IconName | ReactElement | false | null | undefined;\n\n/** What an icon slot holds, drawn: a name as the theme's icon at `size`, anything else as given. */\nexport function slotIcon(icon: IconSlot | ReactNode, size: number, from: string): ReactNode {\n if (typeof icon === \"string\") {\n // \"\" is no icon (`saved ? \"check\" : \"\"`): nothing drawn, nothing warned\n if (!icon) return null;\n return ICON_NAME_SHAPE.test(icon) ? <Icon name={icon} size={size} from={from} /> : <NotAnIcon text={icon} from={from} />;\n }\n return icon;\n}\n\n/** The shape of an icon name: kebab case, as every pack's names are written (\"arrow-right\", \"file-text\"). */\nconst ICON_NAME_SHAPE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/**\n * Whether a slot draws something: an element, or a string shaped as an icon name. Text (\"→\", \"Save\") draws nothing, so\n * a button keeps its even padding for it (Sprint 25.17's review); a name the pack lacks still warns, once its maps load.\n */\nexport function slotDraws(icon: IconSlot | ReactNode): boolean {\n if (typeof icon === \"string\") return ICON_NAME_SHAPE.test(icon);\n return icon != null && icon !== false && icon !== true;\n}\n\n/** Text given to an icon slot: it draws nothing, and says so in development, naming the slot. */\nfunction NotAnIcon({ text, from }: { text: string; from: string }) {\n useEffect(() => {\n warnOnce(\"Icon\", `\"${text}\" is not an icon name, so ${from} draws nothing. Words go in the label; pass an icon name, or an element.`);\n }, [text, from]);\n return null;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/element-type.ts","../../../showcase/src/lib/format-locale.ts"],"names":[],"mappings":"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","file":"chunk-OYNUU346.js","sourcesContent":["/**\n * An element's own component, through a lazy reference (Sprint 25.22's fresh-eyes review). A Next.js server component\n * hands each client component among its children on as a React.lazy reference, not as the component, so a check of\n * `element.type` against a component (PageContainer's header, Card's title, EmptyState's icon) missed every one, and a\n * server page drew without its layout: no colourful band, no contained breadcrumbs, a card's badge out of place. The\n * reference is resolved as React resolves one when it renders it: its component once loaded; while it loads, its promise\n * is thrown, so the component reading it suspends until it has it. Anything else is returned as it is.\n */\nconst LAZY = Symbol.for(\"react.lazy\");\n\ninterface LazyReference {\n $$typeof: symbol;\n _payload: unknown;\n _init: (payload: unknown) => unknown;\n}\n\nconst isLazy = (type: unknown): type is LazyReference =>\n type !== null && typeof type === \"object\" && (type as LazyReference).$$typeof === LAZY && typeof (type as LazyReference)._init === \"function\";\n\nexport function elementType(type: unknown): unknown {\n let resolved = type;\n // a reference to a reference resolves in turn; a handful of steps covers any real chain\n for (let step = 0; step < 8 && isLazy(resolved); step++) resolved = resolved._init(resolved._payload);\n return resolved;\n}\n","/** The last page language and visitor's languages read, and the locale they gave: formatting runs often, they change rarely. */\nlet last: { key: string; locale: string | undefined } | null = null;\n\n/**\n * The form a server-rendered page is written in without LocaleProvider, and what the library writes on a server where no\n * locale is given: an explicit locale, the same on every machine and on both sides of hydration (Sprint 25.20 D2).\n */\nexport const FIXED_FORM = \"en\";\n\n/**\n * The locale the library writes dates, times and numbers in: the app's language, the page's `lang`, in the visitor's own\n * formats where they speak it (Sprint 25.17, the owner's decision of 2 October). An English page shows \"5 minutes ago\"\n * and \"250K\" to a visitor whose browser is Japanese, where it showed \"5 分前\" and \"25万\" in a page of English (WCAG 3.1.2:\n * text in the page's language needs no `lang` of its own), and a British visitor to it keeps \"1 Oct 2026\". The visitor's\n * form counts only in the page's script: a page in traditional Chinese stays traditional for a visitor who reads\n * simplified. A page with no `lang` is written in the browser's language, as before. On a server, where there is no page,\n * English (\"en\"), never the machine's own language (Sprint 25.22's review): server code passes requestLocale's choice.\n */\nexport function formatLocale(): string | undefined {\n if (typeof document === \"undefined\") return FIXED_FORM;\n const page = document.documentElement.lang?.trim();\n if (!page) return undefined;\n return localeFor(page, browserLanguages());\n}\n\n/** The browser's languages, in its order (`navigator.languages`), or none where there is no browser. */\nexport function browserLanguages(): readonly string[] {\n if (typeof navigator === \"undefined\") return [];\n return navigator.languages?.length ? navigator.languages : navigator.language ? [navigator.language] : [];\n}\n\n/**\n * The locale for a page language and the languages a visitor speaks, in their order: the visitor's form of the page's\n * language where they speak it, else the page's own (Sprint 25.20: the same choice on a server, from the request's\n * languages, and in the browser). Undefined for a page language Intl can't read.\n */\nexport function localeFor(page: string, spoken: readonly string[]): string | undefined {\n const key = `${page}|${spoken.join(\",\")}`;\n if (last?.key !== key) last = { key, locale: choose(page, spoken) };\n return last.locale;\n}\n\n/** What a server-rendered app hands the library at its top: the page's language, and the visitor's from the request. */\nexport interface LocaleChoice {\n /** The page's language, as `<html lang>` says, or \"en\". */\n lang: string;\n /** The request's languages, in a browser's order; empty without the header. */\n spoken: string[];\n /** Whether the request's header was given. */\n hasHeader: boolean;\n /** The locale the server writes in, and the browser while it hydrates. */\n server: string;\n}\n\n/** What LocaleProvider hands down for a page language and a request's Accept-Language header. */\nexport function localeChoice(lang: string | undefined, acceptLanguage: string | null | undefined): LocaleChoice {\n const page = lang?.trim() || FIXED_FORM;\n const spoken = acceptedLanguages(acceptLanguage);\n return { lang: page, spoken, hasHeader: !!acceptLanguage, server: localeFor(page, spoken) ?? FIXED_FORM };\n}\n\n/**\n * The locale LocaleProvider writes in on the server for a page language and a request's Accept-Language header (Sprint\n * 25.22's review), for server code's own dates and numbers: a server page passes it to the helpers from\n * `gridsmith-ui/utils`, so its words read as the components' beside them. `requestLocale(LANG, (await\n * headers()).get('accept-language'))`.\n */\nexport function requestLocale(lang: string | undefined, acceptLanguage?: string | null): string {\n return localeChoice(lang, acceptLanguage).server;\n}\n\n/** The most of a request's languages read: browsers send a handful. */\nconst MAX_LANGUAGES = 20;\n\n/**\n * A request's `Accept-Language` header as the languages a browser lists (Sprint 25.20 L1): highest quality first, ties in\n * the header's order, \"*\" and anything with q=0 left out. \"en-GB,en;q=0.9,fr;q=0.8\" is [\"en-GB\", \"en\", \"fr\"].\n */\nexport function acceptedLanguages(header: string | null | undefined): string[] {\n if (!header) return [];\n const read: Array<{ tag: string; q: number; at: number }> = [];\n // a browser lists a handful; a header made up to be long reads no further than the first twenty (the review)\n header.split(\",\").slice(0, MAX_LANGUAGES).forEach((part, at) => {\n const [tag, ...params] = part.trim().split(\";\");\n const name = tag?.trim();\n if (!name || name === \"*\") return;\n const qParam = params.map((p) => p.trim()).find((p) => /^q=/i.test(p));\n const q = qParam ? Number(qParam.slice(2)) : 1;\n if (!(q > 0)) return;\n read.push({ tag: name, q, at });\n });\n return read.sort((a, b) => b.q - a.q || a.at - b.at).map((r) => r.tag);\n}\n\n/** The language and script a tag is written in: \"en\" and \"en-GB\" are both \"en-Latn\"; \"zh-TW\" is \"zh-Hant\", \"zh-CN\" \"zh-Hans\". */\nfunction writtenIn(tag: string): string | null {\n try {\n const locale = new Intl.Locale(tag).maximize();\n return `${locale.language}-${locale.script ?? \"\"}`;\n } catch {\n return null;\n }\n}\n\n/**\n * A visitor's tag as its language, script and region (Sprint 25.20's review): a request's header can carry private-use,\n * extension and variant parts (\"en-x-…\", \"en-GB-u-nu-thai\") that would change the digits a server writes and make every\n * cache keyed by locale grow with each new header. Read by syntax alone, so a server and a browser reduce a tag alike.\n */\nfunction plainTag(tag: string): string | undefined {\n try {\n const locale = new Intl.Locale(tag);\n return [locale.language, locale.script, locale.region].filter(Boolean).join(\"-\");\n } catch {\n return undefined;\n }\n}\n\nfunction choose(page: string, spoken: readonly string[]): string | undefined {\n const language = writtenIn(page);\n // a tag Intl can't read: the browser's language\n if (language === null) return undefined;\n // the visitor's own form of the page's language (\"en-GB\" for an \"en\" page), wherever it is in their list; else the page's\n const own = spoken.find((tag) => typeof tag === \"string\" && writtenIn(tag) === language);\n try {\n return Intl.getCanonicalLocales((own && plainTag(own)) || page)[0];\n } catch {\n return undefined;\n }\n}\n"]}
|
package/dist/chunk-QM4SJKWV.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { createContext, createElement, useContext, useLayoutEffect } from 'react';
|
|
3
|
-
|
|
4
|
-
// ../../showcase/src/lib/page-actions.ts
|
|
5
|
-
var PageActionsCtx = createContext(null);
|
|
6
|
-
var CardSurfaceCtx = createContext(false);
|
|
7
|
-
var SplitPaneCtx = createContext(false);
|
|
8
|
-
var TableCardCtx = createContext(false);
|
|
9
|
-
var RowsCtx = createContext(false);
|
|
10
|
-
var SplitListFramerCtx = createContext(null);
|
|
11
|
-
function useReportToList(kind) {
|
|
12
|
-
const report = useContext(SplitListFramerCtx);
|
|
13
|
-
useLayoutEffect(() => {
|
|
14
|
-
if (!report) return;
|
|
15
|
-
report(kind, true);
|
|
16
|
-
return () => report(kind, false);
|
|
17
|
-
}, [report, kind]);
|
|
18
|
-
}
|
|
19
|
-
function useFramesItself() {
|
|
20
|
-
useReportToList("framed");
|
|
21
|
-
}
|
|
22
|
-
function useScrollsInside() {
|
|
23
|
-
useReportToList("scrolls");
|
|
24
|
-
}
|
|
25
|
-
function SurfaceBoundary({ children, pane = false, framer = null }) {
|
|
26
|
-
return createElement(
|
|
27
|
-
CardSurfaceCtx,
|
|
28
|
-
{ value: false },
|
|
29
|
-
createElement(
|
|
30
|
-
SplitPaneCtx,
|
|
31
|
-
{ value: pane },
|
|
32
|
-
createElement(
|
|
33
|
-
TableCardCtx,
|
|
34
|
-
{ value: false },
|
|
35
|
-
createElement(
|
|
36
|
-
RowsCtx,
|
|
37
|
-
{ value: false },
|
|
38
|
-
createElement(
|
|
39
|
-
PageActionsCtx,
|
|
40
|
-
{ value: null },
|
|
41
|
-
createElement(SplitListFramerCtx, { value: framer }, children)
|
|
42
|
-
)
|
|
43
|
-
)
|
|
44
|
-
)
|
|
45
|
-
)
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export { CardSurfaceCtx, PageActionsCtx, RowsCtx, SplitPaneCtx, SurfaceBoundary, TableCardCtx, useFramesItself, useScrollsInside };
|
|
50
|
-
//# sourceMappingURL=chunk-QM4SJKWV.js.map
|
|
51
|
-
//# sourceMappingURL=chunk-QM4SJKWV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/page-actions.ts","../../../showcase/src/lib/surface-context.ts"],"names":["createContext"],"mappings":";;;;AAwBO,IAAM,cAAA,GAAiB,cAAsC,IAAI;AClBjE,IAAM,cAAA,GAAiBA,cAAc,KAAK;AAS1C,IAAM,YAAA,GAAeA,cAA6B,KAAK;AAOvD,IAAM,YAAA,GAAeA,cAAc,KAAK;AAUxC,IAAM,OAAA,GAAUA,cAAc,KAAK;AAWnC,IAAM,kBAAA,GAAqBA,cAAsC,IAAI,CAAA;AAE5E,SAAS,gBAAgB,IAAA,EAA4B;AACnD,EAAA,MAAM,MAAA,GAAS,WAAW,kBAAkB,CAAA;AAC5C,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,MAAA,CAAO,MAAM,IAAI,CAAA;AACjB,IAAA,OAAO,MAAM,MAAA,CAAO,IAAA,EAAM,KAAK,CAAA;AAAA,EACjC,CAAA,EAAG,CAAC,MAAA,EAAQ,IAAI,CAAC,CAAA;AACnB;AAGO,SAAS,eAAA,GAAkB;AAChC,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAC1B;AAGO,SAAS,gBAAA,GAAmB;AACjC,EAAA,eAAA,CAAgB,SAAS,CAAA;AAC3B;AASO,SAAS,gBAAgB,EAAE,QAAA,EAAU,OAAO,KAAA,EAAO,MAAA,GAAS,MAAK,EAAmF;AAGzJ,EAAA,OAAO,aAAA;AAAA,IAAc,cAAA;AAAA,IAAgB,EAAE,OAAO,KAAA,EAAM;AAAA,IAClD,aAAA;AAAA,MAAc,YAAA;AAAA,MAAc,EAAE,OAAO,IAAA,EAAK;AAAA,MACxC,aAAA;AAAA,QAAc,YAAA;AAAA,QAAc,EAAE,OAAO,KAAA,EAAM;AAAA,QACzC,aAAA;AAAA,UAAc,OAAA;AAAA,UAAS,EAAE,OAAO,KAAA,EAAM;AAAA,UACpC,aAAA;AAAA,YAAc,cAAA;AAAA,YAAgB,EAAE,OAAO,IAAA,EAAK;AAAA,YAC1C,cAAc,kBAAA,EAAoB,EAAE,KAAA,EAAO,MAAA,IAAU,QAAQ;AAAA;AAAC;AAAC;AAAC;AAAC,GAAC;AAC9E","file":"chunk-QM4SJKWV.js","sourcesContent":["import { createContext } from \"react\";\nimport type { ControlSize } from \"../components/Button\";\n\n/**\n * Sprint 25.16 A4 (R28-7): the slot in a page's own PageHeader for its actions (PageActions). PageContainer provides it,\n * its header draws it while a page asks, and the page's PageActions render into it. The review of 1 October:\n * - content that starts afresh (an overlay's body, a SplitView's pane: SurfaceBoundary) has no slot, so a header there\n * (a message's own header, a drawer's) never takes the page's actions;\n * - the page's header is the first slot in the page, so a second header that comes and goes hands nothing on;\n * - a container with no header of its own (a page that wraps itself in one under an area layout) passes its page's\n * actions to the container around it;\n * - the actions take the header's control size (a minimal or snapping header draws its own actions small).\n */\nexport interface PageActionsSlot {\n /** A page below asks for the slot: a PageActions is drawn. */\n wanted: boolean;\n /** Where the actions go: the slot of the page's header, at the size its controls are drawn. */\n target: { el: HTMLElement; size: ControlSize | null } | null;\n /** A header's slot, while drawn, with its controls' size; returns its release. */\n register: (el: HTMLElement, size: ControlSize | null) => () => void;\n /** A PageActions asks for the slot while drawn; returns its release. */\n add: () => () => void;\n}\n\nexport const PageActionsCtx = createContext<PageActionsSlot | null>(null);\n","import { createContext, createElement, useContext, useLayoutEffect, type ReactNode } from \"react\";\nimport { PageActionsCtx } from \"./page-actions\";\n\n/**\n * True inside a Card's surface. A StackedList reads it to inset its rows to the card's header (px-ds-5).\n */\nexport const CardSurfaceCtx = createContext(false);\n\n/**\n * The SplitView pane content sits in (\"list\", \"detail\", \"aside\"), false outside one. A StackedList reads it to take its\n * inset from the pane (Sprint 25.4 C-5): rows keep their padding so the selection rail sits at the pane's edge and never\n * touches content. A pane header (SectionHeading variant=\"pane\") in the detail insets at the page's gutter, as the item's\n * path above it does, and in the list at its rows' inset (the owner's review of 1 October).\n */\nexport type SplitPaneKind = false | \"list\" | \"detail\" | \"aside\";\nexport const SplitPaneCtx = createContext<SplitPaneKind>(false);\n\n/**\n * True inside a Table or DataGrid card (the phone layout below mobileBreakpoint). An EntityCell reads it to keep\n * the avatar beside the text and align to the value column (Sprint 25.4, round 7: the stacked cell made the card\n * three lines taller than it needed to be).\n */\nexport const TableCardCtx = createContext(false);\n\n/**\n * True among a collection's rows: a Table's or a DataGrid's rows and their phone cards, a StackedList's rows, a Timeline's\n * items. Something\n * with a Tab stop of its own adds a stop to every row there, which makes the collection hard to cross: a RelativeTime\n * drops its own, its full timestamp in its name and on hover (Sprint 25.17 A29). A DataList is one record's fields, not\n * rows, so it doesn't set it (the second review). Inside a control (a card or a row that is a button, a link) the time\n * finds that for itself, from the page. Overlays reset it: SurfaceBoundary, a Popover, a HoverCard.\n */\nexport const RowsCtx = createContext(false);\n\n/**\n * Sprint 25.14 A44: what a SplitView's list pane holds, as its content reports it while mounted. \"framed\": content that\n * draws its own frame or cards (a KanbanBoard, a CardGrid, a Table, a DataGrid). \"scrolls\": content with no frame of its\n * own that scrolls inside the pane (a StackedList, a Gantt, a VirtualizedList), which the view's hairline frames. The\n * view drops its frame and surface when the pane holds framed content and nothing that scrolls (P32: no frame around\n * what frames itself; a hairline around what scrolls inside). Here, not in SplitView, so a board or a card grid never\n * imports the resizable panels. Null outside a list pane: overlays and the view's other panes reset it (SurfaceBoundary).\n */\nexport type SplitListReport = (kind: \"framed\" | \"scrolls\", present: boolean) => void;\nexport const SplitListFramerCtx = createContext<SplitListReport | null>(null);\n\nfunction useReportToList(kind: \"framed\" | \"scrolls\") {\n const report = useContext(SplitListFramerCtx);\n useLayoutEffect(() => {\n if (!report) return;\n report(kind, true);\n return () => report(kind, false);\n }, [report, kind]);\n}\n\n/** Tell a SplitView whose list pane this sits in that it draws its own frame or cards (A44). */\nexport function useFramesItself() {\n useReportToList(\"framed\");\n}\n\n/** Tell a SplitView whose list pane this sits in that it scrolls inside the pane with no frame of its own (A44). */\nexport function useScrollsInside() {\n useReportToList(\"scrolls\");\n}\n\n/**\n * Where content starts afresh: an overlay's body, an opened table row's panel, a SplitView's pane. What a Card, a pane\n * or a table card told the content around it stops here (the review of 30 September: a StackedList in a Drawer opened\n * from a Card took the card's inset, and one in a Dialog declared in a list pane the pane's, so neither lined up with\n * the overlay's gutter), and so does the page's actions slot. A pane passes `pane` (which pane its content is in) and\n * the list pane its `framer`.\n */\nexport function SurfaceBoundary({ children, pane = false, framer = null }: { children: ReactNode; pane?: SplitPaneKind; framer?: SplitListReport | null }) {\n // the page's actions belong to the page's own header (Sprint 25.16's review): a header in a pane or an overlay never\n // takes them, and PageActions there renders nothing\n return createElement(CardSurfaceCtx, { value: false },\n createElement(SplitPaneCtx, { value: pane },\n createElement(TableCardCtx, { value: false },\n createElement(RowsCtx, { value: false },\n createElement(PageActionsCtx, { value: null },\n createElement(SplitListFramerCtx, { value: framer }, children))))));\n}\n"]}
|