esewa-ui-library 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -108,15 +108,25 @@ export default App;
108
108
 
109
109
  The `ESewaAlertCard` component is customizable app bar for your eSewa Mini App with support for back, title, and action icons, making navigation and interactions seamless.
110
110
 
111
+ Use useESewaDataProvider to set title for appbar.
112
+
111
113
  ### Usage:
112
114
 
113
115
  ```tsx
114
- import { ESewaAppBar } from 'esewa-ui-library';
116
+ import { ESewaAppBar, useESewaDataProvider } from 'esewa-ui-library';
115
117
 
116
118
  const App = () => {
119
+ const { updateData } = useESewaDataProvider();
120
+
121
+ useEffect(() => {
122
+ updateData({
123
+ title: "Merchant Product Form",
124
+ });
125
+ }, []);
126
+
117
127
  return (
118
128
  <ESewaAppBar
119
- title="App Bar Title"
129
+ icon="icon-es-arrow-left"
120
130
  titleposition="left"
121
131
  onBackIconClick={() => console.log('Back icon clicked')}
122
132
  onTitleClick={() => console.log('Title clicked')}
@@ -582,17 +592,19 @@ const App = () => {
582
592
  <div>
583
593
  <button onClick={openDialog}>Open Dialog</button>
584
594
 
585
- <ESewaDialog
586
- isOpen={isOpen}
587
- title="Sample Dialog"
588
- okText="Confirm"
589
- cancelText="Cancel"
590
- onOk={handleOk}
591
- onCancel={closeDialog}
592
- position="center"
593
- >
594
- <p>Dialog content goes here.</p>
595
- </ESewaDialog>
595
+ {
596
+ isOpen && (<ESewaDialog
597
+ isOpen={isOpen}
598
+ title="Sample Dialog"
599
+ okText="Confirm"
600
+ cancelText="Cancel"
601
+ onOk={handleOk}
602
+ onCancel={closeDialog}
603
+ position="center"
604
+ >
605
+ <p>Dialog content goes here.</p>
606
+ </ESewaDialog>)
607
+ }
596
608
  </div>
597
609
  );
598
610
  };
@@ -1298,9 +1310,10 @@ The `ESewaRadio` component accepts the following props:
1298
1310
  | `label` | `string` | No | `undefined` | The label displayed next to the radio button. |
1299
1311
  | `name` | `string` | Yes | N/A | The name of the radio button, which groups it together with other radio buttons. |
1300
1312
  | `onChange` | `(checked: boolean) => void` | No | `undefined` | Callback function that is triggered when the radio button's checked state changes. |
1301
- | `checked` | `boolean` | No | `undefined` | Determines whether the radio button is selected (`true`) or not (`false`). |
1313
+ | `checked` | `boolean` | Yes | false | Determines whether the radio button is selected (`true`) or not (`false`). |
1302
1314
  | `labelClass`| `string` | No | `''` | A custom class applied to the label element for styling. |
1303
1315
  | `className` | `string` | No | `''` | A custom class applied to the root wrapper element of the radio button component. |
1316
+ | `disabled` | `boolean` | No | false | Used to disable radio state |
1304
1317
 
1305
1318
  # ESewaSanitizeHtml Component
1306
1319
 
@@ -1487,7 +1500,110 @@ export default TooltipExample
1487
1500
  ### Providers
1488
1501
 
1489
1502
  - **ThemeProvider**: `ThemeProvider`
1503
+
1504
+ Wrap your component with this provider to apply theme.
1505
+
1506
+ ```tsx
1507
+ import { StrictMode } from 'react'
1508
+ import { createRoot } from 'react-dom/client'
1509
+ import { ESewaThemeProvider } from 'esewa-ui-library'
1510
+ import App from './App.tsx'
1511
+
1512
+ createRoot(document.getElementById('root')!).render(
1513
+ <StrictMode>
1514
+ <ESewaThemeProvider>
1515
+ <App />
1516
+ </ESewaThemeProvider>
1517
+ </StrictMode>,
1518
+ )
1519
+
1520
+ ```
1521
+
1522
+ In your page
1523
+
1524
+ ```tsx
1525
+ import { useEffect, useState } from "react";
1526
+ import {
1527
+ MoonIcon,
1528
+ SunIcon,
1529
+ } from "@heroicons/react/24/outline";
1530
+
1531
+ const [darkMode, setDarkMode] = useState<boolean>(
1532
+ window.matchMedia('(prefers-color-scheme: dark)').matches
1533
+ );
1534
+
1535
+ const handleThemeToggle = () => {
1536
+ setDarkMode((prevMode) => !prevMode);
1537
+ };
1538
+
1539
+ useEffect(() => {
1540
+ const theme = darkMode ? 'dark' : 'light';
1541
+ document.documentElement.setAttribute('data-theme', theme);
1542
+ }, [darkMode]);
1543
+
1544
+ <button
1545
+ onClick={handleThemeToggle}
1546
+ >
1547
+ {darkMode ? (
1548
+ <SunIcon className="h-6 w-6" />
1549
+ ) : (
1550
+ <MoonIcon className="h-6 w-6" />
1551
+ )}
1552
+ </button>
1553
+
1554
+ ```
1555
+
1490
1556
  - **ESewaProvider**: `ESewaProvider`
1557
+
1558
+ Wrap your component with this provider.
1559
+
1560
+ ```tsx
1561
+ import { StrictMode } from 'react'
1562
+ import { createRoot } from 'react-dom/client'
1563
+ import { ESewaProvider } from 'esewa-ui-library'
1564
+ import App from './App.tsx'
1565
+
1566
+ createRoot(document.getElementById('root')!).render(
1567
+ <StrictMode>
1568
+ <ESewaProvider>
1569
+ <App />
1570
+ </ESewaProvider>
1571
+ </StrictMode>,
1572
+ )
1573
+
1574
+ ```
1575
+
1576
+ then you can use useESewaDataProvider
1577
+
1578
+ ```tsx
1579
+ import { ESewaAppBar, useESewaDataProvider } from 'esewa-ui-library';
1580
+
1581
+ const App = () => {
1582
+ const { updateData } = useESewaDataProvider();
1583
+
1584
+ useEffect(() => {
1585
+ updateData({
1586
+ title: "Merchant Product Form",
1587
+ });
1588
+ }, []);
1589
+
1590
+ return (
1591
+ <ESewaAppBar
1592
+ icon="icon-es-arrow-left"
1593
+ titleposition="left"
1594
+ onBackIconClick={() => console.log('Back icon clicked')}
1595
+ onTitleClick={() => console.log('Title clicked')}
1596
+ onActionIconClick={() => console.log('Action icon clicked')}
1597
+ actionIcon="icon-settings"
1598
+ />
1599
+ );
1600
+ };
1601
+
1602
+ export default App;
1603
+
1604
+ ```
1605
+
1606
+
1491
1607
  - **ESewaPaymentProvider**: `ESewaPaymentProvider`
1492
1608
 
1493
1609
  # Services
@@ -1504,6 +1620,7 @@ This library provides a set of services that allow interaction between the merch
1504
1620
  - [User Detail Request](#user-detail-request)
1505
1621
  - [Media Access Request](#media-access-request)
1506
1622
  - [Validate Payment](#validate-payment)
1623
+ - [Request Payment](#request-payment)
1507
1624
  - [Error Handling](#error-handling)
1508
1625
 
1509
1626
  ## Initialization
@@ -1693,6 +1810,59 @@ const onValidateTransactionClick = () => {
1693
1810
  requestFromMiniApp(obj, CALLBACK_TYPE_ENUM.VALIDATE_TRANSACTION_CALLBACK, validateTransactionCallBack);
1694
1811
  };
1695
1812
  ```
