@barabel324/popups-engine 0.0.7 → 0.0.9

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
@@ -1,8 +1,8 @@
1
1
  # Popups-engine
2
2
 
3
- Движок для управления попапами в React с поддержкой кастомных компонентов и анимаций через motion.
3
+ Движок для управления попапами в React с поддержкой кастомных компонентов и анимаций через `motion`.
4
4
 
5
- Версия motion "^12.24.7"
5
+ Версия `motion`: **^12.24.7**
6
6
 
7
7
  ## Установка
8
8
 
@@ -17,76 +17,78 @@ npm i @barabel324/popups-engine
17
17
  Провайдер для регистрации и управления попапами.
18
18
 
19
19
  ```tsx
20
- <PopupsEngineProvider
21
- popups={popups}
22
- >
20
+ <PopupsEngineProvider popups={popups}>
23
21
  {children}
24
22
 
25
23
  <PopupsEngineRoot
26
24
  id="popups-root"
27
- lockBodyScroll={() => document.body.style.overflow = 'hidden'}
28
- enableBodyScroll={() => document.body.style.overflow = ''}
25
+ lockBodyScroll={() => (document.body.style.overflow = 'hidden')}
26
+ enableBodyScroll={() => (document.body.style.overflow = '')}
29
27
  />
30
28
  </PopupsEngineProvider>
31
29
  ```
32
30
 
33
31
  ### PopupsEngineRoot
34
32
 
35
- Компонент, который рендерит все попапы и обертки. Обычно располагается один раз в корне приложения.
33
+ Компонент, который рендерит все попапы и обёртки. Обычно используется один раз в корне приложения.
36
34
 
37
35
  ```tsx
38
36
  <PopupsEngineRoot
39
37
  id="popups-root"
40
- lockBodyScroll={() => document.body.style.overflow = 'hidden'}
41
- enableBodyScroll={() => document.body.style.overflow = ''}
38
+ lockBodyScroll={() => (document.body.style.overflow = 'hidden')}
39
+ enableBodyScroll={() => (document.body.style.overflow = '')}
42
40
  />
43
41
  ```
44
42
 
45
- | Проп | Тип | Описание |
46
- | ------------------ | ------------ | -------------------------------------------- |
47
- | `id` | `string` | Атрибут `id` для корневого элемента попапов. |
48
- | `lockBodyScroll` | `() => void` | Функция блокировки скролла страницы. |
49
- | `enableBodyScroll` | `() => void` | Функция разблокировки скролла страницы. |
43
+ #### Пропсы
50
44
 
51
- `PopupsEngineProvider` должен оборачивать приложение, а `PopupsEngineRoot` должен быть отрендерен внутри него (обычно один раз).
45
+ | Проп | Тип | Описание |
46
+ | ------------------ | ------------------- | ------------------------------------------------------------------ |
47
+ | `id` | `string` | `id` атрибут для корневого элемента попапов |
48
+ | `lockBodyScroll` | `() => void` | Функция блокировки скролла страницы |
49
+ | `enableBodyScroll` | `() => void` | Функция разблокировки скролла страницы |
50
+ | `components` | `TPEComponents` | Кастомные компоненты. `openPopup` имеет приоритет над этим пропсом |
51
+ | `classNames` | `TPEClassNames` | Кастомные классы. `openPopup` имеет приоритет над этим пропсом |
52
+ | `motionVariants` | `TPEMotionVariants` | Анимации для `motion`-обёртки попапа. `openPopup` имеет приоритет |
52
53
 
53
- ### Хук usePopupsEngineProvider
54
+ `PopupsEngineProvider` должен оборачивать приложение, а `PopupsEngineRoot` должен быть отрендерен внутри него.
55
+
56
+ ## Хук usePopupsEngineProvider
54
57
 
55
58
  Позволяет управлять попапами внутри компонентов.
56
59
 
57
60
  ```ts
58
- const { openPopup, closePopup, closeFirstPopup, closeAllPopups } = usePopupsEngineProvider();
61
+ const {
62
+ openPopup,
63
+ closePopup,
64
+ closeFirstPopup,
65
+ closeAllPopups,
66
+ } = usePopupsEngineProvider();
59
67
 
60
- // открыть попап
61
68
  openPopup({ variant: 'MyPopup', popupProps: { title: 'Hello' } });
62
-
63
- // закрыть последний попап
64
69
  closePopup();
65
-
66
- // закрыть первый попап
67
70
  closeFirstPopup();
68
-
69
- // закрыть все попапы
70
71
  closeAllPopups();
71
72
  ```
