@a-type/ui 0.3.1 → 0.3.3
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/cjs/components/button/Button.js +6 -1
- package/dist/cjs/components/button/Button.js.map +1 -1
- package/dist/cjs/components/camera/Camera.d.ts +1 -0
- package/dist/cjs/components/camera/Camera.js +24 -18
- package/dist/cjs/components/camera/Camera.js.map +1 -1
- package/dist/cjs/components/icon/generated/IconSpritesheet.js +1 -1
- package/dist/cjs/components/icon/generated/IconSpritesheet.js.map +1 -1
- package/dist/cjs/components/icon/generated/iconNames.d.ts +1 -1
- package/dist/cjs/components/icon/generated/iconNames.js +10 -0
- package/dist/cjs/components/icon/generated/iconNames.js.map +1 -1
- package/dist/cjs/components/imageUploader/ImageUploader.js +28 -2
- package/dist/cjs/components/imageUploader/ImageUploader.js.map +1 -1
- package/dist/cjs/components/imageUploader/ImageUploader.stories.d.ts +22 -0
- package/dist/cjs/components/imageUploader/ImageUploader.stories.js +28 -0
- package/dist/cjs/components/imageUploader/ImageUploader.stories.js.map +1 -0
- package/dist/esm/components/button/Button.js +6 -1
- package/dist/esm/components/button/Button.js.map +1 -1
- package/dist/esm/components/camera/Camera.d.ts +1 -0
- package/dist/esm/components/camera/Camera.js +24 -18
- package/dist/esm/components/camera/Camera.js.map +1 -1
- package/dist/esm/components/icon/generated/IconSpritesheet.js +1 -1
- package/dist/esm/components/icon/generated/IconSpritesheet.js.map +1 -1
- package/dist/esm/components/icon/generated/iconNames.d.ts +1 -1
- package/dist/esm/components/icon/generated/iconNames.js +10 -0
- package/dist/esm/components/icon/generated/iconNames.js.map +1 -1
- package/dist/esm/components/imageUploader/ImageUploader.js +29 -3
- package/dist/esm/components/imageUploader/ImageUploader.js.map +1 -1
- package/dist/esm/components/imageUploader/ImageUploader.stories.d.ts +22 -0
- package/dist/esm/components/imageUploader/ImageUploader.stories.js +25 -0
- package/dist/esm/components/imageUploader/ImageUploader.stories.js.map +1 -0
- package/package.json +3 -2
- package/src/components/actions/ActionBar.tsx +38 -0
- package/src/components/actions/ActionButton.tsx +59 -0
- package/src/components/actions/index.ts +2 -0
- package/src/components/actions.ts +1 -0
- package/src/components/avatar/Avatar.tsx +62 -0
- package/src/components/avatar/AvatarList.tsx +71 -0
- package/src/components/avatar/index.ts +2 -0
- package/src/components/avatar.ts +1 -0
- package/src/components/button/Button.stories.tsx +20 -0
- package/src/components/button/Button.tsx +66 -0
- package/src/components/button/ConfirmedButton.tsx +66 -0
- package/src/components/button/classes.tsx +56 -0
- package/src/components/button/index.ts +3 -0
- package/src/components/button.ts +1 -0
- package/src/components/camera/Camera.stories.tsx +40 -0
- package/src/components/camera/Camera.tsx +215 -0
- package/src/components/camera/index.ts +1 -0
- package/src/components/camera.ts +1 -0
- package/src/components/card/Card.stories.tsx +41 -0
- package/src/components/card/Card.tsx +68 -0
- package/src/components/card/index.ts +1 -0
- package/src/components/card.ts +1 -0
- package/src/components/checkbox/Checkbox.tsx +46 -0
- package/src/components/checkbox/index.ts +1 -0
- package/src/components/checkbox.ts +1 -0
- package/src/components/chip/Chip.tsx +29 -0
- package/src/components/chip/index.ts +1 -0
- package/src/components/chip.ts +1 -0
- package/src/components/collapsible/Collapsible.tsx +48 -0
- package/src/components/collapsible/index.ts +1 -0
- package/src/components/collapsible.ts +1 -0
- package/src/components/colorPicker/ColorPicker.tsx +82 -0
- package/src/components/colorPicker/index.ts +1 -0
- package/src/components/colorPicker.ts +1 -0
- package/src/components/contextMenu/contextMenu.tsx +43 -0
- package/src/components/contextMenu.ts +1 -0
- package/src/components/dialog/Dialog.stories.tsx +38 -0
- package/src/components/dialog/Dialog.tsx +267 -0
- package/src/components/dialog/index.ts +1 -0
- package/src/components/dialog.ts +1 -0
- package/src/components/divider/Divider.tsx +26 -0
- package/src/components/divider/index.ts +1 -0
- package/src/components/divider.ts +1 -0
- package/src/components/dropdownMenu/DropdownMenu.stories.tsx +47 -0
- package/src/components/dropdownMenu/DropdownMenu.tsx +89 -0
- package/src/components/dropdownMenu/index.ts +1 -0
- package/src/components/dropdownMenu.ts +1 -0
- package/src/components/errorBoundary/ErrorBoundary.tsx +23 -0
- package/src/components/errorBoundary/index.ts +1 -0
- package/src/components/errorBoundary.ts +1 -0
- package/src/components/forms/Form.tsx +9 -0
- package/src/components/forms/FormikForm.tsx +41 -0
- package/src/components/forms/SubmitButton.tsx +15 -0
- package/src/components/forms/TextField.tsx +112 -0
- package/src/components/forms/index.tsx +4 -0
- package/src/components/forms.ts +1 -0
- package/src/components/icon/Icon.tsx +28 -0
- package/src/components/icon/generated/IconSpritesheet.tsx +442 -0
- package/src/components/icon/generated/iconNames.ts +44 -0
- package/src/components/icon/index.ts +3 -0
- package/src/components/icon.ts +1 -0
- package/src/components/imageUploader/ImageUploader.stories.tsx +39 -0
- package/src/components/imageUploader/ImageUploader.tsx +203 -0
- package/src/components/imageUploader/UploadIcon.tsx +23 -0
- package/src/components/imageUploader/index.ts +1 -0
- package/src/components/imageUploader.ts +1 -0
- package/src/components/infiniteLoadTrigger/InfiniteLoadTrigger.tsx +38 -0
- package/src/components/infiniteLoadTrigger.ts +1 -0
- package/src/components/input/Input.stories.tsx +17 -0
- package/src/components/input/Input.tsx +32 -0
- package/src/components/input/index.ts +1 -0
- package/src/components/input.ts +1 -0
- package/src/components/layouts/PageContent.tsx +51 -0
- package/src/components/layouts/PageFixedArea.tsx +17 -0
- package/src/components/layouts/PageNav.tsx +23 -0
- package/src/components/layouts/PageNowPlaying.tsx +24 -0
- package/src/components/layouts/PageRoot.tsx +29 -0
- package/src/components/layouts/PageSection.tsx +23 -0
- package/src/components/layouts/index.tsx +6 -0
- package/src/components/layouts.ts +1 -0
- package/src/components/liveUpdateTextField/LiveUpdateTextField.tsx +132 -0
- package/src/components/liveUpdateTextField/index.ts +1 -0
- package/src/components/liveUpdateTextField.ts +1 -0
- package/src/components/navBar/NavBar.tsx +59 -0
- package/src/components/navBar/index.ts +1 -0
- package/src/components/navBar.ts +1 -0
- package/src/components/note/Note.tsx +21 -0
- package/src/components/note/index.ts +1 -0
- package/src/components/note.ts +1 -0
- package/src/components/numberStepper/NumberStepper.stories.tsx +21 -0
- package/src/components/numberStepper/NumberStepper.tsx +74 -0
- package/src/components/numberStepper/index.ts +1 -0
- package/src/components/numberStepper.ts +1 -0
- package/src/components/particles/ParticleContext.tsx +11 -0
- package/src/components/particles/ParticleLayer.stories.tsx +46 -0
- package/src/components/particles/ParticleLayer.tsx +28 -0
- package/src/components/particles/index.ts +7 -0
- package/src/components/particles/particlesState.ts +502 -0
- package/src/components/particles.ts +1 -0
- package/src/components/peek/Peek.tsx +74 -0
- package/src/components/peek/index.ts +1 -0
- package/src/components/peek.ts +1 -0
- package/src/components/popover/Popover.tsx +84 -0
- package/src/components/popover/index.ts +1 -0
- package/src/components/popover.ts +1 -0
- package/src/components/relativeTime/RelativeTime.tsx +43 -0
- package/src/components/relativeTime/index.ts +1 -0
- package/src/components/relativeTime.ts +1 -0
- package/src/components/richEditor/EditorContent.tsx +4 -0
- package/src/components/richEditor/RichEditor.tsx +38 -0
- package/src/components/richEditor/index.ts +1 -0
- package/src/components/richEditor.ts +1 -0
- package/src/components/select/Select.tsx +247 -0
- package/src/components/select/index.ts +1 -0
- package/src/components/select.ts +1 -0
- package/src/components/skeletons/skeletons.tsx +27 -0
- package/src/components/skeletons.ts +1 -0
- package/src/components/spinner/Spinner.tsx +59 -0
- package/src/components/spinner/index.ts +1 -0
- package/src/components/spinner.ts +1 -0
- package/src/components/switch/Switch.tsx +23 -0
- package/src/components/switch/index.ts +1 -0
- package/src/components/switch.ts +1 -0
- package/src/components/tabs/tabs.tsx +18 -0
- package/src/components/tabs.ts +1 -0
- package/src/components/textArea/TextArea.stories.tsx +21 -0
- package/src/components/textArea/TextArea.tsx +58 -0
- package/src/components/textArea/index.ts +1 -0
- package/src/components/textArea.ts +1 -0
- package/src/components/toggleGroup/toggleGroup.tsx +11 -0
- package/src/components/toggleGroup.ts +1 -0
- package/src/components/tooltip/Tooltip.tsx +56 -0
- package/src/components/tooltip/index.ts +1 -0
- package/src/components/tooltip.ts +1 -0
- package/src/components/typography/index.ts +1 -0
- package/src/components/typography/typography.tsx +18 -0
- package/src/components/typography.ts +1 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useMergedRef.ts +14 -0
- package/src/hooks/useOnUnmount.ts +20 -0
- package/src/hooks/useSize.ts +164 -0
- package/src/hooks/useStableCallback.ts +11 -0
- package/src/hooks/useToggle.tsx +9 -0
- package/src/hooks/useVisualViewportOffset.ts +35 -0
- package/src/hooks/withClassName.tsx +21 -0
- package/src/hooks.ts +1 -0
- package/src/uno.preset.ts +767 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { withClassName } from '../../hooks.js';
|
|
3
|
+
import { ReactNode, forwardRef } from 'react';
|
|
4
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
5
|
+
|
|
6
|
+
export const navBarItemClass = classNames(
|
|
7
|
+
'layer-components:(flex flex-col items-center justify-center whitespace-nowrap py-1 px-3 bg-transparent rounded-md border-none cursor-pointer text-sm transition-colors h-full gap-6px relative text-inherit)',
|
|
8
|
+
'layer-components:sm:(flex-row-reverse h-auto justify-start gap-2 overflow-visible)',
|
|
9
|
+
'layer-components:hover:bg-primaryWash',
|
|
10
|
+
'layer-components:focus-visible:(outline-none bg-primaryWash)',
|
|
11
|
+
'layer-components:active:bg-primaryWash',
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export interface NavBarItemProps {
|
|
15
|
+
asChild?: boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const NavBarItem = forwardRef<HTMLDivElement, NavBarItemProps>(
|
|
21
|
+
function NavBarItem({ asChild, className, ...rest }, ref) {
|
|
22
|
+
const Comp = asChild ? Slot : 'div';
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Comp
|
|
26
|
+
ref={ref}
|
|
27
|
+
className={classNames(navBarItemClass, className)}
|
|
28
|
+
{...rest}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
},
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export const NavBarItemIconWrapper = withClassName(
|
|
35
|
+
'div',
|
|
36
|
+
'relative flex sm:(p-6px rounded-full bg-lightBlend)',
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const NavBarItemText = withClassName(
|
|
40
|
+
'span',
|
|
41
|
+
'overflow-hidden pl-1 inline-block text-xxs whitespace-nowrap text-ellipsis sm:(text-md leading-normal)',
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const NavBarItemIcon = withClassName(
|
|
45
|
+
'div',
|
|
46
|
+
'relative z-1 [a[data-active=true]_&]:fill-primary-light',
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const NavBarItemPip = withClassName(
|
|
50
|
+
'div',
|
|
51
|
+
'absolute top-6px right-6px w-6px h-6px rounded-full bg-attention shadow-sm',
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
export const NavBarRoot = withClassName(
|
|
55
|
+
'div',
|
|
56
|
+
'flex flex-row items-stretch justify-around w-full rounded-0 rounded-t-lg shadow-lg overflow-hidden z-50 bg-wash border-t border-t-solid border-gray5 p-1 h-auto',
|
|
57
|
+
'pb-[calc(0.25rem+env(safe-area-inset-bottom,0px))]',
|
|
58
|
+
'sm:(bg-transparent flex flex-col rounded-0 border-none border-transparent shadow-none h-min-content overflow-y-auto overflow-x-hidden justify-start items-stretch gap-2 pb-10)',
|
|
59
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './NavBar.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navBar/index.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
|
|
4
|
+
export interface NoteProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function Note({ className, children, ...rest }: NoteProps) {
|
|
9
|
+
return (
|
|
10
|
+
<div className={classNames('pr-20px', className)} {...rest}>
|
|
11
|
+
<div className="flex flex-col p-2 border border-solid border-primary-dark bg-primary-wash color-black relative text-sm italic border-r-0">
|
|
12
|
+
{children}
|
|
13
|
+
<div className="w-20px h-[calc(100%-18px)] absolute bottom--0.5px right--20px border-0 border-solid border-primary-dark border-r border-b bg-primary-wash">
|
|
14
|
+
<div
|
|
15
|
+
className={`absolute top--20px left-0 border-10px border-0 border-solid border-transparent border-b-primary-dark border-l-primary-dark after:(content-[""] absolute top--7px left--9px border-8px border-solid border-transparent border-b-primary-wash border-l-primary-wash)`}
|
|
16
|
+
/>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Note.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './note/index.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { NumberStepper } from './NumberStepper.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'NumberStepper',
|
|
6
|
+
component: NumberStepper,
|
|
7
|
+
argTypes: {},
|
|
8
|
+
parameters: {
|
|
9
|
+
controls: { expanded: true },
|
|
10
|
+
},
|
|
11
|
+
} satisfies Meta<typeof NumberStepper>;
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
|
|
15
|
+
type Story = StoryObj<typeof NumberStepper>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {
|
|
18
|
+
args: {
|
|
19
|
+
value: 0,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { fractionToText } from '@a-type/utils';
|
|
2
|
+
import { MinusIcon, PlusIcon } from '@radix-ui/react-icons';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import { Button } from '../button.js';
|
|
6
|
+
|
|
7
|
+
export interface NumberStepperProps {
|
|
8
|
+
value: number;
|
|
9
|
+
onChange: (value: number) => void;
|
|
10
|
+
highlightChange?: boolean;
|
|
11
|
+
steps?: number[];
|
|
12
|
+
increment?: number;
|
|
13
|
+
renderValue?: (value: number) => ReactNode;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function NumberStepper({
|
|
18
|
+
value,
|
|
19
|
+
onChange,
|
|
20
|
+
highlightChange,
|
|
21
|
+
steps,
|
|
22
|
+
increment: incrementAmount = 1,
|
|
23
|
+
renderValue = fractionToText,
|
|
24
|
+
className,
|
|
25
|
+
...rest
|
|
26
|
+
}: NumberStepperProps) {
|
|
27
|
+
const index = steps?.indexOf(value) ?? 0;
|
|
28
|
+
|
|
29
|
+
const increment = () => {
|
|
30
|
+
if (steps) {
|
|
31
|
+
if (index === steps.length - 1) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
onChange(steps[index + 1]);
|
|
35
|
+
} else {
|
|
36
|
+
onChange(value + incrementAmount);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const decrement = () => {
|
|
41
|
+
if (steps) {
|
|
42
|
+
if (index === 0) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
onChange(steps[index - 1]);
|
|
46
|
+
} else {
|
|
47
|
+
onChange(value - incrementAmount);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const canIncrement = steps ? index < steps.length - 1 : true;
|
|
52
|
+
const canDecrement = steps ? index > 0 : true;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
className={classNames(
|
|
57
|
+
'flex items-center border-default rounded-full overflow-hidden w-min-content flex-shrink-0',
|
|
58
|
+
{
|
|
59
|
+
'bg-accent-wash color-black': !!highlightChange && value !== 1,
|
|
60
|
+
},
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
{...rest}
|
|
64
|
+
>
|
|
65
|
+
<Button color="ghost" onClick={decrement} disabled={!canDecrement}>
|
|
66
|
+
<MinusIcon />
|
|
67
|
+
</Button>
|
|
68
|
+
<div className="w-80px text-center">{renderValue(value)}</div>
|
|
69
|
+
<Button color="ghost" onClick={increment} disabled={!canIncrement}>
|
|
70
|
+
<PlusIcon />
|
|
71
|
+
</Button>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './NumberStepper.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './numberStepper/index.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
import { Particles } from './particlesState.js';
|
|
3
|
+
|
|
4
|
+
const ParticleContext = createContext<Particles | null>(null);
|
|
5
|
+
|
|
6
|
+
export function useParticles() {
|
|
7
|
+
const particles = useContext(ParticleContext);
|
|
8
|
+
return particles;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ParticlesProvider = ParticleContext.Provider;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ParticleLayer } from './ParticleLayer.js';
|
|
3
|
+
import { Button } from '../button.js';
|
|
4
|
+
import { useParticles } from './ParticleContext.js';
|
|
5
|
+
import { MouseEvent } from 'react';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'ParticleLayer',
|
|
9
|
+
component: ParticleLayer,
|
|
10
|
+
argTypes: {},
|
|
11
|
+
parameters: {},
|
|
12
|
+
} satisfies Meta<typeof ParticleLayer>;
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
|
|
16
|
+
type Story = StoryObj<typeof ParticleLayer>;
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
render() {
|
|
20
|
+
return (
|
|
21
|
+
<div className="w-full h-[100vh] relative flex flex-col items-center justify-center">
|
|
22
|
+
<ParticleLayer noPortal>
|
|
23
|
+
<DemoButton />
|
|
24
|
+
</ParticleLayer>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function DemoButton() {
|
|
31
|
+
const particles = useParticles();
|
|
32
|
+
if (!particles) throw new Error('Must be used inside ParticleLayer');
|
|
33
|
+
const burst = (ev: MouseEvent) => {
|
|
34
|
+
particles.addParticles(
|
|
35
|
+
particles.elementExplosion({
|
|
36
|
+
element: ev.currentTarget as HTMLElement,
|
|
37
|
+
count: 10,
|
|
38
|
+
}),
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
return (
|
|
42
|
+
<Button size="icon" onClick={burst}>
|
|
43
|
+
💥
|
|
44
|
+
</Button>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ReactNode, useState } from 'react';
|
|
2
|
+
import { Particles } from './particlesState.js';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
4
|
+
import { ParticlesProvider } from './ParticleContext.js';
|
|
5
|
+
|
|
6
|
+
export function ParticleLayer({
|
|
7
|
+
children,
|
|
8
|
+
noPortal,
|
|
9
|
+
}: {
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
noPortal?: boolean;
|
|
12
|
+
}) {
|
|
13
|
+
const [particles] = useState(() => new Particles({ initialPoolSize: 100 }));
|
|
14
|
+
|
|
15
|
+
const canvas = (
|
|
16
|
+
<canvas
|
|
17
|
+
ref={particles.setCanvas}
|
|
18
|
+
className="fixed inset-0 w-full h-full z-overdraw pointer-events-none"
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ParticlesProvider value={particles}>
|
|
24
|
+
{noPortal ? canvas : createPortal(canvas, document.body)}
|
|
25
|
+
{children}
|
|
26
|
+
</ParticlesProvider>
|
|
27
|
+
);
|
|
28
|
+
}
|