1813
+ #### Request Payment
1814
+ Pass token received from initialize request call with respective request type, callback key , your merchant identifier and request payload
1815
+
1816
+ ```tsx
1817
+ const onRequestPaymentClick = () => {
1818
+ const productPayload = {
1819
+ "product_code": "NP-ES-VIANET",
1820
+ "amount": 28.48,
1821
+ "properties": {
1822
+ "productId": "3299",
1823
+ "payment_id": "1613103_PP",
1824
+ "refId": "400005",
1825
+ "customer_id": "48707",
1826
+ "payer": "CUSTOMER"
1827
+ },
1828
+ "channel": "WEB_USER"
1829
+ };
1830
+
1831
+ const obj = {
1832
+ requestType: REQUEST_TYPE_ENUM.REQUEST_PAYMENT,
1833
+ merchant_identifier: 'IAAAAABTOBAbFhAXHhEHAgoXX0FRR1FJJiw3LCwkJzE=',
1834
+ token: sessionStorage.getItem('miniAppAuthToken'),
1835
+ data: productPayload,
1836
+ callbackKey: "REQUEST_PAYMENT_CALLBACK"
1837
+ };
1838
+
1839
+ const requestPaymentCallBack: any = (data:any) => {
1840
+ console.log("Make payment Response:", data);
1841
+
1842
+ try {
1843
+ if (!data) {
1844
+ throw new Error('Received null or undefined response');
1845
+ }
1846
+ const res = JSON.parse(data);
1847
+
1848
+ if (!res || typeof res !== 'object') {
1849
+ throw new Error('Parsed response is not a valid object');
1850
+ }
1851
+
1852
+ if (res?.error_message) {
1853
+ throw new Error('Error res', res.error_message);
1854
+ }
1855
+
1856
+ setMakePaymentRes(res);
1857
+ } catch (error) {
1858
+ console.error('Error parsing response:', error);
1859
+ }
1860
+ };
1861
+
1862
+ requestFromMiniApp(obj, CALLBACK_TYPE_ENUM.REQUEST_PAYMENT_CALLBACK, requestPaymentCallBack);
1863
+ };
1864
+ ```
1865
+
1696
1866
  ## Error Handling
