paymob-widget-alpha 1.0.1 → 1.0.3

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 (4) hide show
  1. package/README.md +18 -18
  2. package/main.css +1 -1
  3. package/main.js +86 -18
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -43,7 +43,9 @@ new PaymobWidget({
43
43
  currency: 'EGP',
44
44
  theme: 'primary',
45
45
  onSubmit: (plan) => {
46
- // plan = { id, tenure, amount }
46
+ // `onSubmit` is called when the user selects an installment plan and clicks **Buy now** in the widget.
47
+ // The callback receives a `plan` object (e.g. `id`, `tenure`, `amount`) so you can create an order / continue your checkout flow in your app.
48
+ // plan = { id: 123, tenure: 12, amount: 250 }
47
49
  },
48
50
  });
49
51
  ```
@@ -95,16 +97,20 @@ The full list of properties is as follows:
95
97
  <script src="https://cdn.jsdelivr.net/npm/paymob-widget-alpha@latest/main.js" type="module" ></script>
96
98
 
97
99
  <script>
98
- new PaymobWidget({
99
- publicKey: 'egy_pk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
100
- elementId: 'paymob-widget',
101
- amount: 1000,
102
- currency: 'EGP',
103
- theme: 'primary', // "primary" | "light" | "dark"
104
- onSubmit: (plan) => {
105
- // plan = { id, tenure, amount }
106
- },
107
- });
100
+ window.onload = () => {
101
+ new PaymobWidget({
102
+ publicKey: 'egy_pk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
103
+ elementId: 'paymob-widget',
104
+ amount: 1000,
105
+ currency: 'EGP',
106
+ theme: 'primary', // "primary" | "light" | "dark"
107
+ onSubmit: (plan) => {
108
+ // `onSubmit` is called when the user selects an installment plan and clicks **Buy now** in the widget.
109
+ // The callback receives a `plan` object (e.g. `id`, `tenure`, `amount`) so you can create an order / continue your checkout flow in your app.
110
+ // plan = { id: 123, tenure: 12, amount: 250 }
111
+ },
112
+ });
113
+ };
108
114
  </script>
109
115
  </body>
110
116
  </html>
@@ -112,14 +118,8 @@ The full list of properties is as follows:
112
118
 
113
119
  ## Notes
114
120
 
115
- - **Rendering**: The widget renders a React app into your `elementId` container.
121
+ - **Rendering**: The widget renders a Installment Widget into your `elementId` container.
116
122
  - **Isolation**: UI is rendered inside a Shadow DOM wrapper to reduce CSS conflicts with the host page.
117
- - **API base URL**: Base URL is resolved from the key prefix (e.g. `egy_`, `are_`, `sau_`, `pak_`, `omn_`) using `publicKey` (and `clientSecret` as a fallback).
118
- - **Installment plans endpoint**: The widget fetches plans using:
119
- - `POST /api/ecommerce/installment-plans/product` with `{ public_key, amount_cents, currency, integration_id? }`
120
123
 
121
- ## Troubleshooting
122
124
 
123
- - **Container not found**: Ensure an element exists with the same id passed in `elementId`.
124
- - **No plans available**: Verify `publicKey`, `currency`, `amount`, and that installment plans exist for the given product/amount.
125
125
 
package/main.css CHANGED
@@ -28,7 +28,7 @@
28
28
  @import url(https://fonts.googleapis.com/css2?family=Cairo:wght@200..1000&display=swap);
29
29
  @import url(https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@100..900&display=swap);
30
30
  @import url(https://fonts.googleapis.com/css2?family=Montserrat:wght@100..900&display=swap);
31
- @keyframes modal_slideIn__uUuXp{from{transform:translateX(100%);opacity:0}to{transform:translateX(0);opacity:1}}@keyframes modal_slideUp__2GwQS{from{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}.modal_root__sfoqg{position:fixed;inset:0;z-index:10000}.modal_rootMobile__wzN8Q{display:flex;justify-content:flex-end;align-items:stretch}.modal_rootDesktop__CiQty{display:block}.modal_overlay__D1Rh8{position:absolute;inset:0;z-index:0;cursor:pointer;background:rgba(0,0,0,.35);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}.modal_panel__odrOu{position:relative;z-index:1;width:100%}.modal_panelMobile__Pyh\+r{margin-left:0;margin-right:0;margin-top:auto;margin-bottom:0;height:80vh;max-height:80vh;max-width:100%;animation:modal_slideUp__2GwQS .3s ease-out}.modal_panelDesktop__YwVRJ{margin-left:auto;margin-right:0;margin-top:0;margin-bottom:0;height:100%;max-height:100%;max-width:550px;animation:modal_slideIn__uUuXp .3s ease-out}.modal_closeFloatingMobile__Z3pkR{position:absolute;left:50%;top:-50px;transform:translateX(-50%);width:40px;height:40px;border-radius:50%;background-color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 16px rgba(0,0,0,.18);z-index:2}.modal_closeFloatingDesktop__3W3cX{position:absolute;left:-45px;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:50%;background-color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 16px rgba(0,0,0,.18)}.modal_dialog__fapVk{height:100%;max-height:100%;width:100%;display:flex;flex-direction:column;background-color:#fff}.modal_dialogMobile__awaMW{overflow:hidden;box-shadow:0 -4px 24px rgba(0,0,0,.15);border-radius:24px 24px 0 0}.modal_dialogDesktop__z8dIY{overflow:visible;box-shadow:-4px 0 24px rgba(0,0,0,.15);border-radius:0}.modal_dialog__fapVk[data-theme=primary]{--modal-header-bg: #144dff;--modal-title-color: #ffffff;--modal-powered-color: #d0d5dd}.modal_dialog__fapVk[data-theme=dark]{--modal-header-bg: #081f66;--modal-title-color: #ffffff;--modal-powered-color: #d0d5dd}.modal_dialog__fapVk[data-theme=light]{--modal-header-bg: #e8edff;--modal-title-color: #101828;--modal-powered-color: #667085}.modal_header__oe722{position:relative;display:flex;align-items:flex-end;justify-content:space-between;padding:12px 16px;background-color:var(--modal-header-bg);color:var(--modal-title-color)}.modal_title__0XpA9{font-size:14px;font-weight:600}.modal_poweredRow__VXaw8{display:flex;align-items:flex-end;gap:4px}.modal_poweredLabel__a3hHx{font-size:12px;line-height:1;display:flex;align-items:flex-end;color:var(--modal-powered-color)}.modal_logo__jcucM{height:17px;object-fit:contain}.modal_body__SQUnU{flex:1;overflow-y:auto;padding:16px;-webkit-overflow-scrolling:touch}.modal_footer__GKw2U{border-top:1px solid #f3f4f6;padding:16px}.modal_closeIcon__RJJ9p{width:10px;height:10px}
31
+ @keyframes modal_slideIn__uUuXp{from{transform:translateX(100%);opacity:0}to{transform:translateX(0);opacity:1}}@keyframes modal_slideUp__2GwQS{from{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}.modal_root__sfoqg{position:fixed;inset:0;z-index:10000;isolation:isolate}.modal_rootMobile__wzN8Q{display:flex;justify-content:flex-end;align-items:stretch}.modal_rootDesktop__CiQty{display:block}.modal_overlay__D1Rh8{position:absolute;inset:0;z-index:0;cursor:pointer;background:rgba(0,0,0,.35);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}.modal_panel__odrOu{position:relative;z-index:1;width:100%}.modal_panelMobile__Pyh\+r{margin-left:0;margin-right:0;margin-top:auto;margin-bottom:0;height:80vh;max-height:80vh;max-width:100%;animation:modal_slideUp__2GwQS .3s ease-out}.modal_panelDesktop__YwVRJ{margin-left:auto;margin-right:0;margin-top:0;margin-bottom:0;height:100%;max-height:100%;max-width:550px;animation:modal_slideIn__uUuXp .3s ease-out}.modal_closeFloatingMobile__Z3pkR{position:absolute;left:50%;top:-50px;transform:translateX(-50%);width:40px;height:40px;border-radius:50%;background-color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 16px rgba(0,0,0,.18);z-index:2}.modal_closeFloatingDesktop__3W3cX{position:absolute;left:-45px;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:50%;background-color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 16px rgba(0,0,0,.18)}.modal_dialog__fapVk{height:100%;max-height:100%;width:100%;display:flex;flex-direction:column;background-color:#fff}.modal_dialogMobile__awaMW{overflow:hidden;box-shadow:0 -4px 24px rgba(0,0,0,.15);border-radius:24px 24px 0 0}.modal_dialogDesktop__z8dIY{overflow:visible;box-shadow:-4px 0 24px rgba(0,0,0,.15);border-radius:0}.modal_dialog__fapVk[data-theme=primary]{--modal-header-bg: #144dff;--modal-title-color: #ffffff;--modal-powered-color: #d0d5dd}.modal_dialog__fapVk[data-theme=dark]{--modal-header-bg: #081f66;--modal-title-color: #ffffff;--modal-powered-color: #d0d5dd}.modal_dialog__fapVk[data-theme=light]{--modal-header-bg: #e8edff;--modal-title-color: #101828;--modal-powered-color: #667085}.modal_header__oe722{position:relative;display:flex;align-items:flex-end;justify-content:space-between;padding:12px 16px;background-color:var(--modal-header-bg);color:var(--modal-title-color)}.modal_title__0XpA9{font-size:14px;font-weight:600}.modal_poweredRow__VXaw8{display:flex;align-items:flex-end;gap:4px}.modal_poweredLabel__a3hHx{font-size:12px;line-height:1;display:flex;align-items:flex-end;color:var(--modal-powered-color)}.modal_logo__jcucM{height:17px;object-fit:contain}.modal_body__SQUnU{flex:1;overflow-y:auto;padding:16px;-webkit-overflow-scrolling:touch}.modal_footer__GKw2U{border-top:1px solid #f3f4f6;padding:16px}.modal_closeIcon__RJJ9p{width:10px;height:10px}
32
32
  .badge_badge__zVreJ{width:fit-content;height:fit-content;display:flex;align-items:center;justify-content:center;border-radius:1rem;gap:.25rem;mix-blend-mode:multiply}.badge_badge__zVreJ svg,.badge_badge__zVreJ img{width:1rem;height:1rem}.badge_badge__zVreJ img{border-radius:50%}[data-badge-size=sm]{padding:0 .5rem}html[dir=ltr] [data-badge-size=sm],html[lang=en] [data-badge-size=sm]{font-family:"Inter",sans-serif;font-size:.875rem;font-style:normal;line-height:1.5rem;letter-spacing:.01rem;font-weight:500}html[dir=rtl] [data-badge-size=sm],html[lang=ar] [data-badge-size=sm]{font-family:"Cairo",sans-serif;font-size:.875rem;font-style:normal;line-height:1.5rem;letter-spacing:.01rem;font-weight:600}[data-badge-size=md],[data-badge-size=lg]{padding:0 .75rem}html[dir=ltr] [data-badge-size=md],html[lang=en] [data-badge-size=md]{font-family:"Inter",sans-serif;font-size:1rem;font-style:normal;line-height:1.75rem;font-weight:500}html[dir=rtl] [data-badge-size=md],html[lang=ar] [data-badge-size=md]{font-family:"Cairo",sans-serif;font-size:1rem;font-style:normal;line-height:1.75rem;font-weight:600}html[dir=ltr] [data-badge-size=lg],html[lang=en] [data-badge-size=lg]{font-family:"Inter",sans-serif;font-size:1.125rem;font-style:normal;line-height:2rem;font-weight:500}html[dir=rtl] [data-badge-size=lg],html[lang=ar] [data-badge-size=lg]{font-family:"Cairo",sans-serif;font-size:1.125rem;font-style:normal;line-height:2rem;font-weight:600}[data-badge-color=gray],[data-badge-color=grey]{color:#344054;background-color:#f2f4f7}[data-badge-color=gray]:not([data-badge-type=country]):not([data-badge-type=avatar]) path,[data-badge-color=grey]:not([data-badge-type=country]):not([data-badge-type=avatar]) path{fill:#344054 !important}[data-badge-color=primary]{color:#144dff;background-color:#e8edff}[data-badge-color=primary]:not([data-badge-type=country]):not([data-badge-type=avatar]) path{fill:#144dff !important}[data-badge-color=green]{color:#038f6e;background-color:#e6f7f3}[data-badge-color=green]:not([data-badge-type=country]):not([data-badge-type=avatar]) path{fill:#038f6e !important}[data-badge-color=yellow]{color:#dc6803;background-color:#fffaeb}[data-badge-color=yellow]:not([data-badge-type=country]):not([data-badge-type=avatar]) path{fill:#dc6803 !important}[data-badge-color=red]{color:#cc1142;background-color:#ffe8ee}[data-badge-color=red]:not([data-badge-type=country]):not([data-badge-type=avatar]) path{fill:#cc1142 !important}
33
33
  .checkbox-base_checkbox-base__EOx8c{position:relative;display:block;display:flex;align-items:center;justify-content:center;flex-shrink:0}.checkbox-base_checkbox-base__input__yOneo{position:absolute;opacity:0;width:100%;height:100%;margin:0}.checkbox-base_checkbox-base__input__yOneo:disabled+.checkbox-base_checkbox-base__checkbox__cRTaH:before{border:.0625rem solid #d0d5dd;background-color:#f9fafb;cursor:not-allowed}.checkbox-base_checkbox-base__input__yOneo:disabled+.checkbox-base_checkbox-base__checkbox__cRTaH:after{cursor:not-allowed;border-color:rgba(0,0,0,0)}.checkbox-base_checkbox-base__input__yOneo:checked+.checkbox-base_checkbox-base__checkbox__cRTaH:before{border:.0625rem solid #144dff;background-color:#144dff}.checkbox-base_checkbox-base__input__yOneo:checked+.checkbox-base_checkbox-base__checkbox__cRTaH:after{border-color:#fff}.checkbox-base_checkbox-base__input__yOneo:checked:disabled+.checkbox-base_checkbox-base__checkbox__cRTaH:before{border:.0625rem solid #d0d5dd;background-color:#f9fafb}.checkbox-base_checkbox-base__input__yOneo:checked:disabled+.checkbox-base_checkbox-base__checkbox__cRTaH:after{background-color:rgba(0,0,0,0);border-color:#d0d5dd}.checkbox-base_checkbox-base__checkbox__cRTaH{cursor:pointer;display:inline-block;position:relative;width:100%;height:100%}.checkbox-base_checkbox-base__checkbox__cRTaH:before{content:"";box-sizing:border-box;position:absolute;width:100%;height:100%;border:.0625rem solid #d0d5dd;background-color:#fff;transition:200ms linear}.checkbox-base_checkbox-base__checkbox__cRTaH:after{content:"";position:absolute;top:50%;left:50%;transition:200ms linear}html[dir=ltr] .checkbox-base_checkbox-base__checkbox__cRTaH:after,html[lang=en] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-inline-end:solid rgba(0,0,0,0);border-block-end:solid rgba(0,0,0,0)}html[dir=rtl] .checkbox-base_checkbox-base__checkbox__cRTaH:after,html[lang=ar] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-inline-start:solid rgba(0,0,0,0);border-block-end:solid rgba(0,0,0,0)}.checkbox-base_checkbox-base__checkbox__cRTaH:hover:before,.checkbox-base_checkbox-base__checkbox__cRTaH[data-checkbox-base-hovered=true]:before{border:.0625rem solid #144dff;background-color:#e8edff}.checkbox-base_checkbox-base__checkbox__cRTaH:focus:before,.checkbox-base_checkbox-base__checkbox__cRTaH[data-checkbox-base-focused=true]:before{border:.0625rem solid #144dff;background-color:#fff}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after{width:18.75%;height:43.75%;transform:translate(-50%, -60%) rotate(45deg)}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-icon=dash] .checkbox-base_checkbox-base__checkbox__cRTaH:after{width:45%;height:10%;transform:translate(-50%, -65%)}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=sm]{width:1rem;height:1rem}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=sm] .checkbox-base_checkbox-base__checkbox__cRTaH:before{border-radius:.25rem}html[dir=ltr] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=sm][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after,html[lang=en] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=sm][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-inline-end-width:.0625rem;border-block-end-width:.0625rem}html[dir=rtl] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=sm][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after,html[lang=ar] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=sm][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-inline-start-width:.0625rem;border-block-end-width:.0625rem}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=sm][data-checkbox-base-icon=dash] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-width:0;border-block-end-width:.0625rem}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=md]{width:1.25rem;height:1.25rem}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=md] .checkbox-base_checkbox-base__checkbox__cRTaH:before{border-radius:.375rem}html[dir=ltr] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=md][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after,html[lang=en] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=md][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-inline-end-width:.125rem;border-block-end-width:.125rem}html[dir=rtl] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=md][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after,html[lang=ar] .checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=md][data-checkbox-base-icon=tick] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-inline-start-width:.125rem;border-block-end-width:.125rem}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-size=md][data-checkbox-base-icon=dash] .checkbox-base_checkbox-base__checkbox__cRTaH:after{border-width:0;border-block-end-width:.125rem}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-type=radio] .checkbox-base_checkbox-base__checkbox__cRTaH:before{border-radius:50%}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-type=radio] .checkbox-base_checkbox-base__checkbox__cRTaH:after{width:40%;height:40%;border-radius:50%;background-color:rgba(0,0,0,0);transform:translate(-50%, -50%);border:none}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-type=radio] .checkbox-base_checkbox-base__input__yOneo:checked+.checkbox-base_checkbox-base__checkbox__cRTaH:before{border:.0625rem solid #144dff;background-color:#144dff}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-type=radio] .checkbox-base_checkbox-base__input__yOneo:checked+.checkbox-base_checkbox-base__checkbox__cRTaH:after{background-color:#fff}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-type=radio] .checkbox-base_checkbox-base__input__yOneo:checked:disabled+.checkbox-base_checkbox-base__checkbox__cRTaH:before{border:.0625rem solid #d0d5dd;background-color:#f9fafb}.checkbox-base_checkbox-base__EOx8c[data-checkbox-base-type=radio] .checkbox-base_checkbox-base__input__yOneo:checked:disabled+.checkbox-base_checkbox-base__checkbox__cRTaH:after{background-color:#d0d5dd}
34
34
  .checkbox_checkbox-wrapper__zjCk3{width:fit-content;display:flex;gap:.5rem;cursor:pointer}.checkbox_checkbox-wrapper__text-box__XGApL{display:flex;flex-direction:column;gap:.5rem}.checkbox_checkbox-wrapper__text-box__row__2k\+Wo{display:flex;align-items:center;gap:.5rem}.checkbox_checkbox-wrapper__text-box__text__JezoX{color:#344054}.checkbox_checkbox-wrapper__text-box__badge__HmR8b{margin-inline-start:.25rem}.checkbox_checkbox-wrapper__text-box__hint-text__FYD4b{color:#475467;font-family:"Inter",sans-serif;font-size:.875rem;font-style:normal;line-height:1.125rem;letter-spacing:.01rem;font-weight:400}html[dir=rtl] .checkbox_checkbox-wrapper__text-box__hint-text__FYD4b,html[lang=ar] .checkbox_checkbox-wrapper__text-box__hint-text__FYD4b{font-family:"Cairo",sans-serif;font-size:.875rem;font-style:normal;line-height:1.125rem;letter-spacing:.01rem;font-weight:400}.checkbox_checkbox-wrapper__zjCk3[data-checkbox-disabled=true]{pointer-events:none}.checkbox_checkbox-wrapper__zjCk3[data-checkbox-size=sm] .checkbox_checkbox-wrapper__text-box__text__JezoX{line-height:.8rem !important;font-family:"Inter",sans-serif;font-size:.875rem;font-style:normal;line-height:1.5rem;letter-spacing:.01rem;font-weight:500}html[dir=rtl] .checkbox_checkbox-wrapper__zjCk3[data-checkbox-size=sm] .checkbox_checkbox-wrapper__text-box__text__JezoX,html[lang=ar] .checkbox_checkbox-wrapper__zjCk3[data-checkbox-size=sm] .checkbox_checkbox-wrapper__text-box__text__JezoX{font-family:"Cairo",sans-serif;font-size:.875rem;font-style:normal;line-height:1.5rem;letter-spacing:.01rem;font-weight:600}.checkbox_checkbox-wrapper__zjCk3[data-checkbox-size=md] .checkbox_checkbox-wrapper__text-box__text__JezoX{line-height:.82rem !important;font-family:"Inter",sans-serif;font-size:1rem;font-style:normal;line-height:1.75rem;font-weight:500}html[dir=rtl] .checkbox_checkbox-wrapper__zjCk3[data-checkbox-size=md] .checkbox_checkbox-wrapper__text-box__text__JezoX,html[lang=ar] .checkbox_checkbox-wrapper__zjCk3[data-checkbox-size=md] .checkbox_checkbox-wrapper__text-box__text__JezoX{font-family:"Cairo",sans-serif;font-size:1rem;font-style:normal;line-height:1.75rem;font-weight:600}.checkbox_checkbox-wrapper__zjCk3[data-checkbox-alignment=start]{align-items:flex-start}.checkbox_checkbox-wrapper__zjCk3[data-checkbox-alignment=end]{align-items:flex-end}.checkbox_checkbox-wrapper__zjCk3[data-checkbox-alignment=center]{align-items:center}.checkbox_checkbox-wrapper__zjCk3:has(div[class*=badge]){align-items:flex-start}.checkbox_checkbox-wrapper__zjCk3:has(div[class*=badge]) div[data-checkbox-base-size]{margin-block-start:.25rem}
package/main.js CHANGED
@@ -610,11 +610,28 @@ const environment = {
610
610
  };
611
611
  // EXTERNAL MODULE: ../../node_modules/react/jsx-runtime.js
612
612
  var jsx_runtime = __webpack_require__(85);
613
+ ;// ./src/utils/PortalRootContext.tsx
614
+
615
+
616
+ const PortalRootContext = /*#__PURE__*/(0,react.createContext)(null);
617
+ function PortalRootProvider({
618
+ value,
619
+ children
620
+ }) {
621
+ return /*#__PURE__*/(0,jsx_runtime.jsx)(PortalRootContext.Provider, {
622
+ value: value,
623
+ children: children
624
+ });
625
+ }
626
+ function usePortalRoot() {
627
+ return (0,react.useContext)(PortalRootContext);
628
+ }
613
629
  ;// ./src/utils/ShadowWrapper.tsx
614
630
 
615
631
 
616
632
 
617
633
 
634
+
618
635
  const ShadowWrapper = ({
619
636
  elementId,
620
637
  children
@@ -624,17 +641,47 @@ const ShadowWrapper = ({
624
641
  (0,react.useEffect)(() => {
625
642
  if (!document.getElementById(elementId)) return;
626
643
  document.getElementById(elementId).innerHTML = '';
627
- const container = document.getElementById(elementId).appendChild(document.createElement('div'));
644
+ const mountRoot = document.getElementById(elementId);
645
+
646
+ // Create a dedicated Shadow DOM host for the main app.
647
+ const shadowHost = mountRoot.appendChild(document.createElement('div'));
628
648
  if (!('attachShadow' in Element.prototype)) {
629
649
  setError('Shadow DOM is not supported in this browser');
630
650
  return;
631
651
  }
632
652
  try {
633
- let shadow = container.shadowRoot;
653
+ let shadow = shadowHost.shadowRoot;
634
654
  if (!shadow) {
635
- shadow = container.attachShadow({
655
+ shadow = shadowHost.attachShadow({
636
656
  mode: 'open'
637
657
  });
658
+ const appendedHrefs = new Set();
659
+ const appendStylesheetLink = href => {
660
+ if (!href) return;
661
+ if (appendedHrefs.has(href)) return;
662
+ if (shadow.querySelector(`link[rel="stylesheet"][href="${href}"]`)) return;
663
+ const link = document.createElement('link');
664
+ link.rel = 'stylesheet';
665
+ link.href = href;
666
+ shadow.appendChild(link);
667
+ appendedHrefs.add(href);
668
+ };
669
+
670
+ // If the widget script is loaded from a URL (CDN/dev server),
671
+ // also load sibling CSS assets from the same base so Shadow DOM always
672
+ // receives the correct CSS bundle (including CSS Modules).
673
+ const resolveBaseFromScript = () => {
674
+ // Best-effort script tag detection (covers CDN embeds + local dev).
675
+ const scripts = Array.from(document.querySelectorAll('script[src]'));
676
+ const candidates = scripts.map(s => String(s.src || '')).filter(Boolean).filter(src => /\/main\.js(\?.*)?$/.test(src));
677
+ const best = candidates.find(src => src.includes('paymob-widget')) || candidates.find(src => src.includes('paymob_widget')) || candidates[candidates.length - 1];
678
+ return best ? best.replace(/\/[^/]*$/, '') : null;
679
+ };
680
+ const base = resolveBaseFromScript();
681
+ if (base) {
682
+ appendStylesheetLink(`${base}/styles.css`);
683
+ appendStylesheetLink(`${base}/main.css`);
684
+ }
638
685
  environment.PIXEL_CSS_LINKS.forEach(href => {
639
686
  if (href.match(/\.(woff2?|ttf|otf|eot)$/)) {
640
687
  const fontName = 'currencyFont';
@@ -654,11 +701,7 @@ const ShadowWrapper = ({
654
701
  (_shadow = shadow) == null || _shadow.appendChild(style);
655
702
  }).catch(err => console.error(`Failed to load font: ${href}`, err));
656
703
  } else {
657
- var _shadow2;
658
- const link = document.createElement('link');
659
- link.rel = 'stylesheet';
660
- link.href = href;
661
- (_shadow2 = shadow) == null || _shadow2.appendChild(link);
704
+ appendStylesheetLink(href);
662
705
  }
663
706
  });
664
707
  }
@@ -682,7 +725,10 @@ const ShadowWrapper = ({
682
725
  }), container);
683
726
  }
684
727
  if (shadowRoot) {
685
- return /*#__PURE__*/(0,react_dom.createPortal)(children, shadowRoot);
728
+ return /*#__PURE__*/(0,react_dom.createPortal)(/*#__PURE__*/(0,jsx_runtime.jsx)(PortalRootProvider, {
729
+ value: shadowRoot,
730
+ children: children
731
+ }), shadowRoot);
686
732
  }
687
733
  return null;
688
734
  };
@@ -4972,6 +5018,7 @@ const close_namespaceObject = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACY
4972
5018
 
4973
5019
 
4974
5020
 
5021
+
4975
5022
  const MOBILE_BREAKPOINT_PX = 664;
4976
5023
  const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
4977
5024
  function getFocusableElements(root) {
@@ -5001,6 +5048,7 @@ function Modal({
5001
5048
  const titleId = (0,react.useId)();
5002
5049
  const trapContainerRef = (0,react.useRef)(null);
5003
5050
  const dialogRef = (0,react.useRef)(null);
5051
+ const portalRoot = usePortalRoot();
5004
5052
  (0,react.useLayoutEffect)(() => {
5005
5053
  if (!isOpen) return;
5006
5054
  const previousActiveElement = document.activeElement;
@@ -5046,7 +5094,7 @@ function Modal({
5046
5094
  document.addEventListener('keydown', onDocKeyDown);
5047
5095
  return () => {
5048
5096
  document.removeEventListener('keydown', onDocKeyDown);
5049
- document.body.style.overflow = 'auto';
5097
+ document.body.style.overflow = '';
5050
5098
  if (previousActiveElement instanceof HTMLElement && document.contains(previousActiveElement)) {
5051
5099
  previousActiveElement.focus({
5052
5100
  preventScroll: true
@@ -5124,7 +5172,7 @@ function Modal({
5124
5172
  })]
5125
5173
  })]
5126
5174
  });
5127
- return /*#__PURE__*/(0,react_dom.createPortal)(modalContent, document.body);
5175
+ return /*#__PURE__*/(0,react_dom.createPortal)(modalContent, portalRoot != null ? portalRoot : document.body);
5128
5176
  }
5129
5177
  /* harmony default export */ const modal = (Modal);
5130
5178
  ;// ../../node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js
@@ -7798,13 +7846,19 @@ function normalizeBanksWithPlans(installmentPlansProductPayload) {
7798
7846
  var _bankItem$installment, _axios$defaults$baseU, _bankItem$bank_logo;
7799
7847
  const bankInstallmentPlans = (_bankItem$installment = bankItem.installment_plans) != null ? _bankItem$installment : [];
7800
7848
  const installmentOptions = bankInstallmentPlans.map(planFromProduct => {
7849
+ var _planFromProduct$purc, _planFromProduct$conv;
7801
7850
  const interestRate = Number(planFromProduct.interest_rate);
7802
- const badge = interestRate === 0 ? '0% Interest' : `${interestRate}% Interest`;
7851
+ const purchaseFees = Number((_planFromProduct$purc = planFromProduct.purchase_fees) != null ? _planFromProduct$purc : 0);
7852
+ const convenienceFees = Number((_planFromProduct$conv = planFromProduct.convenience_fees) != null ? _planFromProduct$conv : 0);
7853
+ const fees = purchaseFees + convenienceFees;
7854
+ const noFees = !(planFromProduct.purchase_fees || planFromProduct.convenience_fees);
7803
7855
  return {
7804
7856
  id: planFromProduct.id,
7805
7857
  months: Number(planFromProduct.tenure),
7806
7858
  monthlyAmount: Number(planFromProduct.installment_amount),
7807
- badge
7859
+ interestRate,
7860
+ fees,
7861
+ noFees
7808
7862
  };
7809
7863
  });
7810
7864
  const minimumMonthlyFromProduct = Number(bankItem.minimum_plan_amount);
@@ -8122,17 +8176,31 @@ function Widget({
8122
8176
  children: [installmentOption.months, " Months"]
8123
8177
  })]
8124
8178
  }),
8125
- hintText: /*#__PURE__*/(0,jsx_runtime.jsx)("div", {
8179
+ hintText: /*#__PURE__*/(0,jsx_runtime.jsxs)("div", {
8126
8180
  style: {
8127
8181
  display: 'flex',
8128
8182
  alignItems: 'center',
8129
- gap: '10px'
8183
+ gap: '8px',
8184
+ flexWrap: 'wrap'
8130
8185
  },
8131
- children: /*#__PURE__*/(0,jsx_runtime.jsx)(Badge, {
8132
- text: installmentOption.badge,
8186
+ children: [installmentOption.noFees && /*#__PURE__*/(0,jsx_runtime.jsx)(Badge, {
8187
+ text: "No fees",
8133
8188
  color: "green",
8134
8189
  size: "sm"
8135
- })
8190
+ }), installmentOption.fees > 0 && /*#__PURE__*/(0,jsx_runtime.jsxs)("span", {
8191
+ style: {
8192
+ color: '#475467',
8193
+ fontSize: '14px',
8194
+ fontWeight: 400,
8195
+ lineHeight: '18px',
8196
+ letterSpacing: '0.16px'
8197
+ },
8198
+ children: ["Including ", currency, " ", installmentOption.fees, " fees"]
8199
+ }), installmentOption.interestRate === 0 && /*#__PURE__*/(0,jsx_runtime.jsx)(Badge, {
8200
+ text: "0% Interest",
8201
+ color: "green",
8202
+ size: "sm"
8203
+ })]
8136
8204
  })
8137
8205
  }, installmentOption.id))
8138
8206
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paymob-widget-alpha",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "keywords": ["paymob","widget","paymob-widget"],
5
5
  "main": "./main.js",
6
6
  "license": "MIT",