@lerx/promise-modal 0.2.2 → 0.2.4

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.
@@ -13,6 +13,7 @@ export declare class ModalManager {
13
13
  static get unanchored(): boolean;
14
14
  static defineStyleSheet(styleId: string, css: string): void;
15
15
  static applyStyleSheet(): void;
16
+ static getHashedClassNames(styleId: string): string;
16
17
  static reset(): void;
17
18
  static open(modal: Modal): void;
18
19
  }
@@ -1 +1 @@
1
- export declare const style = "\n[data-anchor] {\n display: flex;\n align-items: center;\n justify-content: center;\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 1000;\n transition: background-color ease-in-out;\n}";
1
+ export declare const anchor: string;
@@ -1 +1,3 @@
1
- export declare const style = "\n[data-background] {\n display: none;\n position: fixed;\n inset: 0;\n z-index: -999;\n pointer-events: none;\n}\n\n[data-background] > * {\n pointer-events: none;\n}\n\n[data-background][data-active] {\n pointer-events: all;\n}\n\n[data-background][data-visible] {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n";
1
+ export declare const background: string;
2
+ export declare const active: string;
3
+ export declare const visible: string;
@@ -1 +1,3 @@
1
- export declare const style = "\n[data-foreground] {\n pointer-events: none;\n display: none;\n position: fixed;\n inset: 0;\n z-index: 1;\n}\n\n[data-foreground][data-active] > * {\n pointer-events: all;\n}\n\n[data-foreground][data-visible] {\n display: flex !important;\n justify-content: center;\n align-items: center;\n}\n";
1
+ export declare const foreground: string;
2
+ export declare const active: string;
3
+ export declare const visible: string;
@@ -1 +1 @@
1
- export declare const style = "\n[data-presenter] {\n position: fixed;\n inset: 0;\n pointer-events: none;\n overflow: hidden;\n";
1
+ export declare const presenter: string;
@@ -1,6 +1,7 @@
1
1
  import type { ComponentType, ReactNode } from 'react';
2
2
  import type { AlertContentProps, AlertFooterRender, BackgroundComponent, FooterOptions, ForegroundComponent, ModalBackground } from '../../types';
