@particle-network/ui-react 0.7.0-beta.14 → 0.7.0-beta.15
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/dist/components/UXSimplePopover/index.d.ts +1 -0
- package/dist/components/UXSimplePopover/index.js +1 -0
- package/dist/components/UXSimplePopover/provider.d.ts +22 -0
- package/dist/components/UXSimplePopover/provider.js +197 -0
- package/dist/components/UXSimplePopover/simple-popover.d.ts +5 -2
- package/dist/components/UXSimplePopover/simple-popover.js +74 -122
- package/package.json +3 -3
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SimplePopoverPlacement, SimplePopoverSize } from './simple-popover';
|
|
3
|
+
export interface TriggerOptions {
|
|
4
|
+
placement?: SimplePopoverPlacement;
|
|
5
|
+
size?: SimplePopoverSize;
|
|
6
|
+
offset?: number;
|
|
7
|
+
delay?: number;
|
|
8
|
+
closeDelay?: number;
|
|
9
|
+
contentClassName?: string;
|
|
10
|
+
}
|
|
11
|
+
interface SimplePopoverCtx {
|
|
12
|
+
show: (anchor: HTMLElement, content: React.ReactNode, options?: TriggerOptions) => void;
|
|
13
|
+
hide: (closeDelay?: number) => void;
|
|
14
|
+
prepare: (anchor: HTMLElement, content: React.ReactNode, options?: TriggerOptions) => void;
|
|
15
|
+
toggle: () => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function useSimplePopoverContext(): SimplePopoverCtx | null;
|
|
18
|
+
export interface UXSimplePopoverProviderProps {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export declare const UXSimplePopoverProvider: React.FC<UXSimplePopoverProviderProps>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import react, { createContext, useCallback, useContext, useEffect, useId, useRef, useState } from "react";
|
|
4
|
+
import { tv } from "@heroui/theme";
|
|
5
|
+
import { cn } from "../../utils/index.js";
|
|
6
|
+
const popoverVariants = tv({
|
|
7
|
+
base: 'bg-content1 text-foreground-300 shadow-box text-tiny leading-1.4 rounded-medium max-w-[300px] break-words wrap-break-word antialiased',
|
|
8
|
+
variants: {
|
|
9
|
+
size: {
|
|
10
|
+
sm: 'p-1.5',
|
|
11
|
+
md: 'p-2.5',
|
|
12
|
+
lg: 'p-3.5'
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
size: 'md'
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const PopoverContext = /*#__PURE__*/ createContext(null);
|
|
20
|
+
function useSimplePopoverContext() {
|
|
21
|
+
return useContext(PopoverContext);
|
|
22
|
+
}
|
|
23
|
+
const OFFSET_MARGIN = {
|
|
24
|
+
top: {
|
|
25
|
+
marginBottom: 8
|
|
26
|
+
},
|
|
27
|
+
bottom: {
|
|
28
|
+
marginTop: 8
|
|
29
|
+
},
|
|
30
|
+
left: {
|
|
31
|
+
marginRight: 8
|
|
32
|
+
},
|
|
33
|
+
right: {
|
|
34
|
+
marginLeft: 8
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const MARGIN_SIDE_MAP = {
|
|
38
|
+
top: 'Bottom',
|
|
39
|
+
bottom: 'Top',
|
|
40
|
+
left: 'Right',
|
|
41
|
+
right: 'Left'
|
|
42
|
+
};
|
|
43
|
+
const UXSimplePopoverProvider = ({ children })=>{
|
|
44
|
+
const uid = useId().replace(/:/g, '');
|
|
45
|
+
const popoverRef = useRef(null);
|
|
46
|
+
const openTimerRef = useRef(null);
|
|
47
|
+
const closeTimerRef = useRef(null);
|
|
48
|
+
const triggerModeRef = useRef('hover');
|
|
49
|
+
const currentAnchorRef = useRef(null);
|
|
50
|
+
const [content, setContent] = useState(null);
|
|
51
|
+
const [anchorStyle, setAnchorStyle] = useState({});
|
|
52
|
+
const [contentClassName, setContentClassName] = useState(void 0);
|
|
53
|
+
const [size, setSize] = useState('md');
|
|
54
|
+
const clearTimers = useCallback(()=>{
|
|
55
|
+
if (null !== openTimerRef.current) {
|
|
56
|
+
clearTimeout(openTimerRef.current);
|
|
57
|
+
openTimerRef.current = null;
|
|
58
|
+
}
|
|
59
|
+
if (null !== closeTimerRef.current) {
|
|
60
|
+
clearTimeout(closeTimerRef.current);
|
|
61
|
+
closeTimerRef.current = null;
|
|
62
|
+
}
|
|
63
|
+
}, []);
|
|
64
|
+
const resolveAnchorName = useCallback((anchor)=>{
|
|
65
|
+
if (!anchor.style.getPropertyValue('anchor-name')) anchor.style.setProperty('anchor-name', `--sp-${uid}-${Math.random().toString(36).slice(2, 8)}`);
|
|
66
|
+
return anchor.style.getPropertyValue('anchor-name');
|
|
67
|
+
}, [
|
|
68
|
+
uid
|
|
69
|
+
]);
|
|
70
|
+
const computeAnchorStyle = useCallback((anchorName, options)=>{
|
|
71
|
+
const { placement = 'top', offset = 8 } = options;
|
|
72
|
+
const primarySide = placement.split('-')[0];
|
|
73
|
+
const marginSide = MARGIN_SIDE_MAP[primarySide] ?? 'Bottom';
|
|
74
|
+
const offsetStyle = 8 !== offset ? {
|
|
75
|
+
[`margin${marginSide}`]: offset
|
|
76
|
+
} : OFFSET_MARGIN[primarySide];
|
|
77
|
+
return {
|
|
78
|
+
positionAnchor: anchorName,
|
|
79
|
+
positionArea: placement.replace(/-/g, ' '),
|
|
80
|
+
positionTryFallbacks: 'flip-block, flip-inline, flip-block flip-inline',
|
|
81
|
+
...offsetStyle
|
|
82
|
+
};
|
|
83
|
+
}, []);
|
|
84
|
+
const show = useCallback((anchor, node, options)=>{
|
|
85
|
+
const opts = options ?? {};
|
|
86
|
+
const delay = opts.delay ?? 300;
|
|
87
|
+
clearTimers();
|
|
88
|
+
triggerModeRef.current = 'hover';
|
|
89
|
+
const anchorName = resolveAnchorName(anchor);
|
|
90
|
+
setContent(node);
|
|
91
|
+
setContentClassName(opts.contentClassName);
|
|
92
|
+
setSize(opts.size ?? 'md');
|
|
93
|
+
setAnchorStyle(computeAnchorStyle(anchorName, opts));
|
|
94
|
+
openTimerRef.current = setTimeout(()=>{
|
|
95
|
+
openTimerRef.current = null;
|
|
96
|
+
popoverRef.current?.showPopover();
|
|
97
|
+
}, delay);
|
|
98
|
+
}, [
|
|
99
|
+
clearTimers,
|
|
100
|
+
resolveAnchorName,
|
|
101
|
+
computeAnchorStyle
|
|
102
|
+
]);
|
|
103
|
+
const hide = useCallback((closeDelay)=>{
|
|
104
|
+
const cd = closeDelay ?? 100;
|
|
105
|
+
clearTimers();
|
|
106
|
+
closeTimerRef.current = setTimeout(()=>{
|
|
107
|
+
closeTimerRef.current = null;
|
|
108
|
+
popoverRef.current?.hidePopover();
|
|
109
|
+
}, cd);
|
|
110
|
+
}, [
|
|
111
|
+
clearTimers
|
|
112
|
+
]);
|
|
113
|
+
const prepare = useCallback((anchor, node, options)=>{
|
|
114
|
+
const opts = options ?? {};
|
|
115
|
+
clearTimers();
|
|
116
|
+
triggerModeRef.current = 'click';
|
|
117
|
+
currentAnchorRef.current = anchor;
|
|
118
|
+
const anchorName = resolveAnchorName(anchor);
|
|
119
|
+
setContent(node);
|
|
120
|
+
setContentClassName(opts.contentClassName);
|
|
121
|
+
setSize(opts.size ?? 'md');
|
|
122
|
+
setAnchorStyle(computeAnchorStyle(anchorName, opts));
|
|
123
|
+
}, [
|
|
124
|
+
clearTimers,
|
|
125
|
+
resolveAnchorName,
|
|
126
|
+
computeAnchorStyle
|
|
127
|
+
]);
|
|
128
|
+
const toggle = useCallback(()=>{
|
|
129
|
+
const el = popoverRef.current;
|
|
130
|
+
if (!el) return;
|
|
131
|
+
try {
|
|
132
|
+
if (el.matches(':popover-open')) el.hidePopover();
|
|
133
|
+
else el.showPopover();
|
|
134
|
+
} catch {}
|
|
135
|
+
}, []);
|
|
136
|
+
useEffect(()=>{
|
|
137
|
+
const handlePointerDown = (e)=>{
|
|
138
|
+
const el = popoverRef.current;
|
|
139
|
+
if (!el || 'click' !== triggerModeRef.current) return;
|
|
140
|
+
try {
|
|
141
|
+
if (!el.matches(':popover-open')) return;
|
|
142
|
+
} catch {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const target = e.target;
|
|
146
|
+
if (!el.contains(target) && !currentAnchorRef.current?.contains(target)) el.hidePopover();
|
|
147
|
+
};
|
|
148
|
+
document.addEventListener('pointerdown', handlePointerDown);
|
|
149
|
+
return ()=>document.removeEventListener('pointerdown', handlePointerDown);
|
|
150
|
+
}, []);
|
|
151
|
+
useEffect(()=>()=>{
|
|
152
|
+
clearTimers();
|
|
153
|
+
}, [
|
|
154
|
+
clearTimers
|
|
155
|
+
]);
|
|
156
|
+
const ctx = react.useMemo(()=>({
|
|
157
|
+
show,
|
|
158
|
+
hide,
|
|
159
|
+
prepare,
|
|
160
|
+
toggle
|
|
161
|
+
}), [
|
|
162
|
+
show,
|
|
163
|
+
hide,
|
|
164
|
+
prepare,
|
|
165
|
+
toggle
|
|
166
|
+
]);
|
|
167
|
+
const handlePopoverMouseEnter = useCallback(()=>{
|
|
168
|
+
if ('hover' === triggerModeRef.current) clearTimers();
|
|
169
|
+
}, [
|
|
170
|
+
clearTimers
|
|
171
|
+
]);
|
|
172
|
+
const handlePopoverMouseLeave = useCallback(()=>{
|
|
173
|
+
if ('hover' === triggerModeRef.current) hide();
|
|
174
|
+
}, [
|
|
175
|
+
hide
|
|
176
|
+
]);
|
|
177
|
+
return /*#__PURE__*/ jsxs(PopoverContext.Provider, {
|
|
178
|
+
value: ctx,
|
|
179
|
+
children: [
|
|
180
|
+
children,
|
|
181
|
+
/*#__PURE__*/ jsx("div", {
|
|
182
|
+
ref: popoverRef,
|
|
183
|
+
id: `ux-sp-${uid}`,
|
|
184
|
+
popover: "manual",
|
|
185
|
+
className: cn(popoverVariants({
|
|
186
|
+
size
|
|
187
|
+
}), contentClassName),
|
|
188
|
+
style: anchorStyle,
|
|
189
|
+
onMouseEnter: handlePopoverMouseEnter,
|
|
190
|
+
onMouseLeave: handlePopoverMouseLeave,
|
|
191
|
+
children: content
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
UXSimplePopoverProvider.displayName = 'UX.SimplePopoverProvider';
|
|
197
|
+
export { UXSimplePopoverProvider, useSimplePopoverContext };
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export type SimplePopoverPlacement = 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'left' | 'left-top' | 'left-bottom' | 'right' | 'right-top' | 'right-bottom';
|
|
3
3
|
export type SimplePopoverTriggerType = 'click' | 'hover';
|
|
4
|
+
export type SimplePopoverSize = 'sm' | 'md' | 'lg';
|
|
4
5
|
export interface UXSimplePopoverProps {
|
|
5
6
|
/** Popover content */
|
|
6
7
|
content: React.ReactNode;
|
|
7
8
|
/** Trigger element(s) */
|
|
8
9
|
children: React.ReactNode;
|
|
9
|
-
/** How to open: click
|
|
10
|
+
/** How to open: click or hover */
|
|
10
11
|
triggerType?: SimplePopoverTriggerType;
|
|
11
12
|
/** Placement relative to trigger; uses CSS Anchor Positioning when supported */
|
|
12
13
|
placement?: SimplePopoverPlacement;
|
|
14
|
+
/** Popover padding size */
|
|
15
|
+
size?: SimplePopoverSize;
|
|
13
16
|
/** Hover only: delay before opening (ms) */
|
|
14
17
|
delay?: number;
|
|
15
18
|
/** Hover only: delay before closing (ms) */
|
|
16
19
|
closeDelay?: number;
|
|
17
20
|
/** Distance between popover and trigger (px) */
|
|
18
21
|
offset?: number;
|
|
19
|
-
/** ClassName for the trigger wrapper
|
|
22
|
+
/** ClassName for the trigger wrapper and popover content */
|
|
20
23
|
classNames?: {
|
|
21
24
|
trigger?: string;
|
|
22
25
|
content?: string;
|
|
@@ -1,132 +1,84 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
closeTimerRef.current = null;
|
|
25
|
-
}
|
|
26
|
-
}, []);
|
|
27
|
-
const showPopover = useCallback(()=>{
|
|
28
|
-
clearCloseTimer();
|
|
29
|
-
openTimerRef.current = setTimeout(()=>{
|
|
30
|
-
openTimerRef.current = null;
|
|
31
|
-
popoverRef.current?.showPopover();
|
|
32
|
-
}, delay);
|
|
33
|
-
}, [
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useRef } from "react";
|
|
3
|
+
import { useSimplePopoverContext } from "./provider.js";
|
|
4
|
+
const warnedRef = {
|
|
5
|
+
current: false
|
|
6
|
+
};
|
|
7
|
+
const UXSimplePopover = ({ content, children, triggerType = 'hover', placement = 'top', size = 'md', offset = 8, delay = 300, closeDelay = 100, classNames })=>{
|
|
8
|
+
const ctx = useSimplePopoverContext();
|
|
9
|
+
const ref = useRef(null);
|
|
10
|
+
const contentRef = useRef(content);
|
|
11
|
+
contentRef.current = content;
|
|
12
|
+
const optionsRef = useRef({
|
|
13
|
+
placement,
|
|
14
|
+
size,
|
|
15
|
+
offset,
|
|
16
|
+
delay,
|
|
17
|
+
closeDelay,
|
|
18
|
+
contentClassName: classNames?.content
|
|
19
|
+
});
|
|
20
|
+
optionsRef.current = {
|
|
21
|
+
placement,
|
|
22
|
+
size,
|
|
23
|
+
offset,
|
|
34
24
|
delay,
|
|
35
|
-
|
|
25
|
+
closeDelay,
|
|
26
|
+
contentClassName: classNames?.content
|
|
27
|
+
};
|
|
28
|
+
const isClick = 'click' === triggerType;
|
|
29
|
+
const handleEnter = useCallback(()=>{
|
|
30
|
+
if (ref.current && ctx && !isClick) ctx.show(ref.current, contentRef.current, optionsRef.current);
|
|
31
|
+
}, [
|
|
32
|
+
ctx,
|
|
33
|
+
isClick
|
|
36
34
|
]);
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
closeTimerRef.current = setTimeout(()=>{
|
|
40
|
-
closeTimerRef.current = null;
|
|
41
|
-
popoverRef.current?.hidePopover();
|
|
42
|
-
}, closeDelay);
|
|
35
|
+
const handleLeave = useCallback(()=>{
|
|
36
|
+
if (ctx && !isClick) ctx.hide(optionsRef.current.closeDelay);
|
|
43
37
|
}, [
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
ctx,
|
|
39
|
+
isClick
|
|
46
40
|
]);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
clearCloseTimer
|
|
41
|
+
const handlePointerDown = useCallback(()=>{
|
|
42
|
+
if (ref.current && ctx && isClick) ctx.prepare(ref.current, contentRef.current, optionsRef.current);
|
|
43
|
+
}, [
|
|
44
|
+
ctx,
|
|
45
|
+
isClick
|
|
53
46
|
]);
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
right: {
|
|
68
|
-
marginLeft: offset
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
const primarySide = placement.split('-')[0];
|
|
72
|
-
const popoverAnchorStyle = {
|
|
73
|
-
positionAnchor: anchorName,
|
|
74
|
-
positionArea: placement.replace(/-/g, ' '),
|
|
75
|
-
positionTryFallbacks: 'flip-block, flip-inline, flip-block flip-inline',
|
|
76
|
-
...offsetMargin[primarySide]
|
|
77
|
-
};
|
|
78
|
-
const isClick = 'click' === triggerType;
|
|
79
|
-
const trigger = isClick ? /*#__PURE__*/ jsx("button", {
|
|
80
|
-
type: "button",
|
|
81
|
-
popoverTarget: popoverId,
|
|
82
|
-
popoverTargetAction: "toggle",
|
|
83
|
-
className: classNames.trigger,
|
|
84
|
-
style: {
|
|
85
|
-
margin: 0,
|
|
86
|
-
padding: 0,
|
|
87
|
-
border: 'none',
|
|
88
|
-
font: 'inherit',
|
|
89
|
-
color: 'inherit',
|
|
90
|
-
backgroundColor: 'transparent',
|
|
91
|
-
cursor: 'pointer',
|
|
92
|
-
...triggerAnchorStyle
|
|
93
|
-
},
|
|
94
|
-
children: children
|
|
95
|
-
}) : (()=>{
|
|
96
|
-
const childElement = /*#__PURE__*/ isValidElement(children) && 1 === react.Children.count(children) ? children : null;
|
|
97
|
-
return childElement ? /*#__PURE__*/ cloneElement(childElement, {
|
|
98
|
-
onMouseEnter: showPopover,
|
|
99
|
-
onMouseLeave: hidePopover,
|
|
100
|
-
className: [
|
|
101
|
-
classNames.trigger,
|
|
102
|
-
childElement.props?.className
|
|
103
|
-
].filter(Boolean).join(' '),
|
|
104
|
-
style: {
|
|
105
|
-
...childElement.props?.style,
|
|
106
|
-
...triggerAnchorStyle
|
|
47
|
+
const handleClick = useCallback(()=>{
|
|
48
|
+
if (ctx && isClick) ctx.toggle();
|
|
49
|
+
}, [
|
|
50
|
+
ctx,
|
|
51
|
+
isClick
|
|
52
|
+
]);
|
|
53
|
+
const handleKeyDown = useCallback((e)=>{
|
|
54
|
+
if (isClick && ('Enter' === e.key || ' ' === e.key)) {
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
if (ref.current && ctx) {
|
|
57
|
+
ctx.prepare(ref.current, contentRef.current, optionsRef.current);
|
|
58
|
+
ctx.toggle();
|
|
107
59
|
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
60
|
+
}
|
|
61
|
+
}, [
|
|
62
|
+
ctx,
|
|
63
|
+
isClick
|
|
64
|
+
]);
|
|
65
|
+
if (!ctx && !warnedRef.current) {
|
|
66
|
+
warnedRef.current = true;
|
|
67
|
+
console.warn('[UXSimplePopover] must be used inside <UXSimplePopoverProvider>. Popover will not work.');
|
|
68
|
+
}
|
|
69
|
+
return /*#__PURE__*/ jsx("span", {
|
|
70
|
+
ref: ref,
|
|
71
|
+
className: classNames?.trigger,
|
|
72
|
+
onMouseEnter: handleEnter,
|
|
73
|
+
onMouseLeave: handleLeave,
|
|
74
|
+
...isClick ? {
|
|
75
|
+
role: 'button',
|
|
112
76
|
tabIndex: 0,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return /*#__PURE__*/ jsxs(Fragment, {
|
|
119
|
-
children: [
|
|
120
|
-
trigger,
|
|
121
|
-
/*#__PURE__*/ jsx("div", {
|
|
122
|
-
ref: popoverRef,
|
|
123
|
-
id: popoverId,
|
|
124
|
-
popover: isClick ? 'auto' : 'manual',
|
|
125
|
-
className: cn('bg-content1 text-foreground-300 shadow-box text-tiny leading-1.4 rounded-medium max-w-[300px] p-2.5 break-words wrap-break-word antialiased', classNames.content),
|
|
126
|
-
style: popoverAnchorStyle,
|
|
127
|
-
children: content
|
|
128
|
-
})
|
|
129
|
-
]
|
|
77
|
+
onPointerDownCapture: handlePointerDown,
|
|
78
|
+
onClickCapture: handleClick,
|
|
79
|
+
onKeyDown: handleKeyDown
|
|
80
|
+
} : {},
|
|
81
|
+
children: children
|
|
130
82
|
});
|
|
131
83
|
};
|
|
132
84
|
UXSimplePopover.displayName = 'UXSimplePopover';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-network/ui-react",
|
|
3
|
-
"version": "0.7.0-beta.
|
|
3
|
+
"version": "0.7.0-beta.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@rslib/core": "^0.12.3",
|
|
38
38
|
"@types/react": "^19.1.10",
|
|
39
39
|
"react": "^19.1.0",
|
|
40
|
-
"@particle-network/
|
|
41
|
-
"@particle-network/
|
|
40
|
+
"@particle-network/eslint-config": "0.3.0",
|
|
41
|
+
"@particle-network/lintstaged-config": "0.1.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"react": ">=16.9.0",
|