joopjs 2.0.6 → 2.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.
Files changed (140) hide show
  1. package/.claude/skills/observables.md +28 -0
  2. package/.claude/skills/setup.md +14 -3
  3. package/.cursor/rules/joopjs.mdc +4 -5
  4. package/.github/copilot-instructions.md +3 -1
  5. package/.windsurf/rules/joopjs.md +4 -0
  6. package/CHANGELOG.md +31 -2
  7. package/README.md +19 -7
  8. package/ai-rules/AGENTS.md +21 -0
  9. package/ai-rules/GEMINI.md +17 -3
  10. package/dist/ai/index.js +15 -3
  11. package/dist/ai/index.js.map +1 -1
  12. package/dist/ai/index.mjs +15 -3
  13. package/dist/ai/index.mjs.map +1 -1
  14. package/dist/analytics/index.js +10 -2
  15. package/dist/analytics/index.js.map +1 -1
  16. package/dist/analytics/index.mjs +10 -2
  17. package/dist/analytics/index.mjs.map +1 -1
  18. package/dist/angular/index.d.mts +98 -27
  19. package/dist/angular/index.d.ts +98 -27
  20. package/dist/angular/index.js +44 -0
  21. package/dist/angular/index.js.map +1 -1
  22. package/dist/angular/index.mjs +39 -1
  23. package/dist/angular/index.mjs.map +1 -1
  24. package/dist/api/index.js +15 -3
  25. package/dist/api/index.js.map +1 -1
  26. package/dist/api/index.mjs +15 -3
  27. package/dist/api/index.mjs.map +1 -1
  28. package/dist/auth/index.js +15 -3
  29. package/dist/auth/index.js.map +1 -1
  30. package/dist/auth/index.mjs +15 -3
  31. package/dist/auth/index.mjs.map +1 -1
  32. package/dist/banking/index.js +15 -3
  33. package/dist/banking/index.js.map +1 -1
  34. package/dist/banking/index.mjs +15 -3
  35. package/dist/banking/index.mjs.map +1 -1
  36. package/dist/cache/index.js +15 -3
  37. package/dist/cache/index.js.map +1 -1
  38. package/dist/cache/index.mjs +15 -3
  39. package/dist/cache/index.mjs.map +1 -1
  40. package/dist/{index-DFqEoX_l.d.ts → consent.service-CIHNtx9h.d.ts} +1 -2
  41. package/dist/{index-B_ksKpS1.d.mts → consent.service-DQ-JAEJx.d.mts} +1 -2
  42. package/dist/core/index.d.mts +34 -1
  43. package/dist/core/index.d.ts +34 -1
  44. package/dist/core/index.js +56 -5
  45. package/dist/core/index.js.map +1 -1
  46. package/dist/core/index.mjs +54 -6
  47. package/dist/core/index.mjs.map +1 -1
  48. package/dist/deeplink/index.js +15 -3
  49. package/dist/deeplink/index.js.map +1 -1
  50. package/dist/deeplink/index.mjs +15 -3
  51. package/dist/deeplink/index.mjs.map +1 -1
  52. package/dist/device/index.js +15 -3
  53. package/dist/device/index.js.map +1 -1
  54. package/dist/device/index.mjs +15 -3
  55. package/dist/device/index.mjs.map +1 -1
  56. package/dist/forms/index.js +15 -3
  57. package/dist/forms/index.js.map +1 -1
  58. package/dist/forms/index.mjs +15 -3
  59. package/dist/forms/index.mjs.map +1 -1
  60. package/dist/i18n/index.js +15 -3
  61. package/dist/i18n/index.js.map +1 -1
  62. package/dist/i18n/index.mjs +15 -3
  63. package/dist/i18n/index.mjs.map +1 -1
  64. package/dist/index.d.mts +2 -2
  65. package/dist/index.d.ts +2 -2
  66. package/dist/index.js +50 -8
  67. package/dist/index.js.map +1 -1
  68. package/dist/index.mjs +50 -8
  69. package/dist/index.mjs.map +1 -1
  70. package/dist/{joop-CA3DMeOO.d.ts → joop-Dim2yEKG.d.ts} +1 -1
  71. package/dist/{joop-Bx7Iwj5p.d.mts → joop-GkQw13f9.d.mts} +1 -1
  72. package/dist/native-bridge/index.js +10 -2
  73. package/dist/native-bridge/index.js.map +1 -1
  74. package/dist/native-bridge/index.mjs +10 -2
  75. package/dist/native-bridge/index.mjs.map +1 -1
  76. package/dist/network/index.js +15 -3
  77. package/dist/network/index.js.map +1 -1
  78. package/dist/network/index.mjs +15 -3
  79. package/dist/network/index.mjs.map +1 -1
  80. package/dist/observability/index.js +15 -3
  81. package/dist/observability/index.js.map +1 -1
  82. package/dist/observability/index.mjs +15 -3
  83. package/dist/observability/index.mjs.map +1 -1
  84. package/dist/pwa/index.js +15 -3
  85. package/dist/pwa/index.js.map +1 -1
  86. package/dist/pwa/index.mjs +15 -3
  87. package/dist/pwa/index.mjs.map +1 -1
  88. package/dist/react/index.d.mts +2 -2
  89. package/dist/react/index.d.ts +2 -2
  90. package/dist/react/index.js +15 -3
  91. package/dist/react/index.js.map +1 -1
  92. package/dist/react/index.mjs +15 -3
  93. package/dist/react/index.mjs.map +1 -1
  94. package/dist/router/index.js +15 -3
  95. package/dist/router/index.js.map +1 -1
  96. package/dist/router/index.mjs +15 -3
  97. package/dist/router/index.mjs.map +1 -1
  98. package/dist/security/index.js +15 -3
  99. package/dist/security/index.js.map +1 -1
  100. package/dist/security/index.mjs +15 -3
  101. package/dist/security/index.mjs.map +1 -1
  102. package/dist/session/index.js +15 -3
  103. package/dist/session/index.js.map +1 -1
  104. package/dist/session/index.mjs +15 -3
  105. package/dist/session/index.mjs.map +1 -1
  106. package/dist/state/index.js +15 -3
  107. package/dist/state/index.js.map +1 -1
  108. package/dist/state/index.mjs +15 -3
  109. package/dist/state/index.mjs.map +1 -1
  110. package/dist/storage/index.js +15 -3
  111. package/dist/storage/index.js.map +1 -1
  112. package/dist/storage/index.mjs +15 -3
  113. package/dist/storage/index.mjs.map +1 -1
  114. package/dist/sync/index.js +15 -3
  115. package/dist/sync/index.js.map +1 -1
  116. package/dist/sync/index.mjs +15 -3
  117. package/dist/sync/index.mjs.map +1 -1
  118. package/dist/theme/index.js +15 -3
  119. package/dist/theme/index.js.map +1 -1
  120. package/dist/theme/index.mjs +15 -3
  121. package/dist/theme/index.mjs.map +1 -1
  122. package/dist/ui/index.js +15 -3
  123. package/dist/ui/index.js.map +1 -1
  124. package/dist/ui/index.mjs +15 -3
  125. package/dist/ui/index.mjs.map +1 -1
  126. package/dist/utilities/index.js +46 -4
  127. package/dist/utilities/index.js.map +1 -1
  128. package/dist/utilities/index.mjs +46 -4
  129. package/dist/utilities/index.mjs.map +1 -1
  130. package/dist/vue/index.d.mts +2 -2
  131. package/dist/vue/index.d.ts +2 -2
  132. package/dist/vue/index.js +15 -3
  133. package/dist/vue/index.js.map +1 -1
  134. package/dist/vue/index.mjs +15 -3
  135. package/dist/vue/index.mjs.map +1 -1
  136. package/dist/workflow/index.js +15 -3
  137. package/dist/workflow/index.js.map +1 -1
  138. package/dist/workflow/index.mjs +15 -3
  139. package/dist/workflow/index.mjs.map +1 -1
  140. package/package.json +16 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/banking/iban.utility.ts","../../src/banking/luhn.utility.ts","../../src/banking/amount.utility.ts","../../src/validation/form-validator.ts","../../src/forms/form-builder.ts"],"names":[],"mappings":";;;AAOO,IAAM,cAAN,MAAqB;AAAA,EAClB,aAA4B,EAAC;AAAA,EAErC,UAAU,QAAA,EAAoC;AAC5C,IAAA,IAAA,CAAK,UAAA,CAAW,KAAK,QAAQ,CAAA;AAC7B,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,aAAa,IAAA,CAAK,UAAA,CAAW,MAAA,CAAO,CAAA,CAAA,KAAK,MAAM,QAAQ,CAAA;AAAA,IAC9D,CAAA;AAAA,EACF;AAAA,EAEA,KAAK,KAAA,EAAgB;AACnB,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,UAAA,EAAY;AACtC,MAAA,QAAA,CAAS,KAAK,CAAA;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,YAAA,GAAkC;AAChC,IAAA,OAAO,IAAI,cAAA,CAAkB,CAAA,QAAA,KAAY,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAAA,EACnE;AACF,CAAA;AAMO,IAAM,mBAAA,GAAN,cAAqC,WAAA,CAAe;AAAA,EACjD,MAAA;AAAA,EAER,YAAY,YAAA,EAAiB;AAC3B,IAAA,KAAA,EAAM;AACN,IAAA,IAAA,CAAK,MAAA,GAAS,YAAA;AAAA,EAChB;AAAA,EAEA,QAAA,GAAc;AACZ,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAES,KAAK,KAAA,EAAgB;AAC5B,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,EAClB;AAAA,EAES,UAAU,QAAA,EAAoC;AACrD,IAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AACpB,IAAA,OAAO,KAAA,CAAM,UAAU,QAAQ,CAAA;AAAA,EACjC;AAAA,EAES,YAAA,GAAkC;AACzC,IAAA,OAAO,IAAI,cAAA,CAAkB,CAAA,QAAA,KAAY,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAAA,EACnE;AACF,CAAA;AAKO,IAAM,iBAAN,MAAwB;AAAA,EAC7B,YAAoB,YAAA,EAAsD;AAAtD,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AAAA,EAAuD;AAAA,EAAvD,YAAA;AAAA,EAEpB,UAAU,QAAA,EAAoC;AAC5C,IAAA,OAAO,IAAA,CAAK,aAAa,QAAQ,CAAA;AAAA,EACnC;AAAA;AAAA,EAGA,OAAA,GAAyB;AACvB,IAAA,IAAI,MAAA;AACJ,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,CAAA,CAAA,KAAK;AAAE,MAAA,MAAA,GAAS,CAAA;AAAA,IAAG,CAAC,CAAA;AACjD,IAAA,KAAA,EAAM;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;;;AC5EA,IAAM,YAAA,GAAuC;AAAA,EAC3C,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI;AACtD,CAAA;AAEO,SAAS,aAAa,IAAA,EAAuB;AAClD,EAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,EAAE,EAAE,WAAA,EAAY;AAClD,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAChC,EAAA,IAAI,CAAC,aAAa,OAAO,CAAA,IAAK,MAAM,MAAA,KAAW,YAAA,CAAa,OAAO,CAAA,EAAG,OAAO,KAAA;AAE7E,EAAA,MAAM,OAAA,GAAA,CAAW,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,EAC/C,KAAA,CAAM,EAAE,EACR,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,CAAW,CAAC,CAAA,IAAK,EAAA,GAAA,CAAM,CAAA,CAAE,UAAA,CAAW,CAAC,CAAA,GAAI,EAAA,EAAI,QAAA,EAAS,GAAI,CAAC,CAAA,CACtE,KAAK,EAAE,CAAA;AAEV,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,KAAA,MAAW,MAAM,OAAA,EAAS,SAAA,GAAA,CAAa,YAAY,EAAA,GAAK,QAAA,CAAS,EAAE,CAAA,IAAK,EAAA;AACxE,EAAA,OAAO,SAAA,KAAc,CAAA;AACvB;;;ACbA,IAAM,aAAA,GAA4G;AAAA,EAChH,EAAE,OAAA,EAAS,MAAA,EAAc,OAAA,EAAS,QAAA,EAAuB,SAAS,CAAC,EAAE,CAAA,EAAQ,SAAA,EAAW,CAAA,EAAE;AAAA,EAC1F,EAAE,OAAA,EAAS,QAAA,EAAc,OAAA,EAAS,mBAAA,EAAsB,SAAS,CAAC,EAAE,CAAA,EAAQ,SAAA,EAAW,CAAA,EAAE;AAAA,EACzF,EAAE,OAAA,EAAS,UAAA,EAAc,OAAA,EAAS,qBAAA,EAAuB,SAAS,CAAC,EAAE,CAAA,EAAQ,SAAA,EAAW,CAAA,EAAE;AAAA,EAC1F,EAAE,OAAA,EAAS,KAAA,EAAc,OAAA,EAAS,mBAAA,EAAuB,SAAS,CAAC,EAAE,CAAA,EAAQ,SAAA,EAAW,CAAA,EAAE;AAAA,EAC1F,EAAE,OAAA,EAAS,SAAA,EAAc,OAAA,EAAS,wCAAA,EAA0C,SAAS,CAAC,EAAA,EAAG,EAAA,EAAG,EAAA,EAAG,IAAG,EAAA,EAAG,EAAA,EAAG,IAAG,EAAE,CAAA,EAAG,WAAW,CAAA,EAAE;AAAA,EAC7H,EAAE,OAAA,EAAS,YAAA,EAAc,OAAA,EAAS,iBAAA,EAAuB,SAAS,CAAC,EAAE,CAAA,EAAQ,SAAA,EAAW,CAAA,EAAE;AAAA,EAC1F,EAAE,OAAA,EAAS,UAAA,EAAc,OAAA,EAAS,KAAA,EAAwB,OAAA,EAAS,CAAC,EAAA,EAAG,EAAA,EAAG,EAAA,EAAG,EAAE,CAAA,EAAG,WAAW,CAAA,EAAE;AAAA,EAC/F,EAAE,OAAA,EAAS,MAAA,EAAc,OAAA,EAAS,IAAA,EAAwB,OAAA,EAAS,CAAC,EAAA,EAAG,EAAA,EAAG,EAAE,CAAA,EAAG,SAAA,EAAW,CAAA;AAC5F,CAAA;AAGO,SAAS,aAAa,UAAA,EAA6B;AACxD,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAC3C,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,KAAA;AAC9B,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,KAAA,IAAS,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC3C,IAAA,IAAI,CAAA,GAAI,QAAA,CAAS,MAAA,CAAO,CAAC,GAAG,EAAE,CAAA;AAC9B,IAAA,IAAI,MAAA,EAAQ;AAAE,MAAA,CAAA,IAAK,CAAA;AAAG,MAAA,IAAI,CAAA,GAAI,GAAG,CAAA,IAAK,CAAA;AAAA,IAAG;AACzC,IAAA,GAAA,IAAO,CAAA;AACP,IAAA,MAAA,GAAS,CAAC,MAAA;AAAA,EACZ;AACA,EAAA,OAAO,MAAM,EAAA,KAAO,CAAA;AACtB;AAiBO,SAAS,eAAe,UAAA,EAAqC;AAClE,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAC3C,EAAA,KAAA,MAAW,QAAQ,aAAA,EAAe;AAChC,IAAA,IAAI,KAAK,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA,SAAU,IAAA,CAAK,OAAA;AAAA,EAC7C;AACA,EAAA,OAAO,SAAA;AACT;;;ACnCO,SAAS,cAAc,KAAA,EAAyB;AACrD,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AACxC,IAAA,OAAO,kBAAkB,IAAA,CAAK,KAAK,KAAK,QAAA,CAAS,UAAA,CAAW,KAAK,CAAC,CAAA;AAAA,EACpE;AACA,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,QAAA,CAAS,KAAK,CAAA;AACpD;;;ACDA,IAAM,QAAA,GAAW,oJAAA;AACjB,IAAM,QAAA,GAAW,wBAAA;AAEV,IAAM,oBAAN,MAAwB;AAAA,EAE7B,SAAS,KAAA,EAA+B;AACtC,IAAA,IAAI,KAAA,IAAS,IAAA,IAAQ,KAAA,KAAU,EAAA,IAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,MAAA,KAAW,CAAA,EAAI,OAAO,wBAAA;AAC1F,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,SAAA,CAAU,OAAe,GAAA,EAA4B;AACnD,IAAA,IAAI,MAAA,CAAO,SAAS,EAAE,CAAA,CAAE,SAAS,GAAA,EAAK,OAAO,WAAW,GAAG,CAAA,oBAAA,CAAA;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,SAAA,CAAU,OAAe,GAAA,EAA4B;AACnD,IAAA,IAAI,MAAA,CAAO,SAAS,EAAE,CAAA,CAAE,SAAS,GAAA,EAAK,OAAO,WAAW,GAAG,CAAA,mBAAA,CAAA;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,GAAA,CAAI,OAAwB,GAAA,EAA4B;AACtD,IAAA,IAAI,OAAO,KAAK,CAAA,GAAI,GAAA,EAAK,OAAO,oBAAoB,GAAG,CAAA,CAAA;AACvD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,GAAA,CAAI,OAAwB,GAAA,EAA4B;AACtD,IAAA,IAAI,OAAO,KAAK,CAAA,GAAI,GAAA,EAAK,OAAO,oBAAoB,GAAG,CAAA,CAAA;AACvD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,KAAA,EAA8B;AAClC,IAAA,IAAI,CAAC,SAAS,IAAA,CAAK,MAAA,CAAO,SAAS,EAAE,CAAC,GAAG,OAAO,uBAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,KAAA,EAA8B;AAClC,IAAA,IAAI,CAAC,SAAS,IAAA,CAAK,MAAA,CAAO,SAAS,EAAE,CAAC,GAAG,OAAO,sBAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,KAAK,KAAA,EAA8B;AACjC,IAAA,IAAI,CAAC,YAAA,CAAa,MAAA,CAAO,SAAS,EAAE,CAAC,GAAG,OAAO,cAAA;AAC/C,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,KAAK,KAAA,EAA8B;AACjC,IAAA,MAAM,SAAS,MAAA,CAAO,KAAA,IAAS,EAAE,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACpD,IAAA,IAAI,CAAC,YAAA,CAAa,MAAM,CAAA,EAAG,OAAO,qBAAA;AAClC,IAAA,MAAM,OAAA,GAAU,eAAe,MAAM,CAAA;AACrC,IAAA,IAAI,OAAA,KAAY,WAAW,OAAO,wBAAA;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAA,CAAO,KAAA,EAAwB,GAAA,EAAc,GAAA,EAA6B;AACxE,IAAA,IAAI,CAAC,aAAA,CAAc,KAAK,CAAA,EAAG,OAAO,gBAAA;AAClC,IAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,IAAA,IAAI,QAAQ,MAAA,IAAa,CAAA,GAAI,GAAA,EAAK,OAAO,qBAAqB,GAAG,CAAA,CAAA;AACjE,IAAA,IAAI,QAAQ,MAAA,IAAa,CAAA,GAAI,GAAA,EAAK,OAAO,qBAAqB,GAAG,CAAA,CAAA;AACjE,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,OAAA,CAAQ,KAAA,EAAe,KAAA,EAAe,OAAA,EAAiC;AACrE,IAAA,IAAI,CAAC,MAAM,IAAA,CAAK,MAAA,CAAO,SAAS,EAAE,CAAC,CAAA,EAAG,OAAO,OAAA,IAAW,gBAAA;AACxD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,SAAA,CAAU,KAAA,EAAa,GAAA,EAAW,OAAA,EAAkB,SAAgB,OAAA,EAA+B;AACjG,IAAA,IAAI,KAAA,GAAQ,KAAK,OAAO,oCAAA;AACxB,IAAA,IAAI,WAAW,KAAA,GAAQ,OAAA,SAAgB,CAAA,4BAAA,EAA+B,OAAA,CAAQ,oBAAoB,CAAA,CAAA;AAClG,IAAA,IAAI,WAAW,GAAA,GAAM,OAAA,SAAgB,CAAA,yBAAA,EAA4B,OAAA,CAAQ,oBAAoB,CAAA,CAAA;AAC7F,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,IAAA,GAAO,KAAK,IAAA,CAAA,CAAM,GAAA,CAAI,SAAQ,GAAI,KAAA,CAAM,OAAA,EAAQ,IAAK,KAAU,CAAA;AACrE,MAAA,IAAI,IAAA,GAAO,OAAA,EAAS,OAAO,CAAA,yBAAA,EAA4B,OAAO,CAAA,KAAA,CAAA;AAAA,IAChE;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,iBAAiB,QAAA,EAAwC;AACvD,IAAA,MAAM,cAAwB,EAAC;AAC/B,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,IAAI,QAAA,CAAS,UAAU,CAAA,EAAG,KAAA,EAAA;AAAA,SAAc,WAAA,CAAY,KAAK,2BAA2B,CAAA;AACpF,IAAA,IAAI,QAAA,CAAS,UAAU,EAAA,EAAI,KAAA,EAAA;AAC3B,IAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,QAAQ,CAAA,EAAG,KAAA,EAAA;AAAA,SAAc,WAAA,CAAY,KAAK,uBAAuB,CAAA;AAClF,IAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,QAAQ,CAAA,EAAG,KAAA,EAAA;AAAA,SAAc,WAAA,CAAY,KAAK,aAAa,CAAA;AACxE,IAAA,IAAI,cAAA,CAAe,IAAA,CAAK,QAAQ,CAAA,EAAG,KAAA,EAAA;AAAA,SAAc,WAAA,CAAY,KAAK,wBAAwB,CAAA;AAC1F,IAAA,IAAI,WAAA,CAAY,IAAA,CAAK,QAAQ,CAAA,EAAG;AAAE,MAAA,KAAA,EAAA;AAAS,MAAA,WAAA,CAAY,KAAK,4BAA4B,CAAA;AAAA,IAAG;AAC3F,IAAA,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAC,CAAA;AACtC,IAAA,MAAM,SAA0C,CAAC,WAAA,EAAa,MAAA,EAAQ,MAAA,EAAQ,UAAU,aAAa,CAAA;AACrG,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,CAAO,KAAK,GAAG,WAAA,EAAY;AAAA,EACpD;AAAA;AAAA,EAGA,QAAA,CAAS,OAAgB,KAAA,EAAmD;AAC1E,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,GAAA,GAAqB,IAAA;AACzB,MAAA,QAAQ,KAAK,IAAA;AAAM,QACjB,KAAK,UAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,SAAS,KAAK,CAAA;AAAG,UAAA;AAAA,QAC/C,KAAK,WAAA;AAAc,UAAA,GAAA,GAAM,KAAK,SAAA,CAAU,MAAA,CAAO,SAAS,EAAE,CAAA,EAAG,KAAK,GAAG,CAAA;AAAG,UAAA;AAAA,QACxE,KAAK,WAAA;AAAc,UAAA,GAAA,GAAM,KAAK,SAAA,CAAU,MAAA,CAAO,SAAS,EAAE,CAAA,EAAG,KAAK,GAAG,CAAA;AAAG,UAAA;AAAA,QACxE,KAAK,KAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAA,EAAiB,IAAA,CAAK,GAAG,CAAA;AAAG,UAAA;AAAA,QAC9D,KAAK,KAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAA,EAAiB,IAAA,CAAK,GAAG,CAAA;AAAG,UAAA;AAAA,QAC9D,KAAK,OAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,EAAE,CAAC,CAAA;AAAG,UAAA;AAAA,QAC1D,KAAK,OAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,EAAE,CAAC,CAAA;AAAG,UAAA;AAAA,QAC1D,KAAK,MAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAA,IAAS,EAAE,CAAC,CAAA;AAAG,UAAA;AAAA,QACzD,KAAK,MAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAA,IAAS,EAAE,CAAC,CAAA;AAAG,UAAA;AAAA,QACzD,KAAK,QAAA;AAAc,UAAA,GAAA,GAAM,KAAK,MAAA,CAAO,KAAA,EAAiB,IAAA,CAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAG,UAAA;AAAA,QAC3E,KAAK,SAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA,IAAS,EAAE,CAAA,EAAG,IAAA,CAAK,KAAA,EAAO,IAAA,CAAK,OAAO,CAAA;AAAG,UAAA;AAAA,QACtF,KAAK,QAAA;AAAc,UAAA,GAAA,GAAM,IAAA,CAAK,SAAS,KAAK,CAAA;AAAG,UAAA;AAAA;AAEjD,MAAA,IAAI,GAAA,EAAK,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAAA,IAC1B;AACA,IAAA,OAAO,EAAE,KAAA,EAAO,MAAA,CAAO,MAAA,KAAW,GAAG,MAAA,EAAO;AAAA,EAC9C;AAAA;AAAA,EAGA,YAAA,CAAa,MAA+B,MAAA,EAAwC;AAClF,IAAA,MAAM,SAAyB,EAAC;AAChC,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AACvC,MAAA,MAAM,MAAA,GAAS,KAAK,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA,EAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AACvD,MAAA,IAAI,CAAC,MAAA,CAAO,KAAA,EAAO,MAAA,CAAO,KAAK,IAAI,MAAA,CAAO,MAAA;AAAA,IAC5C;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,YAAY,MAAA,EAAiC;AAC3C,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA;AAAA,EACxC;AACF,CAAA;;;AC5IO,IAAM,YAAN,MAA6B;AAAA,EAC1B,EAAA,GAAK,IAAI,iBAAA,EAAkB;AAAA,EAC3B,OAAA;AAAA,EACC,KAAA;AAAA,EACD,QAAA;AAAA,EACA,WAAA;AAAA,EAER,YAAY,MAAA,EAA4B;AACtC,IAAA,IAAA,CAAK,WAAW,MAAA,CAAO,KAAA;AACvB,IAAA,IAAA,CAAK,WAAA,GAAc,MAAA,CAAO,UAAA,IAAc,EAAC;AACzC,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAO,KAAA,IAAS,EAAA;AAC7B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,mBAAA,CAAuC,IAAA,CAAK,OAAO,MAAA,CAAO,KAAA,EAAO,KAAA,EAAO,KAAK,CAAC,CAAA;AAAA,EACnG;AAAA,EAEQ,MAAA,CAAO,KAAA,EAAU,KAAA,EAAgB,OAAA,EAAqC;AAC5E,IAAA,MAAM,SAA+B,IAAA,CAAK,WAAA,CAAY,MAAA,GAClD,IAAA,CAAK,GAAG,QAAA,CAAS,KAAA,EAAO,IAAA,CAAK,WAAW,IACxC,EAAE,KAAA,EAAO,IAAA,EAAM,MAAA,EAAQ,EAAC,EAAE;AAC9B,IAAA,OAAO,EAAE,OAAO,KAAA,EAAO,OAAA,EAAS,OAAO,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAO;AAAA,EAC7E;AAAA,EAEA,IAAI,KAAA,GAAW;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,KAAA;AAAA,EAAO;AAAA,EACvD,IAAI,KAAA,GAAiB;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,KAAA;AAAA,EAAO;AAAA,EAC7D,IAAI,OAAA,GAAmB;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,OAAA;AAAA,EAAS;AAAA,EACjE,IAAI,KAAA,GAAiB;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,KAAA;AAAA,EAAO;AAAA,EAC7D,IAAI,MAAA,GAAmB;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,MAAA;AAAA,EAAQ;AAAA,EAEhE,SAAS,KAAA,EAAgB;AACvB,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS;AAChC,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,CAAA,CAAE,KAAA,KAAU,KAAA,IAAS,CAAA,CAAE,KAAA,EAAO,CAAA,CAAE,OAAO,CAAC,CAAA;AAAA,EAC/E;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS;AAChC,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,EAAE,GAAG,CAAA,EAAG,OAAA,EAAS,MAAM,CAAA;AAAA,EAC3C;AAAA,EAEA,KAAA,GAAc;AAAE,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,IAAA,CAAK,MAAA,CAAO,KAAK,QAAA,EAAU,KAAA,EAAO,KAAK,CAAC,CAAA;AAAA,EAAG;AAAA,EAE7E,MAAA,GAAS;AAAE,IAAA,OAAO,IAAA,CAAK,QAAQ,YAAA,EAAa;AAAA,EAAG;AACjD;AASO,IAAM,WAAN,MAAe;AAAA,EACZ,OAAA;AAAA,EACA,OAAA;AAAA,EAER,YAAY,MAAA,EAAmC;AAC7C,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,mBAAA,CAAmC,IAAA,CAAK,UAAU,CAAA;AACrE,IAAA,KAAA,MAAW,CAAA,IAAK,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,EAAG;AACrC,MAAA,CAAA,CAAE,MAAA,EAAO,CAAE,SAAA,CAAU,MAAM,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,CAAC,CAAA;AAAA,IAC/D;AAAA,EACF;AAAA,EAEQ,QAAA,GAA0B;AAChC,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AAC3C,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,QAAQ,KAAA,CAAM,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,CAAA;AAAA,MACvC,KAAA,EAAO,QAAQ,IAAA,CAAK,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,CAAA;AAAA,MACtC,OAAA,EAAS,QAAQ,IAAA,CAAK,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA;AAAA,MAC1C,KAAA,EAAO,MAAA,CAAO,WAAA,CAAY,OAAA,CAAQ,IAAI,CAAC,CAAC,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA,EAAG,CAAA,CAAE,KAAK,CAAC,CAAC;AAAA,KACjE;AAAA,EACF;AAAA,EAEA,MAAmB,IAAA,EAA4B;AAAE,IAAA,OAAO,IAAA,CAAK,QAAQ,IAAI,CAAA;AAAA,EAAmB;AAAA,EAC5F,IAAI,KAAA,GAAiB;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,KAAA;AAAA,EAAO;AAAA,EAC7D,IAAI,KAAA,GAAiB;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,KAAA;AAAA,EAAO;AAAA,EAC7D,QAAA,GAAoC;AAAE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAS,CAAE,KAAA;AAAA,EAAO;AAAA,EAC5E,MAAA,GAAmC;AACjC,IAAA,OAAO,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,CAAC,CAAA,KAAM,CAAC,CAAA,EAAG,CAAA,CAAE,MAAM,CAAC,CAAC,CAAA;AAAA,EACnH;AAAA,EACA,KAAA,GAAc;AAAE,IAAA,MAAA,CAAO,MAAA,CAAO,KAAK,OAAO,CAAA,CAAE,QAAQ,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,CAAA;AAAA,EAAG;AAAA,EACrE,cAAA,GAAuB;AAAE,IAAA,MAAA,CAAO,MAAA,CAAO,KAAK,OAAO,CAAA,CAAE,QAAQ,CAAA,CAAA,KAAK,CAAA,CAAE,aAAa,CAAA;AAAA,EAAG;AAAA,EACpF,MAAA,GAAS;AAAE,IAAA,OAAO,IAAA,CAAK,QAAQ,YAAA,EAAa;AAAA,EAAG;AACjD;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,KAAA,CAAmB,KAAA,EAAU,UAAA,EAAmC,KAAA,EAA8B;AAC5F,IAAA,OAAO,IAAI,SAAA,CAAa,EAAE,KAAA,EAAO,UAAA,EAAY,OAAO,CAAA;AAAA,EACtD;AAAA,EAEA,OAAO,MAAA,EAA6C;AAClD,IAAA,OAAO,IAAI,SAAS,MAAM,CAAA;AAAA,EAC5B;AACF","file":"index.js","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n for (const listener of this._listeners) {\n listener(value);\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n listener(this._value);\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","const IBAN_LENGTHS: Record<string, number> = {\n AL: 28, AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22,\n BR: 29, BY: 28, CH: 21, CR: 22, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28,\n EE: 20, EG: 29, ES: 24, FI: 18, FO: 18, FR: 27, GB: 22, GE: 22, GI: 23,\n GL: 18, GR: 27, GT: 28, HR: 21, HU: 28, IE: 22, IL: 23, IQ: 23, IS: 26,\n IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28, LC: 32, LI: 21, LT: 20, LU: 20,\n LV: 21, LY: 25, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27, MT: 31, MU: 30,\n NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29, RO: 24, RS: 22,\n SA: 24, SC: 31, SD: 18, SE: 24, SI: 19, SK: 24, SM: 27, ST: 25, SV: 28,\n TL: 23, TN: 24, TR: 26, UA: 29, VA: 22, VG: 24, XK: 20,\n};\n\nexport function validateIban(iban: string): boolean {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n const country = clean.slice(0, 2);\n if (!IBAN_LENGTHS[country] || clean.length !== IBAN_LENGTHS[country]) return false;\n\n const numeric = (clean.slice(4) + clean.slice(0, 4))\n .split('')\n .map(c => c.charCodeAt(0) >= 65 ? (c.charCodeAt(0) - 55).toString() : c)\n .join('');\n\n let remainder = 0;\n for (const ch of numeric) remainder = (remainder * 10 + parseInt(ch)) % 97;\n return remainder === 1;\n}\n\nexport function formatIban(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().replace(/(.{4})/g, '$1 ').trim();\n}\n\nexport function getIbanCountry(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().slice(0, 2);\n}\n\nexport function parseIban(iban: string): { country: string; checkDigits: string; bban: string } | null {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n if (!validateIban(clean)) return null;\n return { country: clean.slice(0, 2), checkDigits: clean.slice(2, 4), bban: clean.slice(4) };\n}\n\nexport function getSupportedIbanCountries(): string[] {\n return Object.keys(IBAN_LENGTHS).sort();\n}\n","// ── Luhn algorithm & card type detection ──────────────────────────────────\n\nexport type JoopCardNetwork = 'visa' | 'mastercard' | 'amex' | 'discover' | 'unionpay' | 'jcb' | 'diners' | 'maestro' | 'unknown';\n\nexport interface JoopCardInfo {\n network: JoopCardNetwork;\n valid: boolean;\n lengths: number[];\n cvvLength: number;\n formatted: string;\n}\n\nconst CARD_PATTERNS: Array<{ network: JoopCardNetwork; pattern: RegExp; lengths: number[]; cvvLength: number }> = [\n { network: 'amex', pattern: /^3[47]/, lengths: [15], cvvLength: 4 },\n { network: 'diners', pattern: /^3(?:0[0-5]|[68])/, lengths: [14], cvvLength: 3 },\n { network: 'discover', pattern: /^6(?:011|5[0-9]{2})/, lengths: [16], cvvLength: 3 },\n { network: 'jcb', pattern: /^(?:2131|1800|35)/, lengths: [16], cvvLength: 3 },\n { network: 'maestro', pattern: /^(?:5018|5020|5038|6304|6759|676[1-3])/, lengths: [12,13,14,15,16,17,18,19], cvvLength: 3 },\n { network: 'mastercard', pattern: /^5[1-5]|^2[2-7]/, lengths: [16], cvvLength: 3 },\n { network: 'unionpay', pattern: /^62/, lengths: [16,17,18,19], cvvLength: 3 },\n { network: 'visa', pattern: /^4/, lengths: [13,16,19], cvvLength: 3 },\n];\n\n/** Validate a card number using the Luhn algorithm */\nexport function validateLuhn(cardNumber: string): boolean {\n const digits = cardNumber.replace(/\\D/g, '');\n if (digits.length < 8) return false;\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\n/** Compute the Luhn check digit for a partial card number */\nexport function luhnCheckDigit(partial: string): number {\n const digits = partial.replace(/\\D/g, '');\n let sum = 0;\n let double = true;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return (10 - (sum % 10)) % 10;\n}\n\n/** Detect the card network from the card number prefix */\nexport function getCardNetwork(cardNumber: string): JoopCardNetwork {\n const digits = cardNumber.replace(/\\D/g, '');\n for (const card of CARD_PATTERNS) {\n if (card.pattern.test(digits)) return card.network;\n }\n return 'unknown';\n}\n\n/** Get full card validation info */\nexport function getCardInfo(cardNumber: string): JoopCardInfo {\n const digits = cardNumber.replace(/\\D/g, '');\n const match = CARD_PATTERNS.find(c => c.pattern.test(digits));\n const network = match?.network ?? 'unknown';\n const lengths = match?.lengths ?? [13, 14, 15, 16, 19];\n const cvvLength = match?.cvvLength ?? 3;\n const valid = lengths.includes(digits.length) && validateLuhn(digits);\n const formatted = formatCardNumber(digits);\n return { network, valid, lengths, cvvLength, formatted };\n}\n\n/** Format card number with spaces (e.g. 4111 1111 1111 1111 or 3714 496353 98431 for Amex) */\nexport function formatCardNumber(cardNumber: string): string {\n const digits = cardNumber.replace(/\\D/g, '');\n const network = getCardNetwork(digits);\n if (network === 'amex') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{5})$/, '$1 $2 $3');\n }\n if (network === 'diners') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{4})$/, '$1 $2 $3');\n }\n return digits.replace(/(\\d{4})(?=\\d)/g, '$1 ');\n}\n\n/** Validate card expiry (MM/YY or MM/YYYY) */\nexport function isCardExpired(month: number | string, year: number | string): boolean {\n const m = parseInt(String(month), 10);\n let y = parseInt(String(year), 10);\n if (y < 100) y += 2000;\n const now = new Date();\n const expiry = new Date(y, m - 1, 1);\n expiry.setMonth(expiry.getMonth() + 1); // expire at end of month\n return expiry <= now;\n}\n\n/** Validate a CVV/CVC value */\nexport function validateCvv(cvv: string, network: JoopCardNetwork = 'unknown'): boolean {\n const digits = cvv.replace(/\\D/g, '');\n const expectedLength = network === 'amex' ? 4 : 3;\n return digits.length === expectedLength;\n}\n","export function safeAdd(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) + Math.round(b * f)) / f;\n}\n\nexport function safeSubtract(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) - Math.round(b * f)) / f;\n}\n\nexport function safeMultiply(a: number, b: number, decimals = 2): number {\n return parseFloat((a * b).toFixed(decimals));\n}\n\nexport function safeDivide(a: number, b: number, decimals = 2): number {\n if (b === 0) throw new Error('Division by zero');\n return parseFloat((a / b).toFixed(decimals));\n}\n\nexport function roundAmount(amount: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return Math.round(amount * f) / f;\n}\n\nexport function isValidAmount(value: unknown): boolean {\n if (typeof value === 'string') {\n const clean = value.replace(/[,\\s]/g, '');\n return /^-?\\d+(\\.\\d+)?$/.test(clean) && isFinite(parseFloat(clean));\n }\n return typeof value === 'number' && isFinite(value);\n}\n\nexport function clampAmount(amount: number, min: number, max: number): number {\n return Math.min(Math.max(amount, min), max);\n}\n\nexport function toMinorUnits(amount: number, decimalPlaces = 2): number {\n return Math.round(amount * Math.pow(10, decimalPlaces));\n}\n\nexport function fromMinorUnits(amount: number, decimalPlaces = 2): number {\n return amount / Math.pow(10, decimalPlaces);\n}\n\nexport function sumAmounts(...amounts: number[]): number {\n const f = 100;\n return amounts.reduce((acc, a) => acc + Math.round(a * f), 0) / f;\n}\n","import { validateIban } from '../banking/iban.utility';\nimport { validateLuhn, getCardNetwork } from '../banking/luhn.utility';\nimport { isValidAmount } from '../banking/amount.utility';\n\nexport type JoopValidationRule =\n | { type: 'required' }\n | { type: 'minLength'; min: number }\n | { type: 'maxLength'; max: number }\n | { type: 'min'; min: number }\n | { type: 'max'; max: number }\n | { type: 'pattern'; regex: RegExp; message?: string }\n | { type: 'email' }\n | { type: 'phone' }\n | { type: 'iban' }\n | { type: 'luhn' }\n | { type: 'amount'; min?: number; max?: number }\n | { type: 'dateRange'; maxDays?: number; minDate?: Date; maxDate?: Date }\n | { type: 'custom'; validate: (v: unknown) => string | null };\n\nexport interface JoopValidationResult { valid: boolean; errors: string[]; }\nexport type JoopFormErrors = Record<string, string[]>;\nexport type JoopFormSchema = Record<string, JoopValidationRule[]>;\n\nexport interface JoopPasswordStrength {\n score: number; // 0–4\n label: 'very-weak' | 'weak' | 'fair' | 'strong' | 'very-strong';\n suggestions: string[];\n}\n\nconst EMAIL_RE = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$/;\nconst PHONE_RE = /^\\+?[\\d\\s\\-().]{7,20}$/;\n\nexport class JoopFormValidator {\n\n required(value: unknown): string | null {\n if (value == null || value === '' || (Array.isArray(value) && value.length === 0)) return 'This field is required';\n return null;\n }\n\n minLength(value: string, min: number): string | null {\n if (String(value ?? '').length < min) return `Minimum ${min} characters required`;\n return null;\n }\n\n maxLength(value: string, max: number): string | null {\n if (String(value ?? '').length > max) return `Maximum ${max} characters allowed`;\n return null;\n }\n\n min(value: number | string, min: number): string | null {\n if (Number(value) < min) return `Minimum value is ${min}`;\n return null;\n }\n\n max(value: number | string, max: number): string | null {\n if (Number(value) > max) return `Maximum value is ${max}`;\n return null;\n }\n\n email(value: string): string | null {\n if (!EMAIL_RE.test(String(value ?? ''))) return 'Invalid email address';\n return null;\n }\n\n phone(value: string): string | null {\n if (!PHONE_RE.test(String(value ?? ''))) return 'Invalid phone number';\n return null;\n }\n\n iban(value: string): string | null {\n if (!validateIban(String(value ?? ''))) return 'Invalid IBAN';\n return null;\n }\n\n luhn(value: string): string | null {\n const digits = String(value ?? '').replace(/\\D/g, '');\n if (!validateLuhn(digits)) return 'Invalid card number';\n const network = getCardNetwork(digits);\n if (network === 'unknown') return 'Unrecognised card type';\n return null;\n }\n\n amount(value: string | number, min?: number, max?: number): string | null {\n if (!isValidAmount(value)) return 'Invalid amount';\n const n = Number(value);\n if (min !== undefined && n < min) return `Minimum amount is ${min}`;\n if (max !== undefined && n > max) return `Maximum amount is ${max}`;\n return null;\n }\n\n pattern(value: string, regex: RegExp, message?: string): string | null {\n if (!regex.test(String(value ?? ''))) return message ?? 'Invalid format';\n return null;\n }\n\n dateRange(start: Date, end: Date, maxDays?: number, minDate?: Date, maxDate?: Date): string | null {\n if (start > end) return 'Start date must be before end date';\n if (minDate && start < minDate) return `Start date cannot be before ${minDate.toLocaleDateString()}`;\n if (maxDate && end > maxDate) return `End date cannot be after ${maxDate.toLocaleDateString()}`;\n if (maxDays) {\n const days = Math.ceil((end.getTime() - start.getTime()) / 86_400_000);\n if (days > maxDays) return `Date range cannot exceed ${maxDays} days`;\n }\n return null;\n }\n\n passwordStrength(password: string): JoopPasswordStrength {\n const suggestions: string[] = [];\n let score = 0;\n if (password.length >= 8) score++; else suggestions.push('Use at least 8 characters');\n if (password.length >= 12) score++;\n if (/[A-Z]/.test(password)) score++; else suggestions.push('Add uppercase letters');\n if (/[0-9]/.test(password)) score++; else suggestions.push('Add numbers');\n if (/[^A-Za-z0-9]/.test(password)) score++; else suggestions.push('Add special characters');\n if (/(.)\\1{2,}/.test(password)) { score--; suggestions.push('Avoid repeating characters'); }\n score = Math.max(0, Math.min(4, score));\n const labels: JoopPasswordStrength['label'][] = ['very-weak', 'weak', 'fair', 'strong', 'very-strong'];\n return { score, label: labels[score], suggestions };\n }\n\n /** Validate a single value against multiple rules */\n validate(value: unknown, rules: JoopValidationRule[]): JoopValidationResult {\n const errors: string[] = [];\n for (const rule of rules) {\n let err: string | null = null;\n switch (rule.type) {\n case 'required': err = this.required(value); break;\n case 'minLength': err = this.minLength(String(value ?? ''), rule.min); break;\n case 'maxLength': err = this.maxLength(String(value ?? ''), rule.max); break;\n case 'min': err = this.min(value as number, rule.min); break;\n case 'max': err = this.max(value as number, rule.max); break;\n case 'email': err = this.email(String(value ?? '')); break;\n case 'phone': err = this.phone(String(value ?? '')); break;\n case 'iban': err = this.iban(String(value ?? '')); break;\n case 'luhn': err = this.luhn(String(value ?? '')); break;\n case 'amount': err = this.amount(value as string, rule.min, rule.max); break;\n case 'pattern': err = this.pattern(String(value ?? ''), rule.regex, rule.message); break;\n case 'custom': err = rule.validate(value); break;\n }\n if (err) errors.push(err);\n }\n return { valid: errors.length === 0, errors };\n }\n\n /** Validate an entire form object against a schema */\n validateForm(form: Record<string, unknown>, schema: JoopFormSchema): JoopFormErrors {\n const errors: JoopFormErrors = {};\n for (const field of Object.keys(schema)) {\n const result = this.validate(form[field], schema[field]);\n if (!result.valid) errors[field] = result.errors;\n }\n return errors;\n }\n\n isFormValid(errors: JoopFormErrors): boolean {\n return Object.keys(errors).length === 0;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\nimport { JoopFormValidator, JoopValidationRule, JoopValidationResult } from '../validation/form-validator';\n\nexport interface JoopFieldConfig<T = unknown> {\n value: T;\n validators?: JoopValidationRule[];\n label?: string;\n}\n\nexport interface JoopFieldState<T = unknown> {\n value: T;\n dirty: boolean;\n touched: boolean;\n valid: boolean;\n errors: string[];\n}\n\nexport class JoopField<T = unknown> {\n private _v = new JoopFormValidator();\n private _state$: JoopBehaviorSubject<JoopFieldState<T>>;\n readonly label: string;\n private _initial: T;\n private _validators: JoopValidationRule[];\n\n constructor(config: JoopFieldConfig<T>) {\n this._initial = config.value;\n this._validators = config.validators ?? [];\n this.label = config.label ?? '';\n this._state$ = new JoopBehaviorSubject<JoopFieldState<T>>(this._build(config.value, false, false));\n }\n\n private _build(value: T, dirty: boolean, touched: boolean): JoopFieldState<T> {\n const result: JoopValidationResult = this._validators.length\n ? this._v.validate(value, this._validators)\n : { valid: true, errors: [] };\n return { value, dirty, touched, valid: result.valid, errors: result.errors };\n }\n\n get value(): T { return this._state$.getValue().value; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n get touched(): boolean { return this._state$.getValue().touched; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get errors(): string[] { return this._state$.getValue().errors; }\n\n setValue(value: T): void {\n const s = this._state$.getValue();\n this._state$.next(this._build(value, s.value !== value || s.dirty, s.touched));\n }\n\n markTouched(): void {\n const s = this._state$.getValue();\n this._state$.next({ ...s, touched: true });\n }\n\n reset(): void { this._state$.next(this._build(this._initial, false, false)); }\n\n state$() { return this._state$.asObservable(); }\n}\n\nexport interface JoopFormState {\n valid: boolean;\n dirty: boolean;\n touched: boolean;\n value: Record<string, unknown>;\n}\n\nexport class JoopForm {\n private _fields: Record<string, JoopField>;\n private _state$: JoopBehaviorSubject<JoopFormState>;\n\n constructor(fields: Record<string, JoopField>) {\n this._fields = fields;\n this._state$ = new JoopBehaviorSubject<JoopFormState>(this._compute());\n for (const f of Object.values(fields)) {\n f.state$().subscribe(() => this._state$.next(this._compute()));\n }\n }\n\n private _compute(): JoopFormState {\n const entries = Object.entries(this._fields);\n return {\n valid: entries.every(([, f]) => f.valid),\n dirty: entries.some(([, f]) => f.dirty),\n touched: entries.some(([, f]) => f.touched),\n value: Object.fromEntries(entries.map(([k, f]) => [k, f.value])),\n };\n }\n\n field<T = unknown>(name: string): JoopField<T> { return this._fields[name] as JoopField<T>; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n getValue(): Record<string, unknown> { return this._state$.getValue().value; }\n errors(): Record<string, string[]> {\n return Object.fromEntries(Object.entries(this._fields).filter(([, f]) => !f.valid).map(([k, f]) => [k, f.errors]));\n }\n reset(): void { Object.values(this._fields).forEach(f => f.reset()); }\n markAllTouched(): void { Object.values(this._fields).forEach(f => f.markTouched()); }\n state$() { return this._state$.asObservable(); }\n}\n\nexport class JoopFormBuilder {\n field<T = unknown>(value: T, validators?: JoopValidationRule[], label?: string): JoopField<T> {\n return new JoopField<T>({ value, validators, label });\n }\n\n create(schema: Record<string, JoopField>): JoopForm {\n return new JoopForm(schema);\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/banking/iban.utility.ts","../../src/banking/luhn.utility.ts","../../src/banking/amount.utility.ts","../../src/validation/form-validator.ts","../../src/forms/form-builder.ts"],"names":[],"mappings":"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,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA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","file":"index.js","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","const IBAN_LENGTHS: Record<string, number> = {\n AL: 28, AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22,\n BR: 29, BY: 28, CH: 21, CR: 22, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28,\n EE: 20, EG: 29, ES: 24, FI: 18, FO: 18, FR: 27, GB: 22, GE: 22, GI: 23,\n GL: 18, GR: 27, GT: 28, HR: 21, HU: 28, IE: 22, IL: 23, IQ: 23, IS: 26,\n IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28, LC: 32, LI: 21, LT: 20, LU: 20,\n LV: 21, LY: 25, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27, MT: 31, MU: 30,\n NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29, RO: 24, RS: 22,\n SA: 24, SC: 31, SD: 18, SE: 24, SI: 19, SK: 24, SM: 27, ST: 25, SV: 28,\n TL: 23, TN: 24, TR: 26, UA: 29, VA: 22, VG: 24, XK: 20,\n};\n\nexport function validateIban(iban: string): boolean {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n const country = clean.slice(0, 2);\n if (!IBAN_LENGTHS[country] || clean.length !== IBAN_LENGTHS[country]) return false;\n\n const numeric = (clean.slice(4) + clean.slice(0, 4))\n .split('')\n .map(c => c.charCodeAt(0) >= 65 ? (c.charCodeAt(0) - 55).toString() : c)\n .join('');\n\n let remainder = 0;\n for (const ch of numeric) remainder = (remainder * 10 + parseInt(ch)) % 97;\n return remainder === 1;\n}\n\nexport function formatIban(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().replace(/(.{4})/g, '$1 ').trim();\n}\n\nexport function getIbanCountry(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().slice(0, 2);\n}\n\nexport function parseIban(iban: string): { country: string; checkDigits: string; bban: string } | null {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n if (!validateIban(clean)) return null;\n return { country: clean.slice(0, 2), checkDigits: clean.slice(2, 4), bban: clean.slice(4) };\n}\n\nexport function getSupportedIbanCountries(): string[] {\n return Object.keys(IBAN_LENGTHS).sort();\n}\n","// ── Luhn algorithm & card type detection ──────────────────────────────────\n\nexport type JoopCardNetwork = 'visa' | 'mastercard' | 'amex' | 'discover' | 'unionpay' | 'jcb' | 'diners' | 'maestro' | 'unknown';\n\nexport interface JoopCardInfo {\n network: JoopCardNetwork;\n valid: boolean;\n lengths: number[];\n cvvLength: number;\n formatted: string;\n}\n\nconst CARD_PATTERNS: Array<{ network: JoopCardNetwork; pattern: RegExp; lengths: number[]; cvvLength: number }> = [\n { network: 'amex', pattern: /^3[47]/, lengths: [15], cvvLength: 4 },\n { network: 'diners', pattern: /^3(?:0[0-5]|[68])/, lengths: [14], cvvLength: 3 },\n { network: 'discover', pattern: /^6(?:011|5[0-9]{2})/, lengths: [16], cvvLength: 3 },\n { network: 'jcb', pattern: /^(?:2131|1800|35)/, lengths: [16], cvvLength: 3 },\n { network: 'maestro', pattern: /^(?:5018|5020|5038|6304|6759|676[1-3])/, lengths: [12,13,14,15,16,17,18,19], cvvLength: 3 },\n { network: 'mastercard', pattern: /^5[1-5]|^2[2-7]/, lengths: [16], cvvLength: 3 },\n { network: 'unionpay', pattern: /^62/, lengths: [16,17,18,19], cvvLength: 3 },\n { network: 'visa', pattern: /^4/, lengths: [13,16,19], cvvLength: 3 },\n];\n\n/** Validate a card number using the Luhn algorithm */\nexport function validateLuhn(cardNumber: string): boolean {\n const digits = cardNumber.replace(/\\D/g, '');\n if (digits.length < 8) return false;\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\n/** Compute the Luhn check digit for a partial card number */\nexport function luhnCheckDigit(partial: string): number {\n const digits = partial.replace(/\\D/g, '');\n let sum = 0;\n let double = true;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return (10 - (sum % 10)) % 10;\n}\n\n/** Detect the card network from the card number prefix */\nexport function getCardNetwork(cardNumber: string): JoopCardNetwork {\n const digits = cardNumber.replace(/\\D/g, '');\n for (const card of CARD_PATTERNS) {\n if (card.pattern.test(digits)) return card.network;\n }\n return 'unknown';\n}\n\n/** Get full card validation info */\nexport function getCardInfo(cardNumber: string): JoopCardInfo {\n const digits = cardNumber.replace(/\\D/g, '');\n const match = CARD_PATTERNS.find(c => c.pattern.test(digits));\n const network = match?.network ?? 'unknown';\n const lengths = match?.lengths ?? [13, 14, 15, 16, 19];\n const cvvLength = match?.cvvLength ?? 3;\n const valid = lengths.includes(digits.length) && validateLuhn(digits);\n const formatted = formatCardNumber(digits);\n return { network, valid, lengths, cvvLength, formatted };\n}\n\n/** Format card number with spaces (e.g. 4111 1111 1111 1111 or 3714 496353 98431 for Amex) */\nexport function formatCardNumber(cardNumber: string): string {\n const digits = cardNumber.replace(/\\D/g, '');\n const network = getCardNetwork(digits);\n if (network === 'amex') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{5})$/, '$1 $2 $3');\n }\n if (network === 'diners') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{4})$/, '$1 $2 $3');\n }\n return digits.replace(/(\\d{4})(?=\\d)/g, '$1 ');\n}\n\n/** Validate card expiry (MM/YY or MM/YYYY) */\nexport function isCardExpired(month: number | string, year: number | string): boolean {\n const m = parseInt(String(month), 10);\n let y = parseInt(String(year), 10);\n if (y < 100) y += 2000;\n const now = new Date();\n const expiry = new Date(y, m - 1, 1);\n expiry.setMonth(expiry.getMonth() + 1); // expire at end of month\n return expiry <= now;\n}\n\n/** Validate a CVV/CVC value */\nexport function validateCvv(cvv: string, network: JoopCardNetwork = 'unknown'): boolean {\n const digits = cvv.replace(/\\D/g, '');\n const expectedLength = network === 'amex' ? 4 : 3;\n return digits.length === expectedLength;\n}\n","export function safeAdd(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) + Math.round(b * f)) / f;\n}\n\nexport function safeSubtract(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) - Math.round(b * f)) / f;\n}\n\nexport function safeMultiply(a: number, b: number, decimals = 2): number {\n return parseFloat((a * b).toFixed(decimals));\n}\n\nexport function safeDivide(a: number, b: number, decimals = 2): number {\n if (b === 0) throw new Error('Division by zero');\n return parseFloat((a / b).toFixed(decimals));\n}\n\nexport function roundAmount(amount: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return Math.round(amount * f) / f;\n}\n\nexport function isValidAmount(value: unknown): boolean {\n if (typeof value === 'string') {\n const clean = value.replace(/[,\\s]/g, '');\n return /^-?\\d+(\\.\\d+)?$/.test(clean) && isFinite(parseFloat(clean));\n }\n return typeof value === 'number' && isFinite(value);\n}\n\nexport function clampAmount(amount: number, min: number, max: number): number {\n return Math.min(Math.max(amount, min), max);\n}\n\nexport function toMinorUnits(amount: number, decimalPlaces = 2): number {\n return Math.round(amount * Math.pow(10, decimalPlaces));\n}\n\nexport function fromMinorUnits(amount: number, decimalPlaces = 2): number {\n return amount / Math.pow(10, decimalPlaces);\n}\n\nexport function sumAmounts(...amounts: number[]): number {\n const f = 100;\n return amounts.reduce((acc, a) => acc + Math.round(a * f), 0) / f;\n}\n","import { validateIban } from '../banking/iban.utility';\nimport { validateLuhn, getCardNetwork } from '../banking/luhn.utility';\nimport { isValidAmount } from '../banking/amount.utility';\n\nexport type JoopValidationRule =\n | { type: 'required' }\n | { type: 'minLength'; min: number }\n | { type: 'maxLength'; max: number }\n | { type: 'min'; min: number }\n | { type: 'max'; max: number }\n | { type: 'pattern'; regex: RegExp; message?: string }\n | { type: 'email' }\n | { type: 'phone' }\n | { type: 'iban' }\n | { type: 'luhn' }\n | { type: 'amount'; min?: number; max?: number }\n | { type: 'dateRange'; maxDays?: number; minDate?: Date; maxDate?: Date }\n | { type: 'custom'; validate: (v: unknown) => string | null };\n\nexport interface JoopValidationResult { valid: boolean; errors: string[]; }\nexport type JoopFormErrors = Record<string, string[]>;\nexport type JoopFormSchema = Record<string, JoopValidationRule[]>;\n\nexport interface JoopPasswordStrength {\n score: number; // 0–4\n label: 'very-weak' | 'weak' | 'fair' | 'strong' | 'very-strong';\n suggestions: string[];\n}\n\nconst EMAIL_RE = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$/;\nconst PHONE_RE = /^\\+?[\\d\\s\\-().]{7,20}$/;\n\nexport class JoopFormValidator {\n\n required(value: unknown): string | null {\n if (value == null || value === '' || (Array.isArray(value) && value.length === 0)) return 'This field is required';\n return null;\n }\n\n minLength(value: string, min: number): string | null {\n if (String(value ?? '').length < min) return `Minimum ${min} characters required`;\n return null;\n }\n\n maxLength(value: string, max: number): string | null {\n if (String(value ?? '').length > max) return `Maximum ${max} characters allowed`;\n return null;\n }\n\n min(value: number | string, min: number): string | null {\n if (Number(value) < min) return `Minimum value is ${min}`;\n return null;\n }\n\n max(value: number | string, max: number): string | null {\n if (Number(value) > max) return `Maximum value is ${max}`;\n return null;\n }\n\n email(value: string): string | null {\n if (!EMAIL_RE.test(String(value ?? ''))) return 'Invalid email address';\n return null;\n }\n\n phone(value: string): string | null {\n if (!PHONE_RE.test(String(value ?? ''))) return 'Invalid phone number';\n return null;\n }\n\n iban(value: string): string | null {\n if (!validateIban(String(value ?? ''))) return 'Invalid IBAN';\n return null;\n }\n\n luhn(value: string): string | null {\n const digits = String(value ?? '').replace(/\\D/g, '');\n if (!validateLuhn(digits)) return 'Invalid card number';\n const network = getCardNetwork(digits);\n if (network === 'unknown') return 'Unrecognised card type';\n return null;\n }\n\n amount(value: string | number, min?: number, max?: number): string | null {\n if (!isValidAmount(value)) return 'Invalid amount';\n const n = Number(value);\n if (min !== undefined && n < min) return `Minimum amount is ${min}`;\n if (max !== undefined && n > max) return `Maximum amount is ${max}`;\n return null;\n }\n\n pattern(value: string, regex: RegExp, message?: string): string | null {\n if (!regex.test(String(value ?? ''))) return message ?? 'Invalid format';\n return null;\n }\n\n dateRange(start: Date, end: Date, maxDays?: number, minDate?: Date, maxDate?: Date): string | null {\n if (start > end) return 'Start date must be before end date';\n if (minDate && start < minDate) return `Start date cannot be before ${minDate.toLocaleDateString()}`;\n if (maxDate && end > maxDate) return `End date cannot be after ${maxDate.toLocaleDateString()}`;\n if (maxDays) {\n const days = Math.ceil((end.getTime() - start.getTime()) / 86_400_000);\n if (days > maxDays) return `Date range cannot exceed ${maxDays} days`;\n }\n return null;\n }\n\n passwordStrength(password: string): JoopPasswordStrength {\n const suggestions: string[] = [];\n let score = 0;\n if (password.length >= 8) score++; else suggestions.push('Use at least 8 characters');\n if (password.length >= 12) score++;\n if (/[A-Z]/.test(password)) score++; else suggestions.push('Add uppercase letters');\n if (/[0-9]/.test(password)) score++; else suggestions.push('Add numbers');\n if (/[^A-Za-z0-9]/.test(password)) score++; else suggestions.push('Add special characters');\n if (/(.)\\1{2,}/.test(password)) { score--; suggestions.push('Avoid repeating characters'); }\n score = Math.max(0, Math.min(4, score));\n const labels: JoopPasswordStrength['label'][] = ['very-weak', 'weak', 'fair', 'strong', 'very-strong'];\n return { score, label: labels[score], suggestions };\n }\n\n /** Validate a single value against multiple rules */\n validate(value: unknown, rules: JoopValidationRule[]): JoopValidationResult {\n const errors: string[] = [];\n for (const rule of rules) {\n let err: string | null = null;\n switch (rule.type) {\n case 'required': err = this.required(value); break;\n case 'minLength': err = this.minLength(String(value ?? ''), rule.min); break;\n case 'maxLength': err = this.maxLength(String(value ?? ''), rule.max); break;\n case 'min': err = this.min(value as number, rule.min); break;\n case 'max': err = this.max(value as number, rule.max); break;\n case 'email': err = this.email(String(value ?? '')); break;\n case 'phone': err = this.phone(String(value ?? '')); break;\n case 'iban': err = this.iban(String(value ?? '')); break;\n case 'luhn': err = this.luhn(String(value ?? '')); break;\n case 'amount': err = this.amount(value as string, rule.min, rule.max); break;\n case 'pattern': err = this.pattern(String(value ?? ''), rule.regex, rule.message); break;\n case 'custom': err = rule.validate(value); break;\n }\n if (err) errors.push(err);\n }\n return { valid: errors.length === 0, errors };\n }\n\n /** Validate an entire form object against a schema */\n validateForm(form: Record<string, unknown>, schema: JoopFormSchema): JoopFormErrors {\n const errors: JoopFormErrors = {};\n for (const field of Object.keys(schema)) {\n const result = this.validate(form[field], schema[field]);\n if (!result.valid) errors[field] = result.errors;\n }\n return errors;\n }\n\n isFormValid(errors: JoopFormErrors): boolean {\n return Object.keys(errors).length === 0;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\nimport { JoopFormValidator, JoopValidationRule, JoopValidationResult } from '../validation/form-validator';\n\nexport interface JoopFieldConfig<T = unknown> {\n value: T;\n validators?: JoopValidationRule[];\n label?: string;\n}\n\nexport interface JoopFieldState<T = unknown> {\n value: T;\n dirty: boolean;\n touched: boolean;\n valid: boolean;\n errors: string[];\n}\n\nexport class JoopField<T = unknown> {\n private _v = new JoopFormValidator();\n private _state$: JoopBehaviorSubject<JoopFieldState<T>>;\n readonly label: string;\n private _initial: T;\n private _validators: JoopValidationRule[];\n\n constructor(config: JoopFieldConfig<T>) {\n this._initial = config.value;\n this._validators = config.validators ?? [];\n this.label = config.label ?? '';\n this._state$ = new JoopBehaviorSubject<JoopFieldState<T>>(this._build(config.value, false, false));\n }\n\n private _build(value: T, dirty: boolean, touched: boolean): JoopFieldState<T> {\n const result: JoopValidationResult = this._validators.length\n ? this._v.validate(value, this._validators)\n : { valid: true, errors: [] };\n return { value, dirty, touched, valid: result.valid, errors: result.errors };\n }\n\n get value(): T { return this._state$.getValue().value; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n get touched(): boolean { return this._state$.getValue().touched; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get errors(): string[] { return this._state$.getValue().errors; }\n\n setValue(value: T): void {\n const s = this._state$.getValue();\n this._state$.next(this._build(value, s.value !== value || s.dirty, s.touched));\n }\n\n markTouched(): void {\n const s = this._state$.getValue();\n this._state$.next({ ...s, touched: true });\n }\n\n reset(): void { this._state$.next(this._build(this._initial, false, false)); }\n\n state$() { return this._state$.asObservable(); }\n}\n\nexport interface JoopFormState {\n valid: boolean;\n dirty: boolean;\n touched: boolean;\n value: Record<string, unknown>;\n}\n\nexport class JoopForm {\n private _fields: Record<string, JoopField>;\n private _state$: JoopBehaviorSubject<JoopFormState>;\n\n constructor(fields: Record<string, JoopField>) {\n this._fields = fields;\n this._state$ = new JoopBehaviorSubject<JoopFormState>(this._compute());\n for (const f of Object.values(fields)) {\n f.state$().subscribe(() => this._state$.next(this._compute()));\n }\n }\n\n private _compute(): JoopFormState {\n const entries = Object.entries(this._fields);\n return {\n valid: entries.every(([, f]) => f.valid),\n dirty: entries.some(([, f]) => f.dirty),\n touched: entries.some(([, f]) => f.touched),\n value: Object.fromEntries(entries.map(([k, f]) => [k, f.value])),\n };\n }\n\n field<T = unknown>(name: string): JoopField<T> { return this._fields[name] as JoopField<T>; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n getValue(): Record<string, unknown> { return this._state$.getValue().value; }\n errors(): Record<string, string[]> {\n return Object.fromEntries(Object.entries(this._fields).filter(([, f]) => !f.valid).map(([k, f]) => [k, f.errors]));\n }\n reset(): void { Object.values(this._fields).forEach(f => f.reset()); }\n markAllTouched(): void { Object.values(this._fields).forEach(f => f.markTouched()); }\n state$() { return this._state$.asObservable(); }\n}\n\nexport class JoopFormBuilder {\n field<T = unknown>(value: T, validators?: JoopValidationRule[], label?: string): JoopField<T> {\n return new JoopField<T>({ value, validators, label });\n }\n\n create(schema: Record<string, JoopField>): JoopForm {\n return new JoopForm(schema);\n }\n}\n"]}
@@ -1,4 +1,7 @@
1
1
  // src/events/index.ts
2
+ var _onListenerError = (error) => {
3
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
4
+ };
2
5
  var JoopSubject = class {
3
6
  _listeners = [];
4
7
  subscribe(listener) {
@@ -8,8 +11,13 @@ var JoopSubject = class {
8
11
  };
9
12
  }
10
13
  next(value) {
11
- for (const listener of this._listeners) {
12
- listener(value);
14
+ const listeners = this._listeners.slice();
15
+ for (const listener of listeners) {
16
+ try {
17
+ listener(value);
18
+ } catch (error) {
19
+ _onListenerError(error);
20
+ }
13
21
  }
14
22
  }
15
23
  asObservable() {
@@ -30,7 +38,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
30
38
  super.next(value);
31
39
  }
32
40
  subscribe(listener) {
33
- listener(this._value);
41
+ try {
42
+ listener(this._value);
43
+ } catch (error) {
44
+ _onListenerError(error);
45
+ }
34
46
  return super.subscribe(listener);
35
47
  }
36
48
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/banking/iban.utility.ts","../../src/banking/luhn.utility.ts","../../src/banking/amount.utility.ts","../../src/validation/form-validator.ts","../../src/forms/form-builder.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n for (const listener of this._listeners) {\n listener(value);\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n listener(this._value);\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","const IBAN_LENGTHS: Record<string, number> = {\n AL: 28, AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22,\n BR: 29, BY: 28, CH: 21, CR: 22, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28,\n EE: 20, EG: 29, ES: 24, FI: 18, FO: 18, FR: 27, GB: 22, GE: 22, GI: 23,\n GL: 18, GR: 27, GT: 28, HR: 21, HU: 28, IE: 22, IL: 23, IQ: 23, IS: 26,\n IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28, LC: 32, LI: 21, LT: 20, LU: 20,\n LV: 21, LY: 25, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27, MT: 31, MU: 30,\n NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29, RO: 24, RS: 22,\n SA: 24, SC: 31, SD: 18, SE: 24, SI: 19, SK: 24, SM: 27, ST: 25, SV: 28,\n TL: 23, TN: 24, TR: 26, UA: 29, VA: 22, VG: 24, XK: 20,\n};\n\nexport function validateIban(iban: string): boolean {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n const country = clean.slice(0, 2);\n if (!IBAN_LENGTHS[country] || clean.length !== IBAN_LENGTHS[country]) return false;\n\n const numeric = (clean.slice(4) + clean.slice(0, 4))\n .split('')\n .map(c => c.charCodeAt(0) >= 65 ? (c.charCodeAt(0) - 55).toString() : c)\n .join('');\n\n let remainder = 0;\n for (const ch of numeric) remainder = (remainder * 10 + parseInt(ch)) % 97;\n return remainder === 1;\n}\n\nexport function formatIban(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().replace(/(.{4})/g, '$1 ').trim();\n}\n\nexport function getIbanCountry(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().slice(0, 2);\n}\n\nexport function parseIban(iban: string): { country: string; checkDigits: string; bban: string } | null {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n if (!validateIban(clean)) return null;\n return { country: clean.slice(0, 2), checkDigits: clean.slice(2, 4), bban: clean.slice(4) };\n}\n\nexport function getSupportedIbanCountries(): string[] {\n return Object.keys(IBAN_LENGTHS).sort();\n}\n","// ── Luhn algorithm & card type detection ──────────────────────────────────\n\nexport type JoopCardNetwork = 'visa' | 'mastercard' | 'amex' | 'discover' | 'unionpay' | 'jcb' | 'diners' | 'maestro' | 'unknown';\n\nexport interface JoopCardInfo {\n network: JoopCardNetwork;\n valid: boolean;\n lengths: number[];\n cvvLength: number;\n formatted: string;\n}\n\nconst CARD_PATTERNS: Array<{ network: JoopCardNetwork; pattern: RegExp; lengths: number[]; cvvLength: number }> = [\n { network: 'amex', pattern: /^3[47]/, lengths: [15], cvvLength: 4 },\n { network: 'diners', pattern: /^3(?:0[0-5]|[68])/, lengths: [14], cvvLength: 3 },\n { network: 'discover', pattern: /^6(?:011|5[0-9]{2})/, lengths: [16], cvvLength: 3 },\n { network: 'jcb', pattern: /^(?:2131|1800|35)/, lengths: [16], cvvLength: 3 },\n { network: 'maestro', pattern: /^(?:5018|5020|5038|6304|6759|676[1-3])/, lengths: [12,13,14,15,16,17,18,19], cvvLength: 3 },\n { network: 'mastercard', pattern: /^5[1-5]|^2[2-7]/, lengths: [16], cvvLength: 3 },\n { network: 'unionpay', pattern: /^62/, lengths: [16,17,18,19], cvvLength: 3 },\n { network: 'visa', pattern: /^4/, lengths: [13,16,19], cvvLength: 3 },\n];\n\n/** Validate a card number using the Luhn algorithm */\nexport function validateLuhn(cardNumber: string): boolean {\n const digits = cardNumber.replace(/\\D/g, '');\n if (digits.length < 8) return false;\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\n/** Compute the Luhn check digit for a partial card number */\nexport function luhnCheckDigit(partial: string): number {\n const digits = partial.replace(/\\D/g, '');\n let sum = 0;\n let double = true;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return (10 - (sum % 10)) % 10;\n}\n\n/** Detect the card network from the card number prefix */\nexport function getCardNetwork(cardNumber: string): JoopCardNetwork {\n const digits = cardNumber.replace(/\\D/g, '');\n for (const card of CARD_PATTERNS) {\n if (card.pattern.test(digits)) return card.network;\n }\n return 'unknown';\n}\n\n/** Get full card validation info */\nexport function getCardInfo(cardNumber: string): JoopCardInfo {\n const digits = cardNumber.replace(/\\D/g, '');\n const match = CARD_PATTERNS.find(c => c.pattern.test(digits));\n const network = match?.network ?? 'unknown';\n const lengths = match?.lengths ?? [13, 14, 15, 16, 19];\n const cvvLength = match?.cvvLength ?? 3;\n const valid = lengths.includes(digits.length) && validateLuhn(digits);\n const formatted = formatCardNumber(digits);\n return { network, valid, lengths, cvvLength, formatted };\n}\n\n/** Format card number with spaces (e.g. 4111 1111 1111 1111 or 3714 496353 98431 for Amex) */\nexport function formatCardNumber(cardNumber: string): string {\n const digits = cardNumber.replace(/\\D/g, '');\n const network = getCardNetwork(digits);\n if (network === 'amex') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{5})$/, '$1 $2 $3');\n }\n if (network === 'diners') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{4})$/, '$1 $2 $3');\n }\n return digits.replace(/(\\d{4})(?=\\d)/g, '$1 ');\n}\n\n/** Validate card expiry (MM/YY or MM/YYYY) */\nexport function isCardExpired(month: number | string, year: number | string): boolean {\n const m = parseInt(String(month), 10);\n let y = parseInt(String(year), 10);\n if (y < 100) y += 2000;\n const now = new Date();\n const expiry = new Date(y, m - 1, 1);\n expiry.setMonth(expiry.getMonth() + 1); // expire at end of month\n return expiry <= now;\n}\n\n/** Validate a CVV/CVC value */\nexport function validateCvv(cvv: string, network: JoopCardNetwork = 'unknown'): boolean {\n const digits = cvv.replace(/\\D/g, '');\n const expectedLength = network === 'amex' ? 4 : 3;\n return digits.length === expectedLength;\n}\n","export function safeAdd(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) + Math.round(b * f)) / f;\n}\n\nexport function safeSubtract(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) - Math.round(b * f)) / f;\n}\n\nexport function safeMultiply(a: number, b: number, decimals = 2): number {\n return parseFloat((a * b).toFixed(decimals));\n}\n\nexport function safeDivide(a: number, b: number, decimals = 2): number {\n if (b === 0) throw new Error('Division by zero');\n return parseFloat((a / b).toFixed(decimals));\n}\n\nexport function roundAmount(amount: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return Math.round(amount * f) / f;\n}\n\nexport function isValidAmount(value: unknown): boolean {\n if (typeof value === 'string') {\n const clean = value.replace(/[,\\s]/g, '');\n return /^-?\\d+(\\.\\d+)?$/.test(clean) && isFinite(parseFloat(clean));\n }\n return typeof value === 'number' && isFinite(value);\n}\n\nexport function clampAmount(amount: number, min: number, max: number): number {\n return Math.min(Math.max(amount, min), max);\n}\n\nexport function toMinorUnits(amount: number, decimalPlaces = 2): number {\n return Math.round(amount * Math.pow(10, decimalPlaces));\n}\n\nexport function fromMinorUnits(amount: number, decimalPlaces = 2): number {\n return amount / Math.pow(10, decimalPlaces);\n}\n\nexport function sumAmounts(...amounts: number[]): number {\n const f = 100;\n return amounts.reduce((acc, a) => acc + Math.round(a * f), 0) / f;\n}\n","import { validateIban } from '../banking/iban.utility';\nimport { validateLuhn, getCardNetwork } from '../banking/luhn.utility';\nimport { isValidAmount } from '../banking/amount.utility';\n\nexport type JoopValidationRule =\n | { type: 'required' }\n | { type: 'minLength'; min: number }\n | { type: 'maxLength'; max: number }\n | { type: 'min'; min: number }\n | { type: 'max'; max: number }\n | { type: 'pattern'; regex: RegExp; message?: string }\n | { type: 'email' }\n | { type: 'phone' }\n | { type: 'iban' }\n | { type: 'luhn' }\n | { type: 'amount'; min?: number; max?: number }\n | { type: 'dateRange'; maxDays?: number; minDate?: Date; maxDate?: Date }\n | { type: 'custom'; validate: (v: unknown) => string | null };\n\nexport interface JoopValidationResult { valid: boolean; errors: string[]; }\nexport type JoopFormErrors = Record<string, string[]>;\nexport type JoopFormSchema = Record<string, JoopValidationRule[]>;\n\nexport interface JoopPasswordStrength {\n score: number; // 0–4\n label: 'very-weak' | 'weak' | 'fair' | 'strong' | 'very-strong';\n suggestions: string[];\n}\n\nconst EMAIL_RE = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$/;\nconst PHONE_RE = /^\\+?[\\d\\s\\-().]{7,20}$/;\n\nexport class JoopFormValidator {\n\n required(value: unknown): string | null {\n if (value == null || value === '' || (Array.isArray(value) && value.length === 0)) return 'This field is required';\n return null;\n }\n\n minLength(value: string, min: number): string | null {\n if (String(value ?? '').length < min) return `Minimum ${min} characters required`;\n return null;\n }\n\n maxLength(value: string, max: number): string | null {\n if (String(value ?? '').length > max) return `Maximum ${max} characters allowed`;\n return null;\n }\n\n min(value: number | string, min: number): string | null {\n if (Number(value) < min) return `Minimum value is ${min}`;\n return null;\n }\n\n max(value: number | string, max: number): string | null {\n if (Number(value) > max) return `Maximum value is ${max}`;\n return null;\n }\n\n email(value: string): string | null {\n if (!EMAIL_RE.test(String(value ?? ''))) return 'Invalid email address';\n return null;\n }\n\n phone(value: string): string | null {\n if (!PHONE_RE.test(String(value ?? ''))) return 'Invalid phone number';\n return null;\n }\n\n iban(value: string): string | null {\n if (!validateIban(String(value ?? ''))) return 'Invalid IBAN';\n return null;\n }\n\n luhn(value: string): string | null {\n const digits = String(value ?? '').replace(/\\D/g, '');\n if (!validateLuhn(digits)) return 'Invalid card number';\n const network = getCardNetwork(digits);\n if (network === 'unknown') return 'Unrecognised card type';\n return null;\n }\n\n amount(value: string | number, min?: number, max?: number): string | null {\n if (!isValidAmount(value)) return 'Invalid amount';\n const n = Number(value);\n if (min !== undefined && n < min) return `Minimum amount is ${min}`;\n if (max !== undefined && n > max) return `Maximum amount is ${max}`;\n return null;\n }\n\n pattern(value: string, regex: RegExp, message?: string): string | null {\n if (!regex.test(String(value ?? ''))) return message ?? 'Invalid format';\n return null;\n }\n\n dateRange(start: Date, end: Date, maxDays?: number, minDate?: Date, maxDate?: Date): string | null {\n if (start > end) return 'Start date must be before end date';\n if (minDate && start < minDate) return `Start date cannot be before ${minDate.toLocaleDateString()}`;\n if (maxDate && end > maxDate) return `End date cannot be after ${maxDate.toLocaleDateString()}`;\n if (maxDays) {\n const days = Math.ceil((end.getTime() - start.getTime()) / 86_400_000);\n if (days > maxDays) return `Date range cannot exceed ${maxDays} days`;\n }\n return null;\n }\n\n passwordStrength(password: string): JoopPasswordStrength {\n const suggestions: string[] = [];\n let score = 0;\n if (password.length >= 8) score++; else suggestions.push('Use at least 8 characters');\n if (password.length >= 12) score++;\n if (/[A-Z]/.test(password)) score++; else suggestions.push('Add uppercase letters');\n if (/[0-9]/.test(password)) score++; else suggestions.push('Add numbers');\n if (/[^A-Za-z0-9]/.test(password)) score++; else suggestions.push('Add special characters');\n if (/(.)\\1{2,}/.test(password)) { score--; suggestions.push('Avoid repeating characters'); }\n score = Math.max(0, Math.min(4, score));\n const labels: JoopPasswordStrength['label'][] = ['very-weak', 'weak', 'fair', 'strong', 'very-strong'];\n return { score, label: labels[score], suggestions };\n }\n\n /** Validate a single value against multiple rules */\n validate(value: unknown, rules: JoopValidationRule[]): JoopValidationResult {\n const errors: string[] = [];\n for (const rule of rules) {\n let err: string | null = null;\n switch (rule.type) {\n case 'required': err = this.required(value); break;\n case 'minLength': err = this.minLength(String(value ?? ''), rule.min); break;\n case 'maxLength': err = this.maxLength(String(value ?? ''), rule.max); break;\n case 'min': err = this.min(value as number, rule.min); break;\n case 'max': err = this.max(value as number, rule.max); break;\n case 'email': err = this.email(String(value ?? '')); break;\n case 'phone': err = this.phone(String(value ?? '')); break;\n case 'iban': err = this.iban(String(value ?? '')); break;\n case 'luhn': err = this.luhn(String(value ?? '')); break;\n case 'amount': err = this.amount(value as string, rule.min, rule.max); break;\n case 'pattern': err = this.pattern(String(value ?? ''), rule.regex, rule.message); break;\n case 'custom': err = rule.validate(value); break;\n }\n if (err) errors.push(err);\n }\n return { valid: errors.length === 0, errors };\n }\n\n /** Validate an entire form object against a schema */\n validateForm(form: Record<string, unknown>, schema: JoopFormSchema): JoopFormErrors {\n const errors: JoopFormErrors = {};\n for (const field of Object.keys(schema)) {\n const result = this.validate(form[field], schema[field]);\n if (!result.valid) errors[field] = result.errors;\n }\n return errors;\n }\n\n isFormValid(errors: JoopFormErrors): boolean {\n return Object.keys(errors).length === 0;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\nimport { JoopFormValidator, JoopValidationRule, JoopValidationResult } from '../validation/form-validator';\n\nexport interface JoopFieldConfig<T = unknown> {\n value: T;\n validators?: JoopValidationRule[];\n label?: string;\n}\n\nexport interface JoopFieldState<T = unknown> {\n value: T;\n dirty: boolean;\n touched: boolean;\n valid: boolean;\n errors: string[];\n}\n\nexport class JoopField<T = unknown> {\n private _v = new JoopFormValidator();\n private _state$: JoopBehaviorSubject<JoopFieldState<T>>;\n readonly label: string;\n private _initial: T;\n private _validators: JoopValidationRule[];\n\n constructor(config: JoopFieldConfig<T>) {\n this._initial = config.value;\n this._validators = config.validators ?? [];\n this.label = config.label ?? '';\n this._state$ = new JoopBehaviorSubject<JoopFieldState<T>>(this._build(config.value, false, false));\n }\n\n private _build(value: T, dirty: boolean, touched: boolean): JoopFieldState<T> {\n const result: JoopValidationResult = this._validators.length\n ? this._v.validate(value, this._validators)\n : { valid: true, errors: [] };\n return { value, dirty, touched, valid: result.valid, errors: result.errors };\n }\n\n get value(): T { return this._state$.getValue().value; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n get touched(): boolean { return this._state$.getValue().touched; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get errors(): string[] { return this._state$.getValue().errors; }\n\n setValue(value: T): void {\n const s = this._state$.getValue();\n this._state$.next(this._build(value, s.value !== value || s.dirty, s.touched));\n }\n\n markTouched(): void {\n const s = this._state$.getValue();\n this._state$.next({ ...s, touched: true });\n }\n\n reset(): void { this._state$.next(this._build(this._initial, false, false)); }\n\n state$() { return this._state$.asObservable(); }\n}\n\nexport interface JoopFormState {\n valid: boolean;\n dirty: boolean;\n touched: boolean;\n value: Record<string, unknown>;\n}\n\nexport class JoopForm {\n private _fields: Record<string, JoopField>;\n private _state$: JoopBehaviorSubject<JoopFormState>;\n\n constructor(fields: Record<string, JoopField>) {\n this._fields = fields;\n this._state$ = new JoopBehaviorSubject<JoopFormState>(this._compute());\n for (const f of Object.values(fields)) {\n f.state$().subscribe(() => this._state$.next(this._compute()));\n }\n }\n\n private _compute(): JoopFormState {\n const entries = Object.entries(this._fields);\n return {\n valid: entries.every(([, f]) => f.valid),\n dirty: entries.some(([, f]) => f.dirty),\n touched: entries.some(([, f]) => f.touched),\n value: Object.fromEntries(entries.map(([k, f]) => [k, f.value])),\n };\n }\n\n field<T = unknown>(name: string): JoopField<T> { return this._fields[name] as JoopField<T>; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n getValue(): Record<string, unknown> { return this._state$.getValue().value; }\n errors(): Record<string, string[]> {\n return Object.fromEntries(Object.entries(this._fields).filter(([, f]) => !f.valid).map(([k, f]) => [k, f.errors]));\n }\n reset(): void { Object.values(this._fields).forEach(f => f.reset()); }\n markAllTouched(): void { Object.values(this._fields).forEach(f => f.markTouched()); }\n state$() { return this._state$.asObservable(); }\n}\n\nexport class JoopFormBuilder {\n field<T = unknown>(value: T, validators?: JoopValidationRule[], label?: string): JoopField<T> {\n return new JoopField<T>({ value, validators, label });\n }\n\n create(schema: Record<string, JoopField>): JoopForm {\n return new JoopForm(schema);\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/banking/iban.utility.ts","../../src/banking/luhn.utility.ts","../../src/banking/amount.utility.ts","../../src/validation/form-validator.ts","../../src/forms/form-builder.ts"],"names":[],"mappings":"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AAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EACpE,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,EAAI,EAAA,EAAI,EAAA;AAAA,E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","file":"index.mjs","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","const IBAN_LENGTHS: Record<string, number> = {\n AL: 28, AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22,\n BR: 29, BY: 28, CH: 21, CR: 22, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28,\n EE: 20, EG: 29, ES: 24, FI: 18, FO: 18, FR: 27, GB: 22, GE: 22, GI: 23,\n GL: 18, GR: 27, GT: 28, HR: 21, HU: 28, IE: 22, IL: 23, IQ: 23, IS: 26,\n IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28, LC: 32, LI: 21, LT: 20, LU: 20,\n LV: 21, LY: 25, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27, MT: 31, MU: 30,\n NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29, RO: 24, RS: 22,\n SA: 24, SC: 31, SD: 18, SE: 24, SI: 19, SK: 24, SM: 27, ST: 25, SV: 28,\n TL: 23, TN: 24, TR: 26, UA: 29, VA: 22, VG: 24, XK: 20,\n};\n\nexport function validateIban(iban: string): boolean {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n const country = clean.slice(0, 2);\n if (!IBAN_LENGTHS[country] || clean.length !== IBAN_LENGTHS[country]) return false;\n\n const numeric = (clean.slice(4) + clean.slice(0, 4))\n .split('')\n .map(c => c.charCodeAt(0) >= 65 ? (c.charCodeAt(0) - 55).toString() : c)\n .join('');\n\n let remainder = 0;\n for (const ch of numeric) remainder = (remainder * 10 + parseInt(ch)) % 97;\n return remainder === 1;\n}\n\nexport function formatIban(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().replace(/(.{4})/g, '$1 ').trim();\n}\n\nexport function getIbanCountry(iban: string): string {\n return iban.replace(/\\s/g, '').toUpperCase().slice(0, 2);\n}\n\nexport function parseIban(iban: string): { country: string; checkDigits: string; bban: string } | null {\n const clean = iban.replace(/\\s/g, '').toUpperCase();\n if (!validateIban(clean)) return null;\n return { country: clean.slice(0, 2), checkDigits: clean.slice(2, 4), bban: clean.slice(4) };\n}\n\nexport function getSupportedIbanCountries(): string[] {\n return Object.keys(IBAN_LENGTHS).sort();\n}\n","// ── Luhn algorithm & card type detection ──────────────────────────────────\n\nexport type JoopCardNetwork = 'visa' | 'mastercard' | 'amex' | 'discover' | 'unionpay' | 'jcb' | 'diners' | 'maestro' | 'unknown';\n\nexport interface JoopCardInfo {\n network: JoopCardNetwork;\n valid: boolean;\n lengths: number[];\n cvvLength: number;\n formatted: string;\n}\n\nconst CARD_PATTERNS: Array<{ network: JoopCardNetwork; pattern: RegExp; lengths: number[]; cvvLength: number }> = [\n { network: 'amex', pattern: /^3[47]/, lengths: [15], cvvLength: 4 },\n { network: 'diners', pattern: /^3(?:0[0-5]|[68])/, lengths: [14], cvvLength: 3 },\n { network: 'discover', pattern: /^6(?:011|5[0-9]{2})/, lengths: [16], cvvLength: 3 },\n { network: 'jcb', pattern: /^(?:2131|1800|35)/, lengths: [16], cvvLength: 3 },\n { network: 'maestro', pattern: /^(?:5018|5020|5038|6304|6759|676[1-3])/, lengths: [12,13,14,15,16,17,18,19], cvvLength: 3 },\n { network: 'mastercard', pattern: /^5[1-5]|^2[2-7]/, lengths: [16], cvvLength: 3 },\n { network: 'unionpay', pattern: /^62/, lengths: [16,17,18,19], cvvLength: 3 },\n { network: 'visa', pattern: /^4/, lengths: [13,16,19], cvvLength: 3 },\n];\n\n/** Validate a card number using the Luhn algorithm */\nexport function validateLuhn(cardNumber: string): boolean {\n const digits = cardNumber.replace(/\\D/g, '');\n if (digits.length < 8) return false;\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\n/** Compute the Luhn check digit for a partial card number */\nexport function luhnCheckDigit(partial: string): number {\n const digits = partial.replace(/\\D/g, '');\n let sum = 0;\n let double = true;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = parseInt(digits[i], 10);\n if (double) { d *= 2; if (d > 9) d -= 9; }\n sum += d;\n double = !double;\n }\n return (10 - (sum % 10)) % 10;\n}\n\n/** Detect the card network from the card number prefix */\nexport function getCardNetwork(cardNumber: string): JoopCardNetwork {\n const digits = cardNumber.replace(/\\D/g, '');\n for (const card of CARD_PATTERNS) {\n if (card.pattern.test(digits)) return card.network;\n }\n return 'unknown';\n}\n\n/** Get full card validation info */\nexport function getCardInfo(cardNumber: string): JoopCardInfo {\n const digits = cardNumber.replace(/\\D/g, '');\n const match = CARD_PATTERNS.find(c => c.pattern.test(digits));\n const network = match?.network ?? 'unknown';\n const lengths = match?.lengths ?? [13, 14, 15, 16, 19];\n const cvvLength = match?.cvvLength ?? 3;\n const valid = lengths.includes(digits.length) && validateLuhn(digits);\n const formatted = formatCardNumber(digits);\n return { network, valid, lengths, cvvLength, formatted };\n}\n\n/** Format card number with spaces (e.g. 4111 1111 1111 1111 or 3714 496353 98431 for Amex) */\nexport function formatCardNumber(cardNumber: string): string {\n const digits = cardNumber.replace(/\\D/g, '');\n const network = getCardNetwork(digits);\n if (network === 'amex') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{5})$/, '$1 $2 $3');\n }\n if (network === 'diners') {\n return digits.replace(/^(\\d{4})(\\d{6})(\\d{4})$/, '$1 $2 $3');\n }\n return digits.replace(/(\\d{4})(?=\\d)/g, '$1 ');\n}\n\n/** Validate card expiry (MM/YY or MM/YYYY) */\nexport function isCardExpired(month: number | string, year: number | string): boolean {\n const m = parseInt(String(month), 10);\n let y = parseInt(String(year), 10);\n if (y < 100) y += 2000;\n const now = new Date();\n const expiry = new Date(y, m - 1, 1);\n expiry.setMonth(expiry.getMonth() + 1); // expire at end of month\n return expiry <= now;\n}\n\n/** Validate a CVV/CVC value */\nexport function validateCvv(cvv: string, network: JoopCardNetwork = 'unknown'): boolean {\n const digits = cvv.replace(/\\D/g, '');\n const expectedLength = network === 'amex' ? 4 : 3;\n return digits.length === expectedLength;\n}\n","export function safeAdd(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) + Math.round(b * f)) / f;\n}\n\nexport function safeSubtract(a: number, b: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return (Math.round(a * f) - Math.round(b * f)) / f;\n}\n\nexport function safeMultiply(a: number, b: number, decimals = 2): number {\n return parseFloat((a * b).toFixed(decimals));\n}\n\nexport function safeDivide(a: number, b: number, decimals = 2): number {\n if (b === 0) throw new Error('Division by zero');\n return parseFloat((a / b).toFixed(decimals));\n}\n\nexport function roundAmount(amount: number, decimals = 2): number {\n const f = Math.pow(10, decimals);\n return Math.round(amount * f) / f;\n}\n\nexport function isValidAmount(value: unknown): boolean {\n if (typeof value === 'string') {\n const clean = value.replace(/[,\\s]/g, '');\n return /^-?\\d+(\\.\\d+)?$/.test(clean) && isFinite(parseFloat(clean));\n }\n return typeof value === 'number' && isFinite(value);\n}\n\nexport function clampAmount(amount: number, min: number, max: number): number {\n return Math.min(Math.max(amount, min), max);\n}\n\nexport function toMinorUnits(amount: number, decimalPlaces = 2): number {\n return Math.round(amount * Math.pow(10, decimalPlaces));\n}\n\nexport function fromMinorUnits(amount: number, decimalPlaces = 2): number {\n return amount / Math.pow(10, decimalPlaces);\n}\n\nexport function sumAmounts(...amounts: number[]): number {\n const f = 100;\n return amounts.reduce((acc, a) => acc + Math.round(a * f), 0) / f;\n}\n","import { validateIban } from '../banking/iban.utility';\nimport { validateLuhn, getCardNetwork } from '../banking/luhn.utility';\nimport { isValidAmount } from '../banking/amount.utility';\n\nexport type JoopValidationRule =\n | { type: 'required' }\n | { type: 'minLength'; min: number }\n | { type: 'maxLength'; max: number }\n | { type: 'min'; min: number }\n | { type: 'max'; max: number }\n | { type: 'pattern'; regex: RegExp; message?: string }\n | { type: 'email' }\n | { type: 'phone' }\n | { type: 'iban' }\n | { type: 'luhn' }\n | { type: 'amount'; min?: number; max?: number }\n | { type: 'dateRange'; maxDays?: number; minDate?: Date; maxDate?: Date }\n | { type: 'custom'; validate: (v: unknown) => string | null };\n\nexport interface JoopValidationResult { valid: boolean; errors: string[]; }\nexport type JoopFormErrors = Record<string, string[]>;\nexport type JoopFormSchema = Record<string, JoopValidationRule[]>;\n\nexport interface JoopPasswordStrength {\n score: number; // 0–4\n label: 'very-weak' | 'weak' | 'fair' | 'strong' | 'very-strong';\n suggestions: string[];\n}\n\nconst EMAIL_RE = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$/;\nconst PHONE_RE = /^\\+?[\\d\\s\\-().]{7,20}$/;\n\nexport class JoopFormValidator {\n\n required(value: unknown): string | null {\n if (value == null || value === '' || (Array.isArray(value) && value.length === 0)) return 'This field is required';\n return null;\n }\n\n minLength(value: string, min: number): string | null {\n if (String(value ?? '').length < min) return `Minimum ${min} characters required`;\n return null;\n }\n\n maxLength(value: string, max: number): string | null {\n if (String(value ?? '').length > max) return `Maximum ${max} characters allowed`;\n return null;\n }\n\n min(value: number | string, min: number): string | null {\n if (Number(value) < min) return `Minimum value is ${min}`;\n return null;\n }\n\n max(value: number | string, max: number): string | null {\n if (Number(value) > max) return `Maximum value is ${max}`;\n return null;\n }\n\n email(value: string): string | null {\n if (!EMAIL_RE.test(String(value ?? ''))) return 'Invalid email address';\n return null;\n }\n\n phone(value: string): string | null {\n if (!PHONE_RE.test(String(value ?? ''))) return 'Invalid phone number';\n return null;\n }\n\n iban(value: string): string | null {\n if (!validateIban(String(value ?? ''))) return 'Invalid IBAN';\n return null;\n }\n\n luhn(value: string): string | null {\n const digits = String(value ?? '').replace(/\\D/g, '');\n if (!validateLuhn(digits)) return 'Invalid card number';\n const network = getCardNetwork(digits);\n if (network === 'unknown') return 'Unrecognised card type';\n return null;\n }\n\n amount(value: string | number, min?: number, max?: number): string | null {\n if (!isValidAmount(value)) return 'Invalid amount';\n const n = Number(value);\n if (min !== undefined && n < min) return `Minimum amount is ${min}`;\n if (max !== undefined && n > max) return `Maximum amount is ${max}`;\n return null;\n }\n\n pattern(value: string, regex: RegExp, message?: string): string | null {\n if (!regex.test(String(value ?? ''))) return message ?? 'Invalid format';\n return null;\n }\n\n dateRange(start: Date, end: Date, maxDays?: number, minDate?: Date, maxDate?: Date): string | null {\n if (start > end) return 'Start date must be before end date';\n if (minDate && start < minDate) return `Start date cannot be before ${minDate.toLocaleDateString()}`;\n if (maxDate && end > maxDate) return `End date cannot be after ${maxDate.toLocaleDateString()}`;\n if (maxDays) {\n const days = Math.ceil((end.getTime() - start.getTime()) / 86_400_000);\n if (days > maxDays) return `Date range cannot exceed ${maxDays} days`;\n }\n return null;\n }\n\n passwordStrength(password: string): JoopPasswordStrength {\n const suggestions: string[] = [];\n let score = 0;\n if (password.length >= 8) score++; else suggestions.push('Use at least 8 characters');\n if (password.length >= 12) score++;\n if (/[A-Z]/.test(password)) score++; else suggestions.push('Add uppercase letters');\n if (/[0-9]/.test(password)) score++; else suggestions.push('Add numbers');\n if (/[^A-Za-z0-9]/.test(password)) score++; else suggestions.push('Add special characters');\n if (/(.)\\1{2,}/.test(password)) { score--; suggestions.push('Avoid repeating characters'); }\n score = Math.max(0, Math.min(4, score));\n const labels: JoopPasswordStrength['label'][] = ['very-weak', 'weak', 'fair', 'strong', 'very-strong'];\n return { score, label: labels[score], suggestions };\n }\n\n /** Validate a single value against multiple rules */\n validate(value: unknown, rules: JoopValidationRule[]): JoopValidationResult {\n const errors: string[] = [];\n for (const rule of rules) {\n let err: string | null = null;\n switch (rule.type) {\n case 'required': err = this.required(value); break;\n case 'minLength': err = this.minLength(String(value ?? ''), rule.min); break;\n case 'maxLength': err = this.maxLength(String(value ?? ''), rule.max); break;\n case 'min': err = this.min(value as number, rule.min); break;\n case 'max': err = this.max(value as number, rule.max); break;\n case 'email': err = this.email(String(value ?? '')); break;\n case 'phone': err = this.phone(String(value ?? '')); break;\n case 'iban': err = this.iban(String(value ?? '')); break;\n case 'luhn': err = this.luhn(String(value ?? '')); break;\n case 'amount': err = this.amount(value as string, rule.min, rule.max); break;\n case 'pattern': err = this.pattern(String(value ?? ''), rule.regex, rule.message); break;\n case 'custom': err = rule.validate(value); break;\n }\n if (err) errors.push(err);\n }\n return { valid: errors.length === 0, errors };\n }\n\n /** Validate an entire form object against a schema */\n validateForm(form: Record<string, unknown>, schema: JoopFormSchema): JoopFormErrors {\n const errors: JoopFormErrors = {};\n for (const field of Object.keys(schema)) {\n const result = this.validate(form[field], schema[field]);\n if (!result.valid) errors[field] = result.errors;\n }\n return errors;\n }\n\n isFormValid(errors: JoopFormErrors): boolean {\n return Object.keys(errors).length === 0;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\nimport { JoopFormValidator, JoopValidationRule, JoopValidationResult } from '../validation/form-validator';\n\nexport interface JoopFieldConfig<T = unknown> {\n value: T;\n validators?: JoopValidationRule[];\n label?: string;\n}\n\nexport interface JoopFieldState<T = unknown> {\n value: T;\n dirty: boolean;\n touched: boolean;\n valid: boolean;\n errors: string[];\n}\n\nexport class JoopField<T = unknown> {\n private _v = new JoopFormValidator();\n private _state$: JoopBehaviorSubject<JoopFieldState<T>>;\n readonly label: string;\n private _initial: T;\n private _validators: JoopValidationRule[];\n\n constructor(config: JoopFieldConfig<T>) {\n this._initial = config.value;\n this._validators = config.validators ?? [];\n this.label = config.label ?? '';\n this._state$ = new JoopBehaviorSubject<JoopFieldState<T>>(this._build(config.value, false, false));\n }\n\n private _build(value: T, dirty: boolean, touched: boolean): JoopFieldState<T> {\n const result: JoopValidationResult = this._validators.length\n ? this._v.validate(value, this._validators)\n : { valid: true, errors: [] };\n return { value, dirty, touched, valid: result.valid, errors: result.errors };\n }\n\n get value(): T { return this._state$.getValue().value; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n get touched(): boolean { return this._state$.getValue().touched; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get errors(): string[] { return this._state$.getValue().errors; }\n\n setValue(value: T): void {\n const s = this._state$.getValue();\n this._state$.next(this._build(value, s.value !== value || s.dirty, s.touched));\n }\n\n markTouched(): void {\n const s = this._state$.getValue();\n this._state$.next({ ...s, touched: true });\n }\n\n reset(): void { this._state$.next(this._build(this._initial, false, false)); }\n\n state$() { return this._state$.asObservable(); }\n}\n\nexport interface JoopFormState {\n valid: boolean;\n dirty: boolean;\n touched: boolean;\n value: Record<string, unknown>;\n}\n\nexport class JoopForm {\n private _fields: Record<string, JoopField>;\n private _state$: JoopBehaviorSubject<JoopFormState>;\n\n constructor(fields: Record<string, JoopField>) {\n this._fields = fields;\n this._state$ = new JoopBehaviorSubject<JoopFormState>(this._compute());\n for (const f of Object.values(fields)) {\n f.state$().subscribe(() => this._state$.next(this._compute()));\n }\n }\n\n private _compute(): JoopFormState {\n const entries = Object.entries(this._fields);\n return {\n valid: entries.every(([, f]) => f.valid),\n dirty: entries.some(([, f]) => f.dirty),\n touched: entries.some(([, f]) => f.touched),\n value: Object.fromEntries(entries.map(([k, f]) => [k, f.value])),\n };\n }\n\n field<T = unknown>(name: string): JoopField<T> { return this._fields[name] as JoopField<T>; }\n get valid(): boolean { return this._state$.getValue().valid; }\n get dirty(): boolean { return this._state$.getValue().dirty; }\n getValue(): Record<string, unknown> { return this._state$.getValue().value; }\n errors(): Record<string, string[]> {\n return Object.fromEntries(Object.entries(this._fields).filter(([, f]) => !f.valid).map(([k, f]) => [k, f.errors]));\n }\n reset(): void { Object.values(this._fields).forEach(f => f.reset()); }\n markAllTouched(): void { Object.values(this._fields).forEach(f => f.markTouched()); }\n state$() { return this._state$.asObservable(); }\n}\n\nexport class JoopFormBuilder {\n field<T = unknown>(value: T, validators?: JoopValidationRule[], label?: string): JoopField<T> {\n return new JoopField<T>({ value, validators, label });\n }\n\n create(schema: Record<string, JoopField>): JoopForm {\n return new JoopForm(schema);\n }\n}\n"]}
@@ -1,6 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  // src/events/index.ts
4
+ var _onListenerError = (error) => {
5
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
6
+ };
4
7
  var JoopSubject = class {
5
8
  _listeners = [];
6
9
  subscribe(listener) {
@@ -10,8 +13,13 @@ var JoopSubject = class {
10
13
  };
11
14
  }
12
15
  next(value) {
13
- for (const listener of this._listeners) {
14
- listener(value);
16
+ const listeners = this._listeners.slice();
17
+ for (const listener of listeners) {
18
+ try {
19
+ listener(value);
20
+ } catch (error) {
21
+ _onListenerError(error);
22
+ }
15
23
  }
16
24
  }
17
25
  asObservable() {
@@ -32,7 +40,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
32
40
  super.next(value);
33
41
  }
34
42
  subscribe(listener) {
35
- listener(this._value);
43
+ try {
44
+ listener(this._value);
45
+ } catch (error) {
46
+ _onListenerError(error);
47
+ }
36
48
  return super.subscribe(listener);
37
49
  }
38
50
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/i18n/i18n.service.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n for (const listener of this._listeners) {\n listener(value);\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n listener(this._value);\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopDirection = 'ltr' | 'rtl';\nexport type JoopTranslations = Record<string, unknown>;\n\nexport interface JoopLanguageDetail {\n code: string;\n culture: string;\n direction: JoopDirection;\n}\n\nconst RTL_LANGUAGES = ['ar', 'arc', 'ckb', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ps', 'sd', 'ur', 'uz_AF', 'yi'];\n\nexport class JoopI18nService {\n private _lang$ = new JoopBehaviorSubject<string>('');\n private _culture$ = new JoopBehaviorSubject<string>('');\n private _translations: Record<string, JoopTranslations> = {};\n private _fallback = 'en';\n\n setFallback(lang: string): void { this._fallback = lang; }\n\n setLanguage(lang: string): void { this._lang$.next(lang); }\n setLanguageCulture(culture: string): void { this._culture$.next(culture); }\n\n getLanguage(): string { return this._lang$.getValue(); }\n getLanguageCulture(): string { return this._culture$.getValue(); }\n\n language$() { return this._lang$.asObservable(); }\n culture$() { return this._culture$.asObservable(); }\n\n getDirection(): JoopDirection {\n return RTL_LANGUAGES.includes(this._lang$.getValue()) ? 'rtl' : 'ltr';\n }\n\n isRtl(): boolean { return this.getDirection() === 'rtl'; }\n\n getDetails(): JoopLanguageDetail {\n return { code: this.getLanguage(), culture: this.getLanguageCulture(), direction: this.getDirection() };\n }\n\n /** Load translations for a language — merges if called multiple times */\n async loadFromUrl(lang: string, url: string): Promise<void> {\n const res = await fetch(url);\n const data = await res.json();\n this.loadFromObject(lang, data);\n }\n\n loadFromObject(lang: string, translations: JoopTranslations): void {\n this._translations[lang] = { ...(this._translations[lang] ?? {}), ...translations };\n }\n\n /** Get a translated string. Supports dot-notation keys: 'ERRORS.TITLE' */\n t(key: string, params?: Record<string, string>): string {\n const lang = this.getLanguage();\n let result = this._resolve(lang, key) ?? this._resolve(this._fallback, key) ?? key;\n if (params) {\n Object.entries(params).forEach(([k, v]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{\\\\s*${k}\\\\s*\\\\}\\\\}`, 'g'), v);\n });\n }\n return result;\n }\n\n has(key: string): boolean {\n return this._resolve(this.getLanguage(), key) !== null;\n }\n\n /** Apply direction to a DOM element (defaults to document.documentElement) */\n applyDirection(el?: HTMLElement): void {\n if (typeof document === 'undefined') return;\n const target = el ?? document.documentElement;\n const dir = this.getDirection();\n target.setAttribute('dir', dir);\n target.setAttribute('lang', this.getLanguage());\n }\n\n getRtlLanguages(): string[] { return [...RTL_LANGUAGES]; }\n\n private _resolve(lang: string, key: string): string | null {\n const translations = this._translations[lang];\n if (!translations) return null;\n const parts = key.split('.');\n let current: unknown = translations;\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return null;\n current = (current as Record<string, unknown>)[part];\n }\n return typeof current === 'string' ? current : null;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/i18n/i18n.service.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopDirection = 'ltr' | 'rtl';\nexport type JoopTranslations = Record<string, unknown>;\n\nexport interface JoopLanguageDetail {\n code: string;\n culture: string;\n direction: JoopDirection;\n}\n\nconst RTL_LANGUAGES = ['ar', 'arc', 'ckb', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ps', 'sd', 'ur', 'uz_AF', 'yi'];\n\nexport class JoopI18nService {\n private _lang$ = new JoopBehaviorSubject<string>('');\n private _culture$ = new JoopBehaviorSubject<string>('');\n private _translations: Record<string, JoopTranslations> = {};\n private _fallback = 'en';\n\n setFallback(lang: string): void { this._fallback = lang; }\n\n setLanguage(lang: string): void { this._lang$.next(lang); }\n setLanguageCulture(culture: string): void { this._culture$.next(culture); }\n\n getLanguage(): string { return this._lang$.getValue(); }\n getLanguageCulture(): string { return this._culture$.getValue(); }\n\n language$() { return this._lang$.asObservable(); }\n culture$() { return this._culture$.asObservable(); }\n\n getDirection(): JoopDirection {\n return RTL_LANGUAGES.includes(this._lang$.getValue()) ? 'rtl' : 'ltr';\n }\n\n isRtl(): boolean { return this.getDirection() === 'rtl'; }\n\n getDetails(): JoopLanguageDetail {\n return { code: this.getLanguage(), culture: this.getLanguageCulture(), direction: this.getDirection() };\n }\n\n /** Load translations for a language — merges if called multiple times */\n async loadFromUrl(lang: string, url: string): Promise<void> {\n const res = await fetch(url);\n const data = await res.json();\n this.loadFromObject(lang, data);\n }\n\n loadFromObject(lang: string, translations: JoopTranslations): void {\n this._translations[lang] = { ...(this._translations[lang] ?? {}), ...translations };\n }\n\n /** Get a translated string. Supports dot-notation keys: 'ERRORS.TITLE' */\n t(key: string, params?: Record<string, string>): string {\n const lang = this.getLanguage();\n let result = this._resolve(lang, key) ?? this._resolve(this._fallback, key) ?? key;\n if (params) {\n Object.entries(params).forEach(([k, v]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{\\\\s*${k}\\\\s*\\\\}\\\\}`, 'g'), v);\n });\n }\n return result;\n }\n\n has(key: string): boolean {\n return this._resolve(this.getLanguage(), key) !== null;\n }\n\n /** Apply direction to a DOM element (defaults to document.documentElement) */\n applyDirection(el?: HTMLElement): void {\n if (typeof document === 'undefined') return;\n const target = el ?? document.documentElement;\n const dir = this.getDirection();\n target.setAttribute('dir', dir);\n target.setAttribute('lang', this.getLanguage());\n }\n\n getRtlLanguages(): string[] { return [...RTL_LANGUAGES]; }\n\n private _resolve(lang: string, key: string): string | null {\n const translations = this._translations[lang];\n if (!translations) return null;\n const parts = key.split('.');\n let current: unknown = translations;\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return null;\n current = (current as Record<string, unknown>)[part];\n }\n return typeof current === 'string' ? current : null;\n }\n}\n"]}
@@ -1,4 +1,7 @@
1
1
  // src/events/index.ts
2
+ var _onListenerError = (error) => {
3
+ console.error("[joopjs] a subject subscriber threw during emission:", error);
4
+ };
2
5
  var JoopSubject = class {
3
6
  _listeners = [];
4
7
  subscribe(listener) {
@@ -8,8 +11,13 @@ var JoopSubject = class {
8
11
  };
9
12
  }
10
13
  next(value) {
11
- for (const listener of this._listeners) {
12
- listener(value);
14
+ const listeners = this._listeners.slice();
15
+ for (const listener of listeners) {
16
+ try {
17
+ listener(value);
18
+ } catch (error) {
19
+ _onListenerError(error);
20
+ }
13
21
  }
14
22
  }
15
23
  asObservable() {
@@ -30,7 +38,11 @@ var JoopBehaviorSubject = class extends JoopSubject {
30
38
  super.next(value);
31
39
  }
32
40
  subscribe(listener) {
33
- listener(this._value);
41
+ try {
42
+ listener(this._value);
43
+ } catch (error) {
44
+ _onListenerError(error);
45
+ }
34
46
  return super.subscribe(listener);
35
47
  }
36
48
  asObservable() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/events/index.ts","../../src/i18n/i18n.service.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n for (const listener of this._listeners) {\n listener(value);\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n listener(this._value);\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopDirection = 'ltr' | 'rtl';\nexport type JoopTranslations = Record<string, unknown>;\n\nexport interface JoopLanguageDetail {\n code: string;\n culture: string;\n direction: JoopDirection;\n}\n\nconst RTL_LANGUAGES = ['ar', 'arc', 'ckb', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ps', 'sd', 'ur', 'uz_AF', 'yi'];\n\nexport class JoopI18nService {\n private _lang$ = new JoopBehaviorSubject<string>('');\n private _culture$ = new JoopBehaviorSubject<string>('');\n private _translations: Record<string, JoopTranslations> = {};\n private _fallback = 'en';\n\n setFallback(lang: string): void { this._fallback = lang; }\n\n setLanguage(lang: string): void { this._lang$.next(lang); }\n setLanguageCulture(culture: string): void { this._culture$.next(culture); }\n\n getLanguage(): string { return this._lang$.getValue(); }\n getLanguageCulture(): string { return this._culture$.getValue(); }\n\n language$() { return this._lang$.asObservable(); }\n culture$() { return this._culture$.asObservable(); }\n\n getDirection(): JoopDirection {\n return RTL_LANGUAGES.includes(this._lang$.getValue()) ? 'rtl' : 'ltr';\n }\n\n isRtl(): boolean { return this.getDirection() === 'rtl'; }\n\n getDetails(): JoopLanguageDetail {\n return { code: this.getLanguage(), culture: this.getLanguageCulture(), direction: this.getDirection() };\n }\n\n /** Load translations for a language — merges if called multiple times */\n async loadFromUrl(lang: string, url: string): Promise<void> {\n const res = await fetch(url);\n const data = await res.json();\n this.loadFromObject(lang, data);\n }\n\n loadFromObject(lang: string, translations: JoopTranslations): void {\n this._translations[lang] = { ...(this._translations[lang] ?? {}), ...translations };\n }\n\n /** Get a translated string. Supports dot-notation keys: 'ERRORS.TITLE' */\n t(key: string, params?: Record<string, string>): string {\n const lang = this.getLanguage();\n let result = this._resolve(lang, key) ?? this._resolve(this._fallback, key) ?? key;\n if (params) {\n Object.entries(params).forEach(([k, v]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{\\\\s*${k}\\\\s*\\\\}\\\\}`, 'g'), v);\n });\n }\n return result;\n }\n\n has(key: string): boolean {\n return this._resolve(this.getLanguage(), key) !== null;\n }\n\n /** Apply direction to a DOM element (defaults to document.documentElement) */\n applyDirection(el?: HTMLElement): void {\n if (typeof document === 'undefined') return;\n const target = el ?? document.documentElement;\n const dir = this.getDirection();\n target.setAttribute('dir', dir);\n target.setAttribute('lang', this.getLanguage());\n }\n\n getRtlLanguages(): string[] { return [...RTL_LANGUAGES]; }\n\n private _resolve(lang: string, key: string): string | null {\n const translations = this._translations[lang];\n if (!translations) return null;\n const parts = key.split('.');\n let current: unknown = translations;\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return null;\n current = (current as Record<string, unknown>)[part];\n }\n return typeof current === 'string' ? current : null;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/events/index.ts","../../src/i18n/i18n.service.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export type Unsubscribe = () => void;\nexport type Listener<T> = (value: T) => void;\n\n/**\n * Reports a subscriber that threw during emission, without aborting delivery\n * to the remaining subscribers. Defaults to console.error; override to route\n * to your own logger (e.g. in a banking app where dropped events matter).\n */\nlet _onListenerError: (error: unknown) => void = (error) => {\n // eslint-disable-next-line no-console\n console.error('[joopjs] a subject subscriber threw during emission:', error);\n};\n\n/** Override how subscriber errors are reported during emission. */\nexport function setSubjectErrorHandler(handler: (error: unknown) => void): void {\n _onListenerError = handler;\n}\n\n/**\n * Lightweight pub/sub subject — emits to all current subscribers.\n * Replaces RxJS Subject without pulling in the full RxJS dependency.\n */\nexport class JoopSubject<T> {\n private _listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>): Unsubscribe {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter(l => l !== listener);\n };\n }\n\n next(value: T): void {\n // Snapshot so a subscribe()/unsubscribe() triggered by a listener can't\n // disturb this emission, and isolate each listener so one that throws\n // doesn't deprive later subscribers of the value.\n const listeners = this._listeners.slice();\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n _onListenerError(error);\n }\n }\n }\n\n asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Stateful subject — replays the current value to any new subscriber immediately.\n * Replaces RxJS BehaviorSubject.\n */\nexport class JoopBehaviorSubject<T> extends JoopSubject<T> {\n private _value: T;\n\n constructor(initialValue: T) {\n super();\n this._value = initialValue;\n }\n\n getValue(): T {\n return this._value;\n }\n\n override next(value: T): void {\n this._value = value;\n super.next(value);\n }\n\n override subscribe(listener: Listener<T>): Unsubscribe {\n try {\n listener(this._value);\n } catch (error) {\n _onListenerError(error);\n }\n return super.subscribe(listener);\n }\n\n override asObservable(): JoopObservable<T> {\n return new JoopObservable<T>(listener => this.subscribe(listener));\n }\n}\n\n/**\n * Read-only observable handle returned from asObservable().\n */\nexport class JoopObservable<T> {\n constructor(private _subscribeFn: (listener: Listener<T>) => Unsubscribe) {}\n\n subscribe(listener: Listener<T>): Unsubscribe {\n return this._subscribeFn(listener);\n }\n\n /** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */\n getOnce(): T | undefined {\n let result: T | undefined;\n const unsub = this.subscribe(v => { result = v; });\n unsub();\n return result;\n }\n}\n","import { JoopBehaviorSubject } from '../events';\n\nexport type JoopDirection = 'ltr' | 'rtl';\nexport type JoopTranslations = Record<string, unknown>;\n\nexport interface JoopLanguageDetail {\n code: string;\n culture: string;\n direction: JoopDirection;\n}\n\nconst RTL_LANGUAGES = ['ar', 'arc', 'ckb', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ps', 'sd', 'ur', 'uz_AF', 'yi'];\n\nexport class JoopI18nService {\n private _lang$ = new JoopBehaviorSubject<string>('');\n private _culture$ = new JoopBehaviorSubject<string>('');\n private _translations: Record<string, JoopTranslations> = {};\n private _fallback = 'en';\n\n setFallback(lang: string): void { this._fallback = lang; }\n\n setLanguage(lang: string): void { this._lang$.next(lang); }\n setLanguageCulture(culture: string): void { this._culture$.next(culture); }\n\n getLanguage(): string { return this._lang$.getValue(); }\n getLanguageCulture(): string { return this._culture$.getValue(); }\n\n language$() { return this._lang$.asObservable(); }\n culture$() { return this._culture$.asObservable(); }\n\n getDirection(): JoopDirection {\n return RTL_LANGUAGES.includes(this._lang$.getValue()) ? 'rtl' : 'ltr';\n }\n\n isRtl(): boolean { return this.getDirection() === 'rtl'; }\n\n getDetails(): JoopLanguageDetail {\n return { code: this.getLanguage(), culture: this.getLanguageCulture(), direction: this.getDirection() };\n }\n\n /** Load translations for a language — merges if called multiple times */\n async loadFromUrl(lang: string, url: string): Promise<void> {\n const res = await fetch(url);\n const data = await res.json();\n this.loadFromObject(lang, data);\n }\n\n loadFromObject(lang: string, translations: JoopTranslations): void {\n this._translations[lang] = { ...(this._translations[lang] ?? {}), ...translations };\n }\n\n /** Get a translated string. Supports dot-notation keys: 'ERRORS.TITLE' */\n t(key: string, params?: Record<string, string>): string {\n const lang = this.getLanguage();\n let result = this._resolve(lang, key) ?? this._resolve(this._fallback, key) ?? key;\n if (params) {\n Object.entries(params).forEach(([k, v]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{\\\\s*${k}\\\\s*\\\\}\\\\}`, 'g'), v);\n });\n }\n return result;\n }\n\n has(key: string): boolean {\n return this._resolve(this.getLanguage(), key) !== null;\n }\n\n /** Apply direction to a DOM element (defaults to document.documentElement) */\n applyDirection(el?: HTMLElement): void {\n if (typeof document === 'undefined') return;\n const target = el ?? document.documentElement;\n const dir = this.getDirection();\n target.setAttribute('dir', dir);\n target.setAttribute('lang', this.getLanguage());\n }\n\n getRtlLanguages(): string[] { return [...RTL_LANGUAGES]; }\n\n private _resolve(lang: string, key: string): string | null {\n const translations = this._translations[lang];\n if (!translations) return null;\n const parts = key.split('.');\n let current: unknown = translations;\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return null;\n current = (current as Record<string, unknown>)[part];\n }\n return typeof current === 'string' ? current : null;\n }\n}\n"]}