@pulog/ui 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -2
- package/dist/button-Cne9rSSH.d.ts +16 -0
- package/dist/carousel.d.ts +34 -0
- package/dist/carousel.js +196 -0
- package/dist/carousel.js.map +1 -0
- package/dist/chart.d.ts +48 -0
- package/dist/chart.js +248 -0
- package/dist/chart.js.map +1 -0
- package/dist/chunk-JYU5CUA4.js +11 -0
- package/dist/chunk-JYU5CUA4.js.map +1 -0
- package/dist/chunk-LIIDSNMG.js +61 -0
- package/dist/chunk-LIIDSNMG.js.map +1 -0
- package/dist/drawer.d.ts +16 -0
- package/dist/drawer.js +120 -0
- package/dist/drawer.js.map +1 -0
- package/dist/index.d.ts +513 -0
- package/dist/index.js +4281 -0
- package/dist/index.js.map +1 -0
- package/dist/input-otp.d.ts +14 -0
- package/dist/input-otp.js +82 -0
- package/dist/input-otp.js.map +1 -0
- package/dist/resizable.d.ts +10 -0
- package/dist/resizable.js +46 -0
- package/dist/resizable.js.map +1 -0
- package/dist/sonner.d.ts +6 -0
- package/dist/sonner.js +39 -0
- package/dist/sonner.js.map +1 -0
- package/package.json +105 -4
package/README.md
CHANGED
|
@@ -1,3 +1,96 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @pulog/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The complete shared UI kit for TMS apps: every shadcn/Radix primitive that lived in `tms_billing/src/components/ui`
|
|
4
|
+
(52 files, moved verbatim), plus `PortalContainerContext`, `EmptyStateIllustration`, `StatusPage`, `Forbidden`,
|
|
5
|
+
`Can` and `SmartSelect`.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { Button, Popover, PopoverContent, PopoverTrigger } from '@pulog/ui'
|
|
9
|
+
import { Carousel } from '@pulog/ui/carousel' // heavy-library components have their own entry, see below
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What is in it
|
|
13
|
+
|
|
14
|
+
**Main entry `@pulog/ui`** (needs only the common peers):
|
|
15
|
+
`Accordion`, `Alert`, `AlertDialog`, `AspectRatio`, `Avatar`, `Badge`, `Breadcrumb`, `Button`, `ButtonGroup`, `Calendar`, `Card`,
|
|
16
|
+
`Checkbox`, `Collapsible`, `Command`, `ContextMenu`, `Dialog`, `DropdownMenu`, `Empty`, `Field`, `HoverCard`, `Input`, `InputGroup`,
|
|
17
|
+
`Item`, `Kbd`, `Label`, `Menubar`, `MonthPicker`, `NavigationMenu`, `Pagination`, `Popover`, `Progress`, `RadioGroup`, `ScrollArea`,
|
|
18
|
+
`Select`, `Separator`, `Sheet`, `Skeleton`, `Slider`, `Spinner`, `Switch`, `Table`, `Tabs`, `Textarea`, `Toggle`, `ToggleGroup`,
|
|
19
|
+
`Tooltip`, plus `PortalContainerContext` / `usePortalContainer`, `EmptyStateIllustration`, `StatusPage`, `Forbidden`, `Can`, `SmartSelect`.
|
|
20
|
+
|
|
21
|
+
**Subpath entries** - each needs an extra library that is an *optional* peer, so apps that never use the component never
|
|
22
|
+
install it:
|
|
23
|
+
|
|
24
|
+
| Import | Components | Optional peer |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `@pulog/ui/carousel` | `Carousel`, ... | `embla-carousel-react` |
|
|
27
|
+
| `@pulog/ui/chart` | `ChartContainer`, `ChartTooltip`, ... | `recharts` |
|
|
28
|
+
| `@pulog/ui/drawer` | `Drawer`, ... | `vaul` |
|
|
29
|
+
| `@pulog/ui/input-otp` | `InputOTP`, ... | `input-otp` |
|
|
30
|
+
| `@pulog/ui/resizable` | `ResizablePanelGroup`, ... | `react-resizable-panels` |
|
|
31
|
+
| `@pulog/ui/sonner` | `Toaster` | `sonner`, `next-themes` |
|
|
32
|
+
|
|
33
|
+
All entries share one build, so shared modules (`cn`, `PortalContainerContext`, `Button`, ...) exist exactly once.
|
|
34
|
+
Note `sonner` is a Module Federation singleton and the **host** owns the `<Toaster>`; remotes emit through the toast
|
|
35
|
+
bridge (see the remote's `SONNER_MFE_SETUP.md`) - do not mount a second Toaster in a remote just because it is available here.
|
|
36
|
+
|
|
37
|
+
Required peers of the main entry: `react`, `react-dom`, `radix-ui`, `lucide-react`, `react-day-picker`, `cmdk`.
|
|
38
|
+
Depends on `@pulog/utils` (`cn`) and `class-variance-authority`.
|
|
39
|
+
|
|
40
|
+
## Page-level pieces (context-free)
|
|
41
|
+
|
|
42
|
+
These came from `tms_billing` and had app-context dependencies; the package takes them as **props** instead, so it
|
|
43
|
+
imports nothing from the app:
|
|
44
|
+
|
|
45
|
+
| Export | Injected by the app | Notes |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `StatusPage` | `onNavigate` (optional, shows the "Kembali ke beranda" button), `homeLabel` | 404/403 style full-page view |
|
|
48
|
+
| `Forbidden` | `onNavigate`, `homeLabel`, `message`, `detail` | 403 built on `StatusPage`; default texts are Indonesian |
|
|
49
|
+
| `Can` | `can` (required) | renders children when `can(...I)` allows (`all` = every permission). No default policy on purpose |
|
|
50
|
+
|
|
51
|
+
Apps keep tiny wrappers that bind their own context, so call sites do not change:
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
// Forbidden: onNavigate from the remote auth context
|
|
55
|
+
const { onNavigate } = useRemoteAuth()
|
|
56
|
+
return <Forbidden onNavigate={onNavigate} />
|
|
57
|
+
// Can: the check comes from the app's own useMenuAccess()
|
|
58
|
+
const { can } = useMenuAccess()
|
|
59
|
+
return <Can I="DELETE" can={can}>...</Can>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`useMenuAccess`, `MenuAccessContext` and `lib/menu-access` (access policy, enforcement flag, role handling) stay in the app:
|
|
63
|
+
they read env and the remote auth context, which the package must not do. `NotFound` was not moved.
|
|
64
|
+
|
|
65
|
+
## SmartSelect
|
|
66
|
+
|
|
67
|
+
Searchable single/multi select built on `Popover` + `Command` (moved verbatim from `tms_billing`). Fully
|
|
68
|
+
self-contained - it only needs props, no app context.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { SmartSelect } from '@pulog/ui'
|
|
72
|
+
|
|
73
|
+
<SmartSelect options={opts} value={v} onChange={setV} placeholder="Pilih..." /> {/* local filtering */}
|
|
74
|
+
<SmartSelect multiple displayMode="chips" maxVisibleChips={2} value={vs} onChange={setVs} options={opts} />
|
|
75
|
+
<SmartSelect value={v} onChange={setV} onSearch={(q) => fetchOptions(q)} minSearchLength={2} /> {/* server search, debounced */}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Props (`SmartSelectProps`): `options`, `value` (string or string[]), `onChange`, `multiple`, `placeholder`,
|
|
79
|
+
`disabled`, `onSearch` (async -> server mode), `displayMode` (`'count'` | `'chips'`), `maxVisibleChips`,
|
|
80
|
+
`minSearchLength`, `className`, `id`. Option shape: `{ label, value }` (`SmartSelectOption`). Selected labels are cached so they stay
|
|
81
|
+
correct when a server search replaces the option list. Default texts ("Select...") come from props, not i18n.
|
|
82
|
+
|
|
83
|
+
The `Command` / `Dialog` / `InputGroup` / `Textarea` primitives moved with it because SmartSelect depends on them.
|
|
84
|
+
|
|
85
|
+
## Rules
|
|
86
|
+
|
|
87
|
+
- **One `PortalContainerContext` per app.** Popover, Select and DropdownMenu portal into the container this context
|
|
88
|
+
provides (the remote's Shadow DOM root). Apps keep `src/context/PortalContainerContext.tsx` only as a re-export of
|
|
89
|
+
this package's context, and provide it at the Shadow DOM root.
|
|
90
|
+
- No CSS ships. Apps add `@source "../node_modules/@pulog";` so Tailwind generates the classes used here.
|
|
91
|
+
- Every primitive lives here now. Do not fork one into an app - extend it here. Adding a primitive that needs a heavy,
|
|
92
|
+
rarely used library: give it its own subpath entry (see `docs/CONTRIBUTING.md`).
|
|
93
|
+
- Apps keep `src/components/ui/<x>.tsx` as one-line re-exports so existing imports keep working; migrate call sites to
|
|
94
|
+
`@pulog/ui` gradually.
|
|
95
|
+
- `Calendar` carries a legacy `table` class key (react-day-picker v8 name) marked `@ts-expect-error` to keep the
|
|
96
|
+
rendered output identical to billing's; remove it deliberately, with a visual check.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
declare const buttonVariants: (props?: {
|
|
6
|
+
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link";
|
|
7
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg";
|
|
8
|
+
} & class_variance_authority_types.ClassProp) => string;
|
|
9
|
+
declare const Button: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: {
|
|
10
|
+
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link";
|
|
11
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg";
|
|
12
|
+
} & class_variance_authority_types.ClassProp) => string> & {
|
|
13
|
+
asChild?: boolean;
|
|
14
|
+
}, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
15
|
+
|
|
16
|
+
export { Button as B, buttonVariants as b };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import useEmblaCarousel, { UseEmblaCarouselType } from 'embla-carousel-react';
|
|
4
|
+
import { Button } from './index.js';
|
|
5
|
+
import 'class-variance-authority/types';
|
|
6
|
+
import 'class-variance-authority';
|
|
7
|
+
|
|
8
|
+
type CarouselApi = UseEmblaCarouselType[1];
|
|
9
|
+
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
|
|
10
|
+
type CarouselOptions = UseCarouselParameters[0];
|
|
11
|
+
type CarouselPlugin = UseCarouselParameters[1];
|
|
12
|
+
type CarouselProps = {
|
|
13
|
+
opts?: CarouselOptions;
|
|
14
|
+
plugins?: CarouselPlugin;
|
|
15
|
+
orientation?: "horizontal" | "vertical";
|
|
16
|
+
setApi?: (api: CarouselApi) => void;
|
|
17
|
+
};
|
|
18
|
+
type CarouselContextProps = {
|
|
19
|
+
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
|
|
20
|
+
api: ReturnType<typeof useEmblaCarousel>[1];
|
|
21
|
+
scrollPrev: () => void;
|
|
22
|
+
scrollNext: () => void;
|
|
23
|
+
canScrollPrev: boolean;
|
|
24
|
+
canScrollNext: boolean;
|
|
25
|
+
} & CarouselProps;
|
|
26
|
+
declare function useCarousel(): CarouselContextProps;
|
|
27
|
+
declare function Carousel({ orientation, opts, setApi, plugins, className, children, ...props }: React.ComponentProps<"div"> & CarouselProps): react_jsx_runtime.JSX.Element;
|
|
28
|
+
declare function CarouselContent({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
29
|
+
declare function CarouselItem({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
30
|
+
declare function CarouselPrevious({ className, variant, size, ...props }: React.ComponentProps<typeof Button>): react_jsx_runtime.JSX.Element;
|
|
31
|
+
declare function CarouselNext({ className, variant, size, ...props }: React.ComponentProps<typeof Button>): react_jsx_runtime.JSX.Element;
|
|
32
|
+
|
|
33
|
+
export { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, useCarousel };
|
|
34
|
+
export type { CarouselApi };
|
package/dist/carousel.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { Button } from './chunk-LIIDSNMG.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import useEmblaCarousel from 'embla-carousel-react';
|
|
4
|
+
import { cn } from '@pulog/utils';
|
|
5
|
+
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react';
|
|
6
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
var CarouselContext = React.createContext(null);
|
|
9
|
+
function useCarousel() {
|
|
10
|
+
const context = React.useContext(CarouselContext);
|
|
11
|
+
if (!context) {
|
|
12
|
+
throw new Error("useCarousel must be used within a <Carousel />");
|
|
13
|
+
}
|
|
14
|
+
return context;
|
|
15
|
+
}
|
|
16
|
+
function Carousel({
|
|
17
|
+
orientation = "horizontal",
|
|
18
|
+
opts,
|
|
19
|
+
setApi,
|
|
20
|
+
plugins,
|
|
21
|
+
className,
|
|
22
|
+
children,
|
|
23
|
+
...props
|
|
24
|
+
}) {
|
|
25
|
+
const [carouselRef, api] = useEmblaCarousel(
|
|
26
|
+
{
|
|
27
|
+
...opts,
|
|
28
|
+
axis: orientation === "horizontal" ? "x" : "y"
|
|
29
|
+
},
|
|
30
|
+
plugins
|
|
31
|
+
);
|
|
32
|
+
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
|
|
33
|
+
const [canScrollNext, setCanScrollNext] = React.useState(false);
|
|
34
|
+
const onSelect = React.useCallback((api2) => {
|
|
35
|
+
if (!api2) return;
|
|
36
|
+
setCanScrollPrev(api2.canScrollPrev());
|
|
37
|
+
setCanScrollNext(api2.canScrollNext());
|
|
38
|
+
}, []);
|
|
39
|
+
const scrollPrev = React.useCallback(() => {
|
|
40
|
+
api?.scrollPrev();
|
|
41
|
+
}, [api]);
|
|
42
|
+
const scrollNext = React.useCallback(() => {
|
|
43
|
+
api?.scrollNext();
|
|
44
|
+
}, [api]);
|
|
45
|
+
const handleKeyDown = React.useCallback(
|
|
46
|
+
(event) => {
|
|
47
|
+
if (event.key === "ArrowLeft") {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
scrollPrev();
|
|
50
|
+
} else if (event.key === "ArrowRight") {
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
scrollNext();
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
[scrollPrev, scrollNext]
|
|
56
|
+
);
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
if (!api || !setApi) return;
|
|
59
|
+
setApi(api);
|
|
60
|
+
}, [api, setApi]);
|
|
61
|
+
React.useEffect(() => {
|
|
62
|
+
if (!api) return;
|
|
63
|
+
onSelect(api);
|
|
64
|
+
api.on("reInit", onSelect);
|
|
65
|
+
api.on("select", onSelect);
|
|
66
|
+
return () => {
|
|
67
|
+
api?.off("select", onSelect);
|
|
68
|
+
};
|
|
69
|
+
}, [api, onSelect]);
|
|
70
|
+
return /* @__PURE__ */ jsx(
|
|
71
|
+
CarouselContext.Provider,
|
|
72
|
+
{
|
|
73
|
+
value: {
|
|
74
|
+
carouselRef,
|
|
75
|
+
api,
|
|
76
|
+
opts,
|
|
77
|
+
orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
|
78
|
+
scrollPrev,
|
|
79
|
+
scrollNext,
|
|
80
|
+
canScrollPrev,
|
|
81
|
+
canScrollNext
|
|
82
|
+
},
|
|
83
|
+
children: /* @__PURE__ */ jsx(
|
|
84
|
+
"div",
|
|
85
|
+
{
|
|
86
|
+
onKeyDownCapture: handleKeyDown,
|
|
87
|
+
className: cn("relative", className),
|
|
88
|
+
role: "region",
|
|
89
|
+
"aria-roledescription": "carousel",
|
|
90
|
+
"data-slot": "carousel",
|
|
91
|
+
...props,
|
|
92
|
+
children
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
function CarouselContent({ className, ...props }) {
|
|
99
|
+
const { carouselRef, orientation } = useCarousel();
|
|
100
|
+
return /* @__PURE__ */ jsx(
|
|
101
|
+
"div",
|
|
102
|
+
{
|
|
103
|
+
ref: carouselRef,
|
|
104
|
+
className: "overflow-hidden",
|
|
105
|
+
"data-slot": "carousel-content",
|
|
106
|
+
children: /* @__PURE__ */ jsx(
|
|
107
|
+
"div",
|
|
108
|
+
{
|
|
109
|
+
className: cn(
|
|
110
|
+
"flex",
|
|
111
|
+
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
|
|
112
|
+
className
|
|
113
|
+
),
|
|
114
|
+
...props
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
function CarouselItem({ className, ...props }) {
|
|
121
|
+
const { orientation } = useCarousel();
|
|
122
|
+
return /* @__PURE__ */ jsx(
|
|
123
|
+
"div",
|
|
124
|
+
{
|
|
125
|
+
role: "group",
|
|
126
|
+
"aria-roledescription": "slide",
|
|
127
|
+
"data-slot": "carousel-item",
|
|
128
|
+
className: cn(
|
|
129
|
+
"min-w-0 shrink-0 grow-0 basis-full",
|
|
130
|
+
orientation === "horizontal" ? "pl-4" : "pt-4",
|
|
131
|
+
className
|
|
132
|
+
),
|
|
133
|
+
...props
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
function CarouselPrevious({
|
|
138
|
+
className,
|
|
139
|
+
variant = "outline",
|
|
140
|
+
size = "icon-sm",
|
|
141
|
+
...props
|
|
142
|
+
}) {
|
|
143
|
+
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
|
|
144
|
+
return /* @__PURE__ */ jsxs(
|
|
145
|
+
Button,
|
|
146
|
+
{
|
|
147
|
+
"data-slot": "carousel-previous",
|
|
148
|
+
variant,
|
|
149
|
+
size,
|
|
150
|
+
className: cn(
|
|
151
|
+
"absolute touch-manipulation rounded-full",
|
|
152
|
+
orientation === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
153
|
+
className
|
|
154
|
+
),
|
|
155
|
+
disabled: !canScrollPrev,
|
|
156
|
+
onClick: scrollPrev,
|
|
157
|
+
...props,
|
|
158
|
+
children: [
|
|
159
|
+
/* @__PURE__ */ jsx(ChevronLeftIcon, {}),
|
|
160
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Previous slide" })
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
function CarouselNext({
|
|
166
|
+
className,
|
|
167
|
+
variant = "outline",
|
|
168
|
+
size = "icon-sm",
|
|
169
|
+
...props
|
|
170
|
+
}) {
|
|
171
|
+
const { orientation, scrollNext, canScrollNext } = useCarousel();
|
|
172
|
+
return /* @__PURE__ */ jsxs(
|
|
173
|
+
Button,
|
|
174
|
+
{
|
|
175
|
+
"data-slot": "carousel-next",
|
|
176
|
+
variant,
|
|
177
|
+
size,
|
|
178
|
+
className: cn(
|
|
179
|
+
"absolute touch-manipulation rounded-full",
|
|
180
|
+
orientation === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
181
|
+
className
|
|
182
|
+
),
|
|
183
|
+
disabled: !canScrollNext,
|
|
184
|
+
onClick: scrollNext,
|
|
185
|
+
...props,
|
|
186
|
+
children: [
|
|
187
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, {}),
|
|
188
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Next slide" })
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, useCarousel };
|
|
195
|
+
//# sourceMappingURL=carousel.js.map
|
|
196
|
+
//# sourceMappingURL=carousel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/carousel.tsx"],"names":["api"],"mappings":"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","file":"carousel.js","sourcesContent":["import * as React from \"react\"\r\nimport useEmblaCarousel, {\r\n type UseEmblaCarouselType,\r\n} from \"embla-carousel-react\"\r\n\r\nimport { cn } from \"@pulog/utils\"\r\nimport { Button } from \"./button\"\r\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\r\n\r\ntype CarouselApi = UseEmblaCarouselType[1]\r\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\r\ntype CarouselOptions = UseCarouselParameters[0]\r\ntype CarouselPlugin = UseCarouselParameters[1]\r\n\r\ntype CarouselProps = {\r\n opts?: CarouselOptions\r\n plugins?: CarouselPlugin\r\n orientation?: \"horizontal\" | \"vertical\"\r\n setApi?: (api: CarouselApi) => void\r\n}\r\n\r\ntype CarouselContextProps = {\r\n carouselRef: ReturnType<typeof useEmblaCarousel>[0]\r\n api: ReturnType<typeof useEmblaCarousel>[1]\r\n scrollPrev: () => void\r\n scrollNext: () => void\r\n canScrollPrev: boolean\r\n canScrollNext: boolean\r\n} & CarouselProps\r\n\r\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\r\n\r\nfunction useCarousel() {\r\n const context = React.useContext(CarouselContext)\r\n\r\n if (!context) {\r\n throw new Error(\"useCarousel must be used within a <Carousel />\")\r\n }\r\n\r\n return context\r\n}\r\n\r\nfunction Carousel({\r\n orientation = \"horizontal\",\r\n opts,\r\n setApi,\r\n plugins,\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & CarouselProps) {\r\n const [carouselRef, api] = useEmblaCarousel(\r\n {\r\n ...opts,\r\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\r\n },\r\n plugins\r\n )\r\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\r\n const [canScrollNext, setCanScrollNext] = React.useState(false)\r\n\r\n const onSelect = React.useCallback((api: CarouselApi) => {\r\n if (!api) return\r\n setCanScrollPrev(api.canScrollPrev())\r\n setCanScrollNext(api.canScrollNext())\r\n }, [])\r\n\r\n const scrollPrev = React.useCallback(() => {\r\n api?.scrollPrev()\r\n }, [api])\r\n\r\n const scrollNext = React.useCallback(() => {\r\n api?.scrollNext()\r\n }, [api])\r\n\r\n const handleKeyDown = React.useCallback(\r\n (event: React.KeyboardEvent<HTMLDivElement>) => {\r\n if (event.key === \"ArrowLeft\") {\r\n event.preventDefault()\r\n scrollPrev()\r\n } else if (event.key === \"ArrowRight\") {\r\n event.preventDefault()\r\n scrollNext()\r\n }\r\n },\r\n [scrollPrev, scrollNext]\r\n )\r\n\r\n React.useEffect(() => {\r\n if (!api || !setApi) return\r\n setApi(api)\r\n }, [api, setApi])\r\n\r\n React.useEffect(() => {\r\n if (!api) return\r\n onSelect(api)\r\n api.on(\"reInit\", onSelect)\r\n api.on(\"select\", onSelect)\r\n\r\n return () => {\r\n api?.off(\"select\", onSelect)\r\n }\r\n }, [api, onSelect])\r\n\r\n return (\r\n <CarouselContext.Provider\r\n value={{\r\n carouselRef,\r\n api: api,\r\n opts,\r\n orientation:\r\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\r\n scrollPrev,\r\n scrollNext,\r\n canScrollPrev,\r\n canScrollNext,\r\n }}\r\n >\r\n <div\r\n onKeyDownCapture={handleKeyDown}\r\n className={cn(\"relative\", className)}\r\n role=\"region\"\r\n aria-roledescription=\"carousel\"\r\n data-slot=\"carousel\"\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n </CarouselContext.Provider>\r\n )\r\n}\r\n\r\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\r\n const { carouselRef, orientation } = useCarousel()\r\n\r\n return (\r\n <div\r\n ref={carouselRef}\r\n className=\"overflow-hidden\"\r\n data-slot=\"carousel-content\"\r\n >\r\n <div\r\n className={cn(\r\n \"flex\",\r\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\r\n const { orientation } = useCarousel()\r\n\r\n return (\r\n <div\r\n role=\"group\"\r\n aria-roledescription=\"slide\"\r\n data-slot=\"carousel-item\"\r\n className={cn(\r\n \"min-w-0 shrink-0 grow-0 basis-full\",\r\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CarouselPrevious({\r\n className,\r\n variant = \"outline\",\r\n size = \"icon-sm\",\r\n ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\r\n\r\n return (\r\n <Button\r\n data-slot=\"carousel-previous\"\r\n variant={variant}\r\n size={size}\r\n className={cn(\r\n \"absolute touch-manipulation rounded-full\",\r\n orientation === \"horizontal\"\r\n ? \"top-1/2 -left-12 -translate-y-1/2\"\r\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\r\n className\r\n )}\r\n disabled={!canScrollPrev}\r\n onClick={scrollPrev}\r\n {...props}\r\n >\r\n <ChevronLeftIcon />\r\n <span className=\"sr-only\">Previous slide</span>\r\n </Button>\r\n )\r\n}\r\n\r\nfunction CarouselNext({\r\n className,\r\n variant = \"outline\",\r\n size = \"icon-sm\",\r\n ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n const { orientation, scrollNext, canScrollNext } = useCarousel()\r\n\r\n return (\r\n <Button\r\n data-slot=\"carousel-next\"\r\n variant={variant}\r\n size={size}\r\n className={cn(\r\n \"absolute touch-manipulation rounded-full\",\r\n orientation === \"horizontal\"\r\n ? \"top-1/2 -right-12 -translate-y-1/2\"\r\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\r\n className\r\n )}\r\n disabled={!canScrollNext}\r\n onClick={scrollNext}\r\n {...props}\r\n >\r\n <ChevronRightIcon />\r\n <span className=\"sr-only\">Next slide</span>\r\n </Button>\r\n )\r\n}\r\n\r\nexport {\r\n type CarouselApi,\r\n Carousel,\r\n CarouselContent,\r\n CarouselItem,\r\n CarouselPrevious,\r\n CarouselNext,\r\n useCarousel,\r\n}\r\n"]}
|
package/dist/chart.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as RechartsPrimitive from 'recharts';
|
|
4
|
+
import { TooltipValueType } from 'recharts';
|
|
5
|
+
|
|
6
|
+
declare const THEMES: {
|
|
7
|
+
readonly light: "";
|
|
8
|
+
readonly dark: ".dark";
|
|
9
|
+
};
|
|
10
|
+
type TooltipNameType = number | string;
|
|
11
|
+
type ChartConfig = Record<string, {
|
|
12
|
+
label?: React.ReactNode;
|
|
13
|
+
icon?: React.ComponentType;
|
|
14
|
+
} & ({
|
|
15
|
+
color?: string;
|
|
16
|
+
theme?: never;
|
|
17
|
+
} | {
|
|
18
|
+
color?: never;
|
|
19
|
+
theme: Record<keyof typeof THEMES, string>;
|
|
20
|
+
})>;
|
|
21
|
+
declare function ChartContainer({ id, className, children, config, initialDimension, ...props }: React.ComponentProps<"div"> & {
|
|
22
|
+
config: ChartConfig;
|
|
23
|
+
children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"];
|
|
24
|
+
initialDimension?: {
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
};
|
|
28
|
+
}): react_jsx_runtime.JSX.Element;
|
|
29
|
+
declare const ChartStyle: ({ id, config }: {
|
|
30
|
+
id: string;
|
|
31
|
+
config: ChartConfig;
|
|
32
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
33
|
+
declare const ChartTooltip: typeof RechartsPrimitive.Tooltip;
|
|
34
|
+
declare function ChartTooltipContent({ active, payload, className, indicator, hideLabel, hideIndicator, label, labelFormatter, labelClassName, formatter, color, nameKey, labelKey, }: React.ComponentProps<typeof RechartsPrimitive.Tooltip> & React.ComponentProps<"div"> & {
|
|
35
|
+
hideLabel?: boolean;
|
|
36
|
+
hideIndicator?: boolean;
|
|
37
|
+
indicator?: "line" | "dot" | "dashed";
|
|
38
|
+
nameKey?: string;
|
|
39
|
+
labelKey?: string;
|
|
40
|
+
} & Omit<RechartsPrimitive.DefaultTooltipContentProps<TooltipValueType, TooltipNameType>, "accessibilityLayer">): react_jsx_runtime.JSX.Element;
|
|
41
|
+
declare const ChartLegend: React.MemoExoticComponent<(outsideProps: RechartsPrimitive.LegendProps) => React.ReactPortal | null>;
|
|
42
|
+
declare function ChartLegendContent({ className, hideIcon, payload, verticalAlign, nameKey, }: React.ComponentProps<"div"> & {
|
|
43
|
+
hideIcon?: boolean;
|
|
44
|
+
nameKey?: string;
|
|
45
|
+
} & RechartsPrimitive.DefaultLegendContentProps): react_jsx_runtime.JSX.Element;
|
|
46
|
+
|
|
47
|
+
export { ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent };
|
|
48
|
+
export type { ChartConfig };
|
package/dist/chart.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as RechartsPrimitive from 'recharts';
|
|
3
|
+
import { cn } from '@pulog/utils';
|
|
4
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/chart.tsx
|
|
7
|
+
var THEMES = { light: "", dark: ".dark" };
|
|
8
|
+
var INITIAL_DIMENSION = { width: 320, height: 200 };
|
|
9
|
+
var ChartContext = React.createContext(null);
|
|
10
|
+
function useChart() {
|
|
11
|
+
const context = React.useContext(ChartContext);
|
|
12
|
+
if (!context) {
|
|
13
|
+
throw new Error("useChart must be used within a <ChartContainer />");
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
}
|
|
17
|
+
function ChartContainer({
|
|
18
|
+
id,
|
|
19
|
+
className,
|
|
20
|
+
children,
|
|
21
|
+
config,
|
|
22
|
+
initialDimension = INITIAL_DIMENSION,
|
|
23
|
+
...props
|
|
24
|
+
}) {
|
|
25
|
+
const uniqueId = React.useId();
|
|
26
|
+
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
|
|
27
|
+
return /* @__PURE__ */ jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxs(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
"data-slot": "chart",
|
|
31
|
+
"data-chart": chartId,
|
|
32
|
+
className: cn(
|
|
33
|
+
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
|
|
34
|
+
className
|
|
35
|
+
),
|
|
36
|
+
...props,
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsx(ChartStyle, { id: chartId, config }),
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
RechartsPrimitive.ResponsiveContainer,
|
|
41
|
+
{
|
|
42
|
+
initialDimension,
|
|
43
|
+
children
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
) });
|
|
49
|
+
}
|
|
50
|
+
var ChartStyle = ({ id, config }) => {
|
|
51
|
+
const colorConfig = Object.entries(config).filter(
|
|
52
|
+
([, config2]) => config2.theme ?? config2.color
|
|
53
|
+
);
|
|
54
|
+
if (!colorConfig.length) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
"style",
|
|
59
|
+
{
|
|
60
|
+
dangerouslySetInnerHTML: {
|
|
61
|
+
__html: Object.entries(THEMES).map(
|
|
62
|
+
([theme, prefix]) => `
|
|
63
|
+
${prefix} [data-chart=${id}] {
|
|
64
|
+
${colorConfig.map(([key, itemConfig]) => {
|
|
65
|
+
const color = itemConfig.theme?.[theme] ?? itemConfig.color;
|
|
66
|
+
return color ? ` --color-${key}: ${color};` : null;
|
|
67
|
+
}).join("\n")}
|
|
68
|
+
}
|
|
69
|
+
`
|
|
70
|
+
).join("\n")
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
var ChartTooltip = RechartsPrimitive.Tooltip;
|
|
76
|
+
function ChartTooltipContent({
|
|
77
|
+
active,
|
|
78
|
+
payload,
|
|
79
|
+
className,
|
|
80
|
+
indicator = "dot",
|
|
81
|
+
hideLabel = false,
|
|
82
|
+
hideIndicator = false,
|
|
83
|
+
label,
|
|
84
|
+
labelFormatter,
|
|
85
|
+
labelClassName,
|
|
86
|
+
formatter,
|
|
87
|
+
color,
|
|
88
|
+
nameKey,
|
|
89
|
+
labelKey
|
|
90
|
+
}) {
|
|
91
|
+
const { config } = useChart();
|
|
92
|
+
const tooltipLabel = React.useMemo(() => {
|
|
93
|
+
if (hideLabel || !payload?.length) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const [item] = payload;
|
|
97
|
+
const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`;
|
|
98
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
99
|
+
const value = !labelKey && typeof label === "string" ? config[label]?.label ?? label : itemConfig?.label;
|
|
100
|
+
if (labelFormatter) {
|
|
101
|
+
return /* @__PURE__ */ jsx("div", { className: cn("font-medium", labelClassName), children: labelFormatter(value, payload) });
|
|
102
|
+
}
|
|
103
|
+
if (!value) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return /* @__PURE__ */ jsx("div", { className: cn("font-medium", labelClassName), children: value });
|
|
107
|
+
}, [
|
|
108
|
+
label,
|
|
109
|
+
labelFormatter,
|
|
110
|
+
payload,
|
|
111
|
+
hideLabel,
|
|
112
|
+
labelClassName,
|
|
113
|
+
config,
|
|
114
|
+
labelKey
|
|
115
|
+
]);
|
|
116
|
+
if (!active || !payload?.length) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const nestLabel = payload.length === 1 && indicator !== "dot";
|
|
120
|
+
return /* @__PURE__ */ jsxs(
|
|
121
|
+
"div",
|
|
122
|
+
{
|
|
123
|
+
className: cn(
|
|
124
|
+
"grid min-w-32 items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
|
|
125
|
+
className
|
|
126
|
+
),
|
|
127
|
+
children: [
|
|
128
|
+
!nestLabel ? tooltipLabel : null,
|
|
129
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-1.5", children: payload.filter((item) => item.type !== "none").map((item, index) => {
|
|
130
|
+
const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`;
|
|
131
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
132
|
+
const indicatorColor = color ?? item.payload?.fill ?? item.color;
|
|
133
|
+
return /* @__PURE__ */ jsx(
|
|
134
|
+
"div",
|
|
135
|
+
{
|
|
136
|
+
className: cn(
|
|
137
|
+
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
|
|
138
|
+
indicator === "dot" && "items-center"
|
|
139
|
+
),
|
|
140
|
+
children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, item.payload) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
141
|
+
itemConfig?.icon ? /* @__PURE__ */ jsx(itemConfig.icon, {}) : !hideIndicator && /* @__PURE__ */ jsx(
|
|
142
|
+
"div",
|
|
143
|
+
{
|
|
144
|
+
className: cn(
|
|
145
|
+
"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
|
|
146
|
+
{
|
|
147
|
+
"h-2.5 w-2.5": indicator === "dot",
|
|
148
|
+
"w-1": indicator === "line",
|
|
149
|
+
"w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
|
|
150
|
+
"my-0.5": nestLabel && indicator === "dashed"
|
|
151
|
+
}
|
|
152
|
+
),
|
|
153
|
+
style: {
|
|
154
|
+
"--color-bg": indicatorColor,
|
|
155
|
+
"--color-border": indicatorColor
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
),
|
|
159
|
+
/* @__PURE__ */ jsxs(
|
|
160
|
+
"div",
|
|
161
|
+
{
|
|
162
|
+
className: cn(
|
|
163
|
+
"flex flex-1 justify-between leading-none",
|
|
164
|
+
nestLabel ? "items-end" : "items-center"
|
|
165
|
+
),
|
|
166
|
+
children: [
|
|
167
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-1.5", children: [
|
|
168
|
+
nestLabel ? tooltipLabel : null,
|
|
169
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: itemConfig?.label ?? item.name })
|
|
170
|
+
] }),
|
|
171
|
+
item.value != null && /* @__PURE__ */ jsx("span", { className: "font-mono font-medium text-foreground tabular-nums", children: typeof item.value === "number" ? item.value.toLocaleString() : String(item.value) })
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
] })
|
|
176
|
+
},
|
|
177
|
+
index
|
|
178
|
+
);
|
|
179
|
+
}) })
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
var ChartLegend = RechartsPrimitive.Legend;
|
|
185
|
+
function ChartLegendContent({
|
|
186
|
+
className,
|
|
187
|
+
hideIcon = false,
|
|
188
|
+
payload,
|
|
189
|
+
verticalAlign = "bottom",
|
|
190
|
+
nameKey
|
|
191
|
+
}) {
|
|
192
|
+
const { config } = useChart();
|
|
193
|
+
if (!payload?.length) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
return /* @__PURE__ */ jsx(
|
|
197
|
+
"div",
|
|
198
|
+
{
|
|
199
|
+
className: cn(
|
|
200
|
+
"flex items-center justify-center gap-4",
|
|
201
|
+
verticalAlign === "top" ? "pb-3" : "pt-3",
|
|
202
|
+
className
|
|
203
|
+
),
|
|
204
|
+
children: payload.filter((item) => item.type !== "none").map((item, index) => {
|
|
205
|
+
const key = `${nameKey ?? item.dataKey ?? "value"}`;
|
|
206
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
207
|
+
return /* @__PURE__ */ jsxs(
|
|
208
|
+
"div",
|
|
209
|
+
{
|
|
210
|
+
className: cn(
|
|
211
|
+
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
|
|
212
|
+
),
|
|
213
|
+
children: [
|
|
214
|
+
itemConfig?.icon && !hideIcon ? /* @__PURE__ */ jsx(itemConfig.icon, {}) : /* @__PURE__ */ jsx(
|
|
215
|
+
"div",
|
|
216
|
+
{
|
|
217
|
+
className: "h-2 w-2 shrink-0 rounded-[2px]",
|
|
218
|
+
style: {
|
|
219
|
+
backgroundColor: item.color
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
),
|
|
223
|
+
itemConfig?.label
|
|
224
|
+
]
|
|
225
|
+
},
|
|
226
|
+
index
|
|
227
|
+
);
|
|
228
|
+
})
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
function getPayloadConfigFromPayload(config, payload, key) {
|
|
233
|
+
if (typeof payload !== "object" || payload === null) {
|
|
234
|
+
return void 0;
|
|
235
|
+
}
|
|
236
|
+
const payloadPayload = "payload" in payload && typeof payload.payload === "object" && payload.payload !== null ? payload.payload : void 0;
|
|
237
|
+
let configLabelKey = key;
|
|
238
|
+
if (key in payload && typeof payload[key] === "string") {
|
|
239
|
+
configLabelKey = payload[key];
|
|
240
|
+
} else if (payloadPayload && key in payloadPayload && typeof payloadPayload[key] === "string") {
|
|
241
|
+
configLabelKey = payloadPayload[key];
|
|
242
|
+
}
|
|
243
|
+
return configLabelKey in config ? config[configLabelKey] : config[key];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export { ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent };
|
|
247
|
+
//# sourceMappingURL=chart.js.map
|
|
248
|
+
//# sourceMappingURL=chart.js.map
|