orynn 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/index.cjs +823 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +400 -0
- package/dist/index.d.ts +400 -0
- package/dist/index.js +809 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +201 -0
- package/package.json +82 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/cx.ts","../src/controls/Field/Field.tsx","../src/controls/Dropdown/Dropdown.tsx","../src/controls/Input/Input.tsx","../src/internal/dev.ts","../src/core/registry/registry.ts","../src/layout/resolve-columns.ts","../src/core/config/normalize.ts","../src/core/validation/messages.ts","../src/core/validation/rules.ts","../src/core/validation/resolver.ts","../src/core/state/reducer.ts","../src/core/state/use-latest-ref.ts","../src/core/state/use-controllable-state.ts","../src/core/state/use-fieldset-state.ts","../src/layout/FieldGrid.tsx","../src/fieldset/FieldRenderer.tsx","../src/fieldset/register-builtins.tsx","../src/fieldset/Fieldset.tsx","../src/types/validation.ts"],"names":["useId","jsxs","jsx","forwardRef","Dropdown","useCallback","Input","registry","useRef","useState","useMemo","useReducer","Fragment","memo","defaultRegistry"],"mappings":";;;;;;;;;;;;;AACO,SAAS,MAAM,KAAA,EAAyD;AAC7E,EAAA,OAAO,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AACvC;ACCA,SAAS,WAAW,KAAA,EAA4B;AAC9C,EAAA,IAAI,KAAA,IAAS,IAAA,EAAM,OAAO,EAAC;AAC3B,EAAA,OAAA,CAAQ,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAQ,CAAC,KAAK,CAAA,EAAG,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAA,CAAQ,CAAC,CAAC,CAAA;AACvF;AAEA,SAAS,WAAW,GAAA,EAAoD;AACtE,EAAA,MAAM,OAAO,GAAA,CAAI,MAAA,CAAO,CAAC,EAAA,KAAqB,OAAA,CAAQ,EAAE,CAAC,CAAA;AACzD,EAAA,OAAO,KAAK,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,GAAI,MAAA;AAC5C;AAiBO,SAAS,MAAM,KAAA,EAAmB;AACvC,EAAA,MAAM,EAAE,OAAO,WAAA,EAAa,KAAA,EAAO,UAAU,QAAA,EAAU,SAAA,EAAW,UAAS,GAAI,KAAA;AAE/E,EAAA,MAAM,UAAUA,WAAA,EAAM;AACtB,EAAA,MAAM,EAAA,GAAK,MAAM,EAAA,IAAM,OAAA;AAEvB,EAAA,MAAM,QAAA,GAAW,WAAW,KAAK,CAAA;AACjC,EAAA,MAAM,OAAA,GAAU,SAAS,MAAA,GAAS,CAAA;AAElC,EAAA,MAAM,aAAA,GAAgB,WAAA,IAAe,IAAA,GAAO,CAAA,EAAG,EAAE,CAAA,YAAA,CAAA,GAAiB,MAAA;AAClE,EAAA,MAAM,OAAA,GAAU,OAAA,GAAU,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,GAAW,MAAA;AAC1C,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,aAAA,EAAe,OAAO,CAAA;AAEpD,EAAA,MAAM,MAA0B,EAAE,EAAA,EAAI,aAAA,EAAe,OAAA,EAAS,UAAU,QAAA,EAAS;AAEjF,EAAA,uBACEC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,aAAA,EAAe,SAAS,CAAA;AAAA,MACtC,gBAAc,OAAA,IAAW,MAAA;AAAA,MACzB,iBAAe,QAAA,IAAY,MAAA;AAAA,MAC3B,iBAAe,QAAA,IAAY,MAAA;AAAA,MAE1B,QAAA,EAAA;AAAA,QAAA,KAAA,IAAS,wBACRC,cAAA,CAAC,OAAA,EAAA,EAAM,WAAU,oBAAA,EAAqB,OAAA,EAAS,IAC5C,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,QAGD,WAAA,IAAe,wBACdA,cAAA,CAAC,GAAA,EAAA,EAAE,WAAU,0BAAA,EAA2B,EAAA,EAAI,eACzC,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,wBAGFA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EACZ,QAAA,EAAA,OAAO,aAAa,UAAA,GAAa,QAAA,CAAS,GAAG,CAAA,GAAI,QAAA,EACpD,CAAA;AAAA,QAEC,OAAA,oBACCA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,oBAAA,EAAqB,IAAI,OAAA,EAAS,IAAA,EAAK,OAAA,EACjD,QAAA,EAAA,QAAA,CAAS,MAAA,KAAW,CAAA,GAAI,SAAS,CAAC,CAAA,GAAI,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,oCAAO,MAAA,EAAA,EAAc,QAAA,EAAA,CAAA,EAAA,EAAJ,CAAM,CAAO,CAAA,EACrF;AAAA;AAAA;AAAA,GAEJ;AAEJ;AClEO,IAAM,QAAA,mBAA2BC,gBAAA;AAAA,EACtC,SAASC,SAAAA,CAAS,KAAA,EAAO,GAAA,EAAK;AAC5B,IAAA,MAAM;AAAA,MACJ,KAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,WAAA;AAAA,MACA,EAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,GAAG;AAAA,KACL,GAAI,KAAA;AAEJ,IAAA,MAAM,YAAA,GAAeC,iBAAA;AAAA,MACnB,CAAC,KAAA,KAA0C,QAAA,GAAW,KAAA,CAAM,MAAA,CAAO,OAAO,KAAK,CAAA;AAAA,MAC/E,CAAC,QAAQ;AAAA,KACX;AAEA,IAAA,MAAM,aAAa,KAAA,KAAU,MAAA;AAE7B,IAAA,uBACEH,cAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,KAAA;AAAA,QACA,WAAA;AAAA,QACA,KAAA;AAAA,QACA,QAAA;AAAA,QACA,QAAA;AAAA,QACA,EAAA;AAAA,QACA,SAAA;AAAA,QAEC,WAAC,EAAE,EAAA,EAAI,SAAS,aAAA,EAAe,OAAA,uBAC9BD,eAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACE,GAAG,IAAA;AAAA,YACJ,GAAA;AAAA,YACA,EAAA,EAAI,OAAA;AAAA,YACJ,SAAA,EAAU,gBAAA;AAAA,YACV,QAAA;AAAA,YACA,QAAA;AAAA,YACA,gBAAc,OAAA,IAAW,MAAA;AAAA,YACzB,kBAAA,EAAkB,aAAA;AAAA,YACjB,GAAI,UAAA,GAAa,EAAE,KAAA,KAAU,EAAC;AAAA,YAC/B,QAAA,EAAU,YAAA;AAAA,YACV,MAAA;AAAA,YACA,OAAA;AAAA,YAEC,QAAA,EAAA;AAAA,cAAA,WAAA,IAAe,IAAA,oBACdC,cAAAA,CAAC,QAAA,EAAA,EAAO,OAAM,EAAA,EAAG,QAAA,EAAU,UACxB,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,cAED,QAAQ,GAAA,CAAI,CAAC,MAAA,qBACZA,eAAC,QAAA,EAAA,EAA0B,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,UAAU,MAAA,CAAO,QAAA,EAC9D,iBAAO,KAAA,EAAA,EADG,MAAA,CAAO,KAEpB,CACD;AAAA;AAAA;AAAA;AACH;AAAA,KAEJ;AAAA,EAEJ;AACF;ACjEO,IAAM,wBAAwBC,gBAAAA;AAAA,EACnC,SAASG,MAAAA,CAAM,KAAA,EAAO,GAAA,EAAK;AACzB,IAAA,MAAM;AAAA,MACJ,KAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA,GAAO,MAAA;AAAA,MACP,EAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,GAAG;AAAA,KACL,GAAI,KAAA;AAEJ,IAAA,MAAM,YAAA,GAAeD,iBAAAA;AAAA,MACnB,CAAC,KAAA,KAAyC,QAAA,GAAW,KAAA,CAAM,MAAA,CAAO,OAAO,KAAK,CAAA;AAAA,MAC9E,CAAC,QAAQ;AAAA,KACX;AAEA,IAAA,MAAM,aAAa,KAAA,KAAU,MAAA;AAE7B,IAAA,uBACEH,cAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,KAAA;AAAA,QACA,WAAA;AAAA,QACA,KAAA;AAAA,QACA,QAAA;AAAA,QACA,QAAA;AAAA,QACA,EAAA;AAAA,QACA,SAAA;AAAA,QAEC,WAAC,EAAE,EAAA,EAAI,SAAS,aAAA,EAAe,OAAA,uBAC9BA,cAAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACE,GAAG,IAAA;AAAA,YACJ,GAAA;AAAA,YACA,EAAA,EAAI,OAAA;AAAA,YACJ,SAAA,EAAU,aAAA;AAAA,YACV,IAAA;AAAA,YACA,QAAA;AAAA,YACA,QAAA;AAAA,YACA,QAAA;AAAA,YACA,gBAAc,OAAA,IAAW,MAAA;AAAA,YACzB,kBAAA,EAAkB,aAAA;AAAA,YACjB,GAAI,UAAA,GAAa,EAAE,KAAA,KAAU,EAAC;AAAA,YAC/B,QAAA,EAAU,YAAA;AAAA,YACV,MAAA;AAAA,YACA;AAAA;AAAA;AACF;AAAA,KAEJ;AAAA,EAEJ;AACF;;;AC9DO,IAAM,UACX,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,KAAK,QAAA,KAAa,YAAA;AAGvD,SAAS,SAAA,CAAU,WAAoB,OAAA,EAAoC;AAChF,EAAA,IAAI,SAAA,EAAW;AACf,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,OAAO,CAAA,CAAE,CAAA;AAAA,EACtC;AACF;AAEA,IAAM,MAAA,uBAAa,GAAA,EAAY;AAGxB,SAAS,SAAS,OAAA,EAAuB;AAC9C,EAAA,IAAI,CAAC,OAAA,IAAW,MAAA,CAAO,GAAA,CAAI,OAAO,CAAA,EAAG;AACrC,EAAA,MAAA,CAAO,IAAI,OAAO,CAAA;AAClB,EAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,QAAA,EAAW,OAAO,CAAA,CAAE,CAAA;AACnC;;;ACtBA,IAAA,QAAA;AAGA,IAAM,WAAN,MAAwC;AAAA,EAAxC,WAAA,GAAA;AACE,IAAA,YAAA,CAAA,IAAA,EAAA,QAAA,sBAAe,GAAA,EAA+B,CAAA;AAAA,EAAA;AAAA,EAE9C,QAAA,CAAS,MAAc,YAAA,EAAuC;AAC5D,IAAA,IAAI,OAAA,IAAW,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,IAAI,CAAA,EAAG;AACtC,MAAA,QAAA,CAAS,CAAA,YAAA,EAAe,IAAI,CAAA,8DAAA,CAAgE,CAAA;AAAA,IAC9F;AACA,IAAA,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,IAAA,EAAM,YAAY,CAAA;AAAA,EACtC;AAAA,EAEA,IAAI,IAAA,EAA6C;AAC/C,IAAA,OAAO,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AAAA,EAC/B;AAAA,EAEA,IAAI,IAAA,EAAuB;AACzB,IAAA,OAAO,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AAAA,EAC/B;AAAA,EAEA,KAAA,GAAkB;AAChB,IAAA,OAAO,CAAC,GAAG,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,MAAM,CAAA;AAAA,EACjC;AACF,CAAA;AApBE,QAAA,GAAA,IAAA,OAAA,EAAA;AA8BK,SAAS,cAAA,GAAgC;AAC9C,EAAA,OAAO,IAAI,QAAA,EAAS;AACtB;AAQO,IAAM,kCAAiD,cAAA;AAQvD,SAAS,aAAA,CAAc,MAAc,YAAA,EAAuC;AACjF,EAAA,eAAA,CAAgB,QAAA,CAAS,MAAM,YAAY,CAAA;AAC7C;;;ACnDO,IAAM,kBAA8B,EAAE,OAAA,EAAS,GAAG,MAAA,EAAQ,CAAA,EAAG,QAAQ,CAAA,EAAE;AAE9E,IAAM,aAAa,CAAC,CAAA,EAAY,QAAA,KAC9B,OAAO,MAAM,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,CAAC,KAAK,CAAA,IAAK,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,QAAA;AAGnE,SAAS,eAAe,OAAA,EAA2C;AACxE,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,UAAA,CAAW,OAAA,EAAS,OAAA,EAAS,gBAAgB,OAAO,CAAA;AAAA,IAC7D,MAAA,EAAQ,UAAA,CAAW,OAAA,EAAS,MAAA,EAAQ,gBAAgB,MAAM,CAAA;AAAA,IAC1D,MAAA,EAAQ,UAAA,CAAW,OAAA,EAAS,MAAA,EAAQ,gBAAgB,MAAM;AAAA,GAC5D;AACF;AAGO,SAAS,SAAA,CAAU,MAAe,WAAA,EAA6B;AACpE,EAAA,MAAM,CAAA,GAAI,UAAA,CAAW,IAAA,EAAM,CAAC,CAAA;AAC5B,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,WAAA,EAAa,CAAC,CAAC,CAAA;AAC7C;;;ACNA,SAAS,aAAa,GAAA,EAAgD;AACpE,EAAA,IAAI,GAAA,IAAO,MAAM,OAAO,MAAA;AACxB,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,GAAW,CAAA,EAAG,GAAG,CAAA,EAAA,CAAA,GAAO,GAAA;AAChD;AAUO,SAAS,eAAA,CACd,QACAK,SAAAA,EAC0B;AAC1B,EAAA,SAAA;AAAA,IACE,MAAA,IAAU,QAAQ,OAAO,MAAA,KAAW,YAAY,KAAA,CAAM,OAAA,CAAQ,OAAO,MAAM,CAAA;AAAA,IAC3E;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,KAAA,MAAW,KAAA,IAAS,OAAO,MAAA,EAAQ;AACjC,IAAA,SAAA;AAAA,MACE,KAAA,IAAS,IAAA,IAAQ,OAAO,KAAA,KAAU,QAAA;AAAA,MAClC;AAAA,KACF;AACA,IAAA,SAAA;AAAA,MACE,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,KAAK,MAAA,GAAS,CAAA;AAAA,MACtD;AAAA,KACF;AACA,IAAA,SAAA,CAAU,CAAC,KAAK,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,EAAG,CAAA,sBAAA,EAAyB,KAAA,CAAM,IAAI,CAAA,mBAAA,CAAqB,CAAA;AACzF,IAAA,IAAA,CAAK,GAAA,CAAI,MAAM,IAAI,CAAA;AACnB,IAAA,SAAA;AAAA,MACE,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,KAAK,MAAA,GAAS,CAAA;AAAA,MACtD,CAAA,OAAA,EAAU,MAAM,IAAI,CAAA,sBAAA;AAAA,KACtB;AAEA,IAAA,IAAIA,SAAAA,EAAU;AACZ,MAAA,SAAA;AAAA,QACEA,SAAAA,CAAS,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAAA,QACvB,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,YAAA,EAAe,KAAA,CAAM,IAAI,CAAA,qBAAA,EACnCA,SAAAA,CAAS,KAAA,EAAM,CAAE,IAAA,CAAK,IAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,OAChE;AACA,MAAA,MAAM,YAAYA,SAAAA,CAAS,GAAA,CAAI,MAAM,IAAI,CAAA,EAAG,iBAAiB,KAAK,CAAA;AAClE,MAAA,SAAA,CAAU,SAAA,IAAa,IAAA,EAAM,CAAA,OAAA,EAAU,KAAA,CAAM,IAAI,MAAM,KAAA,CAAM,IAAI,CAAA,GAAA,EAAM,SAAS,CAAA,CAAE,CAAA;AAAA,IACpF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,OAAA,EAAS,cAAA,CAAe,MAAA,CAAO,OAAO,CAAA;AAAA,IACtC,GAAA,EAAK,YAAA,CAAa,MAAA,CAAO,GAAG,CAAA;AAAA,IAC5B,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,IAAI,MAAA,CAAO;AAAA,GACb;AACF;;;ACtEA,IAAM,MAAA,GAAS,CAAC,CAAA,EAAY,IAAA,KAAiB,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,IAAI,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,EAAA,GAAK,GAAG,CAAA,CAAA;AAGvE,IAAM,eAAA,GAAoD;AAAA,EAC/D,UAAU,CAAC,EAAE,KAAA,EAAM,KAAM,GAAG,KAAK,CAAA,YAAA,CAAA;AAAA,EACjC,SAAA,EAAW,CAAC,EAAE,KAAA,EAAO,KAAA,EAAM,KAAM,CAAA,EAAG,KAAK,CAAA,kBAAA,EAAqB,MAAA,CAAO,KAAA,EAAO,WAAW,CAAC,CAAA,CAAA;AAAA,EACxF,SAAA,EAAW,CAAC,EAAE,KAAA,EAAO,KAAA,EAAM,KAAM,CAAA,EAAG,KAAK,CAAA,iBAAA,EAAoB,MAAA,CAAO,KAAA,EAAO,WAAW,CAAC,CAAA;AACzF,CAAA;AAEA,IAAM,cAAA,GAAiB,YAAA;AAShB,SAAS,cAAA,CACd,KAAA,EACA,KAAA,EACA,KAAA,EACA,SAAA,EACQ;AACR,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAClC,EAAA,IAAI,QAAA,IAAY,MAAM,OAAO,QAAA;AAE7B,EAAA,MAAM,SAAA,GAAY,gBAAgB,KAAK,CAAA;AACvC,EAAA,IAAI,SAAA,SAAkB,SAAA,CAAU,EAAE,OAAO,KAAA,EAAO,KAAA,IAAS,gBAAgB,CAAA;AAEzE,EAAA,OAAO,KAAA;AACT;;;AChCA,IAAM,OAAA,GAAU,CAAC,KAAA,KACf,KAAA,IAAS,IAAA,IAAQ,KAAA,KAAU,EAAA,IAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,MAAA,KAAW,CAAA;AAE7E,IAAM,QAAA,GAAW,CAAC,KAAA,KAChB,OAAO,UAAU,QAAA,IAAY,KAAA,CAAM,OAAA,CAAQ,KAAK,IAAI,KAAA,CAAM,MAAA,GAAS,MAAA,CAAO,KAAA,IAAS,EAAE,CAAA,CAAE,MAAA;AAQlF,IAAM,YAAA,GAA2E;AAAA,EACtF,QAAA,EAAU,CAAC,KAAA,EAAO,KAAA,KAAU;AAC1B,IAAA,IAAI,KAAA,KAAU,OAAO,OAAO,IAAA;AAC5B,IAAA,OAAO,OAAA,CAAQ,KAAK,CAAA,GAAI,UAAA,GAAa,IAAA;AAAA,EACvC,CAAA;AAAA,EACA,SAAA,EAAW,CAAC,KAAA,EAAO,KAAA,KAAU;AAC3B,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,OAAA,CAAQ,KAAK,GAAG,OAAO,IAAA;AACxD,IAAA,OAAO,QAAA,CAAS,KAAK,CAAA,GAAI,KAAA,GAAQ,WAAA,GAAc,IAAA;AAAA,EACjD,CAAA;AAAA,EACA,SAAA,EAAW,CAAC,KAAA,EAAO,KAAA,KAAU;AAC3B,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,OAAA,CAAQ,KAAK,GAAG,OAAO,IAAA;AACxD,IAAA,OAAO,QAAA,CAAS,KAAK,CAAA,GAAI,KAAA,GAAQ,WAAA,GAAc,IAAA;AAAA,EACjD;AACF,CAAA;AAEA,IAAM,WAAW,IAAI,GAAA,CAAoB,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAC,CAAA;AAQ9D,SAAS,YAAA,CAAa,MAAc,EAAA,EAAkB;AAC3D,EAAA,QAAA,CAAS,GAAA,CAAI,MAAM,EAAE,CAAA;AACvB;AAEO,SAAS,QAAQ,IAAA,EAAkC;AACxD,EAAA,OAAO,QAAA,CAAS,IAAI,IAAI,CAAA;AAC1B;;;AChBO,SAAS,kBAAA,GAAmC;AACjD,EAAA,OAAO,CAAC,QAAQ,MAAA,KAA6B;AAC3C,IAAA,MAAM,SAA2B,EAAC;AAElC,IAAA,KAAA,MAAW,KAAA,IAAS,OAAO,MAAA,EAAQ;AACjC,MAAA,MAAM,aAAa,KAAA,CAAM,UAAA;AACzB,MAAA,IAAI,CAAC,UAAA,EAAY;AAEjB,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAC/B,MAAA,MAAM,SAAuB,EAAC;AAE9B,MAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,UAAU,CAAA,EAAG;AACzC,QAAA,IAAI,QAAQ,UAAA,EAAY;AAExB,QAAA,MAAM,KAAA,GAAS,WAAuC,GAAG,CAAA;AACzD,QAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,KAAA,EAAO;AAE5C,QAAA,MAAM,IAAA,GAAO,QAAQ,GAAG,CAAA;AACxB,QAAA,IAAI,CAAC,IAAA,EAAM;AACT,UAAA,IAAI,OAAA,EAAS;AACX,YAAA,QAAA,CAAS,CAAA,kCAAA,EAAqC,GAAG,CAAA,UAAA,EAAa,KAAA,CAAM,IAAI,CAAA,GAAA,CAAK,CAAA;AAAA,UAC/E;AACA,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,MAAM,CAAA;AACvC,QAAA,IAAI,SAAS,IAAA,EAAM;AAEnB,QAAA,MAAA,CAAO,IAAA,CAAK;AAAA,UACV,IAAA,EAAM,GAAA;AAAA,UACN,SAAS,cAAA,CAAe,KAAA,EAAO,OAAO,KAAA,CAAM,KAAA,EAAO,WAAW,QAAQ;AAAA,SACvE,CAAA;AAAA,MACH;AAEA,MAAA,IAAI,OAAO,MAAA,GAAS,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,GAAI,MAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAGO,IAAM,kCAAsD,kBAAA;;;ACzD5D,IAAM,WAAA,GAAyB;AAAA,EACpC,SAAS,EAAC;AAAA,EACV,QAAQ,EAAC;AAAA,EACT,UAAA,EAAY,KAAA;AAAA,EACZ,aAAA,EAAe;AACjB,CAAA;AAUO,SAAS,WAAA,CAAY,OAAkB,MAAA,EAA+B;AAC3E,EAAA,QAAQ,OAAO,IAAA;AAAM,IACnB,KAAK,OAAA,EAAS;AACZ,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,GAAG,OAAO,KAAA;AACvC,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,EAAE,GAAG,KAAA,CAAM,OAAA,EAAS,CAAC,MAAA,CAAO,IAAI,GAAG,MAAK,EAAE;AAAA,IACxE;AAAA,IACA,KAAK,UAAA,EAAY;AACf,MAAA,MAAM,OAAA,GAAU,EAAE,GAAG,KAAA,CAAM,OAAA,EAAQ;AACnC,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,EAAO,OAAA,CAAQ,IAAI,CAAA,GAAI,IAAA;AACjD,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAQ;AAAA,IAC7B;AAAA,IACA,KAAK,kBAAA;AACH,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,IAAA,EAAK;AAAA,IACtC,KAAK,kBAAA,EAAoB;AACvB,MAAA,MAAM,MAAA,GAAS,EAAE,GAAG,KAAA,CAAM,MAAA,EAAO;AACjC,MAAA,IAAI,MAAA,CAAO,OAAO,MAAA,GAAS,CAAA,SAAU,MAAA,CAAO,IAAI,IAAI,MAAA,CAAO,MAAA;AAAA,WACtD,OAAO,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAC9B,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,QAAQ,UAAA,EAAY,KAAA,EAAO,eAAe,IAAA,EAAK;AAAA,IACpE;AAAA,IACA,KAAK,gBAAA;AACH,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,OAAO,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,aAAA,EAAe,IAAA,EAAK;AAAA,IACnF,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,GAAG,WAAA,EAAY;AAAA,IAC1B;AACE,MAAA,OAAO,KAAA;AAAA;AAEb;AAGO,SAAS,aAAa,IAAA,EAA8B;AACzD,EAAA,IAAI,IAAA,CAAK,YAAY,OAAO,YAAA;AAC5B,EAAA,IAAI,CAAC,IAAA,CAAK,aAAA,EAAe,OAAO,MAAA;AAChC,EAAA,OAAO,OAAO,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,GAAS,IAAI,SAAA,GAAY,OAAA;AAC3D;AAGO,SAAS,YAAA,CACd,QACA,OAAA,EACyB;AACzB,EAAA,MAAM,QAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AACrC,IAAA,IAAI,CAAC,MAAA,CAAO,EAAA,CAAG,MAAA,CAAO,GAAG,CAAA,EAAG,OAAA,CAAQ,GAAG,CAAC,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,GAAI,IAAA;AAAA,EAC1D;AACA,EAAA,OAAO,KAAA;AACT;ACrEO,SAAS,aAAgB,KAAA,EAAU;AACxC,EAAA,MAAM,GAAA,GAAMC,aAAO,KAAK,CAAA;AACxB,EAAA,GAAA,CAAI,OAAA,GAAU,KAAA;AACd,EAAA,OAAO,GAAA;AACT;;;ACEO,SAAS,oBAAA,CAAwB;AAAA,EACtC,KAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,EAIuD;AACrD,EAAA,MAAM,eAAe,KAAA,KAAU,MAAA;AAC/B,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIC,eAAY,YAAY,CAAA;AAEhE,EAAA,MAAM,OAAA,GAAU,eAAgB,KAAA,GAAc,YAAA;AAC9C,EAAA,MAAM,UAAA,GAAa,aAAa,OAAO,CAAA;AACvC,EAAA,MAAM,WAAA,GAAc,aAAa,QAAQ,CAAA;AACzC,EAAA,MAAM,eAAA,GAAkB,aAAa,YAAY,CAAA;AAEjD,EAAA,MAAM,QAAA,GAAWJ,iBAAAA,CAAY,CAAC,IAAA,KAA+B;AAC3D,IAAA,MAAM,WACJ,OAAO,IAAA,KAAS,aAAc,IAAA,CAAwB,UAAA,CAAW,OAAO,CAAA,GAAI,IAAA;AAC9E,IAAA,IAAI,MAAA,CAAO,EAAA,CAAG,QAAA,EAAU,UAAA,CAAW,OAAO,CAAA,EAAG;AAC7C,IAAA,IAAI,CAAC,eAAA,CAAgB,OAAA,EAAS,eAAA,CAAgB,QAAQ,CAAA;AACtD,IAAA,WAAA,CAAY,UAAU,QAAQ,CAAA;AAAA,EAChC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,CAAC,SAAS,QAAQ,CAAA;AAC3B;;;ACfA,IAAM,SAAA,GAAmC,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AA8CzD,SAAS,oBAAA,CACP,MAAA,EACAE,SAAAA,EACA,QAAA,EACQ;AACR,EAAA,MAAM,MAAc,EAAC;AACrB,EAAA,KAAA,MAAW,KAAA,IAAS,OAAO,MAAA,EAAQ;AACjC,IAAA,IAAI,QAAA,IAAY,OAAO,SAAA,CAAU,cAAA,CAAe,KAAK,QAAA,EAAU,KAAA,CAAM,IAAI,CAAA,EAAG;AAC1E,MAAA,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,GAAI,QAAA,CAAS,MAAM,IAAI,CAAA;AAAA,IACvC,CAAA,MAAA,IAAW,KAAA,CAAM,YAAA,KAAiB,MAAA,EAAW;AAC3C,MAAA,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,GAAI,KAAA,CAAM,YAAA;AAAA,IAC1B,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,GAAIA,SAAAA,EAAU,IAAI,KAAA,CAAM,IAAI,GAAG,YAAA,IAAgB,EAAA;AAAA,IAC/D;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;AAaO,SAAS,gBAAA,CACd,MAAA,EACA,OAAA,GAA4C,EAAC,EACZ;AACjC,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA,kBAAA;AAAA,IACA,QAAA,GAAW,eAAA;AAAA,IACX,QAAA,EAAAA,SAAAA;AAAA,IACA,UAAA,GAAa;AAAA,GACf,GAAI,OAAA;AAEJ,EAAA,MAAM,UAAA,GAAaG,aAAA,CAAQ,MAAM,eAAA,CAAgB,MAAA,EAAQH,SAAQ,CAAA,EAAG,CAAC,MAAA,EAAQA,SAAQ,CAAC,CAAA;AAEtF,EAAA,MAAM,UAAA,GAAaC,aAAsB,IAAI,CAAA;AAC7C,EAAA,IAAI,UAAA,CAAW,YAAY,IAAA,EAAM;AAC/B,IAAA,UAAA,CAAW,OAAA,GAAU,oBAAA;AAAA,MACnB,UAAA;AAAA,MACAD,SAAAA;AAAA,MACC,KAAA,IAAS;AAAA,KACZ;AAAA,EACF;AAEA,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,oBAAA,CAA6B;AAAA,IAC7D,KAAA;AAAA,IACA,cAAc,UAAA,CAAW,OAAA;AAAA,IACzB;AAAA,GACD,CAAA;AAED,EAAA,MAAM,MAAA,GAASG,aAAA,CAAQ,OAAO,EAAE,GAAG,UAAA,CAAW,OAAA,EAAS,GAAG,SAAA,EAAU,CAAA,EAAe,CAAC,SAAS,CAAC,CAAA;AAE9F,EAAA,MAAM,CAAC,IAAA,EAAM,QAAQ,CAAA,GAAIC,gBAAA,CAAW,aAAa,WAAW,CAAA;AAE5D,EAAA,MAAM,SAAA,GAAY,aAAqB,MAAM,CAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,aAAa,QAAQ,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,aAAa,MAAM,CAAA;AACrC,EAAA,MAAM,aAAA,GAAgB,aAAa,UAAU,CAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,aAAaJ,SAAQ,CAAA;AACzC,EAAA,MAAM,aAAA,GAAgB,aAAa,UAAU,CAAA;AAC7C,EAAA,MAAM,qBAAA,GAAwB,aAAa,kBAAkB,CAAA;AAC7D,EAAA,MAAM,QAAA,GAAWC,aAAO,CAAC,CAAA;AAEzB,EAAA,MAAM,aAAA,GAAgBH,iBAAAA,CAAY,OAAO,KAAA,KAA+C;AACtF,IAAA,MAAM,KAAA,GAAQ,EAAE,QAAA,CAAS,OAAA;AACzB,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,IAAU,SAAA,CAAU,OAAA;AACxC,IAAA,QAAA,CAAS,EAAE,IAAA,EAAM,kBAAA,EAAoB,CAAA;AAErC,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,OAAA,CAAQ,KAAA,EAAO,UAAU,OAAA,EAAS;AAAA,MACjE,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,GAAI,MAAM,KAAA,GAAQ,EAAE,cAAc,KAAA,CAAM,KAAA,KAAU;AAAC,KACpD,CAAA;AAED,IAAA,IAAI,KAAA,KAAU,QAAA,CAAS,OAAA,EAAS,OAAO,MAAA;AAEvC,IAAA,IAAI,MAAM,KAAA,EAAO;AACf,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,kBAAA,EAAoB,IAAA,EAAM,KAAA,CAAM,KAAA,EAAO,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA,IAAK,IAAI,CAAA;AAAA,IAC7F,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,gBAAA,EAAkB,MAAA,EAAQ,CAAA;AAC3C,MAAA,qBAAA,CAAsB,UAAU,MAAM,CAAA;AAAA,IACxC;AACA,IAAA,OAAO,MAAA;AAAA,EAET,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgBA,iBAAAA;AAAA,IACpB,CAAC,MAAc,IAAA,KAAkB;AAC/B,MAAA,YAAA,CAAa,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,IAAI,GAAG,IAAA,EAAK,CAAE,CAAA;AAClD,MAAA,IAAI,aAAA,CAAc,YAAY,QAAA,EAAU;AACtC,QAAA,KAAK,aAAA,CAAc;AAAA,UACjB,KAAA,EAAO,IAAA;AAAA,UACP,OAAA,EAAS,QAAA;AAAA,UACT,MAAA,EAAQ,EAAE,GAAG,SAAA,CAAU,SAAS,CAAC,IAAI,GAAG,IAAA;AAAK,SAC9C,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAAA,IACA,CAAC,cAAc,aAAa;AAAA,GAC9B;AAEA,EAAA,MAAM,SAAA,GAAYA,kBAAY,CAAC,IAAA,KAAkB,aAAa,IAAc,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAE7F,EAAA,MAAM,WAAA,GAAcA,iBAAAA;AAAA,IAClB,CAAC,IAAA,KAAiB;AAChB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,CAAA;AAChC,MAAA,IAAI,aAAA,CAAc,YAAY,MAAA,EAAQ;AACpC,QAAA,KAAK,cAAc,EAAE,KAAA,EAAO,IAAA,EAAM,OAAA,EAAS,QAAQ,CAAA;AAAA,MACrD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,QAAA,GAAWA,iBAAAA,CAAY,MAAM,aAAA,CAAc,EAAE,OAAA,EAAS,QAAA,EAAU,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAExF,EAAA,MAAM,YAAA,GAAeA,iBAAAA;AAAA,IACnB,CAAC,OAAA,EAAoC,SAAA,KACnC,OAAO,KAAA,KAAsB;AAC3B,MAAA,KAAA,EAAO,cAAA,IAAiB;AACxB,MAAA,QAAA,CAAS;AAAA,QACP,IAAA,EAAM,UAAA;AAAA,QACN,KAAA,EAAO,cAAc,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,EAAE,IAAI;AAAA,OACtD,CAAA;AACD,MAAA,MAAM,SAAS,MAAM,aAAA,CAAc,EAAE,OAAA,EAAS,UAAU,CAAA;AACxD,MAAA,IAAI,MAAA,CAAO,KAAK,MAAM,CAAA,CAAE,WAAW,CAAA,EAAG,OAAA,CAAQ,UAAU,OAAkB,CAAA;AAAA,uBACzD,MAAM,CAAA;AAAA,IACzB,CAAA;AAAA,IACF,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,KAAA,GAAQA,iBAAAA;AAAA,IACZ,CAAC,IAAA,KAA4B;AAC3B,MAAA,MAAM,KAAA,GAAQ,oBAAA;AAAA,QACZ,aAAA,CAAc,OAAA;AAAA,QACd,WAAA,CAAY,OAAA;AAAA,QACZ;AAAA,OACF;AACA,MAAA,UAAA,CAAW,OAAA,GAAU,KAAA;AACrB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAC1B,MAAA,QAAA,CAAS,OAAA,EAAA;AAAA,IACX,CAAA;AAAA,IACA,CAAC,YAAY;AAAA,GACf;AAGA,EAAA,MAAM,eAAA,GAAkBG,YAAAA;AAAA,wBAClB,GAAA;AAAyE,GAC/E;AACA,EAAA,MAAM,WAAA,GAAcH,iBAAAA;AAAA,IAClB,CAAC,IAAA,KAAiB;AAChB,MAAA,MAAM,QAAQ,eAAA,CAAgB,OAAA;AAC9B,MAAA,IAAI,KAAA,GAAQ,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AAC1B,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,KAAA,GAAQ;AAAA,UACN,QAAA,EAAU,CAAC,CAAA,KAAe,aAAA,CAAc,MAAM,CAAC,CAAA;AAAA,UAC/C,WAAA,EAAa,MAAM,WAAA,CAAY,IAAI;AAAA,SACrC;AACA,QAAA,KAAA,CAAM,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,MACvB;AACA,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,eAAe,WAAW;AAAA,GAC7B;AAEA,EAAA,MAAM,KAAA,GAAQK,aAAA,CAAQ,MAAM,YAAA,CAAa,MAAA,EAAQ,UAAA,CAAW,OAAA,IAAW,EAAE,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACpF,EAAA,MAAM,MAAA,GAAS,aAAa,IAAI,CAAA;AAChC,EAAA,MAAM,UAAU,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,MAAM,EAAE,MAAA,KAAW,CAAA;AAEpD,EAAA,MAAM,aAAA,GAAgBL,iBAAAA;AAAA,IACpB,CAAC,IAAA,KAA6B;AAC5B,MAAA,MAAM,QAAA,GAAW,YAAY,IAAI,CAAA;AACjC,MAAA,OAAO;AAAA,QACL,IAAA;AAAA,QACA,KAAA,EAAQ,OAAkB,IAAI,CAAA;AAAA,QAC9B,MAAA,EAAQ,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,IAAM,SAAA;AAAA,QAC9B,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA,IAAK,KAAA;AAAA,QAC/B,KAAA,EAAO,KAAA,CAAM,IAAI,CAAA,IAAK,KAAA;AAAA,QACtB,UAAU,QAAA,CAAS,QAAA;AAAA,QACnB,aAAa,QAAA,CAAS;AAAA,OACxB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,CAAK,QAAQ,IAAA,CAAK,OAAA,EAAS,OAAO,WAAW;AAAA,GACxD;AAEA,EAAA,MAAM,KAAA,GAAuBK,aAAA;AAAA,IAC3B,OAAO;AAAA,MACL,MAAA;AAAA,MACA,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,KAAA;AAAA,MACA,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb;AAAA,KACF,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,CAAK,SAAS,KAAA,EAAO,IAAA,CAAK,QAAQ,MAAM;AAAA,GACnD;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,UAAA;AAAA,IACR,KAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,KAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF;ACzQO,SAAS,UAAU,EAAE,OAAA,EAAS,GAAA,EAAK,SAAA,EAAW,UAAS,EAAmB;AAC/E,EAAA,MAAM,KAAA,GAAiB;AAAA,IACrB,wBAAwB,OAAA,CAAQ,OAAA;AAAA,IAChC,uBAAuB,OAAA,CAAQ,MAAA;AAAA,IAC/B,uBAAuB,OAAA,CAAQ,MAAA;AAAA,IAC/B,GAAI,GAAA,GAAM,EAAE,kBAAA,EAAoB,GAAA,KAAQ;AAAC,GAC3C;AAEA,EAAA,uBACER,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,YAAA,EAAc,SAAS,CAAA,EAAG,KAAA,EAC3C,0BAAAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mBAAA,EAAqB,UAAS,CAAA,EAC/C,CAAA;AAEJ;AAUO,SAAS,aAAA,CAAc,EAAE,IAAA,EAAM,OAAA,EAAS,UAAS,EAAuB;AAC7E,EAAA,IAAI,CAAC,IAAA,EAAM,uBAAOA,cAAAA,CAAAU,uBAAG,QAAA,EAAS,CAAA;AAE9B,EAAA,MAAM,KAAA,GAAiB;AAAA,IACrB,sBAAA,EAAwB,SAAA,CAAU,IAAA,CAAK,OAAA,EAAS,QAAQ,OAAO,CAAA;AAAA,IAC/D,qBAAA,EAAuB,SAAA,CAAU,IAAA,CAAK,MAAA,EAAQ,QAAQ,MAAM,CAAA;AAAA,IAC5D,qBAAA,EAAuB,SAAA,CAAU,IAAA,CAAK,MAAA,EAAQ,QAAQ,MAAM;AAAA,GAC9D;AAEA,EAAA,uBACEV,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kBAAA,EAAmB,OAC/B,QAAA,EACH,CAAA;AAEJ;ACnDA,IAAM,OAAO,MAAM;AAAC,CAAA;AASpB,SAAS,kBAAkB,EAAE,KAAA,EAAO,UAAAK,SAAAA,EAAU,KAAA,EAAO,UAAS,EAAuB;AACnF,EAAA,MAAM,YAAA,GAAeA,SAAAA,CAAS,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAC5C,EAAA,SAAA;AAAA,IACE,YAAA;AAAA,IACA,CAAA,sCAAA,EAAyC,KAAA,CAAM,IAAI,CAAA,UAAA,EAAa,MAAM,IAAI,CAAA,GAAA;AAAA,GAC5E;AACA,EAAA,IAAI,CAAC,cAAc,OAAO,IAAA;AAE1B,EAAA,MAAM,UAAU,YAAA,CAAa,SAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,UAAA,EAAY,QAAA,KAAa,IAAA;AAChD,EAAA,MAAM,UAAA,GAAa,QAAA,KAAa,IAAA,IAAQ,KAAA,CAAM,QAAA,KAAa,IAAA;AAE3D,EAAA,MAAM,KAAA,GAAQ,aAAa,UAAA,GAAa,YAAA,CAAa,WAAW,KAAA,CAAM,KAAK,IAAI,KAAA,CAAM,KAAA;AAGrF,EAAA,MAAM,WAAW,KAAA,CAAM,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,EAAE,OAAO,CAAA;AAElD,EAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KAAkB;AACtC,IAAA,KAAA,CAAM,SAAS,YAAA,CAAa,WAAA,GAAc,aAAa,WAAA,CAAY,IAAI,IAAI,IAAI,CAAA;AAAA,EACjF,CAAA;AAEA,EAAA,uBACEL,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,KAAA,EAAO,QAAA;AAAA,MACP,QAAA;AAAA,MACA,QAAA,EAAU,UAAA;AAAA,MAET,WAAC,EAAE,EAAA,EAAI,aAAA,EAAe,OAAA,uBACrBA,cAAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA;AAAA,UACA,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,KAAA;AAAA,UACA,QAAA,EAAU,YAAA;AAAA,UACV,QAAQ,KAAA,CAAM,WAAA;AAAA,UACd,OAAA,EAAS,IAAA;AAAA,UACT,QAAA,EAAU,UAAA;AAAA,UACV,QAAA,EAAU,MAAM,QAAA,KAAa,IAAA;AAAA,UAC7B,QAAA;AAAA,UACA,OAAA;AAAA,UACA,aAAA;AAAA,UACA,MAAA,EAAQ;AAAA;AAAA;AACV;AAAA,GAEJ;AAEJ;AAOO,IAAM,aAAA,mBAAgCW,UAAA;AAAA,EAC3C,iBAAA;AAAA,EACA,CAAC,IAAA,EAAM,IAAA,KACL,KAAK,KAAA,KAAU,IAAA,CAAK,SACpB,IAAA,CAAK,QAAA,KAAa,KAAK,QAAA,IACvB,IAAA,CAAK,aAAa,IAAA,CAAK,QAAA,IACvB,KAAK,KAAA,CAAM,KAAA,KAAU,KAAK,KAAA,CAAM,KAAA,IAChC,KAAK,KAAA,CAAM,OAAA,KAAY,KAAK,KAAA,CAAM,OAAA,IAClC,KAAK,KAAA,CAAM,MAAA,KAAW,KAAK,KAAA,CAAM,MAAA,IACjC,KAAK,KAAA,CAAM,QAAA,KAAa,KAAK,KAAA,CAAM,QAAA,IACnC,KAAK,KAAA,CAAM,WAAA,KAAgB,KAAK,KAAA,CAAM;AAC1C,CAAA;AC9EA,IAAM,aAAA,GAAgB,CAAC,KAAA,KACrB,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,KAAA,IAAS,IAAA,GAAO,EAAA,GAAK,MAAA,CAAO,KAAK,CAAA;AAGvE,IAAM,eAAyC,CAAC;AAAA,EAC9C,EAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,KAAA,GAAQ,MAAA;AACd,EAAA,uBACEX,cAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,IAAA;AAAA,MACA,SAAA,EAAU,aAAA;AAAA,MACV,IAAA,EAAM,MAAM,SAAA,IAAa,MAAA;AAAA,MACzB,KAAA,EAAO,cAAc,KAAK,CAAA;AAAA,MAC1B,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,QAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,gBAAc,OAAA,IAAW,MAAA;AAAA,MACzB,kBAAA,EAAkB,aAAA;AAAA,MAClB,UAAU,CAAC,KAAA,KAAU,SAAS,KAAA,CAAM,MAAA,CAAO,OAAO,KAAK,CAAA;AAAA,MACvD,MAAA;AAAA,MACA,OAAA;AAAA,MACC,GAAG,KAAA,CAAM;AAAA;AAAA,GACZ;AAEJ,CAAA;AAGA,IAAM,kBAA4C,CAAC;AAAA,EACjD,EAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,KAAA,GAAQ,MAAA;AACd,EAAA,uBACED,eAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,IAAA;AAAA,MACA,SAAA,EAAU,gBAAA;AAAA,MACV,KAAA,EAAO,cAAc,KAAK,CAAA;AAAA,MAC1B,QAAA;AAAA,MACA,QAAA;AAAA,MACA,gBAAc,OAAA,IAAW,MAAA;AAAA,MACzB,kBAAA,EAAkB,aAAA;AAAA,MAClB,UAAU,CAAC,KAAA,KAAU,SAAS,KAAA,CAAM,MAAA,CAAO,OAAO,KAAK,CAAA;AAAA,MACvD,MAAA;AAAA,MACA,OAAA;AAAA,MACC,GAAG,KAAA,CAAM,KAAA;AAAA,MAET,QAAA,EAAA;AAAA,QAAA,KAAA,CAAM,WAAA,IAAe,IAAA,oBACpBC,cAAAA,CAAC,QAAA,EAAA,EAAO,OAAM,EAAA,EAAG,QAAA,EAAU,QAAA,EACxB,QAAA,EAAA,KAAA,CAAM,WAAA,EACT,CAAA;AAAA,QAED,MAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,qBAClBA,eAAC,QAAA,EAAA,EAA0B,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,UAAU,MAAA,CAAO,QAAA,EAC9D,iBAAO,KAAA,EAAA,EADG,MAAA,CAAO,KAEpB,CACD;AAAA;AAAA;AAAA,GACH;AAEJ,CAAA;AAMO,SAAS,iBAAiBK,SAAAA,EAA+B;AAC9D,EAAA,IAAI,CAACA,SAAAA,CAAS,GAAA,CAAI,OAAO,CAAA,EAAG;AAC1B,IAAAA,SAAAA,CAAS,SAAS,OAAA,EAAS,EAAE,WAAW,YAAA,EAAc,YAAA,EAAc,IAAI,CAAA;AAAA,EAC1E;AACA,EAAA,IAAI,CAACA,SAAAA,CAAS,GAAA,CAAI,UAAU,CAAA,EAAG;AAC7B,IAAAA,SAAAA,CAAS,SAAS,UAAA,EAAY;AAAA,MAC5B,SAAA,EAAW,eAAA;AAAA,MACX,YAAA,EAAc,EAAA;AAAA,MACd,cAAA,EAAgB,CAAC,MAAA,KACf,KAAA,CAAM,QAAS,MAAA,CAAwC,OAAO,IAC1D,IAAA,GACA;AAAA,KACP,CAAA;AAAA,EACH;AACF;AAEA,IAAI,MAAA,GAAS,KAAA;AAQN,SAAS,eAAeO,gBAAAA,EAAsC;AACnE,EAAA,IAAI,MAAA,EAAQ;AACZ,EAAA,MAAA,GAAS,IAAA;AACT,EAAA,gBAAA,CAAiBA,gBAAe,CAAA;AAClC;ACzGO,SAAS,SACd,KAAA,EACA;AACA,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,KAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA,kBAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA,EAAAP,SAAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AAEJ,EAAA,cAAA,CAAe,eAAe,CAAA;AAC9B,EAAA,MAAM,iBAAiBA,SAAAA,IAAY,eAAA;AAEnC,EAAA,MAAM,OAAA,GAA4C;AAAA,IAChD,QAAA,EAAU,cAAA;AAAA,IACV,GAAI,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,KAAU,EAAC;AAAA,IACvC,GAAI,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,KAAiB,EAAC;AAAA,IACrD,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,IAC/B,GAAI,kBAAA,GAAqB,EAAE,kBAAA,KAAuB,EAAC;AAAA,IACnD,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,IAC/B,GAAI,UAAA,GAAa,EAAE,UAAA,KAAe;AAAC,GACrC;AAEA,EAAA,MAAM,EAAA,GAAK,gBAAA,CAA0B,MAAA,EAAQ,OAAO,CAAA;AACpD,EAAA,MAAM,EAAE,SAAS,GAAA,EAAK,MAAA,EAAQ,QAAQ,EAAA,EAAI,QAAA,KAAa,EAAA,CAAG,MAAA;AAE1D,EAAA,uBACEN,eAAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,gBAAA,EAAkB,SAAS,CAAA;AAAA,MACzC,IAAI,EAAA,IAAM,QAAA;AAAA,MACV,UAAU,QAAA,IAAY,MAAA;AAAA,MAErB,QAAA,EAAA;AAAA,QAAA,MAAA,IAAU,wBAAQC,cAAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,0BAA0B,QAAA,EAAA,MAAA,EAAO,CAAA;AAAA,wBACtEA,cAAAA,CAAC,SAAA,EAAA,EAAU,OAAA,EAAkB,GAAA,EAC1B,iBAAO,GAAA,CAAI,CAAC,KAAA,qBACXA,eAAC,aAAA,EAAA,EAA+B,IAAA,EAAM,KAAA,CAAM,MAAA,EAAQ,SAClD,QAAA,kBAAAA,cAAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YACC,KAAA;AAAA,YACA,QAAA,EAAU,cAAA;AAAA,YACV,KAAA,EAAO,EAAA,CAAG,aAAA,CAAc,KAAA,CAAM,IAAI,CAAA;AAAA,YAClC,UAAU,QAAA,KAAa;AAAA;AAAA,SACzB,EAAA,EANkB,KAAA,CAAM,IAO1B,CACD,CAAA,EACH;AAAA;AAAA;AAAA,GACF;AAEJ;;;ACrCO,IAAM,cAAA,GAAiB","file":"index.cjs","sourcesContent":["/** Join truthy class names with a space. */\nexport function cx(...names: Array<string | false | null | undefined>): string {\n return names.filter(Boolean).join(\" \");\n}\n","import { useId } from \"react\";\nimport { cx } from \"../../internal/cx\";\nimport type { ErrorProp, FieldProps, FieldRenderContext } from \"../../types/props\";\n\nfunction toMessages(error: ErrorProp): string[] {\n if (error == null) return [];\n return (Array.isArray(error) ? error : [error]).filter((m): m is string => Boolean(m));\n}\n\nfunction joinIds(...ids: Array<string | undefined>): string | undefined {\n const list = ids.filter((id): id is string => Boolean(id));\n return list.length > 0 ? list.join(\" \") : undefined;\n}\n\n/**\n * Layout + accessibility wrapper for a single control. Renders the label,\n * optional description, and an error region, and wires the ARIA relationships\n * (`htmlFor`, `aria-describedby`, `aria-invalid`, `aria-required`).\n *\n * Pass a render function as `children` to receive the resolved ids:\n *\n * ```tsx\n * <Field label=\"Name\" error={error}>\n * {({ id, describedById, invalid }) => (\n * <input id={id} aria-describedby={describedById} aria-invalid={invalid} />\n * )}\n * </Field>\n * ```\n */\nexport function Field(props: FieldProps) {\n const { label, description, error, required, disabled, className, children } = props;\n\n const reactId = useId();\n const id = props.id ?? reactId;\n\n const messages = toMessages(error);\n const invalid = messages.length > 0;\n\n const descriptionId = description != null ? `${id}-description` : undefined;\n const errorId = invalid ? `${id}-error` : undefined;\n const describedById = joinIds(descriptionId, errorId);\n\n const ctx: FieldRenderContext = { id, describedById, invalid, required, disabled };\n\n return (\n <div\n className={cx(\"orynn-field\", className)}\n data-invalid={invalid || undefined}\n data-disabled={disabled || undefined}\n data-required={required || undefined}\n >\n {label != null && (\n <label className=\"orynn-field__label\" htmlFor={id}>\n {label}\n </label>\n )}\n\n {description != null && (\n <p className=\"orynn-field__description\" id={descriptionId}>\n {description}\n </p>\n )}\n\n <div className=\"orynn-field__control\">\n {typeof children === \"function\" ? children(ctx) : children}\n </div>\n\n {invalid && (\n <p className=\"orynn-field__error\" id={errorId} role=\"alert\">\n {messages.length === 1 ? messages[0] : messages.map((m) => <span key={m}>{m}</span>)}\n </p>\n )}\n </div>\n );\n}\n","import { type ChangeEvent, forwardRef, useCallback } from \"react\";\nimport type { DropdownProps } from \"../../types/props\";\nimport { Field } from \"../Field/Field\";\n\n/**\n * A labelled single-select built on the native `<select>` element (accessible\n * and keyboard-navigable out of the box). Works with or without `<Fieldset>`.\n */\nexport const Dropdown = /* @__PURE__ */ forwardRef<HTMLSelectElement, DropdownProps>(\n function Dropdown(props, ref) {\n const {\n label,\n description,\n error,\n className,\n options,\n value,\n onChange,\n placeholder,\n id,\n required,\n disabled,\n onBlur,\n onFocus,\n ...rest\n } = props;\n\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLSelectElement>) => onChange?.(event.target.value, event),\n [onChange],\n );\n\n const controlled = value !== undefined;\n\n return (\n <Field\n label={label}\n description={description}\n error={error}\n required={required}\n disabled={disabled}\n id={id}\n className={className}\n >\n {({ id: fieldId, describedById, invalid }) => (\n <select\n {...rest}\n ref={ref}\n id={fieldId}\n className=\"orynn-dropdown\"\n required={required}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n aria-describedby={describedById}\n {...(controlled ? { value } : {})}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n >\n {placeholder != null && (\n <option value=\"\" disabled={required}>\n {placeholder}\n </option>\n )}\n {options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n )}\n </Field>\n );\n },\n);\n","import { type ChangeEvent, forwardRef, useCallback } from \"react\";\nimport type { InputProps } from \"../../types/props\";\nimport { Field } from \"../Field/Field\";\n\n/**\n * A labelled text input. Controlled when `value` is passed, uncontrolled\n * otherwise (`defaultValue` flows through to the native element). Works with or\n * without `<Fieldset>`.\n */\nexport const Input = /* @__PURE__ */ forwardRef<HTMLInputElement, InputProps>(\n function Input(props, ref) {\n const {\n label,\n description,\n error,\n className,\n value,\n onChange,\n type = \"text\",\n id,\n required,\n disabled,\n readOnly,\n onBlur,\n onFocus,\n ...rest\n } = props;\n\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => onChange?.(event.target.value, event),\n [onChange],\n );\n\n const controlled = value !== undefined;\n\n return (\n <Field\n label={label}\n description={description}\n error={error}\n required={required}\n disabled={disabled}\n id={id}\n className={className}\n >\n {({ id: fieldId, describedById, invalid }) => (\n <input\n {...rest}\n ref={ref}\n id={fieldId}\n className=\"orynn-input\"\n type={type}\n required={required}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid || undefined}\n aria-describedby={describedById}\n {...(controlled ? { value } : {})}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n )}\n </Field>\n );\n },\n);\n","/**\n * Development-only helpers. `__DEV__` is statically replaceable by bundlers, so\n * `invariant` / `warnOnce` bodies tree-shake out of production builds.\n */\nexport const __DEV__: boolean =\n typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\";\n\n/** Throws in development when `condition` is falsy. No-op in production. */\nexport function invariant(condition: unknown, message: string): asserts condition {\n if (condition) return;\n if (__DEV__) {\n throw new Error(`[orynn] ${message}`);\n }\n}\n\nconst warned = new Set<string>();\n\n/** Logs a warning once per unique message. Silent in production. */\nexport function warnOnce(message: string): void {\n if (!__DEV__ || warned.has(message)) return;\n warned.add(message);\n console.warn(`[orynn] ${message}`);\n}\n\n/** Test-only: clear the warn-once cache between cases. */\nexport function resetWarnings(): void {\n warned.clear();\n}\n","import { __DEV__, warnOnce } from \"../../internal/dev\";\nimport type { FieldRegistration, FieldRegistry } from \"../../types/control\";\n\nclass Registry implements FieldRegistry {\n #entries = new Map<string, FieldRegistration>();\n\n register(type: string, registration: FieldRegistration): void {\n if (__DEV__ && this.#entries.has(type)) {\n warnOnce(`Field type \"${type}\" is being re-registered; the previous definition is replaced.`);\n }\n this.#entries.set(type, registration);\n }\n\n get(type: string): FieldRegistration | undefined {\n return this.#entries.get(type);\n }\n\n has(type: string): boolean {\n return this.#entries.has(type);\n }\n\n types(): string[] {\n return [...this.#entries.keys()];\n }\n}\n\n/**\n * Create an isolated field registry. Use this to give a `<Fieldset>` its own set\n * of field types without touching the module-global {@link defaultRegistry}\n * (recommended on the server, where mutating a shared registry per request would\n * leak between requests).\n *\n * @experimental The registry API may change before 1.0.\n */\nexport function createRegistry(): FieldRegistry {\n return new Registry();\n}\n\n/**\n * The module-global registry used by `<Fieldset>` when no `registry` prop is\n * passed. Seeded with the built-in `input` and `dropdown` fields.\n *\n * @experimental\n */\nexport const defaultRegistry: FieldRegistry = /* @__PURE__ */ createRegistry();\n\n/**\n * Register a field type on the {@link defaultRegistry}. Call this once at\n * application start-up, not per render or per request.\n *\n * @experimental\n */\nexport function registerField(type: string, registration: FieldRegistration): void {\n defaultRegistry.register(type, registration);\n}\n","import type { ColumnSpec } from \"../types/config\";\n\n/** V1 default: 3 columns on desktop, 2 on tablet, 1 on mobile. */\nexport const DEFAULT_COLUMNS: ColumnSpec = { desktop: 3, tablet: 2, mobile: 1 };\n\nconst clampCount = (n: unknown, fallback: number): number =>\n typeof n === \"number\" && Number.isFinite(n) && n >= 1 ? Math.floor(n) : fallback;\n\n/** Merge a partial column spec onto the defaults. */\nexport function resolveColumns(partial?: Partial<ColumnSpec>): ColumnSpec {\n return {\n desktop: clampCount(partial?.desktop, DEFAULT_COLUMNS.desktop),\n tablet: clampCount(partial?.tablet, DEFAULT_COLUMNS.tablet),\n mobile: clampCount(partial?.mobile, DEFAULT_COLUMNS.mobile),\n };\n}\n\n/** Clamp a field's column span so it never exceeds the row's column count. */\nexport function clampSpan(span: unknown, columnCount: number): number {\n const n = clampCount(span, 1);\n return Math.min(n, Math.max(columnCount, 1));\n}\n","import { invariant } from \"../../internal/dev\";\nimport { resolveColumns } from \"../../layout/resolve-columns\";\nimport type { ColumnSpec, FieldConfig, FieldsetConfig } from \"../../types/config\";\nimport type { FieldRegistry } from \"../../types/control\";\n\n/** A validated `FieldsetConfig` with every default resolved. */\nexport interface NormalizedFieldsetConfig {\n fields: FieldConfig[];\n columns: ColumnSpec;\n /** CSS length for the grid gap, or `undefined` to use the token default. */\n gap: string | undefined;\n legend: string | undefined;\n id: string | undefined;\n}\n\nfunction normalizeGap(gap: FieldsetConfig[\"gap\"]): string | undefined {\n if (gap == null) return undefined;\n return typeof gap === \"number\" ? `${gap}px` : gap;\n}\n\n/**\n * Validate a `FieldsetConfig` and resolve its defaults. Structural problems\n * throw in development with an actionable message; in production the checks are\n * stripped and normalization is defensive.\n *\n * Pass `registry` (as `<Fieldset>` does) to also validate each field's `type`\n * and run type-specific config checks.\n */\nexport function normalizeConfig(\n config: FieldsetConfig,\n registry?: FieldRegistry,\n): NormalizedFieldsetConfig {\n invariant(\n config != null && typeof config === \"object\" && Array.isArray(config.fields),\n \"`config` must be an object with a `fields` array.\",\n );\n\n const seen = new Set<string>();\n\n for (const field of config.fields) {\n invariant(\n field != null && typeof field === \"object\",\n \"Every entry in `config.fields` must be an object.\",\n );\n invariant(\n typeof field.name === \"string\" && field.name.length > 0,\n \"Every field needs a non-empty string `name`.\",\n );\n invariant(!seen.has(field.name), `Duplicate field name \"${field.name}\" in config.fields.`);\n seen.add(field.name);\n invariant(\n typeof field.type === \"string\" && field.type.length > 0,\n `Field \"${field.name}\" is missing a \"type\".`,\n );\n\n if (registry) {\n invariant(\n registry.has(field.type),\n `Unknown field type \"${field.type}\" on field \"${field.name}\". ` +\n `Registered types: ${registry.types().join(\", \") || \"(none)\"}.`,\n );\n const typeError = registry.get(field.type)?.validateConfig?.(field);\n invariant(typeError == null, `Field \"${field.name}\" (${field.type}): ${typeError}`);\n }\n }\n\n return {\n fields: config.fields,\n columns: resolveColumns(config.columns),\n gap: normalizeGap(config.gap),\n legend: config.legend,\n id: config.id,\n };\n}\n","/** Formats the default message for a built-in rule token. */\ntype MessageFormatter = (ctx: { param: unknown; label: string }) => string;\n\nconst plural = (n: unknown, word: string) => `${n} ${word}${n === 1 ? \"\" : \"s\"}`;\n\n/** Default message templates for the built-in rules. */\nexport const defaultMessages: Record<string, MessageFormatter> = {\n required: ({ label }) => `${label} is required`,\n minLength: ({ param, label }) => `${label} must be at least ${plural(param, \"character\")}`,\n maxLength: ({ param, label }) => `${label} must be at most ${plural(param, \"character\")}`,\n};\n\nconst FALLBACK_LABEL = \"This field\";\n\n/**\n * Resolve the message for a failed rule.\n *\n * Precedence: a per-field override (`validation.messages[token]`) wins; otherwise\n * a built-in template is used; otherwise the token itself is the message (custom\n * rules return a ready-to-show string).\n */\nexport function resolveMessage(\n token: string,\n param: unknown,\n label: string | undefined,\n overrides: Partial<Record<string, string>> | undefined,\n): string {\n const override = overrides?.[token];\n if (override != null) return override;\n\n const formatter = defaultMessages[token];\n if (formatter) return formatter({ param, label: label ?? FALLBACK_LABEL });\n\n return token;\n}\n","import type { RuleFn } from \"../../types/validation\";\n\nconst isEmpty = (value: unknown): boolean =>\n value == null || value === \"\" || (Array.isArray(value) && value.length === 0);\n\nconst asLength = (value: unknown): number =>\n typeof value === \"string\" || Array.isArray(value) ? value.length : String(value ?? \"\").length;\n\n/**\n * Built-in rules. Each returns a token (rule name) on failure or `null` on\n * success; the resolver turns the token into a user-facing message.\n *\n * `minLength` deliberately ignores empty values so `required` owns that error.\n */\nexport const builtInRules: { required: RuleFn; minLength: RuleFn; maxLength: RuleFn } = {\n required: (value, param) => {\n if (param === false) return null;\n return isEmpty(value) ? \"required\" : null;\n },\n minLength: (value, param) => {\n if (typeof param !== \"number\" || isEmpty(value)) return null;\n return asLength(value) < param ? \"minLength\" : null;\n },\n maxLength: (value, param) => {\n if (typeof param !== \"number\" || isEmpty(value)) return null;\n return asLength(value) > param ? \"maxLength\" : null;\n },\n};\n\nconst registry = new Map<string, RuleFn>(Object.entries(builtInRules));\n\n/**\n * Register a validation rule for the built-in resolver. A field opts in by\n * adding a key of the same name to its `validation` config.\n *\n * @experimental The rule API may change before 1.0.\n */\nexport function registerRule(name: string, fn: RuleFn): void {\n registry.set(name, fn);\n}\n\nexport function getRule(name: string): RuleFn | undefined {\n return registry.get(name);\n}\n\nexport function ruleNames(): string[] {\n return [...registry.keys()];\n}\n","import { __DEV__, warnOnce } from \"../../internal/dev\";\nimport type { FieldsetConfig } from \"../../types/config\";\nimport type {\n FieldError,\n ValidationContext,\n ValidationResolver,\n ValidationResult,\n} from \"../../types/validation\";\nimport { resolveMessage } from \"./messages\";\nimport { getRule } from \"./rules\";\n\n/** A synchronous resolver — the built-in resolver's precise return type. */\nexport type SyncResolver = (\n values: Record<string, unknown>,\n config: FieldsetConfig,\n context: ValidationContext,\n) => ValidationResult;\n\n/**\n * The default, rule-based {@link ValidationResolver}. For every field with a\n * `validation` block, each key (other than `messages`) is looked up in the rule\n * registry and run against the field's current value. All fields are validated\n * on every call; callers decide which errors to surface.\n *\n * Synchronous today. Async, schema-based, and cross-field resolvers plug in at\n * the same seam without an API change.\n */\nexport function createRuleResolver(): SyncResolver {\n return (values, config): ValidationResult => {\n const result: ValidationResult = {};\n\n for (const field of config.fields) {\n const validation = field.validation;\n if (!validation) continue;\n\n const value = values[field.name];\n const errors: FieldError[] = [];\n\n for (const key of Object.keys(validation)) {\n if (key === \"messages\") continue;\n\n const param = (validation as Record<string, unknown>)[key];\n if (param === undefined || param === false) continue;\n\n const rule = getRule(key);\n if (!rule) {\n if (__DEV__) {\n warnOnce(`No validator registered for rule \"${key}\" (field \"${field.name}\").`);\n }\n continue;\n }\n\n const token = rule(value, param, values);\n if (token == null) continue;\n\n errors.push({\n rule: key,\n message: resolveMessage(token, param, field.label, validation.messages),\n });\n }\n\n if (errors.length > 0) result[field.name] = errors;\n }\n\n return result;\n };\n}\n\n/** Shared default instance. */\nexport const defaultResolver: ValidationResolver = /* @__PURE__ */ createRuleResolver();\n","import type { FieldStatus } from \"../../types/state\";\nimport type { FieldError, ValidationResult } from \"../../types/validation\";\n\n/** Internal state: everything the fieldset tracks except `values`. */\nexport interface MetaState {\n touched: Record<string, boolean>;\n errors: ValidationResult;\n validating: boolean;\n /** True once any validation run has completed — distinguishes \"idle\" from \"valid\". */\n everValidated: boolean;\n}\n\nexport const initialMeta: MetaState = {\n touched: {},\n errors: {},\n validating: false,\n everValidated: false,\n};\n\nexport type MetaAction =\n | { type: \"touch\"; name: string }\n | { type: \"touchAll\"; names: string[] }\n | { type: \"validation:start\" }\n | { type: \"validation:field\"; name: string; errors: FieldError[] }\n | { type: \"validation:all\"; result: ValidationResult }\n | { type: \"reset\" };\n\nexport function metaReducer(state: MetaState, action: MetaAction): MetaState {\n switch (action.type) {\n case \"touch\": {\n if (state.touched[action.name]) return state;\n return { ...state, touched: { ...state.touched, [action.name]: true } };\n }\n case \"touchAll\": {\n const touched = { ...state.touched };\n for (const name of action.names) touched[name] = true;\n return { ...state, touched };\n }\n case \"validation:start\":\n return { ...state, validating: true };\n case \"validation:field\": {\n const errors = { ...state.errors };\n if (action.errors.length > 0) errors[action.name] = action.errors;\n else delete errors[action.name];\n return { ...state, errors, validating: false, everValidated: true };\n }\n case \"validation:all\":\n return { ...state, errors: action.result, validating: false, everValidated: true };\n case \"reset\":\n return { ...initialMeta };\n default:\n return state;\n }\n}\n\n/** Derive the form-level status roll-up. */\nexport function deriveStatus(meta: MetaState): FieldStatus {\n if (meta.validating) return \"validating\";\n if (!meta.everValidated) return \"idle\";\n return Object.keys(meta.errors).length > 0 ? \"invalid\" : \"valid\";\n}\n\n/** Shallow per-field dirty map: current value differs from initial. */\nexport function computeDirty(\n values: Record<string, unknown>,\n initial: Record<string, unknown>,\n): Record<string, boolean> {\n const dirty: Record<string, boolean> = {};\n for (const key of Object.keys(values)) {\n if (!Object.is(values[key], initial[key])) dirty[key] = true;\n }\n return dirty;\n}\n","import { useRef } from \"react\";\n\n/** A ref whose `.current` always holds the latest value passed on render. */\nexport function useLatestRef<T>(value: T) {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n}\n","import { useCallback, useState } from \"react\";\nimport { useLatestRef } from \"./use-latest-ref\";\n\n/**\n * The single place the controlled / uncontrolled fork lives. When `value` is\n * provided the component is controlled and internal state is bypassed; otherwise\n * `defaultValue` seeds local state. `onChange` fires on every committed change in\n * both modes.\n */\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: {\n value: T | undefined;\n defaultValue: T;\n onChange: ((value: T) => void) | undefined;\n}): readonly [T, (next: T | ((prev: T) => T)) => void] {\n const isControlled = value !== undefined;\n const [uncontrolled, setUncontrolled] = useState<T>(defaultValue);\n\n const current = isControlled ? (value as T) : uncontrolled;\n const currentRef = useLatestRef(current);\n const onChangeRef = useLatestRef(onChange);\n const isControlledRef = useLatestRef(isControlled);\n\n const setValue = useCallback((next: T | ((prev: T) => T)) => {\n const resolved =\n typeof next === \"function\" ? (next as (prev: T) => T)(currentRef.current) : next;\n if (Object.is(resolved, currentRef.current)) return;\n if (!isControlledRef.current) setUncontrolled(resolved);\n onChangeRef.current?.(resolved);\n }, []);\n\n return [current, setValue] as const;\n}\n","import { useCallback, useMemo, useReducer, useRef } from \"react\";\nimport type { FormEvent } from \"react\";\nimport type { FieldsetConfig } from \"../../types/config\";\nimport type { FieldRegistry } from \"../../types/control\";\nimport type { FieldStatus, FieldsetState } from \"../../types/state\";\nimport type {\n FieldError,\n ValidationResolver,\n ValidationResult,\n ValidationTrigger,\n} from \"../../types/validation\";\nimport { type NormalizedFieldsetConfig, normalizeConfig } from \"../config/normalize\";\nimport { defaultResolver } from \"../validation/resolver\";\nimport { computeDirty, deriveStatus, initialMeta, metaReducer } from \"./reducer\";\nimport { useControllableState } from \"./use-controllable-state\";\nimport { useLatestRef } from \"./use-latest-ref\";\n\ntype Values = Record<string, unknown>;\n\n/** Shared empty errors array so unchanged field slices keep a stable identity. */\nconst NO_ERRORS: readonly FieldError[] = Object.freeze([]);\n\nexport interface UseFieldsetStateOptions<TValues extends Values = Values> {\n /** Controlled values. Omit and pass `defaultValue` for uncontrolled. */\n value?: TValues;\n defaultValue?: Partial<TValues>;\n onChange?: (values: TValues) => void;\n /** Called after a full validation pass (`validate()` / submit), not per blur. */\n onValidationChange?: (result: ValidationResult) => void;\n resolver?: ValidationResolver;\n registry?: FieldRegistry;\n /** `\"blur\"` (default) also always validates on submit. */\n validateOn?: ValidationTrigger;\n}\n\n/** Everything a renderer needs for one field. Handlers are referentially stable. */\nexport interface FieldSlice {\n name: string;\n value: unknown;\n errors: FieldError[];\n touched: boolean;\n dirty: boolean;\n setValue: (value: unknown) => void;\n markTouched: () => void;\n}\n\nexport interface UseFieldsetStateReturn<TValues extends Values = Values> {\n config: NormalizedFieldsetConfig;\n state: FieldsetState;\n values: TValues;\n errors: ValidationResult;\n touched: Record<string, boolean>;\n dirty: Record<string, boolean>;\n status: FieldStatus;\n isValid: boolean;\n setFieldValue: (name: string, value: unknown) => void;\n setValues: (values: TValues) => void;\n reset: (next?: Partial<TValues>) => void;\n validate: () => Promise<ValidationResult>;\n handleSubmit: (\n onValid: (values: TValues) => void,\n onInvalid?: (result: ValidationResult) => void,\n ) => (event?: FormEvent) => void;\n getFieldProps: (name: string) => FieldSlice;\n}\n\nfunction computeInitialValues(\n config: NormalizedFieldsetConfig,\n registry: FieldRegistry | undefined,\n provided: Values | undefined,\n): Values {\n const out: Values = {};\n for (const field of config.fields) {\n if (provided && Object.prototype.hasOwnProperty.call(provided, field.name)) {\n out[field.name] = provided[field.name];\n } else if (field.defaultValue !== undefined) {\n out[field.name] = field.defaultValue;\n } else {\n out[field.name] = registry?.get(field.type)?.defaultValue ?? \"\";\n }\n }\n return out;\n}\n\ninterface RunScope {\n field?: string;\n trigger: ValidationTrigger;\n values?: Values;\n}\n\n/**\n * The form engine behind `<Fieldset>`, usable directly when you want to own the\n * markup. Manages values (controlled or uncontrolled), touched/dirty tracking,\n * and validation through a pluggable resolver.\n */\nexport function useFieldsetState<TValues extends Values = Values>(\n config: FieldsetConfig,\n options: UseFieldsetStateOptions<TValues> = {},\n): UseFieldsetStateReturn<TValues> {\n const {\n value,\n defaultValue,\n onChange,\n onValidationChange,\n resolver = defaultResolver,\n registry,\n validateOn = \"blur\",\n } = options;\n\n const normalized = useMemo(() => normalizeConfig(config, registry), [config, registry]);\n\n const initialRef = useRef<Values | null>(null);\n if (initialRef.current === null) {\n initialRef.current = computeInitialValues(\n normalized,\n registry,\n (value ?? defaultValue) as Values | undefined,\n );\n }\n\n const [rawValues, setRawValues] = useControllableState<Values>({\n value: value as Values | undefined,\n defaultValue: initialRef.current,\n onChange: onChange as ((v: Values) => void) | undefined,\n });\n\n const values = useMemo(() => ({ ...initialRef.current, ...rawValues }) as TValues, [rawValues]);\n\n const [meta, dispatch] = useReducer(metaReducer, initialMeta);\n\n const valuesRef = useLatestRef<Values>(values);\n const resolverRef = useLatestRef(resolver);\n const configRef = useLatestRef(config);\n const normalizedRef = useLatestRef(normalized);\n const registryRef = useLatestRef(registry);\n const validateOnRef = useLatestRef(validateOn);\n const onValidationChangeRef = useLatestRef(onValidationChange);\n const runIdRef = useRef(0);\n\n const runValidation = useCallback(async (scope: RunScope): Promise<ValidationResult> => {\n const runId = ++runIdRef.current;\n const input = scope.values ?? valuesRef.current;\n dispatch({ type: \"validation:start\" });\n\n const result = await resolverRef.current(input, configRef.current, {\n trigger: scope.trigger,\n ...(scope.field ? { changedField: scope.field } : {}),\n });\n\n if (runId !== runIdRef.current) return result; // superseded\n\n if (scope.field) {\n dispatch({ type: \"validation:field\", name: scope.field, errors: result[scope.field] ?? [] });\n } else {\n dispatch({ type: \"validation:all\", result });\n onValidationChangeRef.current?.(result);\n }\n return result;\n // refs only — safe to keep stable\n }, []);\n\n const setFieldValue = useCallback(\n (name: string, next: unknown) => {\n setRawValues((prev) => ({ ...prev, [name]: next }));\n if (validateOnRef.current === \"change\") {\n void runValidation({\n field: name,\n trigger: \"change\",\n values: { ...valuesRef.current, [name]: next },\n });\n }\n },\n [setRawValues, runValidation],\n );\n\n const setValues = useCallback((next: TValues) => setRawValues(next as Values), [setRawValues]);\n\n const markTouched = useCallback(\n (name: string) => {\n dispatch({ type: \"touch\", name });\n if (validateOnRef.current === \"blur\") {\n void runValidation({ field: name, trigger: \"blur\" });\n }\n },\n [runValidation],\n );\n\n const validate = useCallback(() => runValidation({ trigger: \"submit\" }), [runValidation]);\n\n const handleSubmit = useCallback(\n (onValid: (values: TValues) => void, onInvalid?: (result: ValidationResult) => void) =>\n async (event?: FormEvent) => {\n event?.preventDefault?.();\n dispatch({\n type: \"touchAll\",\n names: normalizedRef.current.fields.map((f) => f.name),\n });\n const result = await runValidation({ trigger: \"submit\" });\n if (Object.keys(result).length === 0) onValid(valuesRef.current as TValues);\n else onInvalid?.(result);\n },\n [runValidation],\n );\n\n const reset = useCallback(\n (next?: Partial<TValues>) => {\n const fresh = computeInitialValues(\n normalizedRef.current,\n registryRef.current,\n next as Values | undefined,\n );\n initialRef.current = fresh;\n setRawValues(fresh);\n dispatch({ type: \"reset\" });\n runIdRef.current++;\n },\n [setRawValues],\n );\n\n // Stable per-field handler identities so memoized rows don't re-render.\n const handlerCacheRef = useRef(\n new Map<string, { setValue: (v: unknown) => void; markTouched: () => void }>(),\n );\n const getHandlers = useCallback(\n (name: string) => {\n const cache = handlerCacheRef.current;\n let entry = cache.get(name);\n if (!entry) {\n entry = {\n setValue: (v: unknown) => setFieldValue(name, v),\n markTouched: () => markTouched(name),\n };\n cache.set(name, entry);\n }\n return entry;\n },\n [setFieldValue, markTouched],\n );\n\n const dirty = useMemo(() => computeDirty(values, initialRef.current ?? {}), [values]);\n const status = deriveStatus(meta);\n const isValid = Object.keys(meta.errors).length === 0;\n\n const getFieldProps = useCallback(\n (name: string): FieldSlice => {\n const handlers = getHandlers(name);\n return {\n name,\n value: (values as Values)[name],\n errors: meta.errors[name] ?? (NO_ERRORS as FieldError[]),\n touched: meta.touched[name] ?? false,\n dirty: dirty[name] ?? false,\n setValue: handlers.setValue,\n markTouched: handlers.markTouched,\n };\n },\n [values, meta.errors, meta.touched, dirty, getHandlers],\n );\n\n const state: FieldsetState = useMemo(\n () => ({\n values: values as Values,\n touched: meta.touched,\n dirty,\n errors: meta.errors,\n status,\n }),\n [values, meta.touched, dirty, meta.errors, status],\n );\n\n return {\n config: normalized,\n state,\n values,\n errors: meta.errors,\n touched: meta.touched,\n dirty,\n status,\n isValid,\n setFieldValue,\n setValues,\n reset,\n validate,\n handleSubmit,\n getFieldProps,\n };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { cx } from \"../internal/cx\";\nimport type { ColumnSpec } from \"../types/config\";\nimport { clampSpan } from \"./resolve-columns\";\n\n/** CSS custom properties are set inline; the stylesheet consumes them. */\ntype CssVars = CSSProperties & Record<`--${string}`, string | number>;\n\nexport interface FieldGridProps {\n columns: ColumnSpec;\n /** CSS length for the gap; falls back to the `--orynn-grid-gap` token. */\n gap?: string | undefined;\n className?: string | undefined;\n children: ReactNode;\n}\n\n/**\n * Responsive grid. Column counts per breakpoint are passed as CSS variables and\n * applied by the stylesheet through container queries, so the grid responds to\n * its own width rather than the viewport.\n */\nexport function FieldGrid({ columns, gap, className, children }: FieldGridProps) {\n const style: CssVars = {\n \"--orynn-cols-desktop\": columns.desktop,\n \"--orynn-cols-tablet\": columns.tablet,\n \"--orynn-cols-mobile\": columns.mobile,\n ...(gap ? { \"--orynn-grid-gap\": gap } : {}),\n };\n\n return (\n <div className={cx(\"orynn-grid\", className)} style={style}>\n <div className=\"orynn-grid__track\">{children}</div>\n </div>\n );\n}\n\nexport interface FieldGridItemProps {\n /** Per-breakpoint column span; missing breakpoints default to 1. */\n span?: Partial<ColumnSpec> | undefined;\n columns: ColumnSpec;\n children: ReactNode;\n}\n\n/** One cell of a {@link FieldGrid}, optionally spanning multiple columns. */\nexport function FieldGridItem({ span, columns, children }: FieldGridItemProps) {\n if (!span) return <>{children}</>;\n\n const style: CssVars = {\n \"--orynn-span-desktop\": clampSpan(span.desktop, columns.desktop),\n \"--orynn-span-tablet\": clampSpan(span.tablet, columns.tablet),\n \"--orynn-span-mobile\": clampSpan(span.mobile, columns.mobile),\n };\n\n return (\n <div className=\"orynn-grid__item\" style={style}>\n {children}\n </div>\n );\n}\n","import { memo } from \"react\";\nimport { Field } from \"../controls/Field/Field\";\nimport type { FieldSlice } from \"../core/state/use-fieldset-state\";\nimport { invariant } from \"../internal/dev\";\nimport type { FieldConfig } from \"../types/config\";\nimport type { FieldRegistry } from \"../types/control\";\n\nconst noop = () => {};\n\nexport interface FieldRendererProps {\n field: FieldConfig;\n registry: FieldRegistry;\n slice: FieldSlice;\n disabled?: boolean;\n}\n\nfunction FieldRendererImpl({ field, registry, slice, disabled }: FieldRendererProps) {\n const registration = registry.get(field.type);\n invariant(\n registration,\n `No control registered for field type \"${field.type}\" (field \"${field.name}\").`,\n );\n if (!registration) return null;\n\n const Control = registration.component;\n const required = field.validation?.required === true;\n const isDisabled = disabled === true || field.disabled === true;\n\n const value = registration.parseValue ? registration.parseValue(slice.value) : slice.value;\n // The hook decides *when* a field is validated (per `validateOn`); if it has\n // produced errors for this field, show them.\n const messages = slice.errors.map((e) => e.message);\n\n const handleChange = (next: unknown) => {\n slice.setValue(registration.formatValue ? registration.formatValue(next) : next);\n };\n\n return (\n <Field\n label={field.label}\n description={field.description}\n error={messages}\n required={required}\n disabled={isDisabled}\n >\n {({ id, describedById, invalid }) => (\n <Control\n id={id}\n name={field.name}\n value={value}\n onChange={handleChange}\n onBlur={slice.markTouched}\n onFocus={noop}\n disabled={isDisabled}\n readOnly={field.readOnly === true}\n required={required}\n invalid={invalid}\n describedById={describedById}\n config={field}\n />\n )}\n </Field>\n );\n}\n\n/**\n * Resolves a field config to its registered control and wraps it in `<Field>`.\n * Memoized on the parts of the slice that affect output so that changing one\n * field in a large fieldset does not re-render the others.\n */\nexport const FieldRenderer = /* @__PURE__ */ memo(\n FieldRendererImpl,\n (prev, next) =>\n prev.field === next.field &&\n prev.registry === next.registry &&\n prev.disabled === next.disabled &&\n prev.slice.value === next.slice.value &&\n prev.slice.touched === next.slice.touched &&\n prev.slice.errors === next.slice.errors &&\n prev.slice.setValue === next.slice.setValue &&\n prev.slice.markTouched === next.slice.markTouched,\n);\n","import type { DropdownFieldConfig, InputFieldConfig } from \"../types/config\";\nimport type { ControlComponent, FieldRegistry } from \"../types/control\";\n\nconst toStringValue = (value: unknown): string =>\n typeof value === \"string\" ? value : value == null ? \"\" : String(value);\n\n/** Raw `<input>` bound to the {@link ControlProps} contract. `<Field>` wraps it. */\nconst InputControl: ControlComponent<string> = ({\n id,\n name,\n value,\n onChange,\n onBlur,\n onFocus,\n disabled,\n readOnly,\n required,\n invalid,\n describedById,\n config,\n}) => {\n const field = config as InputFieldConfig;\n return (\n <input\n id={id}\n name={name}\n className=\"orynn-input\"\n type={field.inputType ?? \"text\"}\n value={toStringValue(value)}\n placeholder={field.placeholder}\n required={required}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid || undefined}\n aria-describedby={describedById}\n onChange={(event) => onChange(event.target.value, event)}\n onBlur={onBlur}\n onFocus={onFocus}\n {...field.props}\n />\n );\n};\n\n/** Raw `<select>` bound to the {@link ControlProps} contract. */\nconst DropdownControl: ControlComponent<string> = ({\n id,\n name,\n value,\n onChange,\n onBlur,\n onFocus,\n disabled,\n required,\n invalid,\n describedById,\n config,\n}) => {\n const field = config as DropdownFieldConfig;\n return (\n <select\n id={id}\n name={name}\n className=\"orynn-dropdown\"\n value={toStringValue(value)}\n required={required}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n aria-describedby={describedById}\n onChange={(event) => onChange(event.target.value, event)}\n onBlur={onBlur}\n onFocus={onFocus}\n {...field.props}\n >\n {field.placeholder != null && (\n <option value=\"\" disabled={required}>\n {field.placeholder}\n </option>\n )}\n {field.options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n );\n};\n\n/**\n * Seed a registry with the V1 built-in field types. Idempotent: existing\n * registrations (e.g. a consumer override) are left untouched.\n */\nexport function registerBuiltins(registry: FieldRegistry): void {\n if (!registry.has(\"input\")) {\n registry.register(\"input\", { component: InputControl, defaultValue: \"\" });\n }\n if (!registry.has(\"dropdown\")) {\n registry.register(\"dropdown\", {\n component: DropdownControl,\n defaultValue: \"\",\n validateConfig: (config) =>\n Array.isArray((config as Partial<DropdownFieldConfig>).options)\n ? null\n : \"a dropdown field requires an `options` array\",\n });\n }\n}\n\nlet seeded = false;\n\n/**\n * Register the built-ins on the module-global registry exactly once, lazily.\n * Called from `useFieldsetState` / `<Fieldset>` rather than at module load so\n * that importing a standalone control never pulls the built-ins (and the\n * validation engine) into the bundle.\n */\nexport function ensureBuiltins(defaultRegistry: FieldRegistry): void {\n if (seeded) return;\n seeded = true;\n registerBuiltins(defaultRegistry);\n}\n","import { defaultRegistry } from \"../core/registry/registry\";\nimport { type UseFieldsetStateOptions, useFieldsetState } from \"../core/state/use-fieldset-state\";\nimport { cx } from \"../internal/cx\";\nimport { FieldGrid, FieldGridItem } from \"../layout/FieldGrid\";\nimport type { FieldsetProps } from \"../types/props\";\nimport { FieldRenderer } from \"./FieldRenderer\";\nimport { ensureBuiltins } from \"./register-builtins\";\n\n/**\n * Renders a form (or a form section) from a `FieldsetConfig`. Controlled when\n * `value` is passed, uncontrolled otherwise. Renders a native `<fieldset>` — so\n * `disabled` cascades to every control — and does not render its own `<form>`;\n * wrap it in one and use `useFieldsetState().handleSubmit` for submission.\n */\nexport function Fieldset<TValues extends Record<string, unknown> = Record<string, unknown>>(\n props: FieldsetProps<TValues>,\n) {\n const {\n config,\n value,\n defaultValue,\n onChange,\n onValidationChange,\n resolver,\n registry,\n validateOn,\n disabled,\n className,\n id,\n } = props;\n\n ensureBuiltins(defaultRegistry);\n const activeRegistry = registry ?? defaultRegistry;\n\n const options: UseFieldsetStateOptions<TValues> = {\n registry: activeRegistry,\n ...(value !== undefined ? { value } : {}),\n ...(defaultValue !== undefined ? { defaultValue } : {}),\n ...(onChange ? { onChange } : {}),\n ...(onValidationChange ? { onValidationChange } : {}),\n ...(resolver ? { resolver } : {}),\n ...(validateOn ? { validateOn } : {}),\n };\n\n const fs = useFieldsetState<TValues>(config, options);\n const { columns, gap, legend, fields, id: configId } = fs.config;\n\n return (\n <fieldset\n className={cx(\"orynn-fieldset\", className)}\n id={id ?? configId}\n disabled={disabled || undefined}\n >\n {legend != null && <legend className=\"orynn-fieldset__legend\">{legend}</legend>}\n <FieldGrid columns={columns} gap={gap}>\n {fields.map((field) => (\n <FieldGridItem key={field.name} span={field.layout} columns={columns}>\n <FieldRenderer\n field={field}\n registry={activeRegistry}\n slice={fs.getFieldProps(field.name)}\n disabled={disabled === true}\n />\n </FieldGridItem>\n ))}\n </FieldGrid>\n </fieldset>\n );\n}\n","import type { FieldsetConfig } from \"./config\";\n\n/**\n * Per-field validation config. V1 ships `required` / `minLength` / `maxLength`.\n * Future rule keys (regex, email, min, max, validate, ...) are added here without\n * a breaking change.\n */\nexport interface FieldValidation {\n required?: boolean;\n minLength?: number;\n maxLength?: number;\n /** Per-rule message overrides, e.g. `{ required: \"Name is required\" }`. */\n messages?: Partial<Record<string, string>>;\n}\n\n/** A single validation failure. Shape is frozen — new fields must stay optional. */\nexport interface FieldError {\n /** Rule that failed: `\"required\"`, `\"minLength\"`, `\"custom\"`, `\"async\"`, ... */\n rule: string;\n message: string;\n /** Reserved for cross-field / nested errors. Unused in V1. */\n path?: string;\n}\n\n/**\n * Validation output. Key = field name. The reserved key `\"$form\"` holds\n * form-level / cross-field errors.\n */\nexport type ValidationResult = Record<string, FieldError[]>;\n\n/** Reserved key in {@link ValidationResult} for form-level errors. */\nexport const FORM_ERROR_KEY = \"$form\" as const;\n\n/** What triggered a validation run. */\nexport type ValidationTrigger = \"change\" | \"blur\" | \"submit\";\n\nexport interface ValidationContext {\n /** Field whose change/blur triggered this run, if any. */\n changedField?: string;\n trigger: ValidationTrigger;\n}\n\n/**\n * The single seam through which all validation flows. V1's default resolver is\n * rule-based and synchronous; the `Promise` return type keeps async, schema, and\n * cross-field validation additive.\n */\nexport type ValidationResolver = (\n values: Record<string, unknown>,\n config: FieldsetConfig,\n context: ValidationContext,\n) => ValidationResult | Promise<ValidationResult>;\n\n/**\n * A single rule implementation. Returns an error message string on failure, or\n * `null` on success. `allValues` is passed so cross-field rules need no\n * signature change later.\n */\nexport type RuleFn = (\n value: unknown,\n param: unknown,\n allValues: Record<string, unknown>,\n) => string | null;\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentType, SyntheticEvent, SelectHTMLAttributes, ReactNode, ChangeEvent, InputHTMLAttributes, FormEvent } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Per-field validation config. V1 ships `required` / `minLength` / `maxLength`.
|
|
6
|
+
* Future rule keys (regex, email, min, max, validate, ...) are added here without
|
|
7
|
+
* a breaking change.
|
|
8
|
+
*/
|
|
9
|
+
interface FieldValidation {
|
|
10
|
+
required?: boolean;
|
|
11
|
+
minLength?: number;
|
|
12
|
+
maxLength?: number;
|
|
13
|
+
/** Per-rule message overrides, e.g. `{ required: "Name is required" }`. */
|
|
14
|
+
messages?: Partial<Record<string, string>>;
|
|
15
|
+
}
|
|
16
|
+
/** A single validation failure. Shape is frozen — new fields must stay optional. */
|
|
17
|
+
interface FieldError {
|
|
18
|
+
/** Rule that failed: `"required"`, `"minLength"`, `"custom"`, `"async"`, ... */
|
|
19
|
+
rule: string;
|
|
20
|
+
message: string;
|
|
21
|
+
/** Reserved for cross-field / nested errors. Unused in V1. */
|
|
22
|
+
path?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validation output. Key = field name. The reserved key `"$form"` holds
|
|
26
|
+
* form-level / cross-field errors.
|
|
27
|
+
*/
|
|
28
|
+
type ValidationResult = Record<string, FieldError[]>;
|
|
29
|
+
/** Reserved key in {@link ValidationResult} for form-level errors. */
|
|
30
|
+
declare const FORM_ERROR_KEY: "$form";
|
|
31
|
+
/** What triggered a validation run. */
|
|
32
|
+
type ValidationTrigger = "change" | "blur" | "submit";
|
|
33
|
+
interface ValidationContext {
|
|
34
|
+
/** Field whose change/blur triggered this run, if any. */
|
|
35
|
+
changedField?: string;
|
|
36
|
+
trigger: ValidationTrigger;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The single seam through which all validation flows. V1's default resolver is
|
|
40
|
+
* rule-based and synchronous; the `Promise` return type keeps async, schema, and
|
|
41
|
+
* cross-field validation additive.
|
|
42
|
+
*/
|
|
43
|
+
type ValidationResolver = (values: Record<string, unknown>, config: FieldsetConfig, context: ValidationContext) => ValidationResult | Promise<ValidationResult>;
|
|
44
|
+
/**
|
|
45
|
+
* A single rule implementation. Returns an error message string on failure, or
|
|
46
|
+
* `null` on success. `allValues` is passed so cross-field rules need no
|
|
47
|
+
* signature change later.
|
|
48
|
+
*/
|
|
49
|
+
type RuleFn = (value: unknown, param: unknown, allValues: Record<string, unknown>) => string | null;
|
|
50
|
+
|
|
51
|
+
/** A single selectable option in a {@link DropdownFieldConfig}. */
|
|
52
|
+
interface DropdownOption {
|
|
53
|
+
label: string;
|
|
54
|
+
value: string;
|
|
55
|
+
disabled?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** Number of columns at each responsive breakpoint. */
|
|
58
|
+
interface ColumnSpec {
|
|
59
|
+
desktop: number;
|
|
60
|
+
tablet: number;
|
|
61
|
+
mobile: number;
|
|
62
|
+
}
|
|
63
|
+
/** Fields common to every field type. */
|
|
64
|
+
interface BaseFieldConfig {
|
|
65
|
+
/** Unique key within the fieldset; also the key in the values object. */
|
|
66
|
+
name: string;
|
|
67
|
+
label?: string;
|
|
68
|
+
description?: string;
|
|
69
|
+
placeholder?: string;
|
|
70
|
+
disabled?: boolean;
|
|
71
|
+
readOnly?: boolean;
|
|
72
|
+
defaultValue?: unknown;
|
|
73
|
+
validation?: FieldValidation;
|
|
74
|
+
/** Field-level column span, overriding the fieldset's `columns`. */
|
|
75
|
+
layout?: Partial<ColumnSpec>;
|
|
76
|
+
/** Escape hatch: spread verbatim onto the underlying control. */
|
|
77
|
+
props?: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
/** Native `<input>` field. `inputType` maps to the DOM `type` attribute. */
|
|
80
|
+
interface InputFieldConfig extends BaseFieldConfig {
|
|
81
|
+
type: "input";
|
|
82
|
+
inputType?: "text" | "email" | "password" | "number" | "tel" | "url";
|
|
83
|
+
}
|
|
84
|
+
/** Native `<select>` field. */
|
|
85
|
+
interface DropdownFieldConfig extends BaseFieldConfig {
|
|
86
|
+
type: "dropdown";
|
|
87
|
+
options: DropdownOption[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Maps a field `type` string to its config shape. Consumers register custom
|
|
91
|
+
* field types by augmenting this interface:
|
|
92
|
+
*
|
|
93
|
+
* ```ts
|
|
94
|
+
* declare module "orynn" {
|
|
95
|
+
* interface FieldConfigRegistry {
|
|
96
|
+
* rating: RatingFieldConfig;
|
|
97
|
+
* }
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
interface FieldConfigRegistry {
|
|
102
|
+
input: InputFieldConfig;
|
|
103
|
+
dropdown: DropdownFieldConfig;
|
|
104
|
+
}
|
|
105
|
+
/** Discriminated union of every registered field config. */
|
|
106
|
+
type FieldConfig = FieldConfigRegistry[keyof FieldConfigRegistry];
|
|
107
|
+
/** The `type` discriminant of any registered field. */
|
|
108
|
+
type FieldType = keyof FieldConfigRegistry;
|
|
109
|
+
/** Top-level configuration passed to `<Fieldset config={...} />`. */
|
|
110
|
+
interface FieldsetConfig {
|
|
111
|
+
fields: FieldConfig[];
|
|
112
|
+
/** Rendered in a `<legend>` when present. */
|
|
113
|
+
legend?: string;
|
|
114
|
+
/** Columns per breakpoint. Defaults to `{ desktop: 3, tablet: 2, mobile: 1 }`. */
|
|
115
|
+
columns?: Partial<ColumnSpec>;
|
|
116
|
+
/** Grid gap; a number is treated as pixels. */
|
|
117
|
+
gap?: string | number;
|
|
118
|
+
id?: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The contract every control receives from `Fieldset`. This is the stability
|
|
123
|
+
* boundary between the orchestrator and the controls: as long as this holds,
|
|
124
|
+
* either side can change freely.
|
|
125
|
+
*/
|
|
126
|
+
interface ControlProps<TValue = unknown> {
|
|
127
|
+
id: string;
|
|
128
|
+
name: string;
|
|
129
|
+
value: TValue;
|
|
130
|
+
/** Value-first; the DOM event is the optional second argument. */
|
|
131
|
+
onChange: (value: TValue, event?: SyntheticEvent) => void;
|
|
132
|
+
onBlur: () => void;
|
|
133
|
+
onFocus: () => void;
|
|
134
|
+
disabled?: boolean;
|
|
135
|
+
readOnly?: boolean;
|
|
136
|
+
required?: boolean;
|
|
137
|
+
invalid?: boolean;
|
|
138
|
+
/** Space-separated id list to place on the control's `aria-describedby`. */
|
|
139
|
+
describedById?: string;
|
|
140
|
+
/** The full field config, for type-specific data (e.g. dropdown `options`). */
|
|
141
|
+
config: FieldConfig;
|
|
142
|
+
}
|
|
143
|
+
/** A React component that satisfies {@link ControlProps}. */
|
|
144
|
+
type ControlComponent<TValue = any> = ComponentType<ControlProps<TValue>>;
|
|
145
|
+
/** A registry entry for one field `type`. */
|
|
146
|
+
interface FieldRegistration<TValue = any> {
|
|
147
|
+
component: ControlComponent<TValue>;
|
|
148
|
+
/** Value used when neither the config nor the form supplies one. */
|
|
149
|
+
defaultValue?: TValue;
|
|
150
|
+
/** Normalize an incoming value before it reaches the control. */
|
|
151
|
+
parseValue?: (raw: unknown) => TValue;
|
|
152
|
+
/** Normalize an outgoing value before it reaches `onChange`. */
|
|
153
|
+
formatValue?: (value: TValue) => unknown;
|
|
154
|
+
/**
|
|
155
|
+
* Type-specific config validation. Return an error string to reject a field
|
|
156
|
+
* config (thrown in development), or `null` when it is valid. Keeps per-type
|
|
157
|
+
* knowledge out of the core normalizer.
|
|
158
|
+
*/
|
|
159
|
+
validateConfig?: (config: BaseFieldConfig & {
|
|
160
|
+
type: string;
|
|
161
|
+
}) => string | null;
|
|
162
|
+
}
|
|
163
|
+
/** Read-only view of a field registry. */
|
|
164
|
+
interface FieldRegistry {
|
|
165
|
+
register(type: string, registration: FieldRegistration): void;
|
|
166
|
+
get(type: string): FieldRegistration | undefined;
|
|
167
|
+
has(type: string): boolean;
|
|
168
|
+
/** All registered type strings, for error messages. */
|
|
169
|
+
types(): string[];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Error prop accepted by controls: one message or many. */
|
|
173
|
+
type ErrorProp = string | string[] | undefined;
|
|
174
|
+
/** Context handed to `<Field>`'s render function. */
|
|
175
|
+
interface FieldRenderContext {
|
|
176
|
+
/** Resolved control id (generated when not supplied). */
|
|
177
|
+
id: string;
|
|
178
|
+
/** Value for the control's `aria-describedby`, or `undefined`. */
|
|
179
|
+
describedById: string | undefined;
|
|
180
|
+
invalid: boolean;
|
|
181
|
+
required: boolean | undefined;
|
|
182
|
+
disabled: boolean | undefined;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Low-level layout + a11y wrapper. Renders label, description and error region
|
|
186
|
+
* and wires the ARIA relationships. `Input` and `Dropdown` are built on it, and
|
|
187
|
+
* it is exported for custom control authors.
|
|
188
|
+
*/
|
|
189
|
+
interface FieldProps {
|
|
190
|
+
label?: ReactNode;
|
|
191
|
+
description?: ReactNode;
|
|
192
|
+
error?: ErrorProp;
|
|
193
|
+
required?: boolean;
|
|
194
|
+
disabled?: boolean;
|
|
195
|
+
/** Control id; generated with `useId` when omitted. */
|
|
196
|
+
id?: string;
|
|
197
|
+
className?: string;
|
|
198
|
+
children: ReactNode | ((ctx: FieldRenderContext) => ReactNode);
|
|
199
|
+
}
|
|
200
|
+
/** Props shared by the standalone controls. */
|
|
201
|
+
interface SharedControlProps {
|
|
202
|
+
label?: ReactNode;
|
|
203
|
+
description?: ReactNode;
|
|
204
|
+
error?: ErrorProp;
|
|
205
|
+
}
|
|
206
|
+
interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "type">, SharedControlProps {
|
|
207
|
+
value?: string;
|
|
208
|
+
onChange?: (value: string, event?: ChangeEvent<HTMLInputElement>) => void;
|
|
209
|
+
type?: "text" | "email" | "password" | "number" | "tel" | "url";
|
|
210
|
+
}
|
|
211
|
+
interface DropdownProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "onChange" | "value">, SharedControlProps {
|
|
212
|
+
options: DropdownOption[];
|
|
213
|
+
value?: string;
|
|
214
|
+
onChange?: (value: string, event?: ChangeEvent<HTMLSelectElement>) => void;
|
|
215
|
+
/** Renders a non-selectable prompt option when the value is empty. */
|
|
216
|
+
placeholder?: string;
|
|
217
|
+
}
|
|
218
|
+
interface FieldsetProps<TValues extends Record<string, unknown> = Record<string, unknown>> {
|
|
219
|
+
config: FieldsetConfig;
|
|
220
|
+
/** Controlled values. Omit and use `defaultValue` for uncontrolled. */
|
|
221
|
+
value?: TValues;
|
|
222
|
+
defaultValue?: Partial<TValues>;
|
|
223
|
+
onChange?: (values: TValues) => void;
|
|
224
|
+
onValidationChange?: (result: ValidationResult) => void;
|
|
225
|
+
/** Replace validation wholesale. Defaults to the built-in rule resolver. */
|
|
226
|
+
resolver?: ValidationResolver;
|
|
227
|
+
/** Override the field registry for this instance. */
|
|
228
|
+
registry?: FieldRegistry;
|
|
229
|
+
/** When to validate. `"blur"` (default) also always validates on submit. */
|
|
230
|
+
validateOn?: ValidationTrigger;
|
|
231
|
+
/** Disable every field (rendered as a native `<fieldset disabled>`). */
|
|
232
|
+
disabled?: boolean;
|
|
233
|
+
className?: string;
|
|
234
|
+
id?: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* A labelled single-select built on the native `<select>` element (accessible
|
|
239
|
+
* and keyboard-navigable out of the box). Works with or without `<Fieldset>`.
|
|
240
|
+
*/
|
|
241
|
+
declare const Dropdown: react.ForwardRefExoticComponent<DropdownProps & react.RefAttributes<HTMLSelectElement>>;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Layout + accessibility wrapper for a single control. Renders the label,
|
|
245
|
+
* optional description, and an error region, and wires the ARIA relationships
|
|
246
|
+
* (`htmlFor`, `aria-describedby`, `aria-invalid`, `aria-required`).
|
|
247
|
+
*
|
|
248
|
+
* Pass a render function as `children` to receive the resolved ids:
|
|
249
|
+
*
|
|
250
|
+
* ```tsx
|
|
251
|
+
* <Field label="Name" error={error}>
|
|
252
|
+
* {({ id, describedById, invalid }) => (
|
|
253
|
+
* <input id={id} aria-describedby={describedById} aria-invalid={invalid} />
|
|
254
|
+
* )}
|
|
255
|
+
* </Field>
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare function Field(props: FieldProps): react.JSX.Element;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* A labelled text input. Controlled when `value` is passed, uncontrolled
|
|
262
|
+
* otherwise (`defaultValue` flows through to the native element). Works with or
|
|
263
|
+
* without `<Fieldset>`.
|
|
264
|
+
*/
|
|
265
|
+
declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Renders a form (or a form section) from a `FieldsetConfig`. Controlled when
|
|
269
|
+
* `value` is passed, uncontrolled otherwise. Renders a native `<fieldset>` — so
|
|
270
|
+
* `disabled` cascades to every control — and does not render its own `<form>`;
|
|
271
|
+
* wrap it in one and use `useFieldsetState().handleSubmit` for submission.
|
|
272
|
+
*/
|
|
273
|
+
declare function Fieldset<TValues extends Record<string, unknown> = Record<string, unknown>>(props: FieldsetProps<TValues>): react.JSX.Element;
|
|
274
|
+
|
|
275
|
+
/** Form-level validation roll-up. */
|
|
276
|
+
type FieldStatus = "idle" | "validating" | "valid" | "invalid";
|
|
277
|
+
/** The complete state a fieldset tracks. New keys must be additive. */
|
|
278
|
+
interface FieldsetState {
|
|
279
|
+
values: Record<string, unknown>;
|
|
280
|
+
/** Field has been blurred at least once. */
|
|
281
|
+
touched: Record<string, boolean>;
|
|
282
|
+
/** Field value differs from its initial value. */
|
|
283
|
+
dirty: Record<string, boolean>;
|
|
284
|
+
errors: ValidationResult;
|
|
285
|
+
status: FieldStatus;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** A validated `FieldsetConfig` with every default resolved. */
|
|
289
|
+
interface NormalizedFieldsetConfig {
|
|
290
|
+
fields: FieldConfig[];
|
|
291
|
+
columns: ColumnSpec;
|
|
292
|
+
/** CSS length for the grid gap, or `undefined` to use the token default. */
|
|
293
|
+
gap: string | undefined;
|
|
294
|
+
legend: string | undefined;
|
|
295
|
+
id: string | undefined;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Validate a `FieldsetConfig` and resolve its defaults. Structural problems
|
|
299
|
+
* throw in development with an actionable message; in production the checks are
|
|
300
|
+
* stripped and normalization is defensive.
|
|
301
|
+
*
|
|
302
|
+
* Pass `registry` (as `<Fieldset>` does) to also validate each field's `type`
|
|
303
|
+
* and run type-specific config checks.
|
|
304
|
+
*/
|
|
305
|
+
declare function normalizeConfig(config: FieldsetConfig, registry?: FieldRegistry): NormalizedFieldsetConfig;
|
|
306
|
+
|
|
307
|
+
type Values = Record<string, unknown>;
|
|
308
|
+
interface UseFieldsetStateOptions<TValues extends Values = Values> {
|
|
309
|
+
/** Controlled values. Omit and pass `defaultValue` for uncontrolled. */
|
|
310
|
+
value?: TValues;
|
|
311
|
+
defaultValue?: Partial<TValues>;
|
|
312
|
+
onChange?: (values: TValues) => void;
|
|
313
|
+
/** Called after a full validation pass (`validate()` / submit), not per blur. */
|
|
314
|
+
onValidationChange?: (result: ValidationResult) => void;
|
|
315
|
+
resolver?: ValidationResolver;
|
|
316
|
+
registry?: FieldRegistry;
|
|
317
|
+
/** `"blur"` (default) also always validates on submit. */
|
|
318
|
+
validateOn?: ValidationTrigger;
|
|
319
|
+
}
|
|
320
|
+
/** Everything a renderer needs for one field. Handlers are referentially stable. */
|
|
321
|
+
interface FieldSlice {
|
|
322
|
+
name: string;
|
|
323
|
+
value: unknown;
|
|
324
|
+
errors: FieldError[];
|
|
325
|
+
touched: boolean;
|
|
326
|
+
dirty: boolean;
|
|
327
|
+
setValue: (value: unknown) => void;
|
|
328
|
+
markTouched: () => void;
|
|
329
|
+
}
|
|
330
|
+
interface UseFieldsetStateReturn<TValues extends Values = Values> {
|
|
331
|
+
config: NormalizedFieldsetConfig;
|
|
332
|
+
state: FieldsetState;
|
|
333
|
+
values: TValues;
|
|
334
|
+
errors: ValidationResult;
|
|
335
|
+
touched: Record<string, boolean>;
|
|
336
|
+
dirty: Record<string, boolean>;
|
|
337
|
+
status: FieldStatus;
|
|
338
|
+
isValid: boolean;
|
|
339
|
+
setFieldValue: (name: string, value: unknown) => void;
|
|
340
|
+
setValues: (values: TValues) => void;
|
|
341
|
+
reset: (next?: Partial<TValues>) => void;
|
|
342
|
+
validate: () => Promise<ValidationResult>;
|
|
343
|
+
handleSubmit: (onValid: (values: TValues) => void, onInvalid?: (result: ValidationResult) => void) => (event?: FormEvent) => void;
|
|
344
|
+
getFieldProps: (name: string) => FieldSlice;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The form engine behind `<Fieldset>`, usable directly when you want to own the
|
|
348
|
+
* markup. Manages values (controlled or uncontrolled), touched/dirty tracking,
|
|
349
|
+
* and validation through a pluggable resolver.
|
|
350
|
+
*/
|
|
351
|
+
declare function useFieldsetState<TValues extends Values = Values>(config: FieldsetConfig, options?: UseFieldsetStateOptions<TValues>): UseFieldsetStateReturn<TValues>;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Create an isolated field registry. Use this to give a `<Fieldset>` its own set
|
|
355
|
+
* of field types without touching the module-global {@link defaultRegistry}
|
|
356
|
+
* (recommended on the server, where mutating a shared registry per request would
|
|
357
|
+
* leak between requests).
|
|
358
|
+
*
|
|
359
|
+
* @experimental The registry API may change before 1.0.
|
|
360
|
+
*/
|
|
361
|
+
declare function createRegistry(): FieldRegistry;
|
|
362
|
+
/**
|
|
363
|
+
* The module-global registry used by `<Fieldset>` when no `registry` prop is
|
|
364
|
+
* passed. Seeded with the built-in `input` and `dropdown` fields.
|
|
365
|
+
*
|
|
366
|
+
* @experimental
|
|
367
|
+
*/
|
|
368
|
+
declare const defaultRegistry: FieldRegistry;
|
|
369
|
+
/**
|
|
370
|
+
* Register a field type on the {@link defaultRegistry}. Call this once at
|
|
371
|
+
* application start-up, not per render or per request.
|
|
372
|
+
*
|
|
373
|
+
* @experimental
|
|
374
|
+
*/
|
|
375
|
+
declare function registerField(type: string, registration: FieldRegistration): void;
|
|
376
|
+
|
|
377
|
+
/** A synchronous resolver — the built-in resolver's precise return type. */
|
|
378
|
+
type SyncResolver = (values: Record<string, unknown>, config: FieldsetConfig, context: ValidationContext) => ValidationResult;
|
|
379
|
+
/**
|
|
380
|
+
* The default, rule-based {@link ValidationResolver}. For every field with a
|
|
381
|
+
* `validation` block, each key (other than `messages`) is looked up in the rule
|
|
382
|
+
* registry and run against the field's current value. All fields are validated
|
|
383
|
+
* on every call; callers decide which errors to surface.
|
|
384
|
+
*
|
|
385
|
+
* Synchronous today. Async, schema-based, and cross-field resolvers plug in at
|
|
386
|
+
* the same seam without an API change.
|
|
387
|
+
*/
|
|
388
|
+
declare function createRuleResolver(): SyncResolver;
|
|
389
|
+
/** Shared default instance. */
|
|
390
|
+
declare const defaultResolver: ValidationResolver;
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Register a validation rule for the built-in resolver. A field opts in by
|
|
394
|
+
* adding a key of the same name to its `validation` config.
|
|
395
|
+
*
|
|
396
|
+
* @experimental The rule API may change before 1.0.
|
|
397
|
+
*/
|
|
398
|
+
declare function registerRule(name: string, fn: RuleFn): void;
|
|
399
|
+
|
|
400
|
+
export { type BaseFieldConfig, type ColumnSpec, type ControlComponent, type ControlProps, Dropdown, type DropdownFieldConfig, type DropdownOption, type DropdownProps, type ErrorProp, FORM_ERROR_KEY, Field, type FieldConfig, type FieldConfigRegistry, type FieldError, type FieldProps, type FieldRegistration, type FieldRegistry, type FieldRenderContext, type FieldSlice, type FieldStatus, type FieldType, type FieldValidation, Fieldset, type FieldsetConfig, type FieldsetProps, type FieldsetState, Input, type InputFieldConfig, type InputProps, type NormalizedFieldsetConfig, type RuleFn, type SyncResolver, type UseFieldsetStateOptions, type UseFieldsetStateReturn, type ValidationContext, type ValidationResolver, type ValidationResult, type ValidationTrigger, createRegistry, createRuleResolver, defaultRegistry, defaultResolver, normalizeConfig, registerField, registerRule, useFieldsetState };
|