@snack-uikit/stepper 0.5.10-preview-96ca8003.0 → 0.5.10-preview-8df95eca.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
@@ -48,9 +48,10 @@ return (
48
48
  ### Props
49
49
  | name | type | default value | description |
50
50
  |------|------|---------------|-------------|
51
- | children* | `({stepper, ...api}) => ReactElement` | - | Render function. Принимает аргументы: `stepper` - JSX-элемент степпера, `goNext` - перейти на след. шаг, `goPrev` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` добавляет функцию-валидатор, которая принимает в параметры индекс текущего шага, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов. |
51
+ | children* | `({stepper, ...api}) => ReactElement` | - | Render function. Принимает аргументы: `stepper` - JSX-элемент степпера, `goNext(stepIndex?: number)` - перейти на след. шаг, `goPrev(stepIndex?: number)` - перейти на пред. шаг, `resetValidation` - сбросить состояние валидации для текущего шага, `setValidator` переопределяет функцию-валидатор, которая принимает в параметры индекс текущего шага и индекс нового, `isCompleted` - окончен ли процесс, `currentStepIndex` - индекс текущего шага, `stepCount` - кол-во шагов. |
52
52
  | steps* | `StepData[]` | - | Массив шагов |
53
53
  | defaultCurrentStepIndex | `number` | - | Индекс текущего шага по-дефолту |
54
+ | validator | `StepsValidator` | - | Валидатор шагов. Выполняется при смене шага. Принимает первым аргументом индекс текущего, вторым - индекс нового шага. |
54
55
  | className | `string` | - | CSS-класс |
55
56
  | onChangeCurrentStep | `(newValue: number, prevValue: number) => void` | - | Колбек смены текущего степа |
56
57
  | 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-8df95eca.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": "3996b3216cb5ab36014df88c4a9fe41f7586e4b8"
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;