aio-login 9.0.0 → 10.0.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 (4) hide show
  1. package/index.css +1 -0
  2. package/index.d.ts +23 -15
  3. package/index.js +134 -105
  4. package/package.json +1 -1
package/index.css CHANGED
@@ -53,6 +53,7 @@
53
53
  background: #0069ff;
54
54
  color: #fff;
55
55
  font-family: inherit;
56
+ width:100%;
56
57
  }
57
58
 
58
59
  .ai-login-mode {
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FC, ReactNode } from "react";
2
- import { I_formInput } from "aio-input";
2
+ import { I_validateType, I_formField, AITYPE } from "aio-input";
3
3
  import './index.css';
4
4
  type I_loginMode = 'userpass' | 'register' | 'otpcode' | 'otpnumber';
5
5
  export type I_login_key = 'registerButton' | 'userpassButton' | 'otpnumberButton' | 'otpcodeButton' | 'registerTitle' | 'userpassTitle' | 'otpcodeTitle' | 'otpnumberTitle' | 'switchuserpass' | 'switchregister' | 'switchotpnumber' | 'repasswordMatch' | 'usernameRequired' | 'passwordRequired' | 'repasswordRequired' | 'otpnumberRequired' | 'otpcodeLength' | 'registerError' | 'userpassError' | 'otpcodeError' | 'otpnumberError' | 'username' | 'password' | 'repassword' | 'otpnumber' | 'otpcode';
@@ -19,9 +19,6 @@ type I_login_model<T> = {
19
19
  };
20
20
  };
21
21
  };