1697
1867
 
1698
1868
  Errors are returned as JSON responses with an `error_message` field.
@@ -46,16 +46,19 @@ declare global {
46
46
  VALIDATE_TRANSACTION_CALLBACK?: Callback | null;
47
47
  };
48
48
  webkit: {
49
- requestApp: (data: any) => void;
50
- receiveFromApp: (data: any) => void;
51
49
  messageHandlers: {
52
50
  iOSNative: {
53
- requestApp: (data: any) => void;
51
+ postMessage: (data: any) => void;
52
+ INIT_APP_CALLBACK?: Callback | null;
53
+ REQUEST_PAYMENT_CALLBACK?: Callback | null;
54
+ USER_DETAIL_ACCESS_CALLBACK?: Callback | null;
55
+ MEDIA_ACCESS_CALLBACK?: Callback | null;
56
+ LOCATION_ACCESS_CALLBACK?: Callback | null;
57
+ VALIDATE_TRANSACTION_CALLBACK?: Callback | null;
54
58
  };
55
59
  };
56
- receiveDataFromWeb: (data: any) => void;
57
- receiveDataFromApp: (data: any) => void;
58
60
  };
59
61
  }
60
62
  function getDataFromMiniApp(e: any): void;
61
63
  }
64
+ export declare type CallbackKey = keyof Window['Android'] | 'INIT_APP_CALLBACK' | 'REQUEST_PAYMENT_CALLBACK' | 'USER_DETAIL_ACCESS_CALLBACK' | 'MEDIA_ACCESS_CALLBACK' | 'LOCATION_ACCESS_CALLBACK' | 'VALIDATE_TRANSACTION_CALLBACK';
@@ -1,12 +1,14 @@
1
1
  import React from 'react';
2
2
  declare type RadioProps = {
3
- key: any;
3
+ key?: any;
4
4
  label?: string;
5
+ value?: any;
5
6
  name: string;
6
- onChange?: (checked: any) => void;
7
- checked?: boolean;
7
+ onChange?: (value: any, checked: boolean) => void;
8
+ checked: boolean;
8
9
  labelClass?: string;
9
10
  className?: string;
11
+ disabled?: boolean;
10
12
  };
11
13
  export declare const ESewaRadio: React.FC<RadioProps>;
12
14
  export default ESewaRadio;