72
73
 
73
- #### Пропсы openPopup
74
+ ### Пропсы openPopup
74
75
 
75
- | Проп | Тип | Описание |
76
- | ---------------- | --------------------- | --------------------------------------------------------- |
77
- | `variant` | `string` | Ключ попапа из провайдера. |
78
- | `popupProps` | `Record<string, any>` | Пропсы, которые передаются в попап. |
79
- | `isCloseAll` | `boolean` | Закрывать ли все попапы при вызове `close` внутри попапа. |
80
- | `components` | `TPEComponents` | Кастомные компоненты для библиотеки. |
81
- | `classNames` | `TPEClassNames` | Кастомные классы для компонентов библиотеки. |
82
- | `motionVariants` | `TPEMotionVariants` | Анимации для `motion` обертки попапа. |
76
+ | Проп | Тип | Описание |
77
+ | ---------------- | --------------------- | ---------------------------------------------------------------------- |
78
+ | `variant` | `string` | Ключ попапа, зарегистрированного в провайдере |
79
+ | `popupProps` | `Record<string, any>` | Пропсы, передаваемые в компонент попапа |
80
+ | `isCloseAll` | `boolean` | Закрывать ли все попапы при вызове `close` внутри попапа |
81
+ | `components` | `TPEComponents` | Кастомные компоненты. Приоритет над `PopupsEngineRoot` |
82
+ | `classNames` | `TPEClassNames` | Кастомные классы. Приоритет над `PopupsEngineRoot` |
83
+ | `motionVariants` | `TPEMotionVariants` | Анимации для `motion`-обёртки попапа. Приоритет над `PopupsEngineRoot` |
83
84
 
85
+ ## Кастомизация
84
86
 
85
- ## Кастомизация компонентов
87
+ Кастомизация возможна глобально через `PopupsEngineRoot` или локально через `openPopup`.
86
88
 
87
- ### Компоненты
89
+ Пропсы, переданные в `openPopup`, имеют приоритет над пропсами `PopupsEngineRoot`.
88
90
 
89
- Можно передавать кастомные компоненты для обертки и лоудера:
91
+ ### Компоненты
90
92
 
91
93
  ```tsx
92
94
  const components = {
@@ -97,8 +99,6 @@ const components = {
97
99
 
98
100
  ### Классы
99
101
 
100
- Можно передавать кастомные классы для обертки и лоудера:
101
-
102
102
  ```tsx
103
103
  const classNames = {
104
104
  wrapper: 'my-wrapper-class',
@@ -106,10 +106,7 @@ const classNames = {
106
106
  };
107
107
  ```
108
108
 
109
-
110
- ## Анимации через motion (motion/react, framer-motion)
111
-
112
- В каждый попап можно кинуть объект с анимацией motion
109
+ ## Анимации (motion / framer-motion)
113
110
 
114
111
  ```tsx
115
112
  const motionVariants = {
@@ -117,16 +114,13 @@ const motionVariants = {
117
114
  animate: { opacity: 1, y: 0 },
118
115
  exit: { opacity: 0, y: 20 },
119
116
  };
120
-
121
- openPopup({ variant: 'MyPopup', motionVariants });
122
117
  ```
123
118
 
124
119
  ## Дженерики
125
120
 
126
- TPEComponentWrapper — дженерик для типизации попапов. Библиотека автоматически передает в попап служебные пропсы (например `closePopup`), которые можно использовать внутри компонента.
127
-
121
+ `TPEComponentWrapper` — дженерик для типизации попапов. Библиотека автоматически передаёт в компонент служебные пропсы (например, `closePopup`).
128
122
 
129
- ## Минимальный рабочий пример
123
+ ## Минимальный пример
130
124
 
131
125
  ```tsx
132
126
  // '@/popup-templates/message'
@@ -134,66 +128,49 @@ export const PopupMessage: TPEComponentWrapper<TPopupMessage> = ({
134
128
  title,
135
129
  description,
136
130
  closePopup,
137
- }) => {
138
- return (
139
- <div>
140
- <div>
141
- {title}
142
- </div>
143
-
144
- <div>
145
- {description}
146
- </div>
147
-
148
- <button
149
- type="button"
150
- onClick={closePopup}
151
- >
152
- close
153
- </button>
154
- </div>
155
- );
156
- };
131
+ }) => (
132
+ <div>
133
+ <div>{title}</div>
134
+ <div>{description}</div>
135
+ <button type="button" onClick={closePopup}>
136
+ close
137
+ </button>
138
+ </div>
139
+ );
157
140
 
