@socprime/react-ui 0.0.8 → 0.0.10

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 CHANGED
@@ -125,7 +125,7 @@ Deep imports such as `@socprime/react-ui/dist/ui/Button` are blocked by the `exp
125
125
  `Aside`, `PageHeader`, `Tabs`, `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`, `AccordionSection`, `FolderTreeExpandTrigger`, `ScrollArea`, `ScrollBar`, `Separator`, `TreeGuide`, `TreeRow`
126
126
 
127
127
  **Feedback and state**
128
- `Spinner`, `SpinnerCustom`, `SpinnerSquare`, `AnimatedDots`, `Skeleton`, `ConditionalContent`
128
+ `Spinner`, `SpinnerCustom`, `SpinnerSquare`, `AnimatedDots`, `Skeleton`, `Progress`, `ConditionalContent`
129
129
 
130
130
  **Theming**
131
131
  `ThemeToggle`, `applyTheme`, `useDocumentTheme`, `ThemeName`
package/domain.d.ts CHANGED
@@ -1,6 +1,18 @@
1
1
  import * as React$1 from 'react';
2
2
  import { ComponentProps } from 'react';
3
3
 
4
+ interface AttackTimelineStep {
5
+ name: string;
6
+ description: string;
7
+ hit: boolean;
8
+ code: string;
9
+ }
10
+
11
+ interface AttackTimelineProps {
12
+ steps?: AttackTimelineStep[];
13
+ }
14
+ declare const AttackTimeline: React.FC<AttackTimelineProps>;
15
+
4
16
  interface CorrelationTimerProps {
5
17
  isRunning: boolean;
6
18
  runningTime?: number | null;
@@ -20,4 +32,4 @@ declare const SyncProcessBar: () => React$1.JSX.Element;
20
32
 
21
33
  type SyncProcessBarProps = ComponentProps<typeof SyncProcessBar>;
22
34
 
23
- export { CorrelationTimer, type CorrelationTimerProps, Severity, type SeverityProps, SyncProcessBar, type SyncProcessBarProps, type TSeverity };
35
+ export { AttackTimeline, type AttackTimelineProps, type AttackTimelineStep, CorrelationTimer, type CorrelationTimerProps, Severity, type SeverityProps, SyncProcessBar, type SyncProcessBarProps, type TSeverity };
package/index.d.ts CHANGED
@@ -10,6 +10,7 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
10
10
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
11
11
  import * as LabelPrimitive from '@radix-ui/react-label';
12
12
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
13
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
13
14
  import { Root, Item } from '@radix-ui/react-radio-group';
14
15
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
15
16
  import * as SelectPrimitive from '@radix-ui/react-select';
@@ -73,6 +74,12 @@ interface AsideProps {
73
74
  }
74
75
  declare const Aside: React.FC<AsideProps>;
75
76
 
77
+ interface AsideHorizontalProps {
78
+ tabs: AsideTab[];
79
+ className?: string;
80
+ }
81
+ declare const AsideHorizontal: React.FC<AsideHorizontalProps>;
82
+
76
83
  declare const badgeVariants: (props?: ({
77
84
  variant?: "secondary" | "outline" | "yellow" | "purple" | "default" | "dark" | "defaultOutline" | "warning" | "critical" | "success" | "lightBlue" | "redViolet" | null | undefined;
78
85
  } & class_variance_authority_types.ClassProp) | undefined) => string;
@@ -376,6 +383,22 @@ interface LabelInfoProps extends React.ComponentProps<typeof LabelPrimitive.Root
376
383
  }
377
384
  declare const LabelInfo: React.FC<LabelInfoProps>;
378
385
 
386
+ interface MobileNavItem {
387
+ id: string;
388
+ label: string;
389
+ icon: React.FC<{
390
+ className?: string;
391
+ }>;
392
+ to?: string;
393
+ }
394
+ interface MobileNavProps {
395
+ items: MobileNavItem[];
396
+ logo?: React.ReactNode;
397
+ title?: string;
398
+ className?: string;
399
+ }
400
+ declare const MobileNav: React.FC<MobileNavProps>;
401
+
379
402
  interface MultiSelectOption {
380
403
  label: string;
381
404
  value: string;
@@ -450,6 +473,11 @@ type PaginationItemProps = ComponentProps<typeof PaginationItem>;
450
473
  type PaginationNextProps = ComponentProps<typeof PaginationNext>;
451
474
  type PaginationPreviousProps = ComponentProps<typeof PaginationPrevious>;
452
475
 
476
+ interface ProgressProps extends React$1.ComponentProps<typeof ProgressPrimitive.Root> {
477
+ indicatorClassName?: string;
478
+ }
479
+ declare const Progress: React$1.FC<ProgressProps>;
480
+
453
481
  declare function RadioGroup({ className, ...props }: React$1.ComponentProps<typeof Root>): React$1.JSX.Element;
454
482
  declare function RadioGroupItem({ className, ...props }: React$1.ComponentProps<typeof Item>): React$1.JSX.Element;
455
483
 
@@ -503,6 +531,7 @@ interface SelectDefaultProps {
503
531
  loading?: boolean;
504
532
  disabled?: boolean;
505
533
  style?: React.CSSProperties;
534
+ icon?: React.ReactNode;
506
535
  renderItemLabel?: (value: string) => React.ReactNode;
507
536
  renderTriggerLabel?: (value: string) => React.ReactNode;
508
537
  onChange?: (value: string) => void;
@@ -706,4 +735,4 @@ declare function TreeRow({ className, children, ...props }: ComponentProps<'div'
706
735
  type TreeGuideProps = ComponentProps<typeof TreeGuide>;
707
736
  type TreeRowProps = ComponentProps<typeof TreeRow>;
708
737
 
709
- export { Accordion, type AccordionChevronVariant, AccordionContent, type AccordionContentProps, AccordionItem, type AccordionItemProps, type AccordionProps, AccordionSection, type AccordionSectionProps, AccordionTrigger, type AccordionTriggerProps, AnimatedDots, type AnimatedDotsProps, Aside, type AsideProps, type AsideTab, Badge, type BadgeProps, Button, type ButtonProps, Checkbox, type CheckboxProps, ConditionalContent, type ConditionalContentProps, ConfirmDeleteDialog, type ConfirmDeleteDialogProps, ConfirmDeleteDialog as ConfirmDialog, DefaultDialog, type DefaultDialogProps, DeleteButtonConfirm, type DeleteButtonConfirmProps, Dialog, DialogClose, type DialogCloseProps, DialogContent, type DialogContentProps, DialogDescription, type DialogDescriptionProps, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogOverlay, type DialogOverlayProps, DialogPortal, type DialogPortalProps, type DialogProps, DialogTitle, type DialogTitleProps, DialogTrigger, type DialogTriggerProps, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, type DropdownMenuGroupProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, type DropdownMenuPortalProps, type DropdownMenuProps, DropdownMenuRadioGroup, type DropdownMenuRadioGroupProps, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, type DropdownMenuSeparatorProps, DropdownMenuShortcut, type DropdownMenuShortcutProps, DropdownMenuSub, DropdownMenuSubContent, type DropdownMenuSubContentProps, type DropdownMenuSubProps, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, type DropdownMenuTriggerProps, DropdownsCheckbox, type DropdownsCheckboxOption, type DropdownsCheckboxProps, DropdownsSelect, type DropdownsSelectOption, type DropdownsSelectProps, EmptyState, type EmptyStateProps, Field, FieldContent, type FieldContentProps, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorProps, FieldGroup, type FieldGroupProps, FieldLabel, type FieldLabelProps, FieldLegend, type FieldLegendProps, type FieldProps, FieldSeparator, type FieldSeparatorProps, FieldSet, type FieldSetProps, FieldTitle, type FieldTitleProps, FolderTreeExpandTrigger, type FolderTreeExpandTriggerProps, GroupHeaderRow, type GroupHeaderRowProps, HelperText, type HelperTextProps, Input, InputNumber, type InputNumberProps, InputPassword, type InputPasswordProps, type InputProps, Label, LabelInfo, type LabelInfoProps, type LabelProps, MultiSelect, type MultiSelectOption, type MultiSelectProps, PageHeader, type PageHeaderProps, Pagination, PaginationContent, type PaginationContentProps, PaginationEllipsis, type PaginationEllipsisProps, PaginationItem, type PaginationItemProps, PaginationLink, type PaginationLinkProps, PaginationNext, type PaginationNextProps, PaginationPrevious, type PaginationPreviousProps, type PaginationProps, PaginationWrap, type PaginationWrapProps, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, ScrollArea, type ScrollAreaOrientation, type ScrollAreaProps, ScrollBar, SearchInput, SearchInputFields, type SearchInputFieldsProps, type SearchInputProps, Select, SelectContent, type SelectContentProps, SelectDefault, type SelectDefaultProps, SelectGroup, type SelectGroupProps, SelectItem, type SelectItemProps, SelectLabel, type SelectLabelProps, type SelectProps, SelectScrollDownButton, type SelectScrollDownButtonProps, SelectScrollUpButton, type SelectScrollUpButtonProps, SelectSeparator, type SelectSeparatorProps, SelectTrigger, type SelectTriggerProps, SelectValue, type SelectValueProps, Separator, type SeparatorProps, ServerGroupedTableBody, type ServerGroupedTableBodyProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Slider, type SliderProps, SortableHeader, type SortableHeaderProps, Spinner, SpinnerCircle, type SpinnerCircleProps, SpinnerCustom, type SpinnerProps, SpinnerSquare, type SpinnerSquareProps, type SuggestionOption, Suggestions, type SuggestionsProps, Switch, type SwitchProps, type TabItem, Table, TableBody, type TableBodyProps, TableCaption, type TableCaptionProps, TableCell, type TableCellProps, TableFooter, type TableFooterProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, TableWrap, type TableWrapProps, Tabs, type TabsProps, TextTruncate, type TextTruncateProps, Textarea, type TextareaProps, ThemeToggle, type ThemeToggleProps, Toaster, Tooltip, TooltipContent, type TooltipContentProps, TooltipParent, type TooltipParentProps, type TooltipProps, TooltipProvider, type TooltipProviderProps, TooltipTrigger, type TooltipTriggerProps, TreeGuide, type TreeGuideProps, TreeRow, type TreeRowProps, badgeVariants, buttonVariants };
738
+ export { Accordion, type AccordionChevronVariant, AccordionContent, type AccordionContentProps, AccordionItem, type AccordionItemProps, type AccordionProps, AccordionSection, type AccordionSectionProps, AccordionTrigger, type AccordionTriggerProps, AnimatedDots, type AnimatedDotsProps, Aside, AsideHorizontal, type AsideHorizontalProps, type AsideProps, type AsideTab, Badge, type BadgeProps, Button, type ButtonProps, Checkbox, type CheckboxProps, ConditionalContent, type ConditionalContentProps, ConfirmDeleteDialog, type ConfirmDeleteDialogProps, ConfirmDeleteDialog as ConfirmDialog, DefaultDialog, type DefaultDialogProps, DeleteButtonConfirm, type DeleteButtonConfirmProps, Dialog, DialogClose, type DialogCloseProps, DialogContent, type DialogContentProps, DialogDescription, type DialogDescriptionProps, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogOverlay, type DialogOverlayProps, DialogPortal, type DialogPortalProps, type DialogProps, DialogTitle, type DialogTitleProps, DialogTrigger, type DialogTriggerProps, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, type DropdownMenuGroupProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, type DropdownMenuPortalProps, type DropdownMenuProps, DropdownMenuRadioGroup, type DropdownMenuRadioGroupProps, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, type DropdownMenuSeparatorProps, DropdownMenuShortcut, type DropdownMenuShortcutProps, DropdownMenuSub, DropdownMenuSubContent, type DropdownMenuSubContentProps, type DropdownMenuSubProps, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, type DropdownMenuTriggerProps, DropdownsCheckbox, type DropdownsCheckboxOption, type DropdownsCheckboxProps, DropdownsSelect, type DropdownsSelectOption, type DropdownsSelectProps, EmptyState, type EmptyStateProps, Field, FieldContent, type FieldContentProps, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorProps, FieldGroup, type FieldGroupProps, FieldLabel, type FieldLabelProps, FieldLegend, type FieldLegendProps, type FieldProps, FieldSeparator, type FieldSeparatorProps, FieldSet, type FieldSetProps, FieldTitle, type FieldTitleProps, FolderTreeExpandTrigger, type FolderTreeExpandTriggerProps, GroupHeaderRow, type GroupHeaderRowProps, HelperText, type HelperTextProps, Input, InputNumber, type InputNumberProps, InputPassword, type InputPasswordProps, type InputProps, Label, LabelInfo, type LabelInfoProps, type LabelProps, MobileNav, type MobileNavItem, type MobileNavProps, MultiSelect, type MultiSelectOption, type MultiSelectProps, PageHeader, type PageHeaderProps, Pagination, PaginationContent, type PaginationContentProps, PaginationEllipsis, type PaginationEllipsisProps, PaginationItem, type PaginationItemProps, PaginationLink, type PaginationLinkProps, PaginationNext, type PaginationNextProps, PaginationPrevious, type PaginationPreviousProps, type PaginationProps, PaginationWrap, type PaginationWrapProps, Progress, type ProgressProps, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, ScrollArea, type ScrollAreaOrientation, type ScrollAreaProps, ScrollBar, SearchInput, SearchInputFields, type SearchInputFieldsProps, type SearchInputProps, Select, SelectContent, type SelectContentProps, SelectDefault, type SelectDefaultProps, SelectGroup, type SelectGroupProps, SelectItem, type SelectItemProps, SelectLabel, type SelectLabelProps, type SelectProps, SelectScrollDownButton, type SelectScrollDownButtonProps, SelectScrollUpButton, type SelectScrollUpButtonProps, SelectSeparator, type SelectSeparatorProps, SelectTrigger, type SelectTriggerProps, SelectValue, type SelectValueProps, Separator, type SeparatorProps, ServerGroupedTableBody, type ServerGroupedTableBodyProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Slider, type SliderProps, SortableHeader, type SortableHeaderProps, Spinner, SpinnerCircle, type SpinnerCircleProps, SpinnerCustom, type SpinnerProps, SpinnerSquare, type SpinnerSquareProps, type SuggestionOption, Suggestions, type SuggestionsProps, Switch, type SwitchProps, type TabItem, Table, TableBody, type TableBodyProps, TableCaption, type TableCaptionProps, TableCell, type TableCellProps, TableFooter, type TableFooterProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, TableWrap, type TableWrapProps, Tabs, type TabsProps, TextTruncate, type TextTruncateProps, Textarea, type TextareaProps, ThemeToggle, type ThemeToggleProps, Toaster, Tooltip, TooltipContent, type TooltipContentProps, TooltipParent, type TooltipParentProps, type TooltipProps, TooltipProvider, type TooltipProviderProps, TooltipTrigger, type TooltipTriggerProps, TreeGuide, type TreeGuideProps, TreeRow, type TreeRowProps, badgeVariants, buttonVariants };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@socprime/react-ui",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "SOC Prime React UI component library and Storybook design system.",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -92,6 +92,7 @@
92
92
  "@radix-ui/react-label": "^2.1.8",
93
93
  "@radix-ui/react-navigation-menu": "^1.2.14",
94
94
  "@radix-ui/react-popover": "^1.1.15",
95
+ "@radix-ui/react-progress": "^1.1.8",
95
96
  "@radix-ui/react-radio-group": "^1.3.8",
96
97
  "@radix-ui/react-scroll-area": "^1.2.10",
97
98
  "@radix-ui/react-select": "^2.2.6",
@@ -0,0 +1,39 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from "react";
3
+ import { Link, useLocation } from "react-router-dom";
4
+ import { cn } from "../../lib/cn.js";
5
+ const AsideHorizontal = ({ tabs, className }) => {
6
+ const { pathname } = useLocation();
7
+ const activeRef = useRef(null);
8
+ useEffect(() => {
9
+ activeRef.current?.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
10
+ }, [pathname]);
11
+ const links = tabs.filter(({ title }) => !title);
12
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
13
+ /* @__PURE__ */ jsx("div", { className: "flex snap-x gap-2 overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: links.map(({ id, label, icon, to }) => {
14
+ const Icon = icon || void 0;
15
+ const isActive = pathname.startsWith(id);
16
+ return /* @__PURE__ */ jsxs(
17
+ Link,
18
+ {
19
+ ref: isActive ? activeRef : void 0,
20
+ to: to ?? id,
21
+ className: cn(
22
+ "flex shrink-0 snap-start items-center gap-2 rounded-full border px-4 py-2 text-xs font-medium whitespace-nowrap transition-colors",
23
+ isActive ? "border-btn-primary/50 bg-btn-primary/10 text-foreground [&_svg]:text-btn-primary" : "border-border text-subdued hover:bg-hover hover:text-foreground"
24
+ ),
25
+ children: [
26
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "size-4" }),
27
+ label
28
+ ]
29
+ },
30
+ id
31
+ );
32
+ }) }),
33
+ /* @__PURE__ */ jsx("div", { className: "from-primary pointer-events-none absolute inset-y-0 left-0 w-6 bg-gradient-to-r to-transparent" }),
34
+ /* @__PURE__ */ jsx("div", { className: "from-primary pointer-events-none absolute inset-y-0 right-0 w-6 bg-gradient-to-l to-transparent" })
35
+ ] });
36
+ };
37
+ export {
38
+ AsideHorizontal
39
+ };
package/ui/Aside/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { Aside } from "./Aside.js";
2
+ import { AsideHorizontal } from "./AsideHorizontal.js";
2
3
  export {
3
- Aside
4
+ Aside,
5
+ AsideHorizontal
4
6
  };
@@ -0,0 +1,35 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { CyberpunkCorner } from "./CyberpunkCorner.js";
3
+ import { TimelineDividers } from "./TimelineDividers.js";
4
+ import { TimelineSegments } from "./TimelineSegments.js";
5
+ import { TimelineStepItem } from "./TimelineStepItem.js";
6
+ import { useTimeline } from "./useTimeline.js";
7
+ const AttackTimeline = ({ steps }) => {
8
+ const { mouseX, timelineWidth, handleMouseMove, handleMouseLeave } = useTimeline();
9
+ if (!steps) {
10
+ return null;
11
+ }
12
+ return /* @__PURE__ */ jsxs("div", { className: "relative p-[12px]", children: [
13
+ /* @__PURE__ */ jsx(CyberpunkCorner, { position: "top-left" }),
14
+ /* @__PURE__ */ jsx(CyberpunkCorner, { position: "top-right" }),
15
+ /* @__PURE__ */ jsx(CyberpunkCorner, { position: "bottom-left" }),
16
+ /* @__PURE__ */ jsx(CyberpunkCorner, { position: "bottom-right" }),
17
+ /* @__PURE__ */ jsx("div", { className: "mb-4 flex items-center gap-2" }),
18
+ /* @__PURE__ */ jsxs(
19
+ "div",
20
+ {
21
+ className: "relative flex w-full items-start justify-between pt-2.5",
22
+ onMouseMove: handleMouseMove,
23
+ onMouseLeave: handleMouseLeave,
24
+ children: [
25
+ /* @__PURE__ */ jsx(TimelineSegments, { steps }),
26
+ /* @__PURE__ */ jsx(TimelineDividers, { mouseX, timelineWidth }),
27
+ steps.map((step, index) => /* @__PURE__ */ jsx(TimelineStepItem, { step, index, totalSteps: steps.length }, index))
28
+ ]
29
+ }
30
+ )
31
+ ] });
32
+ };
33
+ export {
34
+ AttackTimeline
35
+ };
@@ -0,0 +1,29 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useThemeColors } from "../../lib/useThemeColors.js";
3
+ const GLOW_SHADOW = "0 0 8px rgba(74, 193, 142, 0.6)";
4
+ const CyberpunkCorner = ({ position }) => {
5
+ const { success } = useThemeColors();
6
+ const isTop = position.startsWith("top");
7
+ const isLeft = position.endsWith("left");
8
+ const edge = isTop ? "top-0" : "bottom-0";
9
+ const side = isLeft ? "left-0" : "right-0";
10
+ return /* @__PURE__ */ jsxs("div", { className: `pointer-events-none absolute ${edge} ${side} h-3 w-3`, children: [
11
+ /* @__PURE__ */ jsx(
12
+ "div",
13
+ {
14
+ className: `absolute ${edge} ${side} h-[1px] w-3`,
15
+ style: { backgroundColor: success, boxShadow: GLOW_SHADOW }
16
+ }
17
+ ),
18
+ /* @__PURE__ */ jsx(
19
+ "div",
20
+ {
21
+ className: `absolute ${edge} ${side} h-3 w-[1px]`,
22
+ style: { backgroundColor: success, boxShadow: GLOW_SHADOW }
23
+ }
24
+ )
25
+ ] });
26
+ };
27
+ export {
28
+ CyberpunkCorner
29
+ };
@@ -0,0 +1,36 @@
1
+ import { Fragment, jsx } from "react/jsx-runtime";
2
+ import { memo, useMemo } from "react";
3
+ import { calculateLineHeight } from "./useTimeline.js";
4
+ const TOTAL_MARKS = Math.floor(100 / 0.4);
5
+ const TimelineDividers = memo(
6
+ ({ mouseX, timelineWidth }) => {
7
+ const marks = useMemo(
8
+ () => Array.from({ length: TOTAL_MARKS }, (_, i) => {
9
+ const leftPosition = i * 0.4;
10
+ const height = calculateLineHeight(leftPosition, mouseX, timelineWidth);
11
+ const opacity = i % 3 === 0 ? 0.6 : 0.4;
12
+ const topOffset = 16 - height / 2;
13
+ return { i, leftPosition, height, opacity, topOffset };
14
+ }),
15
+ [mouseX, timelineWidth]
16
+ );
17
+ return /* @__PURE__ */ jsx(Fragment, { children: marks.map(({ i, leftPosition, height, opacity, topOffset }) => /* @__PURE__ */ jsx(
18
+ "div",
19
+ {
20
+ className: "absolute w-[1px] bg-[#3b3d4f] transition-all duration-75",
21
+ style: {
22
+ height: `${height}px`,
23
+ opacity,
24
+ left: `${leftPosition}%`,
25
+ top: `${topOffset}px`,
26
+ zIndex: 0
27
+ }
28
+ },
29
+ `mark-${i}`
30
+ )) });
31
+ }
32
+ );
33
+ TimelineDividers.displayName = "TimelineDividers";
34
+ export {
35
+ TimelineDividers
36
+ };
@@ -0,0 +1,42 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ const getSegmentColor = (current, next) => {
3
+ const isActiveStatus = (s) => s.hit === true || s.hit === false;
4
+ const currentActive = isActiveStatus(current);
5
+ const nextActive = isActiveStatus(next);
6
+ if (currentActive && nextActive) {
7
+ return "#4ac18e";
8
+ }
9
+ if (currentActive && !nextActive) {
10
+ return "linear-gradient(to right, #4ac18e, #3b3d4f)";
11
+ }
12
+ if (!currentActive && nextActive) {
13
+ return "linear-gradient(to right, #3b3d4f, #4ac18e)";
14
+ }
15
+ return "#3b3d4f";
16
+ };
17
+ const TimelineSegments = ({ steps }) => {
18
+ const segmentWidth = 100 / steps.length;
19
+ return steps.map((step, index) => {
20
+ if (index === steps.length - 1) {
21
+ return null;
22
+ }
23
+ const leftPosition = index * segmentWidth + segmentWidth / 2;
24
+ const lineColor = getSegmentColor(step, steps[index + 1]);
25
+ return /* @__PURE__ */ jsx(
26
+ "div",
27
+ {
28
+ className: "absolute top-4 h-[1px]",
29
+ style: {
30
+ left: `${leftPosition}%`,
31
+ width: `${segmentWidth}%`,
32
+ background: lineColor,
33
+ zIndex: 1
34
+ }
35
+ },
36
+ `segment-${index}`
37
+ );
38
+ });
39
+ };
40
+ export {
41
+ TimelineSegments
42
+ };
@@ -0,0 +1,58 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { ScrollArea } from "../ScrollArea/index.js";
3
+ import { Tooltip } from "../Tooltip/index.js";
4
+ const TimelineStepItem = ({ step, totalSteps }) => {
5
+ return /* @__PURE__ */ jsxs(
6
+ "div",
7
+ {
8
+ className: "relative flex flex-col items-center text-center",
9
+ style: { width: `${100 / totalSteps}%`, zIndex: 1 },
10
+ children: [
11
+ /* @__PURE__ */ jsx(
12
+ Tooltip,
13
+ {
14
+ className: "border-border bg-secondary w-[820px] border py-4 text-center",
15
+ classNameArrow: "bg-secondary fill-secondary",
16
+ content: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
17
+ /* @__PURE__ */ jsxs("div", { className: "text-default mb-1 text-xs font-medium", children: [
18
+ step.name,
19
+ " ",
20
+ /* @__PURE__ */ jsxs("span", { className: `${step.hit ? "text-success" : "text-gray-chateau/80"} text-xs`, children: [
21
+ "(",
22
+ step.code,
23
+ ")"
24
+ ] })
25
+ ] }),
26
+ /* @__PURE__ */ jsx(
27
+ ScrollArea,
28
+ {
29
+ orientation: "vertical",
30
+ className: "max-h-[300px]",
31
+ onWheel: (event) => event.stopPropagation(),
32
+ children: /* @__PURE__ */ jsx("div", { className: "text-subdued text-2xs", children: step.description })
33
+ }
34
+ )
35
+ ] }),
36
+ children: /* @__PURE__ */ jsx("div", { className: "group mb-4", children: /* @__PURE__ */ jsx(
37
+ "div",
38
+ {
39
+ className: `h-[13px] w-[13px] rotate-45 transform shadow-[0_0_0_4px_#252838] transition-all duration-300 ${step.hit ? "group-hover:border-success group-hover:bg-success border-success bg-secondary border-[1.5px] group-hover:scale-150 group-hover:shadow-[0_0_16px_rgba(74,193,142,0.6)]" : "bg-secondary border-gray-chateau/80 border-[1.5px]"}`,
40
+ children: step.hit && /* @__PURE__ */ jsx("div", { className: "bg-success absolute top-1/2 left-1/2 h-1 w-1 -translate-x-1/2 -translate-y-1/2 transform" })
41
+ }
42
+ ) })
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsx(
46
+ "span",
47
+ {
48
+ className: `text-3xs font-medium ${step.hit ? "text-default" : "text-gray-chateau/80"}`,
49
+ children: step.name
50
+ }
51
+ )
52
+ ]
53
+ }
54
+ );
55
+ };
56
+ export {
57
+ TimelineStepItem
58
+ };
@@ -0,0 +1,4 @@
1
+ import { AttackTimeline } from "./AttackTimeline.js";
2
+ export {
3
+ AttackTimeline
4
+ };
File without changes
@@ -0,0 +1,34 @@
1
+ import { useCallback, useState } from "react";
2
+ const calculateLineHeight = (linePositionPercent, mouseX, timelineWidth) => {
3
+ if (mouseX === null || timelineWidth === 0) return 24;
4
+ const linePositionPx = linePositionPercent / 100 * timelineWidth;
5
+ const distance = Math.abs(mouseX - linePositionPx);
6
+ const maxDistance = 80;
7
+ if (distance > maxDistance) return 24;
8
+ const factor = 1 - distance / maxDistance;
9
+ const maxHeight = 72;
10
+ return 24 + (maxHeight - 24) * factor;
11
+ };
12
+ const useTimeline = () => {
13
+ const [hoveredIndex, setHoveredIndex] = useState(null);
14
+ const [mouseX, setMouseX] = useState(null);
15
+ const [timelineWidth, setTimelineWidth] = useState(0);
16
+ const handleMouseMove = useCallback((e) => {
17
+ const rect = e.currentTarget.getBoundingClientRect();
18
+ setMouseX(e.clientX - rect.left);
19
+ setTimelineWidth(rect.width);
20
+ }, []);
21
+ const handleMouseLeave = useCallback(() => setMouseX(null), []);
22
+ return {
23
+ mouseX,
24
+ hoveredIndex,
25
+ timelineWidth,
26
+ setHoveredIndex,
27
+ handleMouseMove,
28
+ handleMouseLeave
29
+ };
30
+ };
31
+ export {
32
+ calculateLineHeight,
33
+ useTimeline
34
+ };
@@ -0,0 +1,111 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
3
+ import { MenuIcon, XIcon } from "lucide-react";
4
+ import { motion } from "motion/react";
5
+ import { useState } from "react";
6
+ import { Link, useLocation } from "react-router-dom";
7
+ import { cn } from "../../lib/cn.js";
8
+ import { Dialog, DialogClose, DialogOverlay, DialogPortal, DialogTrigger } from "../Dialog/index.js";
9
+ const isPathActive = (pathname, linkTo) => pathname === linkTo || pathname.startsWith(`${linkTo}/`);
10
+ const MobileNav = ({ items, logo, title, className }) => {
11
+ const [open, setOpen] = useState(false);
12
+ const { pathname } = useLocation();
13
+ return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: setOpen, children: [
14
+ /* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
15
+ "button",
16
+ {
17
+ "aria-label": "Open menu",
18
+ className: cn(
19
+ "border-border text-foreground hover:bg-hover flex size-10 cursor-pointer items-center justify-center rounded-full border transition-colors lg:hidden",
20
+ className
21
+ ),
22
+ children: /* @__PURE__ */ jsx(MenuIcon, { className: "size-5" })
23
+ }
24
+ ) }),
25
+ /* @__PURE__ */ jsxs(DialogPortal, { children: [
26
+ /* @__PURE__ */ jsx(DialogOverlay, { className: "backdrop-blur-sm" }),
27
+ /* @__PURE__ */ jsx(DialogPrimitive.Content, { asChild: true, "aria-describedby": void 0, children: /* @__PURE__ */ jsxs(
28
+ motion.div,
29
+ {
30
+ className: "border-border bg-primary fixed inset-y-0 left-0 z-50 flex w-[300px] max-w-[85vw] flex-col border-r shadow-2xl",
31
+ initial: { x: "-100%" },
32
+ animate: { x: 0 },
33
+ transition: { type: "spring", damping: 30, stiffness: 300 },
34
+ children: [
35
+ /* @__PURE__ */ jsxs("div", { className: "border-border flex items-center justify-between border-b px-5 py-4", children: [
36
+ /* @__PURE__ */ jsxs(DialogPrimitive.Title, { className: "flex items-center gap-3", children: [
37
+ logo,
38
+ title && /* @__PURE__ */ jsx("span", { className: "text-lg font-semibold", children: title })
39
+ ] }),
40
+ /* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx(
41
+ "button",
42
+ {
43
+ "aria-label": "Close menu",
44
+ className: "border-border text-foreground hover:bg-hover flex size-9 cursor-pointer items-center justify-center rounded-full border transition-colors",
45
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-4" })
46
+ }
47
+ ) })
48
+ ] }),
49
+ /* @__PURE__ */ jsx("nav", { className: "flex flex-1 flex-col gap-1 overflow-y-auto p-4", children: items.map(({ id, label, icon, to }, index) => {
50
+ const Icon = icon;
51
+ const linkTo = to ?? id;
52
+ const isActive = isPathActive(pathname, linkTo);
53
+ return /* @__PURE__ */ jsx(
54
+ motion.div,
55
+ {
56
+ initial: { opacity: 0, x: -24 },
57
+ animate: { opacity: 1, x: 0 },
58
+ transition: { delay: 0.08 + index * 0.05, duration: 0.25 },
59
+ children: /* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsxs(
60
+ Link,
61
+ {
62
+ to: linkTo,
63
+ className: cn(
64
+ "group relative flex w-full items-center gap-3 rounded-lg px-4 py-3 transition-colors",
65
+ isActive ? "bg-btn-primary/10" : "hover:bg-hover"
66
+ ),
67
+ children: [
68
+ /* @__PURE__ */ jsx(
69
+ "span",
70
+ {
71
+ className: cn(
72
+ "bg-btn-primary absolute inset-y-2 left-0 w-1 rounded-full transition-opacity",
73
+ isActive ? "opacity-100" : "opacity-0"
74
+ )
75
+ }
76
+ ),
77
+ /* @__PURE__ */ jsx(
78
+ Icon,
79
+ {
80
+ className: cn(
81
+ "size-5 transition-colors",
82
+ isActive ? "text-btn-primary" : "text-subdued group-hover:text-foreground"
83
+ )
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsx(
87
+ "span",
88
+ {
89
+ className: cn(
90
+ "text-sm font-medium transition-colors",
91
+ isActive ? "text-foreground" : "text-subdued group-hover:text-foreground"
92
+ ),
93
+ children: label
94
+ }
95
+ )
96
+ ]
97
+ }
98
+ ) })
99
+ },
100
+ id
101
+ );
102
+ }) })
103
+ ]
104
+ }
105
+ ) })
106
+ ] })
107
+ ] });
108
+ };
109
+ export {
110
+ MobileNav
111
+ };
@@ -0,0 +1,4 @@
1
+ import { MobileNav } from "./MobileNav.js";
2
+ export {
3
+ MobileNav
4
+ };
@@ -0,0 +1,33 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as ProgressPrimitive from "@radix-ui/react-progress";
3
+ import { cn } from "../../lib/cn.js";
4
+ const Progress = ({
5
+ className,
6
+ value,
7
+ max = 100,
8
+ indicatorClassName,
9
+ ...props
10
+ }) => {
11
+ const percentage = max > 0 ? Math.min(100, Math.max(0, (value ?? 0) / max * 100)) : 0;
12
+ return /* @__PURE__ */ jsx(
13
+ ProgressPrimitive.Root,
14
+ {
15
+ "data-slot": "progress",
16
+ className: cn("bg-border relative h-1.5 w-full overflow-hidden rounded-full", className),
17
+ value,
18
+ max,
19
+ ...props,
20
+ children: /* @__PURE__ */ jsx(
21
+ ProgressPrimitive.Indicator,
22
+ {
23
+ "data-slot": "progress-indicator",
24
+ className: cn("bg-btn-primary h-full w-full flex-1 transition-all", indicatorClassName),
25
+ style: { transform: `translateX(-${100 - percentage}%)` }
26
+ }
27
+ )
28
+ }
29
+ );
30
+ };
31
+ export {
32
+ Progress
33
+ };
@@ -0,0 +1,4 @@
1
+ import { Progress } from "./Progress.js";
2
+ export {
3
+ Progress
4
+ };
@@ -18,10 +18,16 @@ const SelectDefault = ({
18
18
  loading,
19
19
  disabled,
20
20
  style,
21
+ icon,
21
22
  renderItemLabel,
22
23
  renderTriggerLabel,
23
24
  onChange
24
25
  }) => {
26
+ const selectValueDefault = /* @__PURE__ */ jsx(SelectValue, { placeholder, children: value && renderTriggerLabel ? renderTriggerLabel(value) : void 0 });
27
+ const renderValue = icon ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
28
+ icon,
29
+ selectValueDefault
30
+ ] }) : selectValueDefault;
25
31
  return /* @__PURE__ */ jsxs(Select, { value, onValueChange: onChange, children: [
26
32
  /* @__PURE__ */ jsx(
27
33
  SelectTrigger,
@@ -32,7 +38,7 @@ const SelectDefault = ({
32
38
  disabled,
33
39
  loading,
34
40
  style,
35
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder, children: value && renderTriggerLabel ? renderTriggerLabel(value) : void 0 })
41
+ children: renderValue
36
42
  }
37
43
  ),
38
44
  /* @__PURE__ */ jsx(SelectContent, { children: /* @__PURE__ */ jsx(SelectGroup, { children: options.filter((option) => option.value !== "").map((option) => /* @__PURE__ */ jsx(SelectItem, { className: "cursor-pointer", value: option.value, children: renderItemLabel ? renderItemLabel(option.value) : option.label }, option.value)) }) })
@@ -1,3 +1,4 @@
1
+ export * from "../AttackTimeline/index.js";
1
2
  export * from "../CorrelationTimer/index.js";
2
3
  export * from "../Severity/index.js";
3
4
  export * from "../SyncProcessBar/index.js";
package/ui/index.js CHANGED
@@ -15,9 +15,11 @@ export * from "./Input/index.js";
15
15
  export * from "./InputNumber/index.js";
16
16
  export * from "./InputPassword/index.js";
17
17
  export * from "./Label/index.js";
18
+ export * from "./MobileNav/index.js";
18
19
  export * from "./MultiSelect/index.js";
19
20
  export * from "./PageHeader/index.js";
20
21
  export * from "./Pagination/index.js";
22
+ export * from "./Progress/index.js";
21
23
  export * from "./RadioGroup/index.js";
22
24
  export * from "./ScrollArea/index.js";
23
25
  export * from "./SearchInput/index.js";