analytica-frontend-lib 1.0.34 → 1.0.36

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.
@@ -1,31 +1,58 @@
1
1
  "use client";
2
2
 
3
3
  // src/components/DropdownMenu/DropdownMenu.tsx
4
+ import { SignOut, User } from "phosphor-react";
4
5
  import {
5
- createContext,
6
- useState,
7
- useCallback,
8
- useContext,
9
6
  forwardRef,
10
7
  useEffect,
11
8
  useRef,
12
- useMemo
9
+ isValidElement,
10
+ Children,
11
+ cloneElement,
12
+ useState
13
13
  } from "react";
14
+ import { create, useStore } from "zustand";
14
15
  import { jsx, jsxs } from "react/jsx-runtime";
15
- var DropdownMenuContext = createContext(
16
- void 0
17
- );
16
+ function createDropdownStore() {
17
+ return create((set) => ({
18
+ open: false,
19
+ setOpen: (open) => set({ open })
20
+ }));
21
+ }
22
+ var useDropdownStore = (externalStore) => {
23
+ if (!externalStore) {
24
+ throw new Error(
25
+ "Component must be used within a DropdownMenu (store is missing)"
26
+ );
27
+ }
28
+ return externalStore;
29
+ };
30
+ var injectStore = (children, store) => {
31
+ return Children.map(children, (child) => {
32
+ if (isValidElement(child)) {
33
+ const typedChild = child;
34
+ const newProps = {
35
+ store
36
+ };
37
+ if (typedChild.props.children) {
38
+ newProps.children = injectStore(typedChild.props.children, store);
39
+ }
40
+ return cloneElement(typedChild, newProps);
41
+ }
42
+ return child;
43
+ });
44
+ };
18
45
  var DropdownMenu = ({ children, open, onOpenChange }) => {
19
- const [internalOpen, setInternalOpen] = useState(false);
46
+ const storeRef = useRef(null);
47
+ storeRef.current ??= createDropdownStore();
48
+ const store = storeRef.current;
20
49
  const isControlled = open !== void 0;
21
- const currentOpen = isControlled ? open : internalOpen;
22
- const setOpen = useCallback(
23
- (newOpen) => {
24
- if (onOpenChange) onOpenChange(newOpen);
25
- if (!isControlled) setInternalOpen(newOpen);
26
- },
27
- [isControlled, onOpenChange]
28
- );
50
+ const uncontrolledOpen = useStore(store, (s) => s.open);
51
+ const currentOpen = isControlled ? open : uncontrolledOpen;
52
+ const setOpen = (newOpen) => {
53
+ onOpenChange?.(newOpen);
54
+ if (!isControlled) store.setState({ open: newOpen });
55
+ };
29
56
  const menuRef = useRef(null);
30
57
  const handleArrowDownOrArrowUp = (event) => {
31
58
  const menuContent = menuRef.current?.querySelector('[role="menu"]');
@@ -61,6 +88,7 @@ var DropdownMenu = ({ children, open, onOpenChange }) => {
61
88
  }
62
89
  };
63
90
  useEffect(() => {
91
+ onOpenChange?.(currentOpen);
64
92
  if (currentOpen) {
65
93
  document.addEventListener("mousedown", handleClickOutside);
66
94
  document.addEventListener("keydown", handleDownkey);
@@ -70,17 +98,17 @@ var DropdownMenu = ({ children, open, onOpenChange }) => {
70
98
  document.removeEventListener("keydown", handleDownkey);
71
99
  };
72
100
  }, [currentOpen]);
73
- const value = useMemo(
74
- () => ({ open: currentOpen, setOpen }),
75
- [currentOpen, setOpen]
76
- );
77
- return /* @__PURE__ */ jsx(DropdownMenuContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { className: "relative", ref: menuRef, children }) });
101
+ useEffect(() => {
102
+ if (isControlled) {
103
+ store.setState({ open });
104
+ }
105
+ }, []);
106
+ return /* @__PURE__ */ jsx("div", { className: "relative", ref: menuRef, children: injectStore(children, store) });
78
107
  };