158
141
  // '@/popup-templates'
159
142
  const popups = {
160
- message: lazy(
161
- () => import('@views/popup-templates/message'),
162
- ),
143
+ message: lazy(() => import('@views/popup-templates/message')),
163
144
  };
164
145
 
165
146
  // '@/show-popup'
166
147
  export const ShowPopup = () => {
167
148
  const { openPopup } = usePopupsEngineProvider();
168
149
 
169
- const handleButtonClick = () => {
170
- openPopup({
171
- variant: 'message',
172
- popupProps: {
173
- title: `I am popup`,
174
- description: 'Destroyer of the worlds',
175
- },
176
- });
177
- };
178
-
179
150
  return (
180
- <div>
181
- <button
182
- type="button"
183
- onClick={handleButtonClick}
184
- >
185
- Press
186
- </button>
187
- </div>
151
+ <button
152
+ type="button"
153
+ onClick={() =>
154
+ openPopup({
155
+ variant: 'message',
156
+ popupProps: {
157
+ title: 'I am popup',
158
+ description: 'Destroyer of the worlds',
159
+ },
160
+ })
161
+ }
162
+ >
163
+ Press
164
+ </button>
188
165
  );
189
166
  };
190
167
 
191
168
  // 'app.tsx'
192
- <PopupsEngineProvider
193
- popups={popups}
194
- >
195
- <ShowPopup />
169
+ import { PopupsEngineProvider, PopupsEngineRoot } from '@barabel324/popups-engine';
170
+ import '@barabel324/popups-engine/css';
196
171
 
172
+ <PopupsEngineProvider popups={popups}>
173
+ <ShowPopup />
197
174
  <PopupsEngineRoot />
198
175
  </PopupsEngineProvider>