package/dist/index.js CHANGED
@@ -186,7 +186,7 @@ var StyledAppBar = styled__default.header.attrs(function (_ref) {
186
186
  return {
187
187
  titleposition: titleposition
188
188
  };
189
- })(_templateObject$3 || (_templateObject$3 = _taggedTemplateLiteralLoose(["\n .e-app-bar {\n display: flex;\n justify-content: space-between;\n flex-direction: row;\n align-items: center;\n background-color: var(--appbar-bg-top);\n padding: 7px 12px;\n position: fixed;\n height: 42px;\n left: 0;\n right: 0;\n gap: var(--values-value-8);\n\n &--nav-icon, &--close-icon {\n padding: 7px;\n color: var(--white);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n /* Title section */\n &--title-wrapper {\n display: flex;\n justify-content: ", ";\n align-items: center;\n width: 100%; // Ensures the title section takes full width to apply the alignment\n }\n\n &--title {\n display: flex;\n align-items: center;\n gap: 12px;\n overflow: hidden;\n // display: -webkit-box;\n // -webkit-line-clamp: 1;\n // line-clamp: 1;\n // -webkit-box-orient: vertical;\n }\n\n &--title-image img {\n width: 32px;\n object-fit: cover;\n // margin-left: -32px;\n background: var(--white);\n border: 1px solid var(--border);\n border-radius: var(--grid-borderradius-border-radius-xs);\n }\n\n &--title-label {\n color: var(--white);\n letter-spacing: 0.4px;\n font-size: var(--values-value-16);\n font-weight: 500;\n }\n }\n"])), function (props) {
189
+ })(_templateObject$3 || (_templateObject$3 = _taggedTemplateLiteralLoose(["\n width: 100%;\n\n .e-app-bar {\n display: flex;\n justify-content: space-between;\n flex-direction: row;\n align-items: center;\n background-color: var(--appbar-bg-top);\n padding: 7px 12px;\n position: relative;\n height: 42px;\n // left: 0;\n // right: 0;\n gap: var(--values-value-8);\n\n &--nav-icon, &--close-icon {\n padding: 7px;\n color: var(--white);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n /* Title section */\n &--title-wrapper {\n display: flex;\n justify-content: ", ";\n align-items: center;\n width: 100%; // Ensures the title section takes full width to apply the alignment\n }\n\n &--title {\n display: flex;\n align-items: center;\n gap: 12px;\n overflow: hidden;\n // display: -webkit-box;\n // -webkit-line-clamp: 1;\n // line-clamp: 1;\n // -webkit-box-orient: vertical;\n }\n\n &--title-image img {\n width: 32px;\n object-fit: cover;\n // margin-left: -32px;\n background: var(--white);\n border: 1px solid var(--border);\n border-radius: var(--grid-borderradius-border-radius-xs);\n }\n\n &--title-label {\n color: var(--white);\n letter-spacing: 0.4px;\n font-size: var(--values-value-16);\n font-weight: 500;\n }\n }\n"])), function (props) {
190
190
  return props.titleposition === 'left' ? 'flex-start' : props.titleposition === 'right' ? 'flex-end' : 'center';
191
191
  });