22
- type I_registerInputs = {
23
- [field: string]: I_formInput;
24
- };
25
22
  type I_AILogin<T> = {
26
23
  app: FC<{
27
24
  user: T;
@@ -45,50 +42,61 @@ type I_AILogin<T> = {
45
42
  html: ReactNode;
46
43
  time: number;
47
44
  };
48
- validate?: (p: {
49
- field: string;
50
- data: I_login_model<T>;
51
- value: any;
52
- input: I_formInput;
53
- }) => string | undefined;
54
45
  otpnumber?: {
55
46
  path: string;
56
47
  method: 'post' | 'get';
57
- body?: (data: I_login_model<T>) => any;
48
+ body?: (otpnumber: string) => any;
58
49
  onSuccess: (response: any) => Promise<{
59
50
  message?: string;
60
51
  }>;
52
+ validate?: (number: string) => string | undefined;
61
53
  };
62
54
  otpcode?: {
63
55
  length: number;
64
56
  method: 'post' | 'get';
65
- body?: (data: I_login_model<T>) => any;
57
+ body?: (otpcode: string) => any;
66
58
  path: string;
67
59
  onSuccess: (response: any) => Promise<{
68
60
  user: T;
69
61
  token: string;
70
62
  message?: string;
71
63
  }>;
64
+ validate?: (code: string) => string | undefined;
72
65
  };
73
66
  userpass?: {
74
67
  path: string;
75
68
  method: 'post' | 'get';
76
- body?: (data: I_login_model<T>) => any;
69
+ body?: (data: I_login_model<T>["userpass"]) => any;
77
70
  onSuccess: (response: any) => Promise<{
78
71
  user: T;
79
72
  token: string;
80
73
  message?: string;
81
74
  }>;
75
+ validate?: (p: {
76
+ field: 'username' | 'password';
77
+ value: string;
78
+ data: I_login_model<T>["userpass"];
79
+ }) => string | undefined;
82
80
  };
83
81
  register?: {
84
- inputs?: (model: I_login_model<T>) => I_registerInputs;
82
+ inputs?: (model: I_login_model<T>["register"]) => (AITYPE & {
83
+ label: string;
84
+ required?: boolean;
85
+ validateType?: I_validateType;
86
+ field: I_formField<T>;
87
+ })[];
85
88
  path: string;
86
89
  method: 'post' | 'get';
87
- body?: (data: I_login_model<T>) => any;
90
+ body?: (data: I_login_model<T>["register"]) => any;
88
91
  onSuccess: (response: any) => Promise<{
89
92
  message?: string;
90
93
  }>;
91
94
  defaultData?: any;
95
+ validate?: (p: {
96
+ data: I_login_model<T>["register"];
97
+ field: string;
98
+ value: any;
99
+ }) => string | undefined;
92
100
  };
93
101
  getStatus?: (response: any) => number;
94
102
  getMessage?: (response: any) => string;
package/index.js CHANGED
@@ -7,8 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
- import { useEffect, useState } from "react";
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ import { useEffect, useRef, useState } from "react";
12
12
  import { useForm } from "aio-input";
13
13
  import { AddToAttrs, FixUrl, Storage } from "aio-utils";
14
14
  import { Loading, Alert } from "aio-popup";
@@ -25,13 +25,15 @@ export function AIOLogin_updateCatchedUser(loginId, newUser) {
25
25
  return storage.save('data', newStoredData);
26
26
  }
27
27
  const useLoading = (rootProps) => {
28
- const { register, translate = () => { }, fa, validate = () => { return undefined; }, userpass, splash, otpnumber, otpcode } = rootProps;
28
+ const { register, translate = () => { }, fa, userpass, splash, otpnumber, otpcode } = rootProps;
29
29
  const [storage] = useState(new Storage('ai-login' + rootProps.id));
30
30
  const [loading] = useState(new Loading());
31
31
  const [splashing, setSplashing] = useState(!!rootProps.splash);
32
32
  const [data, setData] = useState();
33
33
  const [checkingToken, setCheckingToken] = useState();
34
34
  const [mode, setMode] = useState(getMode);
35
+ const modeRef = useRef(mode);
36
+ modeRef.current = mode;
35
37
  function getMode(mode) {
36
38
  let key = 'userpass';
37
39
  if (mode) {
@@ -56,72 +58,121 @@ const useLoading = (rootProps) => {
56
58
  title: _jsx("div", { className: "ai-login-title", children: trans(key + 'Title') })
57
59
  };
58
60
  }
59
- const formHook = useForm({
60
- initData: () => getModel(), fa,
61
- isFieldActive: (field) => mode.key === field.split('.')[0],
62
- inputs: () => {
63
- let inputs = {
64
- 'userpass.username': { type: 'text', label: trans('username') },
65
- 'userpass.password': { type: 'password', preview: true, label: trans('password') },
66
- 'register.username': { type: 'text', label: trans('username') },
67
- 'register.password': { type: 'password', preview: true, label: trans('password') },
68
- 'register.repassword': { type: 'password', preview: true, label: trans('repassword') },
69
- 'otpnumber': { type: 'text', maxLength: 11, filter: ['number'], label: trans('otpnumber') },
70
- 'otpcode': { type: 'text', maxLength: (otpcode === null || otpcode === void 0 ? void 0 : otpcode.length) || 4, filter: ['number'], label: trans('otpcode') }
71
- };
72
- if (register && register.inputs) {
73
- const registerInputs = register.inputs({});
74
- for (let field in registerInputs) {
75
- const input = registerInputs[field];
76
- inputs[`register.properties.${field}`] = Object.assign(Object.assign({}, input), { inputProps: Object.assign(Object.assign({}, input.inputAttrs), { 'aria-label': `aio-login-${field}` }) });
77
- }
78
- }
79
- return inputs;
80
- },
81
- validate: ({ field, data, value, input }) => {
82
- if (field === 'otpcode') {
83
- if ((value || '').length !== ((otpcode === null || otpcode === void 0 ? void 0 : otpcode.length) || 4)) {
84
- return trans('otpcodeLength');
85
- }
86
- }
87
- if (!value) {
88
- if (field === 'otpnumber') {
89
- return trans('otpnumberRequired');
90
- }
91
- if (field === 'userpass.username') {
92
- return trans('usernameRequired');
93
- }
94
- if (field === 'userpass.password') {
95
- return trans('passwordRequired');
96
- }
97
- if (field === 'register.username') {
98
- return trans('usernameRequired');
99
- }
100
- if (field === 'register.password') {
101
- return trans('passwordRequired');
102
- }
103
- if (field === 'register.repassword') {
104
- return trans('repasswordRequired');
105
- }
106
- }
107
- if (field === 'register.repassword' && data.register.password !== value) {
108
- return trans('repasswordMatch');
109
- }
110
- return validate({ field, data, value, input });
61
+ const userpassHook = useForm({
62
+ initData: getModel().userpass,
63
+ getLayout: (context) => {
64
+ const { validate = () => { return undefined; } } = userpass || {};
65
+ return getLayout({
66
+ scroll: true,
67
+ v: [
68
+ {
69
+ input: {
70
+ field: 'username', type: 'text', label: trans('username'),
71
+ validate: ({ field, value, data }) => validate({ data, field: field, value })
72
+ }
73
+ },
74
+ {
75
+ input: {
76
+ field: 'password', type: 'password', preview: true, label: trans('password'), validate: ({ field, value, data }) => validate({ data, field: field, value })
77
+ }
78
+ }
79
+ ]
80
+ }, context);
111
81
  },
112
- onSubmit: (data) => __awaiter(void 0, void 0, void 0, function* () {
113
- const { path, method, body = () => { }, onSuccess } = rootProps[mode.key];
82
+ onSubmit: (data) => onSubmit(data)
83
+ });
84
+ // const otpnumberHook = useForm<{otpnumber:string}>({
85
+ // initData: {otpnumber:''},
86
+ // getLayout: (context) => {
87
+ // const { validate = () => { return undefined } } = otpnumber || {}
88
+ // const {title,submitText} = modeRef.current
89
+ // return getLayout({
90
+ // attrs: { className: "ai-login-form" },
91
+ // v: [
92
+ // { html:title },
93
+ // {
94
+ // scroll: true,
95
+ // v: [
96
+ // {
97
+ // input: { field:'otpnumber',type: 'text', maxLength: 11, filter: ['number'], label: trans('otpnumber'),validate:({value})=>validate(value) }
98
+ // }
99
+ // ]
100
+ // },
101
+ // { html: <div style={{ height: 24 }}></div>, size: 24, },
102
+ // { html: context.renderSubmitButton(submitText,{ className: 'ai-login-submit' })},
103
+ // { html: renderModes() }
104
+ // ]
105
+ // },context)
106
+ // },
107
+ // onSubmit: (data)=>onSubmit<string>(data.otpnumber)
108
+ // })
109
+ // const otpcodeHook = useForm<{otpcode:string}>({
110
+ // initData: {otpcode:''},
111
+ // getLayout: (context) => {
112
+ // const { validate = () => { return undefined } } = otpcode || {}
113
+ // return getLayout({
114
+ // scroll: true,
115
+ // v: [
116
+ // {
117
+ // input: { field:'otpcode',type: 'text', maxLength: otpcode?.length || 4, filter: ['number'], label: trans('otpcode'),validate:({value})=>validate(value) }
118
+ // }
119
+ // ]
120
+ // },context)
121
+ // },
122
+ // onSubmit: (data)=>onSubmit<string>(data.otpcode)
123
+ // })
124
+ // const registerHook = useForm<I_login_model<T>["register"]>({
125
+ // initData: getModel().register,
126
+ // getLayout: (context) => {
127
+ // const { inputs = () => [],validate = ()=>{return undefined} } = register || {}
128
+ // return getLayout<I_login_model<T>["register"]>({
129
+ // scroll: true,
130
+ // v: [
131
+ // { input: { field: 'username', type: 'text', label: trans('username') } },
132
+ // { input: { field: 'password', type: 'password', preview: true, label: trans('password') } },
133
+ // { input: { field: 'repassword', type: 'password', preview: true, label: trans('repassword') } },
134
+ // {
135
+ // v: inputs(context.getData()).map((input) => {
136
+ // return { input:{...input,field:`properties.${input.field}`,validate:({field,value,data})=>validate({data,field,value})} }
137
+ // })
138
+ // }
139
+ // ]
140
+ // },context)
141
+ // },
142
+ // onSubmit: (data)=>onSubmit<I_login_model<T>["register"]>(data)
143
+ // })
144
+ function onSubmit(data) {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ const { path, method, body = () => { } } = rootProps[mode.key];
114
147
  const { base_url } = rootProps;
115
148
  const url = FixUrl(base_url, path);
116
149
  loading.show('login0');
117
- loading.hide('login0');
118
150
  axios[method](url, body(data)).then(success).catch(response => {
119
- const subtext = getMessage(response, mode.key);
120
- Alert({ type: 'error', text: trans(`${mode.key}Error`), subtext });
151
+ const text = getMessage(response, mode.key);
152
+ loading.hide('login0');
153
+ Alert({ type: 'error', title: trans(`${mode.key}Error`), text });
121
154
  });
122
- })
123
- });
124
- function changeMode(mode) { formHook.setData(getModel()); setMode(getMode(mode)); }
155
+ });
156
+ }
157
+ function getLayout(node, context) {
158
+ const { title, submitText } = modeRef.current;
159
+ return {
160
+ attrs: { className: "ai-login-form" },
161
+ v: [
162
+ { html: title },
163
+ node,
164
+ { html: _jsx("div", { style: { height: 24 } }), size: 24, },
165
+ { html: context.renderSubmitButton(submitText, { className: 'ai-login-submit' }) },
166
+ { html: renderModes() }
167
+ ]
168
+ };
169
+ }
170
+ function changeMode(mode) {
171
+ if (mode === 'userpass') {
172
+ userpassHook.changeData(getModel().userpass);
173
+ }
174
+ //else if(mode === 'register'){registerHook.changeData(getModel().register)}
175
+ }
125
176
  function success_1(response, mode) {
126
177
  return __awaiter(this, void 0, void 0, function* () {
127
178
  if (!rootProps[mode]) {
@@ -133,7 +184,7 @@ const useLoading = (rootProps) => {
133
184
  loading.hide('login0');
134
185
  if (typeof res !== 'object' || !res.user || typeof res.token !== 'string') {
135
186
  const message = `onSuccess of props.${mode}.${mode === 'userpass' ? 'api' : 'codeApi'} should returns {user:any,token:string}`;
136
- Alert({ type: 'error', text: trans(`${mode}Error`), subtext: message });
187
+ Alert({ type: 'error', title: trans(`${mode}Error`), text: message });
137
188
  }
138
189
  else {
139
190
  if (res.message) {
@@ -167,6 +218,7 @@ const useLoading = (rootProps) => {
167
218
  }
168
219
  function success(response) {
169
220
  return __awaiter(this, void 0, void 0, function* () {
221
+ loading.hide('login0');
170
222
  if (mode.key === 'userpass' || mode.key === 'otpcode') {
171
223
  success_1(response, mode.key);
172
224
  }
@@ -176,9 +228,8 @@ const useLoading = (rootProps) => {
176
228
  });
177
229
  }
178
230
  const getStatus = (error, name) => {
179
- let text = `${name} unknown status.`, subtext = 'please set getStatus props in useLogin for extracting status';
231
+ let title = `${name} unknown status.`, text = 'please set getStatus props in useLogin for extracting status';
180
232
  if (error.response) {
181
- const data = error.response.data;
182
233
  let status = error.response.status;
183
234
  if (typeof status !== 'number') {
184
235
  const { getStatus = () => { } } = rootProps;
@@ -188,10 +239,10 @@ const useLoading = (rootProps) => {
188
239
  }
189
240
  }
190
241
  }
191
- Alert({ type: 'error', text, subtext });
242
+ Alert({ type: 'error', title, text });
192
243
  };
193
244
  const getMessage = (error, name) => {
194
- let text = `${name} unknown message.`, subtext = 'please set getMessage props in useLogin for extracting message';
245
+ let title = `${name} unknown message.`, text = 'please set getMessage props in useLogin for extracting message';
195
246
  if (error.response) {
196
247
  const data = error.response.data;
197
248
  if (typeof data === 'string') {
@@ -217,7 +268,7 @@ const useLoading = (rootProps) => {
217
268
  else if (typeof error.message === 'string') {
218
269
  return error.message;
219
270
  }
220
- Alert({ text, subtext, type: 'error' });
271
+ Alert({ title, text, type: 'error' });
221
272
  return 'unkown message';
222
273
  };
223
274
  const checkTokenCatch = (error) => {
@@ -226,11 +277,11 @@ const useLoading = (rootProps) => {
226
277
  logout();
227
278
  }
228
279
  const message = getMessage(error, 'checking token');
229
- let text = 'error in checking token';
280
+ let title = 'error in checking token';
230
281
  if (rootProps.fa) {
231
- text = 'خطا در بررسی توکن';
282
+ title = 'خطا در بررسی توکن';
232
283
  }
233
- Alert({ type: 'error', text, subtext: message });
284
+ Alert({ type: 'error', title, text: message });
234
285
  };
235
286
  const checkTokenThen = (response, user, token) => {
236
287
  const { checkToken } = rootProps;
@@ -244,7 +295,7 @@ const useLoading = (rootProps) => {
244
295
  logout();
245
296
  }
246
297
  else {
247
- Alert({ type: 'error', text: 'check token error', subtext: 'checkToken.getResult should returns boolean' });
298
+ Alert({ type: 'error', title: 'check token error', text: 'checkToken.getResult should returns boolean' });
248
299
  }
249
300
  };
250
301
  function CheckToken() {
@@ -327,27 +378,8 @@ const useLoading = (rootProps) => {
327
378
  }
328
379
  return model;
329
380
  }
330
- const getFormNode = () => {
331
- let registerInputs = {};
332
- if (register && register.inputs) {
333
- registerInputs = register.inputs(formHook.data);
334
- }
335
- const registerFields = Object.keys(registerInputs);
336
- return {
337
- scroll: true,
338
- v: [
339
- { input: 'userpass.username', show: mode.key === 'userpass' },
340
- { input: 'userpass.password', show: mode.key === 'userpass' },
341
- { input: 'register.username', show: mode.key === 'register' },
342
- { input: 'register.password', show: mode.key === 'register' },
343
- { input: 'register.repassword', show: mode.key === 'register' },
344
- { input: 'otpnumber', show: mode.key === 'otpnumber' },
345
- { input: 'otpcode', show: mode.key === 'otpcode' },
346
- { v: registerFields.map((field) => ({ input: `register.properties.${field}`, show: mode.key === 'register' })) }
347
- ]
348
- };
349
- };
350
381
  function renderMode(modeKey) {
382
+ const mode = modeRef.current;
351
383
  if (mode.key === modeKey) {
352
384
  return null;
353
385
  }
@@ -357,17 +389,14 @@ const useLoading = (rootProps) => {
357
389
  return (_jsxs("div", { className: "ai-login-modes", children: [userpass && renderMode('userpass'), register && renderMode('register'), otpnumber && renderMode('otpnumber')] }));
358
390
  }
359
391
  function renderLoginBox() {
360
- const { title } = mode;
361
- return formHook.render({
362
- attrs: { className: "ai-login-form" },
363
- v: [
364
- { html: title },
365
- getFormNode(),
366
- { html: _jsx("div", { style: { height: 24 } }), size: 24, },
367
- { submitButton: { text: mode.submitText, attrs: { className: 'ai-login-submit' } } },
368
- { html: renderModes() }
369
- ]
370
- });
392
+ const { key } = mode;
393
+ if (key === 'userpass') {
394
+ return _jsx(_Fragment, { children: userpassHook.renderLayout });
395
+ }
396
+ //if(key === 'register'){return <>{registerHook.renderLayout}</>}
397
+ //if(key === 'otpnumber'){return <>{otpnumberHook.renderLayout}</>}
398
+ //if(key === 'otpcode'){return <>{otpcodeHook.renderLayout}</>}
399
+ return null;
371
400
  }
372
401
  const bf_layout = (type) => {
373
402
  const fn = rootProps[type];
@@ -404,7 +433,7 @@ const useLoading = (rootProps) => {
404
433
  splashing, loading, checkingToken,
405
434
  data, setData,
406
435
  getMessage, trans,
407
- getModel, formHook,
436
+ getModel,
408
437
  mode, getMode, setMode, changeMode,
409
438
  renderApp, renderLoginBox, renderLoginPage
410
439
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aio-login",
3
- "version": "9.0.0",
3
+ "version": "10.0.0",
4
4
  "description": "handle all types of popup and modals in react",
5
5
  "main": "index.js",
6
6
  "scripts": {