199
176
  ```
@@ -92,6 +92,12 @@ declare type TPEProvider = {
92
92
  declare type TPERoot = {
93
93
  /** аттрибут id рута */
94
94
  id?: string;
95
+ /** кастомные компоненты либы */
96
+ components?: TPEComponents;
97
+ /** кастомные классы для компонентов либы */
98
+ classNames?: TPEClassNames;
99
+ /** Варианты анимации обертки для motion */
100
+ motionVariants?: TPEMotionVariants;
95
101
  /** Каллбак для вызова разрешающего метода скролл лока */
96
102
  enableBodyScroll?: () => void;
97
103
  /** Каллбак для вызова запрещающего метода скролл лока */
@@ -106,6 +112,8 @@ declare type TPEWrapper = FCClass<{
106
112
  * Варианты анимации обертки для motion
107
113
  */
108
114
  motionVariants?: TPEMotionVariants;
115
+ /** функция закрытия текущего попапа */
116
+ closePopup: () => void;
109
117
  }>;
110
118
 
111
119
  export declare const usePopupsEngineProvider: () => TPEContext;
@@ -1,7 +1,7 @@
1
- import { jsx as o } from "react/jsx-runtime";
2
- import { createContext as g, useContext as x, useRef as N, useEffect as h, Suspense as V, useState as D, useCallback as O, useMemo as f } from "react";
3
- import { motion as R, AnimatePresence as $ } from "motion/react";
4
- const y = g({
1
+ import { jsx as n } from "react/jsx-runtime";
2
+ import { createContext as g, useContext as x, useRef as D, useEffect as y, Suspense as O, useState as R, useCallback as $, useMemo as f } from "react";
3
+ import { motion as b, AnimatePresence as j } from "motion/react";
4
+ const L = g({
5
5
  openPopup: () => {
6
6
  },
7
7
  closePopup: () => {
@@ -10,140 +10,145 @@ const y = g({
10
10
  },
11
11
  closeAllPopups: () => {
12
12
  }
13
- }), w = g({
13
+ }), k = g({
14
14
  popupList: []
15
- }), L = g({
15
+ }), A = g({
16
16
  popups: {}
17
- }), k = () => x(y), b = () => x(w), j = () => x(L), F = "_parent_wmksm_1", I = {
18
- parent: F
19
- }, S = {
17
+ }), F = () => x(L), I = () => x(k), S = () => x(A), z = "_parent_wmksm_1", K = {
18
+ parent: z
19
+ }, M = {
20
20
  initial: { opacity: 0 },
21
21
  animate: { opacity: 1 },
22
22
  exit: { opacity: 0 }
23
- }, z = ({
24
- className: n,
25
- motionVariants: u = S,
26
- children: p
23
+ }, q = ({
24
+ className: o,
25
+ motionVariants: m = M,
26
+ closePopup: p,
27
+ children: t
27
28
  }) => {
28
- const t = N(null), { closePopup: e } = k(), a = (r) => {
29
- r.target === t.current && e();
29
+ const r = D(null), i = (c) => {
30
+ c.target === r.current && p();
30
31
  };
31
- return /* @__PURE__ */ o(
32
- R.div,
32
+ return /* @__PURE__ */ n(
33
+ b.div,
33
34
  {
34
- variants: u,
35
+ variants: m,
35
36
  initial: "initial",
36
37
  animate: "animate",
37
38
  exit: "exit",
38
- ref: t,
39
- className: n ?? I.parent,
40
- onClick: a,
41
- children: p
39
+ ref: r,
40
+ className: o ?? K.parent,
41
+ onClick: i,
42
+ children: t
42
43
  }
43
44
  );
44
- }, K = "_parent_1ud1o_1", M = {
45
- parent: K
46
- }, q = ({
47
- className: n
48
- }) => /* @__PURE__ */ o(
45
+ }, G = "_parent_1ud1o_1", H = {
46
+ parent: G
47
+ }, J = ({
48
+ className: o
49
+ }) => /* @__PURE__ */ n(
49
50
  "div",
50
51
  {
51
- className: n ?? M.parent,
52
+ className: o ?? H.parent,
52
53
  children: "Loading..."
53
54
  }
54
- ), Q = ({
55
- className: n,
56
- id: u = "popups-engine-root",
57
- enableBodyScroll: p,
58
- lockBodyScroll: t
55
+ ), W = ({
56
+ className: o,
57
+ id: m = "popups-engine-root",
58
+ components: p,
59
+ classNames: t,
60
+ motionVariants: r,
61
+ enableBodyScroll: i,
62
+ lockBodyScroll: c
59
63
  }) => {
60
- const { popupList: e } = b(), { popups: a } = j(), { closePopup: r, closeAllPopups: l } = k();
61
- return h(() => (e.length > 0 && t?.(), () => {
62
- e.length > 0 && p?.();
64
+ const { popupList: s } = I(), { popups: v } = S(), { closePopup: a, closeAllPopups: u } = F();
65
+ return y(() => (s.length > 0 && c?.(), () => {
66
+ s.length > 0 && i?.();
63
67
  }), [
64
- e,
65
- p,
66
- t
67
- ]), h(() => {
68
- const i = (P) => {
69
- P.key === "Escape" && (e.at(-1)?.isCloseAll ? l : r)();
68
+ s,
69
+ i,
70
+ c
71
+ ]), y(() => {
72
+ const e = (d) => {
73
+ d.key === "Escape" && (s.at(-1)?.isCloseAll ? u : a)();
70
74
  };
71
- return e.length > 0 && window.addEventListener("keydown", i), () => {
72
- window.removeEventListener("keydown", i);
75
+ return s.length > 0 && window.addEventListener("keydown", e), () => {
76
+ window.removeEventListener("keydown", e);
73
77
  };
74
78
  }, [
75
- e,
76
- r,
77
- l
78
- ]), /* @__PURE__ */ o(
79
+ s,
80
+ a,
81
+ u
82
+ ]), /* @__PURE__ */ n(
79
83
  "div",
80
84
  {
81
- className: n,
82
- id: u,
83
- children: /* @__PURE__ */ o($, { children: e.map((i) => {
85
+ className: o,
86
+ id: m,
87
+ children: /* @__PURE__ */ n(j, { children: s.map((e) => {
84
88
  const {
85
- popupID: P,
86
- variant: d,
87
- popupProps: s,
88
- isCloseAll: v,
89
- components: c,
90
- classNames: E,
91
- motionVariants: m
92
- } = i, A = c?.wrapper ?? z, _ = c?.loader ?? q, C = a[d];
93
- return C ? /* @__PURE__ */ o(
94
- A,
89
+ popupID: d,
90
+ variant: l,
91
+ popupProps: E,
92
+ isCloseAll: P,
93
+ components: w,
94
+ classNames: C,
95
+ motionVariants: V
96
+ } = e, _ = w?.wrapper || p?.wrapper || q, N = w?.loader || p?.loader || J, h = v[l];
97
+ return h ? /* @__PURE__ */ n(
98
+ _,
95
99
  {
96
- className: E?.wrapper,
97
- motionVariants: m,
98
- children: /* @__PURE__ */ o(
99
- V,
100
+ className: C?.wrapper || t?.wrapper,
101
+ motionVariants: V || r,
102
+ closePopup: P ? u : a,
103
+ children: /* @__PURE__ */ n(
104
+ O,
100
105
  {
101
- fallback: /* @__PURE__ */ o(_, { className: E?.loader }),
102
- children: /* @__PURE__ */ o(
103
- C,
106
+ fallback: /* @__PURE__ */ n(N, { className: C?.loader || t?.loader }),
107
+ children: /* @__PURE__ */ n(
108
+ h,
104
109
  {
105
- ...s,
106
- closePopup: v ? l : r
110
+ ...E,
111
+ closePopup: P ? u : a
107
112
  }
108
113
  )
109
114
  }
110
115
  )
111
116
  },
112
- P
117
+ d
113
118
  ) : null;
114
119
  }) })
115
120
  }
116
121
  );
117
- }, T = ({
118
- popups: n,
119
- children: u
122
+ }, X = ({
123
+ popups: o,
124
+ children: m
120
125
  }) => {
121
- const [p, t] = D([]), e = O((s) => {
122
- const v = Object.keys(n), { variant: c } = s;
123
- c && (v.some((m) => m === c) ? t((m) => [...m, {
124
- ...s,
126
+ const [p, t] = R([]), r = $((e) => {
127
+ const d = Object.keys(o), { variant: l } = e;
128
+ l && (d.some((P) => P === l) ? t((P) => [...P, {
129
+ ...e,
125
130
  popupID: Date.now()
126
- }]) : console.error(`there are no "${c}" popup`));
127
- }, [n]), a = () => {
128
- t((s) => s.slice(0, -1));
129
- }, r = () => {
130
- t((s) => s.slice(1));
131
- }, l = () => {
131
+ }]) : console.error(`there are no "${l}" popup`));
132
+ }, [o]), i = () => {
133
+ t((e) => e.slice(0, -1));
134
+ }, c = () => {
135
+ t((e) => e.slice(1));
136
+ }, s = () => {
132
137
  t(() => []);
133
- }, i = f(() => ({
134
- openPopup: e,
135
- closePopup: a,
136
- closeFirstPopup: r,
137
- closeAllPopups: l
138
- }), [e]), P = f(() => ({
138
+ }, v = f(() => ({
139
+ openPopup: r,
140
+ closePopup: i,
141
+ closeFirstPopup: c,
142
+ closeAllPopups: s
143
+ }), [r]), a = f(() => ({
139
144
  popupList: p
140
- }), [p]), d = f(() => ({
141
- popups: n
142
- }), [n]);
143
- return /* @__PURE__ */ o(y.Provider, { value: i, children: /* @__PURE__ */ o(w.Provider, { value: P, children: /* @__PURE__ */ o(L.Provider, { value: d, children: u }) }) });
145
+ }), [p]), u = f(() => ({
146
+ popups: o
147
+ }), [o]);
148
+ return /* @__PURE__ */ n(L.Provider, { value: v, children: /* @__PURE__ */ n(k.Provider, { value: a, children: /* @__PURE__ */ n(A.Provider, { value: u, children: m }) }) });
144
149
  };
145
150
  export {
146
- T as PopupsEngineProvider,
147
- Q as PopupsEngineRoot,
148
- k as usePopupsEngineProvider
151
+ X as PopupsEngineProvider,
152
+ W as PopupsEngineRoot,
153
+ F as usePopupsEngineProvider
149
154
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barabel324/popups-engine",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "main": "./dist/popups-engine.js",
6
6
  "types": "./dist/popups-engine.d.ts",