192
192
  var ESewaAppBar = function ESewaAppBar(_ref2) {
@@ -7083,18 +7083,22 @@ var EsewaFullPageLoadingScreen = function EsewaFullPageLoadingScreen(_ref) {
7083
7083
  };
7084
7084
 
7085
7085
  var _templateObject$l;
7086
- var StyledRadio = styled__default.div(_templateObject$l || (_templateObject$l = _taggedTemplateLiteralLoose(["\n .container{\n display:flex;\n align-items: center;\n gap: 8px;\n }\n\n .container input[type=\"radio\" i] {\n margin: 0;\n appearance: none;\n width: 16px;\n height: 16px;\n border: 2px solid var(--secondary);\n border-radius: 50%;\n position: relative;\n cursor: pointer;\n transition: border-color 0.3s ease;\n }\n\n .container input[type=\"radio\"]:checked {\n border-color: var(--primary);\n }\n\n .container input[type=\"radio\"]::before {\n content: '';\n width: 10px;\n height: 10px;\n background-color: transparent;\n border-radius: 50%;\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transition: background-color 0.3s ease;\n }\n\n .container input[type=\"radio\"]:checked::before {\n background-color: var(--primary);\n }\n"])));
7086
+ var StyledRadio = styled__default.div(_templateObject$l || (_templateObject$l = _taggedTemplateLiteralLoose(["\n .container{\n display:flex;\n align-items: center;\n gap: 8px;\n }\n\n .container input[type=\"radio\" i] {\n margin: 0;\n appearance: none;\n width: 16px;\n height: 16px;\n border: 2px solid var(--secondary);\n border-radius: 50%;\n position: relative;\n cursor: pointer;\n transition: border-color 0.3s ease;\n }\n\n .container input[type=\"radio\"]:checked {\n border-color: var(--primary);\n }\n\n .container input[type=\"radio\"]::before {\n content: '';\n width: 10px;\n height: 10px;\n background-color: transparent;\n border-radius: 50%;\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transition: background-color 0.3s ease;\n }\n\n .container input[type=\"radio\"]:checked::before {\n background-color: var(--primary);\n }\n\n .container input[type=\"radio\"]:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n"])));
7087
7087
  var ESewaRadio = function ESewaRadio(_ref) {
7088
7088
  var label = _ref.label,
7089
+ value = _ref.value,
7089
7090
  name = _ref.name,
7090
7091
  className = _ref.className,
7091
7092
  _ref$labelClass = _ref.labelClass,
7092
7093
  labelClass = _ref$labelClass === void 0 ? '' : _ref$labelClass,
7093
7094
  onChange = _ref.onChange,
7094
- checked = _ref.checked;
7095
+ _ref$checked = _ref.checked,
7096
+ checked = _ref$checked === void 0 ? false : _ref$checked,
7097
+ _ref$disabled = _ref.disabled,
7098
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled;
7095
7099
  var handleRadioChange = function handleRadioChange(e) {
7096
- if (onChange) {
7097
- onChange(e.target.checked);
7100
+ if (onChange && !disabled) {
7101
+ onChange(value, e.target.checked);
7098
7102
  }
7099
7103
  };
7100
7104
  return React__default.createElement(StyledRadio, null, React__default.createElement("div", {
@@ -7104,8 +7108,10 @@ var ESewaRadio = function ESewaRadio(_ref) {
7104
7108
  }, React__default.createElement("input", {
7105
7109
  type: 'radio',
7106
7110
  name: name,
7111
+ value: value,
7107
7112
  checked: checked,
7108
- onChange: handleRadioChange
7113
+ onChange: handleRadioChange,
7114
+ disabled: disabled
7109
7115
  }), React__default.createElement("span", {
7110
7116
  className: "" + labelClass
7111
7117
  }, label))));
@@ -7683,7 +7689,7 @@ var CONNECT_APP = function CONNECT_APP(data) {
7683
7689
  if (isiOS) {
7684
7690
  var _window$webkit;
7685
7691
  if ((_window$webkit = window.webkit) !== null && _window$webkit !== void 0 && _window$webkit.messageHandlers.iOSNative) {
7686
- window.webkit.messageHandlers.iOSNative.requestApp(data);
7692
+ window.webkit.messageHandlers.iOSNative.postMessage(data);
7687
7693
  } else {
7688
7694
  console.warn('iOS interface not available');
7689
7695
  }
@@ -7694,8 +7700,7 @@ var requestFromMiniApp = function requestFromMiniApp(data, callbackKey, callback
7694
7700
  if (window.Android) {
7695
7701
  window.Android[callbackKey] = callback;
7696
7702
  } else if ((_window$webkit2 = window.webkit) !== null && _window$webkit2 !== void 0 && (_window$webkit2$messa = _window$webkit2.messageHandlers) !== null && _window$webkit2$messa !== void 0 && _window$webkit2$messa.iOSNative) {
7697
- window.miniAppResponse = window.miniAppResponse || {};
7698
- window.miniAppResponse[callbackKey] = callback;
7703
+ window.webkit.messageHandlers.iOSNative[callbackKey] = callback;
7699
7704
  }
7700
7705
  CONNECT_APP(JSON.stringify(data));
7701
7706
  };
@@ -7865,11 +7870,13 @@ var useDebounce = function useDebounce(value, delay) {
7865
7870
  };
7866
7871
 
7867
7872
  var loadGoogleFont = function loadGoogleFont() {
7868
- if (!document.querySelector("link[href*='Source+Sans+Pro']")) {
7869
- var link = document.createElement('link');
7870
- link.href = 'https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@300;400;600;700&display=swap';
7871
- link.rel = 'stylesheet';
7872
- document.head.appendChild(link);
7873
+ if (typeof window !== 'undefined' && document) {
7874
+ if (!document.querySelector("link[href*='Source+Sans+Pro']")) {
7875
+ var link = document.createElement('link');
7876
+ link.href = 'https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@300;400;600;700&display=swap';
7877
+ link.rel = 'stylesheet';
7878
+ document.head.appendChild(link);
7879
+ }
7873
7880
  }
7874
7881
  };
7875
7882
  loadGoogleFont();