3
3
  interface AlertProps<B> {
4
+ group?: string;
4
5
  subtype?: 'info' | 'success' | 'warning' | 'error';
5
6
  title?: ReactNode;
6
7
  subtitle?: ReactNode;
@@ -13,5 +14,5 @@ interface AlertProps<B> {
13
14
  ForegroundComponent?: ForegroundComponent;
14
15
  BackgroundComponent?: BackgroundComponent;
15
16
  }
16
- export declare const alert: <B = any>({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: AlertProps<B>) => Promise<void>;
17
+ export declare const alert: <B = any>({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: AlertProps<B>) => Promise<void>;
17
18
  export {};
@@ -1,6 +1,7 @@
1
1
  import type { ComponentType, ReactNode } from 'react';
2
2
  import type { BackgroundComponent, ConfirmContentProps, ConfirmFooterRender, FooterOptions, ForegroundComponent, ModalBackground } from '../../types';
3
3
  interface ConfirmProps<B> {
4
+ group?: string;
4
5
  subtype?: 'info' | 'success' | 'warning' | 'error';
5
6
  title?: ReactNode;
6
7
  subtitle?: ReactNode;
@@ -13,5 +14,5 @@ interface ConfirmProps<B> {
13
14
  ForegroundComponent?: ForegroundComponent;
14
15
  BackgroundComponent?: BackgroundComponent;
15
16
  }
16
- export declare const confirm: <B = any>({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: ConfirmProps<B>) => Promise<boolean>;
17
+ export declare const confirm: <B = any>({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: ConfirmProps<B>) => Promise<boolean>;
17
18
  export {};
@@ -1,11 +1,12 @@
1
1
  import type { ComponentType, ReactNode } from 'react';
2
2
  import type { BackgroundComponent, FooterOptions, ForegroundComponent, ModalBackground, PromptContentProps, PromptFooterRender, PromptInputProps } from '../../types';
3
3
  interface PromptProps<T, B = any> {
4
+ group?: string;
4
5
  title?: ReactNode;
5
6
  subtitle?: ReactNode;
6
7
  content?: ReactNode | ComponentType<PromptContentProps>;
7
- Input: (props: PromptInputProps<T>) => ReactNode;
8
8
  defaultValue?: T;
9
+ Input: (props: PromptInputProps<T>) => ReactNode;
9
10
  disabled?: (value: T) => boolean;
10
11
  returnOnCancel?: boolean;
11
12
  background?: ModalBackground<B>;
@@ -16,5 +17,5 @@ interface PromptProps<T, B = any> {
16
17
  ForegroundComponent?: ForegroundComponent;
17
18
  BackgroundComponent?: BackgroundComponent;
18
19
  }
19
- export declare const prompt: <T, B = any>({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: PromptProps<T, B>) => Promise<T>;
20
+ export declare const prompt: <T, B = any>({ group, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }: PromptProps<T, B>) => Promise<T>;
20
21
  export {};
@@ -5,6 +5,7 @@ type AbstractNodeProps<T, B> = BaseModal<T, B> & ManagedEntity;
5
5
  export declare abstract class AbstractNode<T, B> {
6
6
  #private;
7
7
  readonly id: number;
8
+ readonly group?: string;
8
9
  readonly initiator: string;
9
10
  readonly title?: ReactNode;
10
11
  readonly subtitle?: ReactNode;
@@ -16,7 +17,7 @@ export declare abstract class AbstractNode<T, B> {
16
17
  readonly BackgroundComponent?: BackgroundComponent;
17
18
  get alive(): boolean;
18
19
  get visible(): boolean;
19
- constructor({ id, initiator, title, subtitle, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AbstractNodeProps<T, B>);
20
+ constructor({ id, initiator, group, title, subtitle, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AbstractNodeProps<T, B>);
20
21
  subscribe(listener: Fn): () => void;
21
22
  publish(): void;
22
23
  protected resolve(result: T | null): void;
@@ -7,7 +7,7 @@ export declare class AlertNode<B> extends AbstractNode<null, B> {
7
7
  readonly subtype?: 'info' | 'success' | 'warning' | 'error';
8
8
  readonly content?: ReactNode | ComponentType<AlertContentProps>;
9
9
  readonly footer?: AlertFooterRender | Pick<FooterOptions, 'confirm' | 'hideConfirm'> | false;
10
- constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AlertNodeProps<B>);
10
+ constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: AlertNodeProps<B>);
11
11
  onClose(): void;
12
12
  onConfirm(): void;
13
13
  }
@@ -7,7 +7,7 @@ export declare class ConfirmNode<B> extends AbstractNode<boolean, B> {
7
7
  readonly subtype?: 'info' | 'success' | 'warning' | 'error';
8
8
  readonly content?: ReactNode | ComponentType<ConfirmContentProps>;
9
9
  readonly footer?: ConfirmFooterRender | FooterOptions | false;
10
- constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: ConfirmNodeProps<B>);
10
+ constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: ConfirmNodeProps<B>);
11
11
  onClose(): void;
12
12
  onConfirm(): void;
13
13
  }
@@ -11,7 +11,7 @@ export declare class PromptNode<T, B> extends AbstractNode<T, B> {
11
11
  readonly disabled?: (value: T) => boolean;
12
12
  readonly returnOnCancel?: boolean;
13
13
  readonly footer?: PromptFooterRender<T> | FooterOptions | false;
14
- constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: PromptNodeProps<T, B>);
14
+ constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }: PromptNodeProps<T, B>);
15
15
  onChange(value: T): void;
16
16
  onConfirm(): void;
17
17
  onClose(): void;
@@ -1,3 +1,3 @@
1
1
  import type { Fn } from '../@aileron/declare';
2
2
  import type { ModalNode } from '../core';
3
- export declare const useActiveModalCount: (validate?: Fn<[ModalNode?], boolean | undefined>, refreshKey?: string | number) => number;
3
+ export declare const useActiveModalCount: (validate?: Fn<[node?: ModalNode], boolean | undefined>, refreshKey?: string | number) => number;
package/dist/index.cjs CHANGED
@@ -4,11 +4,14 @@ const jsxRuntime = require('react/jsx-runtime');
4
4
  const react = require('react');
5
5
  const convert = require('@winglet/common-utils/convert');
6
6
  const hook = require('@winglet/react-utils/hook');
7
+ const hash = require('@winglet/common-utils/hash');
7
8
  const lib = require('@winglet/common-utils/lib');
8
- const styleManager = require('@winglet/react-utils/style-manager');
9
+ const compressCss = require('@winglet/style-utils/compressCss');
10
+ const styleManager = require('@winglet/style-utils/styleManager');
9
11
  const reactDom = require('react-dom');
10
12
  const array = require('@winglet/common-utils/array');
11
13
  const hoc = require('@winglet/react-utils/hoc');
14
+ const classNames = require('@winglet/style-utils/classNames');
12
15
  const filter = require('@winglet/common-utils/filter');
13
16
  const render = require('@winglet/react-utils/render');
14
17
  const console = require('@winglet/common-utils/console');
@@ -22,13 +25,14 @@ class ModalManager {
22
25
  }
23
26
  static #anchor = null;
24
27
  static #scope = `promise-modal-${lib.getRandomString(36)}`;
28
+ static #hash = hash.polynomialHash(ModalManager.#scope);
25
29
  static anchor(options) {
26
30
  if (ModalManager.#anchor)
27
31
  return ModalManager.#anchor;
28
32
  const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
29
33
  const node = document.createElement(tag);
30
- node.setAttribute('id', `${prefix}-${lib.getRandomString(36)}`);
31
- node.setAttribute('data-scope', ModalManager.#scope);
34
+ node.id = `${prefix}-${lib.getRandomString(36)}`;
35
+ node.className = ModalManager.#scope;
32
36
  root.appendChild(node);
33
37
  ModalManager.#anchor = node;
34
38
  return node;
@@ -48,12 +52,15 @@ class ModalManager {
48
52
  static #styleManager = styleManager.styleManagerFactory(ModalManager.#scope);
49
53
  static #styleSheetDefinition = new Map();
50
54
  static defineStyleSheet(styleId, css) {
51
- ModalManager.#styleSheetDefinition.set(styleId, styleManager.compressCss(css));
55
+ ModalManager.#styleSheetDefinition.set(styleId, compressCss.compressCss(css));
52
56
  }
53
57
  static applyStyleSheet() {
54
58
  for (const [styleId, css] of ModalManager.#styleSheetDefinition)
55
59
  ModalManager.#styleManager(styleId, css, true);
56
60
  }
61
+ static getHashedClassNames(styleId) {
62
+ return `${styleId}-${ModalManager.#hash}`;
63
+ }
57
64
  static reset() {
58
65
  ModalManager.#active = false;
59
66
  ModalManager.#anchor = null;
@@ -66,11 +73,12 @@ class ModalManager {
66
73
  }
67
74
  }
68
75
 
69
- const alert = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
76
+ const alert = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
70
77
  return new Promise((resolve, reject) => {
71
78
  try {
72
79
  ModalManager.open({
73
80
  type: 'alert',
81
+ group,
74
82
  subtype,
75
83
  resolve: () => resolve(),
76
84
  title,
@@ -91,11 +99,12 @@ const alert = ({ subtype, title, subtitle, content, background, footer, dimmed,
91
99
  });
92
100
  };
93
101
 
94
- const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
102
+ const confirm = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
95
103
  return new Promise((resolve, reject) => {
96
104
  try {
97
105
  ModalManager.open({
98
106
  type: 'confirm',
107
+ group,
99
108
  subtype,
100
109
  resolve: (result) => resolve(result ?? false),
101
110
  title,
@@ -116,11 +125,12 @@ const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed
116
125
  });
117
126
  };
118
127
 
119
- const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
128
+ const prompt = ({ group, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
120
129
  return new Promise((resolve, reject) => {
121
130
  try {
122
131
  ModalManager.open({
123
132
  type: 'prompt',
133
+ group,
124
134
  resolve: (result) => resolve(result),
125
135
  title,
126
136
  subtitle,
@@ -146,6 +156,7 @@ const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, retur
146
156
 
147
157
  class AbstractNode {
148
158
  id;
159
+ group;
149
160
  initiator;
150
161
  title;
151
162
  subtitle;
@@ -165,8 +176,9 @@ class AbstractNode {
165
176
  }
166
177
  #resolve;
167
178
  #listeners = new Set();
168
- constructor({ id, initiator, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
179
+ constructor({ id, initiator, group, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
169
180
  this.id = id;
181
+ this.group = group;
170
182
  this.initiator = initiator;
171
183
  this.title = title;
172
184
  this.subtitle = subtitle;
@@ -218,9 +230,10 @@ class AlertNode extends AbstractNode {
218
230
  subtype;
219
231
  content;
220
232
  footer;
221
- constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
233
+ constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
222
234
  super({
223
235
  id,
236
+ group,
224
237
  initiator,
225
238
  title,
226
239
  subtitle,
@@ -250,9 +263,10 @@ class ConfirmNode extends AbstractNode {
250
263
  subtype;
251
264
  content;
252
265
  footer;
253
- constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
266
+ constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
254
267
  super({
255
268
  id,
269
+ group,
256
270
  initiator,
257
271
  title,
258
272
  subtitle,
@@ -286,9 +300,10 @@ class PromptNode extends AbstractNode {
286
300
  returnOnCancel;
287
301
  footer;
288
302
  #value;
289
- constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
303
+ constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
290
304
  super({
291
305
  id,
306
+ group,
292
307
  initiator,
293
308
  title,
294
309
  subtitle,
@@ -367,7 +382,8 @@ const useActiveModalCount = (validate = defaultValidate, refreshKey = 0) => {
367
382
  const { modalIds, getModalNode } = useModalManagerContext();
368
383
  return react.useMemo(() => {
369
384
  let count = 0;
370
- for (const id of modalIds) {
385
+ for (let index = 0; index < modalIds.length; index++) {
386
+ const id = modalIds[index];
371
387
  if (validate(getModalNode(id)))
372
388
  count++;
373
389
  }
@@ -622,8 +638,11 @@ const usePathname = () => {
622
638
  return { pathname };
623
639
  };
624
640
 
641
+ const background = ModalManager.getHashedClassNames('background');
642
+ const active$1 = ModalManager.getHashedClassNames('background-active');
643
+ const visible$1 = ModalManager.getHashedClassNames('background-visible');
625
644
  const style$3 = `
626
- [data-background] {
645
+ .${background} {
627
646
  display: none;
628
647
  position: fixed;
629
648
  inset: 0;
@@ -631,22 +650,22 @@ const style$3 = `
631
650
  pointer-events: none;
632
651
  }
633
652
 
634
- [data-background] > * {
653
+ .${background} > * {
635
654
  pointer-events: none;
636
655
  }
637
656
 
638
- [data-background][data-active] {
657
+ .${background}.${active$1} {
639
658
  pointer-events: all;
640
659
  }
641
660
 
642
- [data-background][data-visible] {
661
+ .${background}.${visible$1} {
643
662
  display: flex;
644
663
  align-items: center;
645
664
  justify-content: center;
646
665
  }
647
666
  `;
648
-
649
667
  ModalManager.defineStyleSheet('background', style$3);
668
+
650
669
  const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
651
670
  const { BackgroundComponent } = useConfigurationContext();
652
671
  const { context: userDefinedContext } = useUserDefinedContext();
@@ -657,9 +676,15 @@ const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
657
676
  event.stopPropagation();
658
677
  }, [modal, onClose]);
659
678
  const Background = react.useMemo(() => modal?.BackgroundComponent || BackgroundComponent, [BackgroundComponent, modal]);
679
+ const className = react.useMemo(() => modal
680
+ ? classNames.cx(background, {
681
+ [active$1]: modal.closeOnBackdropClick && modal.visible,
682
+ [visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
683
+ })
684
+ : undefined, [modal]);
660
685
  if (!modal)
661
686
  return null;
662
- return (jsxRuntime.jsx("div", { "data-background": true, "data-active": styleManager.dataCondition(modal.closeOnBackdropClick && modal.visible), "data-visible": styleManager.dataCondition(modal.manualDestroy ? modal.alive : modal.visible), onClick: handleClose, children: Background && (jsxRuntime.jsx(Background, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext })) }));
687
+ return (jsxRuntime.jsx("div", { className: className, onClick: handleClose, children: Background && (jsxRuntime.jsx(Background, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext })) }));
663
688
  };
664
689
 
665
690
  const AlertInner = react.memo(({ modal, handlers }) => {
@@ -739,8 +764,11 @@ const PromptInner = react.memo(({ modal, handlers }) => {
739
764
  })) : (jsxRuntime.jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
740
765
  });
741
766
 
767
+ const foreground = ModalManager.getHashedClassNames('foreground');
768
+ const active = ModalManager.getHashedClassNames('foreground-active');
769
+ const visible = ModalManager.getHashedClassNames('foreground-visible');
742
770
  const style$2 = `
743
- [data-foreground] {
771
+ .${foreground} {
744
772
  pointer-events: none;
745
773
  display: none;
746
774
  position: fixed;
@@ -748,26 +776,32 @@ const style$2 = `
748
776
  z-index: 1;
749
777
  }
750
778
 
751
- [data-foreground][data-active] > * {
779
+ .${foreground}.${active} > * {
752
780
  pointer-events: all;
753
781
  }
754
782
 
755
- [data-foreground][data-visible] {
783
+ .${foreground}.${visible} {
756
784
  display: flex !important;
757
785
  justify-content: center;
758
786
  align-items: center;
759
787
  }
760
788
  `;
761
-
762
789
  ModalManager.defineStyleSheet('foreground', style$2);
790
+
763
791
  const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
764
792
  const { ForegroundComponent } = useConfigurationContext();
765
793
  const { context: userDefinedContext } = useUserDefinedContext();
766
794
  const { modal, onChange, onConfirm, onClose, onDestroy } = useModal(modalId);
767
795
  const Foreground = react.useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
796
+ const className = react.useMemo(() => modal
797
+ ? classNames.cx(foreground, {
798
+ [active]: modal.visible,
799
+ [visible]: modal.manualDestroy ? modal.alive : modal.visible,
800
+ })
801
+ : undefined, [modal]);
768
802
  if (!modal)
769
803
  return null;
770
- return (jsxRuntime.jsx("div", { "data-foreground": true, "data-active": styleManager.dataCondition(modal.visible), "data-visible": styleManager.dataCondition(modal.manualDestroy ? modal.alive : modal.visible), children: jsxRuntime.jsxs(Foreground, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext, children: [modal.type === 'alert' && (jsxRuntime.jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsxRuntime.jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsxRuntime.jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
804
+ return (jsxRuntime.jsx("div", { className: className, children: jsxRuntime.jsxs(Foreground, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext, children: [modal.type === 'alert' && (jsxRuntime.jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsxRuntime.jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsxRuntime.jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
771
805
  };
772
806
 
773
807
  const useSubscribeModal = (modal) => {
@@ -781,15 +815,16 @@ const useSubscribeModal = (modal) => {
781
815
  return version;
782
816
  };
783
817
 
818
+ const presenter = ModalManager.getHashedClassNames('presenter');
784
819
  const style$1 = `
785
- [data-presenter] {
820
+ .${presenter} {
786
821
  position: fixed;
787
822
  inset: 0;
788
823
  pointer-events: none;
789
824
  overflow: hidden;
790
825
  `;
791
-
792
826
  ModalManager.defineStyleSheet('presenter', style$1);
827
+
793
828
  const { increment } = lib.counterFactory(1);
794
829
  const Presenter = react.memo(({ modalId }) => {
795
830
  const ref = react.useRef(null);
@@ -800,11 +835,12 @@ const Presenter = react.memo(({ modalId }) => {
800
835
  ref.current.style.zIndex = `${increment()}`;
801
836
  }
802
837
  });
803
- return (jsxRuntime.jsxs("div", { ref: ref, "data-presenter": true, children: [jsxRuntime.jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsxRuntime.jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
838
+ return (jsxRuntime.jsxs("div", { ref: ref, className: presenter, children: [jsxRuntime.jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsxRuntime.jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
804
839
  });
805
840
 
841
+ const anchor = ModalManager.getHashedClassNames('anchor');
806
842
  const style = `
807
- [data-anchor] {
843
+ .${anchor} {
808
844
  display: flex;
809
845
  align-items: center;
810
846
  justify-content: center;
@@ -814,8 +850,8 @@ const style = `
814
850
  z-index: 1000;
815
851
  transition: background-color ease-in-out;
816
852
  }`;
817
-
818
853
  ModalManager.defineStyleSheet('anchor', style);
854
+
819
855
  const AnchorInner = () => {
820
856
  const [version, update] = hook.useVersion();
821
857
  const { modalIds, setUpdater } = useModalManagerContext();
@@ -824,7 +860,7 @@ const AnchorInner = () => {
824
860
  }, [setUpdater, update]);
825
861
  const options = useConfigurationOptions();
826
862
  const dimmed = useActiveModalCount(validateDimmable, version);
827
- return (jsxRuntime.jsx("div", { "data-anchor": true, style: {
863
+ return (jsxRuntime.jsx("div", { className: anchor, style: {
828
864
  transitionDuration: options.duration,
829
865
  backgroundColor: dimmed ? options.backdrop : 'transparent',
830
866
  }, children: array.map(modalIds, (id) => (jsxRuntime.jsx(Presenter, { modalId: id }, id))) }));
package/dist/index.mjs CHANGED
@@ -2,11 +2,14 @@ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { createContext, useContext, useMemo, forwardRef, memo, useRef, useState, useLayoutEffect, useCallback, Fragment, useEffect, useImperativeHandle } from 'react';
3
3
  import { convertMsFromDuration } from '@winglet/common-utils/convert';
4
4
  import { useReference, useOnMountLayout, useHandle, useVersion, useOnMount } from '@winglet/react-utils/hook';
5
+ import { polynomialHash } from '@winglet/common-utils/hash';
5
6
  import { getRandomString, counterFactory } from '@winglet/common-utils/lib';
6
- import { styleManagerFactory, compressCss, destroyScope, dataCondition } from '@winglet/react-utils/style-manager';
7
+ import { compressCss } from '@winglet/style-utils/compressCss';
8
+ import { styleManagerFactory, destroyScope } from '@winglet/style-utils/styleManager';
7
9
  import { createPortal } from 'react-dom';
8
10
  import { map } from '@winglet/common-utils/array';
9
11
  import { withErrorBoundary } from '@winglet/react-utils/hoc';
12
+ import { cx } from '@winglet/style-utils/classNames';
10
13
  import { isString, isFunction } from '@winglet/common-utils/filter';
11
14
  import { renderComponent } from '@winglet/react-utils/render';
12
15
  import { printError } from '@winglet/common-utils/console';
@@ -20,13 +23,14 @@ class ModalManager {
20
23
  }
21
24
  static #anchor = null;
22
25
  static #scope = `promise-modal-${getRandomString(36)}`;
26
+ static #hash = polynomialHash(ModalManager.#scope);
23
27
  static anchor(options) {
24
28
  if (ModalManager.#anchor)
25
29
  return ModalManager.#anchor;
26
30
  const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
27
31
  const node = document.createElement(tag);
28
- node.setAttribute('id', `${prefix}-${getRandomString(36)}`);
29
- node.setAttribute('data-scope', ModalManager.#scope);
32
+ node.id = `${prefix}-${getRandomString(36)}`;
33
+ node.className = ModalManager.#scope;
30
34
  root.appendChild(node);
31
35
  ModalManager.#anchor = node;
32
36
  return node;
@@ -52,6 +56,9 @@ class ModalManager {
52
56
  for (const [styleId, css] of ModalManager.#styleSheetDefinition)
53
57
  ModalManager.#styleManager(styleId, css, true);
54
58
  }
59
+ static getHashedClassNames(styleId) {
60
+ return `${styleId}-${ModalManager.#hash}`;
61
+ }
55
62
  static reset() {
56
63
  ModalManager.#active = false;
57
64
  ModalManager.#anchor = null;
@@ -64,11 +71,12 @@ class ModalManager {
64
71
  }
65
72
  }
66
73
 
67
- const alert = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
74
+ const alert = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
68
75
  return new Promise((resolve, reject) => {
69
76
  try {
70
77
  ModalManager.open({
71
78
  type: 'alert',
79
+ group,
72
80
  subtype,
73
81
  resolve: () => resolve(),
74
82
  title,
@@ -89,11 +97,12 @@ const alert = ({ subtype, title, subtitle, content, background, footer, dimmed,
89
97
  });
90
98
  };
91
99
 
92
- const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
100
+ const confirm = ({ group, subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
93
101
  return new Promise((resolve, reject) => {
94
102
  try {
95
103
  ModalManager.open({
96
104
  type: 'confirm',
105
+ group,
97
106
  subtype,
98
107
  resolve: (result) => resolve(result ?? false),
99
108
  title,
@@ -114,11 +123,12 @@ const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed
114
123
  });
115
124
  };
116
125
 
117
- const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
126
+ const prompt = ({ group, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
118
127
  return new Promise((resolve, reject) => {
119
128
  try {
120
129
  ModalManager.open({
121
130
  type: 'prompt',
131
+ group,
122
132
  resolve: (result) => resolve(result),
123
133
  title,
124
134
  subtitle,
@@ -144,6 +154,7 @@ const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, retur
144
154
 
145
155
  class AbstractNode {
146
156
  id;
157
+ group;
147
158
  initiator;
148
159
  title;
149
160
  subtitle;
@@ -163,8 +174,9 @@ class AbstractNode {
163
174
  }
164
175
  #resolve;
165
176
  #listeners = new Set();
166
- constructor({ id, initiator, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
177
+ constructor({ id, initiator, group, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
167
178
  this.id = id;
179
+ this.group = group;
168
180
  this.initiator = initiator;
169
181
  this.title = title;
170
182
  this.subtitle = subtitle;
@@ -216,9 +228,10 @@ class AlertNode extends AbstractNode {
216
228
  subtype;
217
229
  content;
218
230
  footer;
219
- constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
231
+ constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
220
232
  super({
221
233
  id,
234
+ group,
222
235
  initiator,
223
236
  title,
224
237
  subtitle,
@@ -248,9 +261,10 @@ class ConfirmNode extends AbstractNode {
248
261
  subtype;
249
262
  content;
250
263
  footer;
251
- constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
264
+ constructor({ id, group, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
252
265
  super({
253
266
  id,
267
+ group,
254
268
  initiator,
255
269
  title,
256
270
  subtitle,
@@ -284,9 +298,10 @@ class PromptNode extends AbstractNode {
284
298
  returnOnCancel;
285
299
  footer;
286
300
  #value;
287
- constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
301
+ constructor({ id, group, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
288
302
  super({
289
303
  id,
304
+ group,
290
305
  initiator,
291
306
  title,
292
307
  subtitle,
@@ -365,7 +380,8 @@ const useActiveModalCount = (validate = defaultValidate, refreshKey = 0) => {
365
380
  const { modalIds, getModalNode } = useModalManagerContext();
366
381
  return useMemo(() => {
367
382
  let count = 0;
368
- for (const id of modalIds) {
383
+ for (let index = 0; index < modalIds.length; index++) {
384
+ const id = modalIds[index];
369
385
  if (validate(getModalNode(id)))
370
386
  count++;
371
387
  }
@@ -620,8 +636,11 @@ const usePathname = () => {
620
636
  return { pathname };
621
637
  };
622
638
 
639
+ const background = ModalManager.getHashedClassNames('background');
640
+ const active$1 = ModalManager.getHashedClassNames('background-active');
641
+ const visible$1 = ModalManager.getHashedClassNames('background-visible');
623
642
  const style$3 = `
624
- [data-background] {
643
+ .${background} {
625
644
  display: none;
626
645
  position: fixed;
627
646
  inset: 0;
@@ -629,22 +648,22 @@ const style$3 = `
629
648
  pointer-events: none;
630
649
  }
631
650
 
632
- [data-background] > * {
651
+ .${background} > * {
633
652
  pointer-events: none;
634
653
  }
635
654
 
636
- [data-background][data-active] {
655
+ .${background}.${active$1} {
637
656
  pointer-events: all;
638
657
  }
639
658
 
640
- [data-background][data-visible] {
659
+ .${background}.${visible$1} {
641
660
  display: flex;
642
661
  align-items: center;
643
662
  justify-content: center;
644
663
  }
645
664
  `;
646
-
647
665
  ModalManager.defineStyleSheet('background', style$3);
666
+
648
667
  const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
649
668
  const { BackgroundComponent } = useConfigurationContext();
650
669
  const { context: userDefinedContext } = useUserDefinedContext();
@@ -655,9 +674,15 @@ const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
655
674
  event.stopPropagation();
656
675
  }, [modal, onClose]);
657
676
  const Background = useMemo(() => modal?.BackgroundComponent || BackgroundComponent, [BackgroundComponent, modal]);
677
+ const className = useMemo(() => modal
678
+ ? cx(background, {
679
+ [active$1]: modal.closeOnBackdropClick && modal.visible,
680
+ [visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
681
+ })
682
+ : undefined, [modal]);
658
683
  if (!modal)
659
684
  return null;
660
- return (jsx("div", { "data-background": true, "data-active": dataCondition(modal.closeOnBackdropClick && modal.visible), "data-visible": dataCondition(modal.manualDestroy ? modal.alive : modal.visible), onClick: handleClose, children: Background && (jsx(Background, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext })) }));
685
+ return (jsx("div", { className: className, onClick: handleClose, children: Background && (jsx(Background, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext })) }));
661
686
  };
662
687
 
663
688
  const AlertInner = memo(({ modal, handlers }) => {
@@ -737,8 +762,11 @@ const PromptInner = memo(({ modal, handlers }) => {
737
762
  })) : (jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
738
763
  });
739
764
 
765
+ const foreground = ModalManager.getHashedClassNames('foreground');
766
+ const active = ModalManager.getHashedClassNames('foreground-active');
767
+ const visible = ModalManager.getHashedClassNames('foreground-visible');
740
768
  const style$2 = `
741
- [data-foreground] {
769
+ .${foreground} {
742
770
  pointer-events: none;
743
771
  display: none;
744
772
  position: fixed;
@@ -746,26 +774,32 @@ const style$2 = `
746
774
  z-index: 1;
747
775
  }
748
776
 
749
- [data-foreground][data-active] > * {
777
+ .${foreground}.${active} > * {
750
778
  pointer-events: all;
751
779
  }
752
780
 
753
- [data-foreground][data-visible] {
781
+ .${foreground}.${visible} {
754
782
  display: flex !important;
755
783
  justify-content: center;
756
784
  align-items: center;
757
785
  }
758
786
  `;
759
-
760
787
  ModalManager.defineStyleSheet('foreground', style$2);
788
+
761
789
  const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
762
790
  const { ForegroundComponent } = useConfigurationContext();
763
791
  const { context: userDefinedContext } = useUserDefinedContext();
764
792
  const { modal, onChange, onConfirm, onClose, onDestroy } = useModal(modalId);
765
793
  const Foreground = useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
794
+ const className = useMemo(() => modal
795
+ ? cx(foreground, {
796
+ [active]: modal.visible,
797
+ [visible]: modal.manualDestroy ? modal.alive : modal.visible,
798
+ })
799
+ : undefined, [modal]);
766
800
  if (!modal)
767
801
  return null;
768
- return (jsx("div", { "data-foreground": true, "data-active": dataCondition(modal.visible), "data-visible": dataCondition(modal.manualDestroy ? modal.alive : modal.visible), children: jsxs(Foreground, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext, children: [modal.type === 'alert' && (jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
802
+ return (jsx("div", { className: className, children: jsxs(Foreground, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext, children: [modal.type === 'alert' && (jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
769
803
  };
770
804
 
771
805
  const useSubscribeModal = (modal) => {
@@ -779,15 +813,16 @@ const useSubscribeModal = (modal) => {
779
813
  return version;
780
814
  };
781
815
 
816
+ const presenter = ModalManager.getHashedClassNames('presenter');
782
817
  const style$1 = `
783
- [data-presenter] {
818
+ .${presenter} {
784
819
  position: fixed;
785
820
  inset: 0;
786
821
  pointer-events: none;
787
822
  overflow: hidden;
788
823
  `;
789
-
790
824
  ModalManager.defineStyleSheet('presenter', style$1);
825
+
791
826
  const { increment } = counterFactory(1);
792
827
  const Presenter = memo(({ modalId }) => {
793
828
  const ref = useRef(null);
@@ -798,11 +833,12 @@ const Presenter = memo(({ modalId }) => {
798
833
  ref.current.style.zIndex = `${increment()}`;
799
834
  }
800
835
  });
801
- return (jsxs("div", { ref: ref, "data-presenter": true, children: [jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
836
+ return (jsxs("div", { ref: ref, className: presenter, children: [jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
802
837
  });
803
838
 
839
+ const anchor = ModalManager.getHashedClassNames('anchor');
804
840
  const style = `
805
- [data-anchor] {
841
+ .${anchor} {
806
842
  display: flex;
807
843
  align-items: center;
808
844
  justify-content: center;
@@ -812,8 +848,8 @@ const style = `
812
848
  z-index: 1000;
813
849
  transition: background-color ease-in-out;
814
850
  }`;
815
-
816
851
  ModalManager.defineStyleSheet('anchor', style);
852
+
817
853
  const AnchorInner = () => {
818
854
  const [version, update] = useVersion();
819
855
  const { modalIds, setUpdater } = useModalManagerContext();
@@ -822,7 +858,7 @@ const AnchorInner = () => {
822
858
  }, [setUpdater, update]);
823
859
  const options = useConfigurationOptions();
824
860
  const dimmed = useActiveModalCount(validateDimmable, version);
825
- return (jsx("div", { "data-anchor": true, style: {
861
+ return (jsx("div", { className: anchor, style: {
826
862
  transitionDuration: options.duration,
827
863
  backgroundColor: dimmed ? options.backdrop : 'transparent',
828
864
  }, children: map(modalIds, (id) => (jsx(Presenter, { modalId: id }, id))) }));
@@ -3,6 +3,7 @@ import type { Dictionary } from '../@aileron/declare';
3
3
  import type { ModalBackground } from './background';
4
4
  import type { ModalFrameProps } from './modal';
5
5
  export interface BaseModal<T, B> {
6
+ group?: string;
6
7
  title?: ReactNode;
7
8
  subtitle?: ReactNode;
8
9
  background?: ModalBackground<B>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lerx/promise-modal",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Universal React modal utility that can be used outside React components with promise-based results for alert, confirm, and prompt modals",
5
5
  "keywords": [
6
6
  "react",
@@ -65,8 +65,9 @@
65
65
  "version:patch": "yarn version patch"
66
66
  },
67
67
  "dependencies": {
68
- "@winglet/common-utils": "^0.2.1",
69
- "@winglet/react-utils": "^0.2.2"
68
+ "@winglet/common-utils": "^0.2.2",
69
+ "@winglet/react-utils": "^0.2.4",
70
+ "@winglet/style-utils": "^0.2.1"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@chromatic-com/storybook": "^3.2.6",