@snack-uikit/stepper 0.5.10-preview-96ca8003.0 → 0.5.10-preview-fa22a93d.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,27 +10,28 @@
10
10
  #### Использование
11
11
 
12
12
  Компонент принимает массив шагов. В проп children принимает render-колбек, в который отдает сам компонент, методы управления и поля состояния.
13
- При вызове метода `goNext` вызывается валидация текущего шага. Функция валидации должна вернуть результат валидации в Promise. При успешной валдиции компонент переходит на следующий шаг, а при ошибке остается на текущем.
13
+ При вызове метода `goNext` вызывается валидация текущего шага. Функция валидации принимает индекс текущего шага и должна вернуть результат валидации в Promise<boolean>. При успешной валдиции компонент переходит на следующий шаг, а при ошибке остается на текущем.
14
14
  При вызове метода `goPrev` компонент переходит на предыдущий шаг.
15
15
 
16
16
 
17
17
  ```tsx
18
18
  const steps = [
19
- { title: 'Step #1', validation: validation1 },
20
- { title: 'Step #2', validation: validation2 },
21
- { title: 'Step #3', validation: validation3 },
22
- { title: 'Step #4', validation: validation4 },
19
+ { title: 'Step #1' },
20
+ { title: 'Step #2' },
21
+ { title: 'Step #3' },
22
+ { title: 'Step #4' },
23
23
  ];
24
24
 
25
25
  // ...
26
26
 
27
27
  return (
28
- <Stepper steps={steps}>
28
+ <Stepper steps={steps} validator={validatorFunction}>
29
29
  {({
30
30
  stepper, // JSX элемент компонента
31
31
  isCompleted, // состояние завершенности всей цепочки
32
32
  goNext, // функция перехода к след. шагу
33
33
  goPrev, // функция перехода к предыдущему шагу
34
+ setValidator, // функция установки валидатора
34
35
  }) => (
35
36
  <>
36
37
  {stepper}
@@ -48,9 +49,10 @@ return (
48
49
  ### Props
49
50
  | name | type | default value | description |
50
51
  |------|------|---------------|-------------|
51
- | children* | `({stepper, ...api}) => ReactElement` | - | Render function. Принимает аргументы: `stepper` - JSX-элемент степпера, `goNext` - перейти на след. шаг, `goPrev` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` добавляет функцию-валидатор, которая принимает в параметры индекс текущего шага, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов. |
52
+ | children* | `({stepper, ...api}) => ReactElement` | - | Render function. Принимает аргументы: `stepper` - JSX-элемент степпера, `goNext(stepIndex?: number)` - перейти на след. шаг, `goPrev(stepIndex?: number)` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` переопределяет функцию-валидатор, которая принимает в параметры индекс текущего шага и индекс нового, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов. |
52
53
  | steps* | `StepData[]` | - | Массив шагов |
53
54
  | defaultCurrentStepIndex | `number` | - | Индекс текущего шага по-дефолту |
55
+ | validator | `StepsValidator` | - | Валидатор шагов. Выполняется при смене шага. Принимает первым аргументом индекс текущего, вторым - индекс нового шага. |
54
56
  | className | `string` | - | CSS-класс |
55
57
  | onChangeCurrentStep | `(newValue: number, prevValue: number) => void` | - | Колбек смены текущего степа |
56
58
  | onCompleteChange | `(isCompleted: boolean) => void` | - | Колбек изменения завершенности |
@@ -1,6 +1,6 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { WithSupportProps } from '@snack-uikit/utils';
3
- import { StepData, StepperApi } from '../../types';
3
+ import { StepData, StepperApi, StepsValidator } from '../../types';
4
4
  export type StepperState = StepperApi & {
5
5
  stepper: ReactElement;
6
6
  };
@@ -9,11 +9,13 @@ export type StepperProps = WithSupportProps<{
9
9
  steps: StepData[];
10
10
  /** Индекс текущего шага по-дефолту */
11
11
  defaultCurrentStepIndex: number;
12
+ /** Валидатор шагов. Выполняется при смене шага. Принимает первым аргументом индекс текущего, вторым - индекс нового шага. */
13
+ validator?: StepsValidator;
12
14
  /** CSS-класс */
13
15
  className?: string;
14
16
  /**
15
17
  * Render function. Принимает аргументы: `stepper` - JSX-элемент степпера,
16
- * `goNext` - перейти на след. шаг, `goPrev` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` добавляет функцию-валидатор, которая принимает в параметры индекс текущего шага, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов.
18
+ * `goNext(stepIndex?: number)` - перейти на след. шаг, `goPrev(stepIndex?: number)` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` переопределяет функцию-валидатор, которая принимает в параметры индекс текущего шага и индекс нового, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов.
17
19
  * @type ({stepper, ...api}) => ReactElement
18
20
  */
19
21
  children: (params: StepperState) => ReactElement;
@@ -22,4 +24,4 @@ export type StepperProps = WithSupportProps<{
22
24
  /** Колбек изменения завершенности */
23
25
  onCompleteChange?: (isCompleted: boolean) => void;
24
26
  }>;
25
- export declare function Stepper({ children, steps, className, onChangeCurrentStep, onCompleteChange, defaultCurrentStepIndex, ...props }: StepperProps): import("react/jsx-runtime").JSX.Element;
27
+ export declare function Stepper({ children, steps, className, onChangeCurrentStep, onCompleteChange, defaultCurrentStepIndex, validator: validatorProp, ...props }: StepperProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,12 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  var __rest = (this && this.__rest) || function (s, e) {
2
11
  var t = {};
3
12
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -17,8 +26,9 @@ import { STEP_STATE } from '../../constants';
17
26
  import { Step } from '../../helperComponents';
18
27
  import { StepperContext } from '../../StepperContext';
19
28
  import styles from './styles.module.css';
29
+ const DEFAULT_VALIDATOR = () => __awaiter(void 0, void 0, void 0, function* () { return true; });
20
30
  export function Stepper(_a) {
21
- var { children, steps, className, onChangeCurrentStep, onCompleteChange, defaultCurrentStepIndex = 0 } = _a, props = __rest(_a, ["children", "steps", "className", "onChangeCurrentStep", "onCompleteChange", "defaultCurrentStepIndex"]);
31
+ var { children, steps, className, onChangeCurrentStep, onCompleteChange, defaultCurrentStepIndex = 0, validator: validatorProp = DEFAULT_VALIDATOR } = _a, props = __rest(_a, ["children", "steps", "className", "onChangeCurrentStep", "onCompleteChange", "defaultCurrentStepIndex", "validator"]);
22
32
  const isCompletedByDefault = defaultCurrentStepIndex === steps.length - 1;
23
33
  const [currentStepState, setCurrentStepState] = useState(isCompletedByDefault ? STEP_STATE.Completed : STEP_STATE.Current);
24
34
  const [currentStepIndex, setCurrentStepIndexValue] = useState(defaultCurrentStepIndex);
@@ -35,18 +45,14 @@ export function Stepper(_a) {
35
45
  return newValue;
36
46
  });
37
47
  }, [onChangeCurrentStep]);
38
- const goNext = useCallback(() => {
39
- var _a, _b, _c;
40
- if (currentStepIndex >= steps.length || isCompleted) {
48
+ const goNext = useCallback((newStepIndexUnsafety = currentStepIndex + 1) => {
49
+ if (currentStepIndex >= steps.length || isCompleted || newStepIndexUnsafety <= currentStepIndex) {
41
50
  return;
42
51
  }
43
- const currentStep = steps[currentStepIndex];
52
+ const newStepIndex = Math.min(steps.length - 1, newStepIndexUnsafety);
44
53
  setCurrentStepState(STEP_STATE.Loading);
45
- Promise.all([
46
- (_b = (_a = currentStep.validation) === null || _a === void 0 ? void 0 : _a.call(currentStep)) !== null && _b !== void 0 ? _b : Promise.resolve(true),
47
- (_c = stepsValidator === null || stepsValidator === void 0 ? void 0 : stepsValidator.value(currentStepIndex)) !== null && _c !== void 0 ? _c : Promise.resolve(true),
48
- ])
49
- .then(results => results.every(isValid => isValid))
54
+ const validator = (stepsValidator === null || stepsValidator === void 0 ? void 0 : stepsValidator.value) || validatorProp;
55
+ validator(currentStepIndex, newStepIndex)
50
56
  .catch(() => false)
51
57
  .then(isValid => {
52
58
  if (!isValid) {
@@ -59,11 +65,11 @@ export function Stepper(_a) {
59
65
  setIsCompleted(true);
60
66
  }
61
67
  else {
62
- setCurrentStepIndex(currentStepIndex + 1);
68
+ setCurrentStepIndex(newStepIndex);
63
69
  setCurrentStepState(STEP_STATE.Current);
64
70
  }
65
71
  });
66
- }, [currentStepIndex, isCompleted, setCurrentStepIndex, steps, stepsValidator]);
72
+ }, [currentStepIndex, isCompleted, setCurrentStepIndex, steps.length, stepsValidator === null || stepsValidator === void 0 ? void 0 : stepsValidator.value, validatorProp]);
67
73
  const goPrev = useCallback((index = currentStepIndex - 1) => {
68
74
  if (currentStepIndex === 0 || index < 0 || index > currentStepIndex) {
69
75
  return;
package/dist/types.d.ts CHANGED
@@ -2,11 +2,10 @@ import { JSX } from 'react';
2
2
  import { ValueOf } from '@snack-uikit/utils';
3
3
  import { STEP_STATE } from './constants';
4
4
  export type StepState = ValueOf<typeof STEP_STATE>;
5
- export type StepsValidator = (stepIndex: number) => Promise<boolean>;
5
+ export type StepsValidator = (prevStepIndex: number, newStepIndex: number) => Promise<boolean>;
6
6
  export type StepData = {
7
7
  title: string;
8
8
  description?: string;
9
- validation?(): Promise<boolean>;
10
9
  };
11
10
  export type StepViewData = StepData & {
12
11
  onClick?(): void;
@@ -15,8 +14,8 @@ export type StepViewData = StepData & {
15
14
  };
16
15
  export type StepperApi = {
17
16
  stepper: JSX.Element;
18
- goNext(): void;
19
- goPrev(): void;
17
+ goNext(stepIndex?: number): void;
18
+ goPrev(stepIndex?: number): void;
20
19
  resetValidation(): void;
21
20
  setValidator(validator: StepsValidator): void;
22
21
  isCompleted: boolean;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Stepper",
7
- "version": "0.5.10-preview-96ca8003.0",
7
+ "version": "0.5.10-preview-fa22a93d.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -39,5 +39,5 @@
39
39
  "@snack-uikit/utils": "3.2.0",
40
40
  "classnames": "2.3.2"
41
41
  },
42
- "gitHead": "f34f4124d15e2215a4eca379bb530b21cf63b87b"
42
+ "gitHead": "8bc73eadbb15f1db5f9778820a423c54170732f9"
43
43
  }
@@ -18,11 +18,13 @@ export type StepperProps = WithSupportProps<{
18
18
  steps: StepData[];
19
19
  /** Индекс текущего шага по-дефолту */
20
20
  defaultCurrentStepIndex: number;
21
+ /** Валидатор шагов. Выполняется при смене шага. Принимает первым аргументом индекс текущего, вторым - индекс нового шага. */
22
+ validator?: StepsValidator;
21
23
  /** CSS-класс */
22
24
  className?: string;
23
25
  /**
24
26
  * Render function. Принимает аргументы: `stepper` - JSX-элемент степпера,
25
- * `goNext` - перейти на след. шаг, `goPrev` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` добавляет функцию-валидатор, которая принимает в параметры индекс текущего шага, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов.
27
+ * `goNext(stepIndex?: number)` - перейти на след. шаг, `goPrev(stepIndex?: number)` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` переопределяет функцию-валидатор, которая принимает в параметры индекс текущего шага и индекс нового, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов.
26
28
  * @type ({stepper, ...api}) => ReactElement
27
29
  */
28
30
  children: (params: StepperState) => ReactElement;
@@ -32,6 +34,8 @@ export type StepperProps = WithSupportProps<{
32
34
  onCompleteChange?: (isCompleted: boolean) => void;
33
35
  }>;
34
36
 
37
+ const DEFAULT_VALIDATOR = async () => true;
38
+
35
39
  export function Stepper({
36
40
  children,
37
41
  steps,
@@ -39,6 +43,7 @@ export function Stepper({
39
43
  onChangeCurrentStep,
40
44
  onCompleteChange,
41
45
  defaultCurrentStepIndex = 0,
46
+ validator: validatorProp = DEFAULT_VALIDATOR,
42
47
  ...props
43
48
  }: StepperProps) {
44
49
  const isCompletedByDefault = defaultCurrentStepIndex === steps.length - 1;
@@ -65,37 +70,38 @@ export function Stepper({
65
70
  [onChangeCurrentStep],
66
71
  );
67
72
 
68
- const goNext = useCallback(() => {
69
- if (currentStepIndex >= steps.length || isCompleted) {
70
- return;
71
- }
72
-
73
- const currentStep = steps[currentStepIndex];
74
-
75
- setCurrentStepState(STEP_STATE.Loading);
76
-
77
- Promise.all([
78
- currentStep.validation?.() ?? Promise.resolve(true),
79
- stepsValidator?.value(currentStepIndex) ?? Promise.resolve(true),
80
- ])
81
- .then(results => results.every(isValid => isValid))
82
- .catch(() => false)
83
- .then(isValid => {
84
- if (!isValid) {
85
- setCurrentStepState(STEP_STATE.Rejected);
86
- return;
87
- }
73
+ const goNext = useCallback(
74
+ (newStepIndexUnsafety: number = currentStepIndex + 1) => {
75
+ if (currentStepIndex >= steps.length || isCompleted || newStepIndexUnsafety <= currentStepIndex) {
76
+ return;
77
+ }
88
78
 
89
- if (currentStepIndex === steps.length - 1) {
90
- // завершился последний шаг
91
- setCurrentStepState(STEP_STATE.Completed);
92
- setIsCompleted(true);
93
- } else {
94
- setCurrentStepIndex(currentStepIndex + 1);
95
- setCurrentStepState(STEP_STATE.Current);
96
- }
97
- });
98
- }, [currentStepIndex, isCompleted, setCurrentStepIndex, steps, stepsValidator]);
79
+ const newStepIndex = Math.min(steps.length - 1, newStepIndexUnsafety);
80
+
81
+ setCurrentStepState(STEP_STATE.Loading);
82
+
83
+ const validator = stepsValidator?.value || validatorProp;
84
+
85
+ validator(currentStepIndex, newStepIndex)
86
+ .catch(() => false)
87
+ .then(isValid => {
88
+ if (!isValid) {
89
+ setCurrentStepState(STEP_STATE.Rejected);
90
+ return;
91
+ }
92
+
93
+ if (currentStepIndex === steps.length - 1) {
94
+ // завершился последний шаг
95
+ setCurrentStepState(STEP_STATE.Completed);
96
+ setIsCompleted(true);
97
+ } else {
98
+ setCurrentStepIndex(newStepIndex);
99
+ setCurrentStepState(STEP_STATE.Current);
100
+ }
101
+ });
102
+ },
103
+ [currentStepIndex, isCompleted, setCurrentStepIndex, steps.length, stepsValidator?.value, validatorProp],
104
+ );
99
105
 
100
106
  const goPrev = useCallback(
101
107
  (index: number = currentStepIndex - 1) => {
package/src/types.ts CHANGED
@@ -6,12 +6,11 @@ import { STEP_STATE } from './constants';
6
6
 
7
7
  export type StepState = ValueOf<typeof STEP_STATE>;
8
8
 
9
- export type StepsValidator = (stepIndex: number) => Promise<boolean>;
9
+ export type StepsValidator = (prevStepIndex: number, newStepIndex: number) => Promise<boolean>;
10
10
 
11
11
  export type StepData = {
12
12
  title: string;
13
13
  description?: string;
14
- validation?(): Promise<boolean>;
15
14
  };
16
15
 
17
16
  export type StepViewData = StepData & {
@@ -22,8 +21,8 @@ export type StepViewData = StepData & {
22
21
 
23
22
  export type StepperApi = {
24
23
  stepper: JSX.Element;
25
- goNext(): void;
26
- goPrev(): void;
24
+ goNext(stepIndex?: number): void;
25
+ goPrev(stepIndex?: number): void;
27
26
  resetValidation(): void;
28
27
  setValidator(validator: StepsValidator): void;
29
28
  isCompleted: boolean;