79
- var DropdownMenuTrigger = forwardRef(({ className, children, onClick, ...props }, ref) => {
80
- const context = useContext(DropdownMenuContext);
81
- if (!context)
82
- throw new Error("DropdownMenuTrigger must be used within a DropdownMenu");
83
- const { open, setOpen } = context;
108
+ var DropdownMenuTrigger = forwardRef(({ className, children, onClick, store: externalStore, ...props }, ref) => {
109
+ const store = useDropdownStore(externalStore);
110
+ const open = useStore(store, (s) => s.open);
111
+ const toggleOpen = () => store.setState({ open: !open });
84
112
  return /* @__PURE__ */ jsx(
85
113
  "button",
86
114
  {
@@ -88,7 +116,7 @@ var DropdownMenuTrigger = forwardRef(({ className, children, onClick, ...props }
88
116
  className: `border border-border-200 cursor-pointer bg-background-muted hover:bg-background-200 transition-colors px-4 py-2 rounded-sm ${className}`,
89
117
  onClick: (e) => {
90
118
  e.stopPropagation();
91
- setOpen(!open);
119
+ toggleOpen();
92
120
  if (onClick) onClick(e);
93
121
  },
94
122
  "aria-expanded": open,
@@ -113,15 +141,16 @@ var ALIGN_CLASSES = {
113
141
  center: "left-1/2 -translate-x-1/2",
114
142
  end: "right-0"
115
143
  };
116
- var MenuLabel = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
117
- "fieldset",
118
- {
119
- ref,
120
- role: "group",
121
- className: `text-sm w-full ${inset ? "pl-8" : ""} ${className ?? ""}`,
122
- ...props
123
- }
124
- ));
144
+ var MenuLabel = forwardRef(({ className, inset, store: _store, ...props }, ref) => {
145
+ return /* @__PURE__ */ jsx(
146
+ "div",
147
+ {
148
+ ref,
149
+ className: `text-sm w-full ${inset ? "pl-8" : ""} ${className ?? ""}`,
150
+ ...props
151
+ }
152
+ );
153
+ });
125
154
  MenuLabel.displayName = "MenuLabel";
126
155
  var MenuContent = forwardRef(
127
156
  ({
@@ -130,9 +159,11 @@ var MenuContent = forwardRef(
130
159
  side = "bottom",
131
160
  sideOffset = 4,
132
161
  children,
162
+ store: externalStore,
133
163
  ...props
134
164
  }, ref) => {
135
- const { open } = useContext(DropdownMenuContext);
165
+ const store = useDropdownStore(externalStore);
166
+ const open = useStore(store, (s) => s.open);
136
167
  const [isVisible, setIsVisible] = useState(open);
137
168
  useEffect(() => {
138
169
  if (open) {
@@ -175,15 +206,18 @@ MenuContent.displayName = "MenuContent";
175
206
  var MenuItem = forwardRef(
176
207
  ({
177
208
  className,
178
- inset,
179
209
  size = "small",
180
210
  children,
181
211
  iconRight,
182
212
  iconLeft,
183
213
  disabled = false,
184
214
  onClick,
215
+ variant = "menu",
216
+ store: externalStore,
185
217
  ...props
186
218
  }, ref) => {
219
+ const store = useDropdownStore(externalStore);
220
+ const setOpen = useStore(store, (s) => s.setOpen);
187
221
  const sizeClasses = ITEM_SIZE_CLASSES[size];
188
222
  const handleClick = (e) => {
189
223
  if (disabled) {
@@ -192,17 +226,27 @@ var MenuItem = forwardRef(
192
226
  return;
193
227
  }
194
228
  onClick?.(e);
229
+ setOpen(false);
230
+ };
231
+ const getVariantClasses = () => {
232
+ if (variant === "profile") {
233
+ return "relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0";
234
+ }
235
+ return "relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0";
236
+ };
237
+ const getVariantProps = () => {
238
+ return variant === "profile" ? { "data-variant": "profile" } : {};
195
239
  };
196
240
  return /* @__PURE__ */ jsxs(
197
241
  "div",
198
242
  {
199
243
  ref,
200
244
  role: "menuitem",
245
+ ...getVariantProps(),
201
246
  "aria-disabled": disabled,
202
247
  className: `
203
248
  focus-visible:bg-background-50
204
- relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0
205
- ${inset && "pl-8"}
249
+ ${getVariantClasses()}
206
250
  ${sizeClasses}
207
251
  ${className}
208
252
  ${disabled ? "cursor-not-allowed text-text-400" : "cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground"}
@@ -223,7 +267,7 @@ var MenuItem = forwardRef(
223
267
  }
224
268
  );
225
269
  MenuItem.displayName = "MenuItem";
226
- var MenuSeparator = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
270
+ var MenuSeparator = forwardRef(({ className, store: _store, ...props }, ref) => /* @__PURE__ */ jsx(
227
271
  "div",
228
272
  {
229
273
  ref,
@@ -232,6 +276,88 @@ var MenuSeparator = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
232
276
  }
233
277
  ));
234
278
  MenuSeparator.displayName = "MenuSeparator";
279
+ var ProfileMenuTrigger = forwardRef(({ className, onClick, store: externalStore, ...props }, ref) => {
280
+ const store = useDropdownStore(externalStore);
281
+ const open = useStore(store, (s) => s.open);
282
+ const toggleOpen = () => store.setState({ open: !open });
283
+ return /* @__PURE__ */ jsx(
284
+ "button",
285
+ {
286
+ ref,
287
+ className: `rounded-lg size-10 bg-background-50 flex items-center justify-center ${className}`,
288
+ onClick: (e) => {
289
+ e.stopPropagation();
290
+ toggleOpen();
291
+ onClick?.(e);
292
+ },
293
+ "aria-expanded": open,
294
+ ...props,
295
+ children: /* @__PURE__ */ jsx("span", { className: "size-6 rounded-full bg-background-100 flex items-center justify-center", children: /* @__PURE__ */ jsx(User, { className: "text-background-950", size: 18 }) })
296
+ }
297
+ );
298
+ });
299
+ ProfileMenuTrigger.displayName = "ProfileMenuTrigger";
300
+ var ProfileMenuHeader = forwardRef(({ className, name, email, store: _store, ...props }, ref) => {
301
+ return /* @__PURE__ */ jsxs(
302
+ "div",
303
+ {
304
+ ref,
305
+ "data-component": "ProfileMenuHeader",
306
+ className: `
307
+ flex flex-row gap-4 items-center
308
+ ${className}
309
+ `,
310
+ ...props,
311
+ children: [
312
+ /* @__PURE__ */ jsx("span", { className: "size-16 bg-background-100 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx(User, { size: 34, className: "text-background-950" }) }),
313
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col ", children: [
314
+ /* @__PURE__ */ jsx("p", { className: "text-xl font-bold text-text-950", children: name }),
315
+ /* @__PURE__ */ jsx("p", { className: "text-md text-text-600", children: email })
316
+ ] })
317
+ ]
318
+ }
319
+ );
320
+ });
321
+ ProfileMenuHeader.displayName = "ProfileMenuHeader";
322
+ var ProfileMenuSection = forwardRef(({ className, children, store: _store, ...props }, ref) => {
323
+ return /* @__PURE__ */ jsx(
324
+ "div",
325
+ {
326
+ ref,
327
+ className: `
328
+ flex flex-col p-2
329
+ ${className}
330
+ `,
331
+ ...props,
332
+ children
333
+ }
334
+ );
335
+ });
336
+ ProfileMenuSection.displayName = "ProfileMenuSection";
337
+ var ProfileMenuFooter = forwardRef(
338
+ ({ className, disabled = false, onClick, store: externalStore, ...props }, ref) => {
339
+ const store = useDropdownStore(externalStore);
340
+ const setOpen = useStore(store, (s) => s.setOpen);
341
+ return /* @__PURE__ */ jsxs(
342
+ "button",
343
+ {
344
+ ref,
345
+ className: `inline-flex items-center justify-center rounded-full cursor-pointer font-medium text-md px-5 py-2.5 w-full bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed ${className}`,
346
+ disabled,
347
+ onClick: (e) => {
348
+ setOpen(false);
349
+ onClick?.(e);
350
+ },
351
+ ...props,
352
+ children: [
353
+ /* @__PURE__ */ jsx("span", { className: "mr-2 flex items-center", children: /* @__PURE__ */ jsx(SignOut, {}) }),
354
+ /* @__PURE__ */ jsx("span", { children: "Sair" })
355
+ ]
356
+ }
357
+ );
358
+ }
359
+ );
360
+ ProfileMenuFooter.displayName = "ProfileMenuFooter";
235
361
  var DropdownMenu_default = DropdownMenu;
236
362
  export {
237
363
  DropdownMenuTrigger,
@@ -239,6 +365,12 @@ export {
239
365
  MenuItem,
240
366
  MenuLabel,
241
367
  MenuSeparator,
242
- DropdownMenu_default as default
368
+ ProfileMenuFooter,
369
+ ProfileMenuHeader,
370
+ ProfileMenuSection,
371
+ ProfileMenuTrigger,
372
+ createDropdownStore,
373
+ DropdownMenu_default as default,
374
+ useDropdownStore
243
375
  };
244
376
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n useState,\n useCallback,\n useContext,\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n useMemo,\n} from 'react';\n\ntype DropdownMenuContextType = {\n open: boolean;\n setOpen: (open: boolean) => void;\n};\n\nconst DropdownMenuContext = createContext<DropdownMenuContextType | undefined>(\n undefined\n);\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({ children, open, onOpenChange }: DropdownMenuProps) => {\n const [internalOpen, setInternalOpen] = useState(false);\n const isControlled = open !== undefined;\n const currentOpen = isControlled ? open : internalOpen;\n\n const setOpen = useCallback(\n (newOpen: boolean) => {\n if (onOpenChange) onOpenChange(newOpen);\n if (!isControlled) setInternalOpen(newOpen);\n },\n [isControlled, onOpenChange]\n );\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n useEffect(() => {\n if (currentOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [currentOpen]);\n\n const value = useMemo(\n () => ({ open: currentOpen, setOpen }),\n [currentOpen, setOpen]\n );\n return (\n <DropdownMenuContext.Provider value={value}>\n <div className=\"relative\" ref={menuRef}>\n {children}\n </div>\n </DropdownMenuContext.Provider>\n );\n};\n\nconst DropdownMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement>\n>(({ className, children, onClick, ...props }, ref) => {\n const context = useContext(DropdownMenuContext);\n if (!context)\n throw new Error('DropdownMenuTrigger must be used within a DropdownMenu');\n\n const { open, setOpen } = context;\n\n return (\n <button\n ref={ref}\n className={`border border-border-200 cursor-pointer bg-background-muted hover:bg-background-200 transition-colors px-4 py-2 rounded-sm ${className}`}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(!open);\n if (onClick) onClick(e);\n }}\n aria-expanded={open}\n {...props}\n >\n {children}\n </button>\n );\n});\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MenuLabel = forwardRef<\n HTMLFieldSetElement,\n HTMLAttributes<HTMLFieldSetElement> & { inset?: boolean }\n>(({ className, inset, ...props }, ref) => (\n <fieldset\n ref={ref}\n role=\"group\"\n className={`text-sm w-full ${inset ? 'pl-8' : ''} ${className ?? ''}`}\n {...props}\n />\n));\nMenuLabel.displayName = 'MenuLabel';\n\nconst MenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n sideOffset?: number;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n sideOffset = 4,\n children,\n ...props\n },\n ref\n ) => {\n const { open } = useContext(DropdownMenuContext)!;\n const [isVisible, setIsVisible] = useState(open);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n return (\n <div\n ref={ref}\n role=\"menu\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${className}\n `}\n style={{\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nMenuContent.displayName = 'MenuContent';\n\nconst MenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n }\n>(\n (\n {\n className,\n inset,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n ...props\n },\n ref\n ) => {\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e as MouseEvent<HTMLDivElement>);\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0\n ${inset && 'pl-8'}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n {children}\n {iconRight}\n </div>\n );\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={`my-1 h-px bg-border-200 ${className}`}\n {...props}\n />\n));\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport default DropdownMenu;\nexport { DropdownMenuTrigger, MenuContent, MenuItem, MenuLabel, MenuSeparator };\n"],"mappings":";;;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EAIA;AAAA,OACK;AA+FD,cA0KA,YA1KA;AAxFN,IAAM,sBAAsB;AAAA,EAC1B;AACF;AAQA,IAAM,eAAe,CAAC,EAAE,UAAU,MAAM,aAAa,MAAyB;AAC5E,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,eAAe,SAAS;AAC9B,QAAM,cAAc,eAAe,OAAO;AAE1C,QAAM,UAAU;AAAA,IACd,CAAC,YAAqB;AACpB,UAAI,aAAc,cAAa,OAAO;AACtC,UAAI,CAAC,aAAc,iBAAgB,OAAO;AAAA,IAC5C;AAAA,IACA,CAAC,cAAc,YAAY;AAAA,EAC7B;AAEA,QAAM,UAAU,OAA8B,IAAI;AAElD,QAAM,2BAA2B,CAAC,UAAoC;AACpE,UAAM,cAAc,QAAQ,SAAS,cAAc,eAAe;AAClE,QAAI,aAAa;AACf,YAAM,eAAe;AAErB,YAAM,QAAQ,MAAM;AAAA,QAClB,YAAY;AAAA,UACV;AAAA,QACF;AAAA,MACF,EAAE,OAAO,CAAC,OAA0B,cAAc,WAAW;AAE7D,UAAI,MAAM,WAAW,EAAG;AAExB,YAAM,cAAc,SAAS;AAC7B,YAAM,eAAe,MAAM,UAAU,CAAC,SAAS,SAAS,WAAW;AAEnE,UAAI;AACJ,UAAI,MAAM,QAAQ,aAAa;AAC7B,oBAAY,iBAAiB,KAAK,KAAK,eAAe,KAAK,MAAM;AAAA,MACnE,OAAO;AAEL,oBACE,iBAAiB,KACb,MAAM,SAAS,KACd,eAAe,IAAI,MAAM,UAAU,MAAM;AAAA,MAClD;AAEA,YAAM,SAAS,GAAG,MAAM;AAAA,IAC1B;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,UAAoC;AACzD,QAAI,MAAM,QAAQ,UAAU;AAC1B,cAAQ,KAAK;AAAA,IACf,WAAW,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;AAC/D,+BAAyB,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,QAAM,qBAAqB,CAAC,UAAiC;AAC3D,QAAI,QAAQ,WAAW,CAAC,QAAQ,QAAQ,SAAS,MAAM,MAAc,GAAG;AACtE,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAEA,YAAU,MAAM;AACd,QAAI,aAAa;AACf,eAAS,iBAAiB,aAAa,kBAAkB;AACzD,eAAS,iBAAiB,WAAW,aAAa;AAAA,IACpD;AAEA,WAAO,MAAM;AACX,eAAS,oBAAoB,aAAa,kBAAkB;AAC5D,eAAS,oBAAoB,WAAW,aAAa;AAAA,IACvD;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,QAAQ;AAAA,IACZ,OAAO,EAAE,MAAM,aAAa,QAAQ;AAAA,IACpC,CAAC,aAAa,OAAO;AAAA,EACvB;AACA,SACE,oBAAC,oBAAoB,UAApB,EAA6B,OAC5B,8BAAC,SAAI,WAAU,YAAW,KAAK,SAC5B,UACH,GACF;AAEJ;AAEA,IAAM,sBAAsB,WAG1B,CAAC,EAAE,WAAW,UAAU,SAAS,GAAG,MAAM,GAAG,QAAQ;AACrD,QAAM,UAAU,WAAW,mBAAmB;AAC9C,MAAI,CAAC;AACH,UAAM,IAAI,MAAM,wDAAwD;AAE1E,QAAM,EAAE,MAAM,QAAQ,IAAI;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,8HAA8H,SAAS;AAAA,MAClJ,SAAS,CAAC,MAAM;AACd,UAAE,gBAAgB;AAClB,gBAAQ,CAAC,IAAI;AACb,YAAI,QAAS,SAAQ,CAAC;AAAA,MACxB;AAAA,MACA,iBAAe;AAAA,MACd,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ,CAAC;AACD,oBAAoB,cAAc;AAElC,IAAM,oBAAoB;AAAA,EACxB,OAAO;AAAA,EACP,QAAQ;AACV;AAEA,IAAM,eAAe;AAAA,EACnB,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AACR;AAEA,IAAM,gBAAgB;AAAA,EACpB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AACP;AAEA,IAAM,YAAY,WAGhB,CAAC,EAAE,WAAW,OAAO,GAAG,MAAM,GAAG,QACjC;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,MAAK;AAAA,IACL,WAAW,kBAAkB,QAAQ,SAAS,EAAE,IAAI,aAAa,EAAE;AAAA,IAClE,GAAG;AAAA;AACN,CACD;AACD,UAAU,cAAc;AAExB,IAAM,cAAc;AAAA,EAQlB,CACE;AAAA,IACE;AAAA,IACA,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,EAAE,KAAK,IAAI,WAAW,mBAAmB;AAC/C,UAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAE/C,cAAU,MAAM;AACd,UAAI,MAAM;AACR,qBAAa,IAAI;AAAA,MACnB,OAAO;AACL,cAAM,QAAQ,WAAW,MAAM,aAAa,KAAK,GAAG,GAAG;AACvD,eAAO,MAAM,aAAa,KAAK;AAAA,MACjC;AAAA,IACF,GAAG,CAAC,IAAI,CAAC;AAET,QAAI,CAAC,UAAW,QAAO;AAEvB,UAAM,qBAAqB,MAAM;AAC/B,YAAM,WAAW,aAAa,IAAI;AAClC,YAAM,aAAa,cAAc,KAAK;AAEtC,aAAO,YAAY,QAAQ,IAAI,UAAU;AAAA,IAC3C;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW;AAAA;AAAA,UAET,OAAO,oCAAoC,oCAAoC;AAAA,UAC/E,mBAAmB,CAAC;AAAA,UACpB,SAAS;AAAA;AAAA,QAEX,OAAO;AAAA,UACL,WAAW,SAAS,WAAW,aAAa;AAAA,UAC5C,cAAc,SAAS,QAAQ,aAAa;AAAA,UAC5C,YAAY,SAAS,UAAU,aAAa;AAAA,UAC5C,aAAa,SAAS,SAAS,aAAa;AAAA,QAC9C;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AAEA,YAAY,cAAc;AAE1B,IAAM,WAAW;AAAA,EAUf,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,cAAc,kBAAkB,IAAI;AAE1C,UAAM,cAAc,CAClB,MACG;AACH,UAAI,UAAU;AACZ,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB;AAAA,MACF;AACA,gBAAU,CAA+B;AAAA,IAC3C;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,iBAAe;AAAA,QACf,WAAW;AAAA;AAAA;AAAA,YAGP,SAAS,MAAM;AAAA,YACf,WAAW;AAAA,YACX,SAAS;AAAA,YAET,WACI,qCACA,+IACN;AAAA;AAAA,QAEF,SAAS;AAAA,QACT,WAAW,CAAC,MAAM;AAChB,cAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,IAAK,aAAY,CAAC;AAAA,QACvD;AAAA,QACA,UAAU,WAAW,KAAK;AAAA,QACzB,GAAG;AAAA,QAEH;AAAA;AAAA,UACA;AAAA,UACA;AAAA;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AACA,SAAS,cAAc;AAEvB,IAAM,gBAAgB,WAGpB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,2BAA2B,SAAS;AAAA,IAC9C,GAAG;AAAA;AACN,CACD;AACD,cAAc,cAAc;AAE5B,IAAO,uBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["'use client';\n\nimport { SignOut, User } from 'phosphor-react';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n} from 'react';\nimport { create, StoreApi, useStore } from 'zustand';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n setOpen: (open) => set({ open }),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n const newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {\n store,\n };\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({ children, open, onOpenChange }: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const isControlled = open !== undefined;\n const uncontrolledOpen = useStore(store, (s) => s.open);\n const currentOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = (newOpen: boolean) => {\n onOpenChange?.(newOpen);\n if (!isControlled) store.setState({ open: newOpen });\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n const menuContent = menuRef.current?.querySelector('[role=\"menu\"]');\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.findIndex((item) => item === focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: globalThis.MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n useEffect(() => {\n onOpenChange?.(currentOpen);\n if (currentOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [currentOpen]);\n\n useEffect(() => {\n if (isControlled) {\n store.setState({ open: open });\n }\n }, []);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, children, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={`border border-border-200 cursor-pointer bg-background-muted hover:bg-background-200 transition-colors px-4 py-2 rounded-sm ${className}`}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n if (onClick) onClick(e);\n }}\n aria-expanded={open}\n {...props}\n >\n {children}\n </button>\n );\n});\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`text-sm w-full ${inset ? 'pl-8' : ''} ${className ?? ''}`}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst MenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n sideOffset?: number;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n sideOffset = 4,\n children,\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n return (\n <div\n ref={ref}\n role=\"menu\"\n className={`\n bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md border-border-100\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${className}\n `}\n style={{\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\nconst MenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e as MouseEvent<HTMLDivElement>);\n setOpen(false);\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClick(e);\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n {children}\n {iconRight}\n </div>\n );\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={`my-1 h-px bg-border-200 ${className}`}\n {...props}\n />\n));\nMenuSeparator.displayName = 'MenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={`rounded-lg size-10 bg-background-50 flex items-center justify-center ${className}`}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-background-100 flex items-center justify-center\">\n <User className=\"text-background-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={`\n flex flex-row gap-4 items-center\n ${className}\n `}\n {...props}\n >\n <span className=\"size-16 bg-background-100 rounded-full flex items-center justify-center\">\n <User size={34} className=\"text-background-950\" />\n </span>\n <div className=\"flex flex-col \">\n <p className=\"text-xl font-bold text-text-950\">{name}</p>\n <p className=\"text-md text-text-600\">{email}</p>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={`\n flex flex-col p-2\n ${className}\n `}\n {...props}\n >\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = forwardRef<\n HTMLButtonElement,\n HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n }\n>(\n (\n { className, disabled = false, onClick, store: externalStore, ...props },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <button\n ref={ref}\n className={`inline-flex items-center justify-center rounded-full cursor-pointer font-medium text-md px-5 py-2.5 w-full bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed ${className}`}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOut />\n </span>\n <span>Sair</span>\n </button>\n );\n }\n);\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n MenuContent,\n MenuItem,\n MenuLabel,\n MenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,60 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Progress bar size variants
6
+ */
7
+ type ProgressBarSize = 'small' | 'medium';
8
+ /**
9
+ * Progress bar color variants
10
+ */
11
+ type ProgressBarVariant = 'blue' | 'green';
12
+ /**
13
+ * ProgressBar component props interface
14
+ */
15
+ type ProgressBarProps = {
16
+ /** Progress value between 0 and 100 */
17
+ value: number;
18
+ /** Maximum value (defaults to 100) */
19
+ max?: number;
20
+ /** Size variant of the progress bar */
21
+ size?: ProgressBarSize;
22
+ /** Color variant of the progress bar */
23
+ variant?: ProgressBarVariant;
24
+ /** Optional label to display */
25
+ label?: ReactNode;
26
+ /** Show percentage text */
27
+ showPercentage?: boolean;
28
+ /** Additional CSS classes */
29
+ className?: string;
30
+ /** Label CSS classes */
31
+ labelClassName?: string;
32
+ /** Percentage text CSS classes */
33
+ percentageClassName?: string;
34
+ };
35
+ /**
36
+ * ProgressBar component for Analytica Ensino platforms
37
+ *
38
+ * A progress bar component with size and color variants designed for tracking
39
+ * activity progress (blue) and performance metrics (green).
40
+ * Uses the Analytica Ensino Design System colors from styles.css with automatic
41
+ * light/dark mode support. Includes Text component integration for consistent typography.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * // Basic progress bar
46
+ * <ProgressBar value={65} />
47
+ *
48
+ * // Activity progress (blue)
49
+ * <ProgressBar variant="blue" value={45} label="Progress" showPercentage />
50
+ *
51
+ * // Performance metrics (green)
52
+ * <ProgressBar variant="green" size="medium" value={85} label="Performance" />
53
+ *
54
+ * // Small size with custom max value
55
+ * <ProgressBar size="small" value={3} max={5} showPercentage />
56
+ * ```
57
+ */
58
+ declare const ProgressBar: ({ value, max, size, variant, label, showPercentage, className, labelClassName, percentageClassName, }: ProgressBarProps) => react_jsx_runtime.JSX.Element;
59
+
60
+ export { type ProgressBarProps, ProgressBar as default };
@@ -0,0 +1,60 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Progress bar size variants
6
+ */
7
+ type ProgressBarSize = 'small' | 'medium';
8
+ /**
9
+ * Progress bar color variants
10
+ */
11
+ type ProgressBarVariant = 'blue' | 'green';
12
+ /**
13
+ * ProgressBar component props interface
14
+ */
15
+ type ProgressBarProps = {
16
+ /** Progress value between 0 and 100 */
17
+ value: number;
18
+ /** Maximum value (defaults to 100) */
19
+ max?: number;
20
+ /** Size variant of the progress bar */
21
+ size?: ProgressBarSize;
22
+ /** Color variant of the progress bar */
23
+ variant?: ProgressBarVariant;
24
+ /** Optional label to display */
25
+ label?: ReactNode;
26
+ /** Show percentage text */
27
+ showPercentage?: boolean;
28
+ /** Additional CSS classes */
29
+ className?: string;
30
+ /** Label CSS classes */
31
+ labelClassName?: string;
32
+ /** Percentage text CSS classes */
33
+ percentageClassName?: string;
34
+ };
35
+ /**
36
+ * ProgressBar component for Analytica Ensino platforms
37
+ *
38
+ * A progress bar component with size and color variants designed for tracking
39
+ * activity progress (blue) and performance metrics (green).
40
+ * Uses the Analytica Ensino Design System colors from styles.css with automatic
41
+ * light/dark mode support. Includes Text component integration for consistent typography.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * // Basic progress bar
46
+ * <ProgressBar value={65} />
47
+ *
48
+ * // Activity progress (blue)
49
+ * <ProgressBar variant="blue" value={45} label="Progress" showPercentage />
50
+ *
51
+ * // Performance metrics (green)
52
+ * <ProgressBar variant="green" size="medium" value={85} label="Performance" />
53
+ *
54
+ * // Small size with custom max value
55
+ * <ProgressBar size="small" value={3} max={5} showPercentage />
56
+ * ```
57
+ */
58
+ declare const ProgressBar: ({ value, max, size, variant, label, showPercentage, className, labelClassName, percentageClassName, }: ProgressBarProps) => react_jsx_runtime.JSX.Element;
59
+
60
+ export { type ProgressBarProps, ProgressBar as default };