@flikk/ui 1.0.0-beta.11 → 1.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ai/ApprovalCard/ApprovalCard.js +1 -1
- package/dist/components/ai/MessageHistory/MessageHistory.js +1 -0
- package/dist/components/ai/PromptInput/PromptInput.js +7 -125
- package/dist/components/ai/PromptInput/VoiceRecorder.js +0 -77
- package/dist/components/ai/StreamingResponse/StreamingResponse.js +1 -0
- package/dist/components/ai/StreamingResponse/StreamingResponse.types.d.ts +7 -7
- package/dist/components/ai/index.js +1 -0
- package/dist/components/core/Accordion/Accordion.d.ts +1 -1
- package/dist/components/core/Accordion/Accordion.js +2 -2
- package/dist/components/core/Accordion/Accordion.theme.d.ts +2 -2
- package/dist/components/core/Accordion/Accordion.theme.js +4 -4
- package/dist/components/core/Accordion/Accordion.types.d.ts +19 -20
- package/dist/components/core/Accordion/AccordionBody.d.ts +3 -0
- package/dist/components/core/Accordion/{AccordionContent.js → AccordionBody.js} +4 -4
- package/dist/components/core/Accordion/AccordionItem.js +1 -1
- package/dist/components/core/Accordion/AccordionTrigger.js +14 -7
- package/dist/components/core/Accordion/index.d.ts +2 -2
- package/dist/components/core/Alert/Alert.js +5 -1
- package/dist/components/core/Alert/Alert.types.d.ts +4 -4
- package/dist/components/core/Avatar/Avatar.js +22 -18
- package/dist/components/core/Avatar/Avatar.theme.js +1 -1
- package/dist/components/core/Avatar/Avatar.types.d.ts +9 -8
- package/dist/components/core/AvatarGroup/AvatarGroup.js +2 -2
- package/dist/components/core/Badge/Badge.js +7 -5
- package/dist/components/core/Badge/Badge.theme.js +11 -4
- package/dist/components/core/Badge/Badge.types.d.ts +2 -2
- package/dist/components/core/Breadcrumbs/Breadcrumbs.js +7 -3
- package/dist/components/core/Breadcrumbs/Breadcrumbs.types.d.ts +1 -1
- package/dist/components/core/Button/Button.js +2 -8
- package/dist/components/core/Button/Button.theme.js +7 -7
- package/dist/components/core/Calendar/Calendar.js +3 -3
- package/dist/components/core/Calendar/CalendarEvent/CalendarEvent.types.d.ts +5 -6
- package/dist/components/core/Card/Card.d.ts +2 -2
- package/dist/components/core/Card/Card.js +3 -3
- package/dist/components/core/Card/Card.theme.js +3 -3
- package/dist/components/core/Card/Card.types.d.ts +4 -4
- package/dist/components/core/Card/CardBody.d.ts +3 -0
- package/dist/components/core/Card/CardBody.js +11 -0
- package/dist/components/core/Card/index.d.ts +2 -2
- package/dist/components/core/Carousel/Carousel.js +4 -4
- package/dist/components/core/Carousel/Carousel.types.d.ts +4 -4
- package/dist/components/core/Carousel/CarouselBody.d.ts +4 -0
- package/dist/components/core/Carousel/{CarouselContent.js → CarouselBody.js} +3 -3
- package/dist/components/core/Carousel/index.d.ts +2 -1
- package/dist/components/core/ContextMenu/ContextMenu.d.ts +2 -2
- package/dist/components/core/ContextMenu/ContextMenu.js +6 -6
- package/dist/components/core/ContextMenu/ContextMenu.types.d.ts +2 -2
- package/dist/components/core/ContextMenu/ContextMenuBody.d.ts +6 -0
- package/dist/components/core/ContextMenu/{ContextMenuContent.js → ContextMenuBody.js} +4 -4
- package/dist/components/core/ContextMenu/ContextMenuSubBody.d.ts +6 -0
- package/dist/components/core/ContextMenu/{ContextMenuSubContent.js → ContextMenuSubBody.js} +4 -4
- package/dist/components/core/ContextMenu/index.d.ts +1 -1
- package/dist/components/core/Drawer/Drawer.d.ts +2 -2
- package/dist/components/core/Drawer/Drawer.js +28 -9
- package/dist/components/core/Drawer/Drawer.theme.js +1 -1
- package/dist/components/core/Drawer/Drawer.types.d.ts +8 -6
- package/dist/components/core/Drawer/DrawerBody.d.ts +5 -0
- package/dist/components/core/Drawer/DrawerBody.js +11 -0
- package/dist/components/core/Drawer/index.d.ts +2 -1
- package/dist/components/core/Dropdown/Dropdown.types.d.ts +3 -3
- package/dist/components/core/Dropdown/DropdownSection.js +3 -1
- package/dist/components/core/FileTypeIcon/FileTypeIcon.d.ts +3 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.js +33 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.d.ts +2 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.js +12 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.types.d.ts +19 -0
- package/dist/components/core/FileTypeIcon/fileTypes.d.ts +7 -0
- package/dist/components/core/FileTypeIcon/fileTypes.js +30 -0
- package/dist/components/core/FileTypeIcon/index.d.ts +2 -0
- package/dist/components/core/MenuItem/MenuItem.js +3 -1
- package/dist/components/core/MenuItem/MenuItem.theme.js +1 -1
- package/dist/components/core/MenuItem/MenuItem.types.d.ts +1 -1
- package/dist/components/core/Message/Message.d.ts +1 -1
- package/dist/components/core/Message/Message.js +3 -3
- package/dist/components/core/Message/Message.theme.js +2 -2
- package/dist/components/core/Message/Message.types.d.ts +7 -7
- package/dist/components/core/Message/MessageAvatar.d.ts +2 -2
- package/dist/components/core/Message/MessageAvatar.js +3 -3
- package/dist/components/core/Message/MessageBody.d.ts +8 -0
- package/dist/components/core/Message/{MessageContent.js → MessageBody.js} +3 -3
- package/dist/components/core/Message/index.d.ts +2 -0
- package/dist/components/core/Modal/Modal.js +5 -1
- package/dist/components/core/Modal/Modal.theme.js +1 -1
- package/dist/components/core/Modal/Modal.types.d.ts +5 -2
- package/dist/components/core/ModalStack/ModalStackModal.js +1 -0
- package/dist/components/core/PageHeading/PageHeading.types.d.ts +1 -1
- package/dist/components/core/PageHeading/PageHeadingBackButton.js +3 -1
- package/dist/components/core/Popover/Popover.d.ts +1 -1
- package/dist/components/core/Popover/Popover.js +4 -4
- package/dist/components/core/Popover/Popover.theme.d.ts +1 -1
- package/dist/components/core/Popover/Popover.theme.js +2 -2
- package/dist/components/core/Popover/Popover.types.d.ts +3 -3
- package/dist/components/core/Popover/PopoverBody.d.ts +7 -0
- package/dist/components/core/Popover/{PopoverContent.js → PopoverBody.js} +24 -13
- package/dist/components/core/Popover/index.d.ts +4 -3
- package/dist/components/core/Tabs/Tabs.animations.d.ts +2 -2
- package/dist/components/core/Tabs/Tabs.animations.js +3 -3
- package/dist/components/core/Tabs/Tabs.d.ts +1 -1
- package/dist/components/core/Tabs/Tabs.js +3 -3
- package/dist/components/core/Tabs/Tabs.theme.d.ts +1 -1
- package/dist/components/core/Tabs/Tabs.theme.js +2 -2
- package/dist/components/core/Tabs/Tabs.types.d.ts +9 -9
- package/dist/components/core/Tabs/TabsBody.d.ts +6 -0
- package/dist/components/core/Tabs/{TabsContent.js → TabsBody.js} +8 -8
- package/dist/components/core/Tabs/index.d.ts +2 -2
- package/dist/components/core/Tag/Tag.d.ts +1 -1
- package/dist/components/core/Tag/Tag.js +2 -2
- package/dist/components/core/Tag/Tag.types.d.ts +1 -1
- package/dist/components/core/Toast/Toast.js +5 -1
- package/dist/components/core/Toast/Toast.types.d.ts +9 -9
- package/dist/components/core/index.d.ts +1 -1
- package/dist/components/core/index.js +7 -3
- package/dist/components/data-display/Feed/Feed.animations.d.ts +40 -0
- package/dist/components/data-display/Feed/Feed.animations.js +26 -0
- package/dist/components/data-display/Feed/Feed.d.ts +5 -1
- package/dist/components/data-display/Feed/Feed.js +87 -52
- package/dist/components/data-display/Feed/Feed.theme.js +11 -13
- package/dist/components/data-display/Feed/Feed.types.d.ts +35 -34
- package/dist/components/data-display/Feed/index.d.ts +1 -1
- package/dist/components/data-display/GanttChart/GanttTaskBar.js +11 -9
- package/dist/components/data-display/GanttChart/GanttTaskContextMenu.js +1 -1
- package/dist/components/data-display/KPI/KPI.js +2 -2
- package/dist/components/data-display/KPI/KPI.types.d.ts +3 -3
- package/dist/components/data-display/Metric/Metric.js +2 -2
- package/dist/components/data-display/Metric/Metric.types.d.ts +3 -3
- package/dist/components/data-display/Table/TableColumnManager.js +2 -1
- package/dist/components/data-display/Table/TableFilter.js +2 -1
- package/dist/components/data-display/Timeline/TimelineMarker.js +2 -2
- package/dist/components/effects/3d/index.d.ts +1 -1
- package/dist/components/effects/AIOrb/AIOrb.d.ts +1 -0
- package/dist/components/effects/AIOrb/AIOrb.js +3 -2
- package/dist/components/effects/AIOrb/AIOrb.types.d.ts +1 -0
- package/dist/components/effects/AIOrb/hooks/index.d.ts +2 -0
- package/dist/components/effects/AIOrb/hooks/useOrbState.d.ts +20 -0
- package/dist/components/effects/AIOrb/hooks/useOrbState.js +27 -0
- package/dist/components/effects/AIOrb/index.d.ts +2 -2
- package/dist/components/effects/AIOrb/variants/Aura/Aura.d.ts +3 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.js +75 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.shaders.d.ts +28 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.shaders.js +191 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.types.d.ts +53 -0
- package/dist/components/effects/AIOrb/variants/Aura/ShaderCanvas.d.ts +17 -0
- package/dist/components/effects/AIOrb/variants/Aura/ShaderCanvas.js +149 -0
- package/dist/components/effects/AIOrb/variants/Aura/index.d.ts +2 -0
- package/dist/components/effects/AIOrb/variants/DotSphere/DotSphere.js +38 -7
- package/dist/components/effects/AIOrb/variants/DotSphere/DotSphere.types.d.ts +6 -0
- package/dist/components/effects/AIOrb/variants/Liquid/Liquid.js +34 -8
- package/dist/components/effects/AIOrb/variants/Liquid/Liquid.types.d.ts +6 -0
- package/dist/components/effects/AIOrb/variants/index.d.ts +2 -0
- package/dist/components/effects/CustomCursor/CustomCursor.d.ts +2 -2
- package/dist/components/effects/CustomCursor/CustomCursor.js +50 -47
- package/dist/components/effects/GlassSurface/GlassSurface.js +24 -12
- package/dist/components/effects/GlassSurface/GlassSurface.types.d.ts +8 -0
- package/dist/components/forms/Checkbox/Checkbox.js +1 -1
- package/dist/components/forms/Checkbox/Checkbox.types.d.ts +5 -5
- package/dist/components/forms/Checkbox/CheckboxGroup.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPicker.d.ts +1 -1
- package/dist/components/forms/ColorPicker/ColorPicker.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerBody.d.ts +7 -0
- package/dist/components/forms/ColorPicker/{ColorPickerContent.js → ColorPickerBody.js} +5 -5
- package/dist/components/forms/ColorPicker/index.d.ts +2 -2
- package/dist/components/forms/DatePicker/DatePicker.d.ts +7 -3
- package/dist/components/forms/DatePicker/DatePicker.js +6 -5
- package/dist/components/forms/DatePicker/DatePicker.theme.js +3 -3
- package/dist/components/forms/DatePicker/DatePicker.types.d.ts +9 -4
- package/dist/components/forms/DatePicker/DatePickerBody.d.ts +7 -0
- package/dist/components/forms/DatePicker/{DatePickerContent.js → DatePickerBody.js} +10 -9
- package/dist/components/forms/DatePicker/index.d.ts +2 -2
- package/dist/components/forms/FileUpload/FileUpload.js +0 -78
- package/dist/components/forms/Input/Input.js +2 -2
- package/dist/components/forms/Input/Input.types.d.ts +4 -4
- package/dist/components/forms/Mention/Mention.js +2 -2
- package/dist/components/forms/Radio/Radio.js +1 -1
- package/dist/components/forms/Radio/Radio.types.d.ts +5 -5
- package/dist/components/forms/Radio/RadioGroup.js +1 -1
- package/dist/components/forms/Select/Select.js +2 -2
- package/dist/components/forms/Select/Select.types.d.ts +4 -4
- package/dist/components/forms/Switch/Switch.js +1 -1
- package/dist/components/forms/Switch/Switch.types.d.ts +4 -4
- package/dist/components/forms/Textarea/Textarea.js +2 -2
- package/dist/components/forms/Textarea/Textarea.types.d.ts +4 -4
- package/dist/components/forms/TimePicker/TimePickerContent.js +1 -78
- package/dist/components/forms/index.d.ts +2 -2
- package/dist/components/forms/index.js +2 -80
- package/dist/components/layout/FormLayout/FormLayout.d.ts +0 -2
- package/dist/components/layout/FormLayout/FormLayout.js +12 -6
- package/dist/components/layout/FormLayout/FormLayout.theme.js +2 -5
- package/dist/components/layout/FormLayout/FormLayout.types.d.ts +8 -26
- package/dist/components/layout/FormLayout/FormLayoutSection.js +3 -2
- package/dist/components/layout/FormLayout/index.d.ts +1 -1
- package/dist/index.js +197 -199
- package/dist/styles.css +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/paletteGenerator.d.ts +46 -0
- package/package.json +1 -1
- package/src/styles/theme.css +2 -6
- package/dist/components/core/Accordion/AccordionContent.d.ts +0 -3
- package/dist/components/core/Card/CardContent.d.ts +0 -3
- package/dist/components/core/Card/CardContent.js +0 -11
- package/dist/components/core/Carousel/CarouselContent.d.ts +0 -4
- package/dist/components/core/ContextMenu/ContextMenuContent.d.ts +0 -6
- package/dist/components/core/ContextMenu/ContextMenuSubContent.d.ts +0 -6
- package/dist/components/core/Drawer/DrawerContent.d.ts +0 -5
- package/dist/components/core/Drawer/DrawerContent.js +0 -11
- package/dist/components/core/Loader/Loader.d.ts +0 -24
- package/dist/components/core/Loader/Loader.js +0 -57
- package/dist/components/core/Loader/Loader.theme.d.ts +0 -27
- package/dist/components/core/Loader/Loader.theme.js +0 -60
- package/dist/components/core/Loader/Loader.types.d.ts +0 -71
- package/dist/components/core/Loader/index.d.ts +0 -2
- package/dist/components/core/Message/MessageContent.d.ts +0 -8
- package/dist/components/core/Popover/PopoverContent.d.ts +0 -7
- package/dist/components/core/Tabs/TabsContent.d.ts +0 -6
- package/dist/components/forms/ColorPicker/ColorPickerContent.d.ts +0 -7
- package/dist/components/forms/DatePicker/DatePickerContent.d.ts +0 -7
- package/dist/components/layout/FormLayout/FormLayoutBody.d.ts +0 -3
- package/dist/components/layout/FormLayout/FormLayoutBody.js +0 -91
- package/dist/components/layout/FormLayout/FormLayoutHeader.d.ts +0 -3
- package/dist/components/layout/FormLayout/FormLayoutHeader.js +0 -12
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { HTMLAttributes, ReactNode } from
|
|
1
|
+
import { HTMLAttributes, ReactNode } from "react";
|
|
2
2
|
/**
|
|
3
3
|
* Toast visual variant
|
|
4
4
|
*/
|
|
5
|
-
export type ToastVariant =
|
|
5
|
+
export type ToastVariant = "default" | "glass";
|
|
6
6
|
/**
|
|
7
7
|
* Toast state (e.g., loading indicator)
|
|
8
8
|
*/
|
|
9
|
-
export type ToastState =
|
|
10
|
-
export type ToastPosition =
|
|
9
|
+
export type ToastState = "default" | "loading";
|
|
10
|
+
export type ToastPosition = "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right";
|
|
11
11
|
export interface ToastAction {
|
|
12
12
|
label: string;
|
|
13
13
|
onClick: () => void;
|
|
@@ -42,15 +42,15 @@ export interface ToastData {
|
|
|
42
42
|
id: string;
|
|
43
43
|
variant?: ToastVariant;
|
|
44
44
|
state?: ToastState;
|
|
45
|
-
title?:
|
|
46
|
-
subtitle?:
|
|
45
|
+
title?: ReactNode;
|
|
46
|
+
subtitle?: ReactNode;
|
|
47
47
|
icon?: ReactNode;
|
|
48
48
|
action?: ToastAction;
|
|
49
49
|
duration?: number;
|
|
50
50
|
dismissible?: boolean;
|
|
51
51
|
onDismiss?: () => void;
|
|
52
52
|
}
|
|
53
|
-
export interface ToastProps extends HTMLAttributes<HTMLDivElement> {
|
|
53
|
+
export interface ToastProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
54
54
|
/** Toast data */
|
|
55
55
|
toast: ToastData;
|
|
56
56
|
/** Custom class name */
|
|
@@ -93,7 +93,7 @@ export interface ToastProviderProps {
|
|
|
93
93
|
}
|
|
94
94
|
export interface ToastContextValue {
|
|
95
95
|
toasts: ToastData[];
|
|
96
|
-
addToast: (toast: Omit<ToastData,
|
|
96
|
+
addToast: (toast: Omit<ToastData, "id">) => string;
|
|
97
97
|
removeToast: (id: string) => void;
|
|
98
98
|
removeAllToasts: () => void;
|
|
99
99
|
}
|
|
@@ -121,7 +121,7 @@ export interface UseToastReturn {
|
|
|
121
121
|
info: (title: string, options?: UseToastOptions & {
|
|
122
122
|
subtitle?: string;
|
|
123
123
|
}) => string;
|
|
124
|
-
loading: (title: string, options?: Omit<UseToastOptions,
|
|
124
|
+
loading: (title: string, options?: Omit<UseToastOptions, "state"> & {
|
|
125
125
|
subtitle?: string;
|
|
126
126
|
}) => string;
|
|
127
127
|
dismiss: (id: string) => void;
|
|
@@ -18,7 +18,6 @@ export * from "./Dropdown";
|
|
|
18
18
|
export * from "./Kbd";
|
|
19
19
|
export * from "./MenuItem";
|
|
20
20
|
export * from "./Link";
|
|
21
|
-
export * from "./Loader";
|
|
22
21
|
export * from "./Modal";
|
|
23
22
|
export * from "./ModalStack";
|
|
24
23
|
export * from "./PageHeading";
|
|
@@ -48,3 +47,4 @@ export * from "./OfflineIndicator";
|
|
|
48
47
|
export * from "./ContextMenu";
|
|
49
48
|
export * from "./Pill";
|
|
50
49
|
export * from "./SocialIcon";
|
|
50
|
+
export * from "./FileTypeIcon";
|
|
@@ -18,11 +18,13 @@ export { CalendarMini } from './Calendar/CalendarMini/CalendarMini.js';
|
|
|
18
18
|
export { Card } from './Card/Card.js';
|
|
19
19
|
export { CardStack } from './CardStack/CardStack.js';
|
|
20
20
|
export { Carousel } from './Carousel/Carousel.js';
|
|
21
|
+
export { CarouselBody } from './Carousel/CarouselBody.js';
|
|
21
22
|
export { CommandPalette } from './CommandPalette/CommandPalette.js';
|
|
22
23
|
export { commandPaletteTheme } from './CommandPalette/CommandPalette.theme.js';
|
|
23
24
|
export { Separator } from './Separator/Separator.js';
|
|
24
25
|
export { separatorTheme } from './Separator/Separator.theme.js';
|
|
25
26
|
export { Drawer } from './Drawer/Drawer.js';
|
|
27
|
+
export { DrawerBody } from './Drawer/DrawerBody.js';
|
|
26
28
|
export { Dropdown } from './Dropdown/Dropdown.js';
|
|
27
29
|
export { DropdownTrigger } from './Dropdown/DropdownTrigger.js';
|
|
28
30
|
export { DropdownMenu } from './Dropdown/DropdownMenu.js';
|
|
@@ -34,13 +36,13 @@ export { Kbd } from './Kbd/Kbd.js';
|
|
|
34
36
|
export { MenuItem } from './MenuItem/MenuItem.js';
|
|
35
37
|
export { menuItemTheme } from './MenuItem/MenuItem.theme.js';
|
|
36
38
|
export { Link } from './Link/Link.js';
|
|
37
|
-
export { Loader } from './Loader/Loader.js';
|
|
38
39
|
export { Modal } from './Modal/Modal.js';
|
|
39
40
|
export { ModalStack } from './ModalStack/ModalStack.js';
|
|
40
41
|
export { PageHeading } from './PageHeading/PageHeading.js';
|
|
41
42
|
export { Pagination } from './Pagination/Pagination.js';
|
|
42
43
|
export { Popover } from './Popover/Popover.js';
|
|
43
44
|
export { PopoverContext, usePopoverContext } from './Popover/PopoverContext.js';
|
|
45
|
+
export { PopoverBody } from './Popover/PopoverBody.js';
|
|
44
46
|
export { Progress } from './Progress/Progress.js';
|
|
45
47
|
export { Rating } from './Rating/Rating.js';
|
|
46
48
|
export { ScrollArea } from './ScrollArea/ScrollArea.js';
|
|
@@ -52,7 +54,7 @@ export { SlidingNumber } from './SlidingNumber/SlidingNumber.js';
|
|
|
52
54
|
export { Tabs } from './Tabs/Tabs.js';
|
|
53
55
|
export { TabsList } from './Tabs/TabsList.js';
|
|
54
56
|
export { TabsTrigger } from './Tabs/TabsTrigger.js';
|
|
55
|
-
export {
|
|
57
|
+
export { TabsBody } from './Tabs/TabsBody.js';
|
|
56
58
|
export { TabsContext, useTabsContext } from './Tabs/TabsContext.js';
|
|
57
59
|
export { Tooltip } from './Tooltip/Tooltip.js';
|
|
58
60
|
export { baseTooltipVariants, getTooltipVariants, tooltipSpringConfig } from './Tooltip/Tooltip.animations.js';
|
|
@@ -71,6 +73,7 @@ export { Message } from './Message/Message.js';
|
|
|
71
73
|
export { messageTheme } from './Message/Message.theme.js';
|
|
72
74
|
export { messageListTheme } from './Message/MessageList.theme.js';
|
|
73
75
|
export { TypeWriter } from './Message/TypeWriter.js';
|
|
76
|
+
export { MessageBody } from './Message/MessageBody.js';
|
|
74
77
|
export { Empty } from './Empty/Empty.js';
|
|
75
78
|
export { emptyTheme } from './Empty/Empty.theme.js';
|
|
76
79
|
export { Masonry } from './Masonry/Masonry.js';
|
|
@@ -94,8 +97,9 @@ export { contextMenuTheme } from './ContextMenu/ContextMenu.theme.js';
|
|
|
94
97
|
export { Pill } from './Pill/Pill.js';
|
|
95
98
|
export { pillTheme } from './Pill/Pill.theme.js';
|
|
96
99
|
export { SocialIcon } from './SocialIcon/SocialIcon.js';
|
|
100
|
+
export { FileTypeIcon } from './FileTypeIcon/FileTypeIcon.js';
|
|
97
101
|
export { AnimatePresence } from 'motion/react';
|
|
98
|
-
export {
|
|
102
|
+
export { CardBody } from './Card/CardBody.js';
|
|
99
103
|
export { CardFooter } from './Card/CardFooter.js';
|
|
100
104
|
export { CardHeader } from './Card/CardHeader.js';
|
|
101
105
|
export { CardSubtitle } from './Card/CardSubtitle.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const EASE: readonly [0.04, 0.62, 0.23, 0.98];
|
|
2
|
+
export declare const STAGGER_IN = 0.05;
|
|
3
|
+
export declare const STAGGER_OUT = 0.04;
|
|
4
|
+
export declare const STAGGER_BASE_DELAY = 0.15;
|
|
5
|
+
export declare const collapseLayerExitTiming: {
|
|
6
|
+
height: {
|
|
7
|
+
duration: number;
|
|
8
|
+
delay: number;
|
|
9
|
+
ease: readonly [0.04, 0.62, 0.23, 0.98];
|
|
10
|
+
};
|
|
11
|
+
opacity: {
|
|
12
|
+
duration: number;
|
|
13
|
+
delay: number;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare const collapseLayerEnterTiming: {
|
|
17
|
+
height: {
|
|
18
|
+
duration: number;
|
|
19
|
+
delay: number;
|
|
20
|
+
ease: readonly [0.04, 0.62, 0.23, 0.98];
|
|
21
|
+
};
|
|
22
|
+
opacity: {
|
|
23
|
+
duration: number;
|
|
24
|
+
delay: number;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare const expandLayerEnterTiming: {
|
|
28
|
+
height: {
|
|
29
|
+
duration: number;
|
|
30
|
+
delay: number;
|
|
31
|
+
ease: readonly [0.04, 0.62, 0.23, 0.98];
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export declare const expandLayerExitTiming: {
|
|
35
|
+
height: {
|
|
36
|
+
duration: number;
|
|
37
|
+
delay: number;
|
|
38
|
+
ease: readonly [0.04, 0.62, 0.23, 0.98];
|
|
39
|
+
};
|
|
40
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Feed.Collapse — multi-stage animation timing
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
const EASE = [0.04, 0.62, 0.23, 0.98];
|
|
5
|
+
// Stagger timing
|
|
6
|
+
const STAGGER_IN = 0.05; // 50ms between each item entering
|
|
7
|
+
const STAGGER_OUT = 0.04; // 40ms between each item exiting (slightly faster)
|
|
8
|
+
const STAGGER_BASE_DELAY = 0.15; // items start shortly after height begins expanding
|
|
9
|
+
// Collapsed layer (curve + label) — exit = collapsing away, enter = reappearing
|
|
10
|
+
const collapseLayerExitTiming = {
|
|
11
|
+
height: { duration: 0.3, delay: 0, ease: EASE },
|
|
12
|
+
opacity: { duration: 0.2, delay: 0 },
|
|
13
|
+
};
|
|
14
|
+
const collapseLayerEnterTiming = {
|
|
15
|
+
height: { duration: 0.35, delay: 0.05, ease: EASE },
|
|
16
|
+
opacity: { duration: 0.25, delay: 0.15 },
|
|
17
|
+
};
|
|
18
|
+
// Expanded layer (children container) — enter = growing, exit = shrinking
|
|
19
|
+
const expandLayerEnterTiming = {
|
|
20
|
+
height: { duration: 0.4, delay: 0, ease: EASE },
|
|
21
|
+
};
|
|
22
|
+
const expandLayerExitTiming = {
|
|
23
|
+
height: { duration: 0.35, delay: 0.05, ease: EASE },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { EASE, STAGGER_BASE_DELAY, STAGGER_IN, STAGGER_OUT, collapseLayerEnterTiming, collapseLayerExitTiming, expandLayerEnterTiming, expandLayerExitTiming };
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { FeedProps, FeedItemProps } from "./Feed.types";
|
|
2
|
+
import type { FeedProps, FeedItemProps, FeedCollapseProps, FeedTheme } from "./Feed.types";
|
|
3
|
+
export declare const useFeedContext: () => {
|
|
4
|
+
theme: FeedTheme;
|
|
5
|
+
};
|
|
3
6
|
export declare const Feed: React.ForwardRefExoticComponent<FeedProps & React.RefAttributes<HTMLDivElement>> & {
|
|
4
7
|
Item: React.ForwardRefExoticComponent<FeedItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
8
|
+
Collapse: React.FC<FeedCollapseProps>;
|
|
5
9
|
};
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import React__default, { createContext, useMemo, useState, useContext } from 'react';
|
|
2
|
+
import React__default, { createContext, useMemo, useState, useCallback, useContext } from 'react';
|
|
3
|
+
import { useReducedMotion, motion } from 'motion/react';
|
|
4
|
+
import { ChevronUpDownIcon } from '@heroicons/react/16/solid';
|
|
3
5
|
import { cn } from '../../../utils/cn.js';
|
|
4
6
|
import { feedTheme } from './Feed.theme.js';
|
|
5
|
-
import {
|
|
6
|
-
import { Button } from '../../core/Button/Button.js';
|
|
7
|
-
import { Textarea } from '../../forms/Textarea/Textarea.js';
|
|
8
|
-
import '../../forms/Textarea/Textarea.theme.js';
|
|
7
|
+
import { collapseLayerExitTiming, collapseLayerEnterTiming, EASE, expandLayerEnterTiming, expandLayerExitTiming, STAGGER_BASE_DELAY, STAGGER_IN, STAGGER_OUT } from './Feed.animations.js';
|
|
9
8
|
|
|
10
9
|
// ---------------------------------------------------------------------------
|
|
11
10
|
// Context
|
|
@@ -29,60 +28,96 @@ FeedRoot.displayName = "Feed";
|
|
|
29
28
|
// ---------------------------------------------------------------------------
|
|
30
29
|
// Feed.Item
|
|
31
30
|
// ---------------------------------------------------------------------------
|
|
32
|
-
const
|
|
31
|
+
const FeedItemInner = ({ icon, indicatorClassName, timestamp, children }) => {
|
|
33
32
|
const { theme } = useFeedContext();
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
case "avatar":
|
|
43
|
-
case "comment-input":
|
|
44
|
-
return (jsx("div", { className: theme.avatarIndicatorStyle, children: jsx(Avatar, { src: avatar === null || avatar === void 0 ? void 0 : avatar.src, alt: (_a = avatar === null || avatar === void 0 ? void 0 : avatar.alt) !== null && _a !== void 0 ? _a : "", className: "size-10 ring-8 ring-[var(--color-background)]" }) }));
|
|
45
|
-
case "default":
|
|
46
|
-
default:
|
|
47
|
-
return (jsx("div", { className: theme.dotIndicatorStyle, children: jsx("span", { className: "size-1.5 rounded-full bg-[var(--color-text-muted)]" }) }));
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
// ------- Content rendering -------
|
|
51
|
-
const renderContent = () => {
|
|
52
|
-
switch (variant) {
|
|
53
|
-
case "default":
|
|
54
|
-
case "icon":
|
|
55
|
-
return (jsxs("div", { className: cn(theme.contentStyle, "py-1.5"), children: [jsxs("p", { className: theme.actionTextStyle, children: [title && jsxs("span", { className: theme.titleStyle, children: [title, " "] }), children] }), timestamp && jsx("p", { className: theme.timestampStyle, children: timestamp })] }));
|
|
56
|
-
case "avatar":
|
|
57
|
-
return (jsxs("div", { className: theme.contentStyle, children: [title && (jsx("p", { className: cn(theme.titleStyle, "text-base"), children: title })), jsx("p", { className: cn(theme.actionTextStyle, "mt-0.5"), children: children }), timestamp && jsx("p", { className: theme.timestampStyle, children: timestamp })] }));
|
|
58
|
-
case "comment-input": {
|
|
59
|
-
const handleSubmit = () => {
|
|
60
|
-
const trimmed = inputValue.trim();
|
|
61
|
-
if (trimmed && onSubmit) {
|
|
62
|
-
onSubmit(trimmed);
|
|
63
|
-
setInputValue("");
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const handleKeyDown = (e) => {
|
|
67
|
-
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
68
|
-
e.preventDefault();
|
|
69
|
-
handleSubmit();
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
return (jsxs("div", { className: theme.commentInputWrapperStyle, children: [jsx(Textarea, { size: "sm", rows: 3, placeholder: placeholder, value: inputValue, onChange: (e) => setInputValue(e.target.value), onKeyDown: handleKeyDown }), jsx("div", { className: theme.commentInputFooterStyle, children: jsx(Button, { size: "sm", onClick: handleSubmit, children: submitLabel }) })] }));
|
|
73
|
-
}
|
|
74
|
-
default:
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
return (jsx("li", { ref: ref, className: className, ...props, children: jsxs("div", { className: theme.itemInnerStyle, children: [jsx("span", { "aria-hidden": "true", className: theme.connectorStyle }), jsxs("div", { className: theme.itemContentStyle, children: [renderIndicator(), renderContent()] })] }) }));
|
|
33
|
+
return (jsxs("div", { className: theme.itemInnerStyle, children: [jsx("span", { "aria-hidden": "true", className: theme.connectorStyle }), jsxs("div", { className: theme.itemContentStyle, children: [icon ? (jsx("div", { className: cn(theme.indicatorStyle, indicatorClassName), children: icon })) : (jsx("div", { className: cn(theme.dotIndicatorStyle, indicatorClassName), children: jsx("span", { className: "size-1.5 rounded-full bg-[var(--color-text-muted)]" }) })), jsxs("div", { className: theme.contentStyle, children: [children, timestamp && jsx("p", { className: theme.timestampStyle, children: timestamp })] })] })] }));
|
|
34
|
+
};
|
|
35
|
+
const FeedItem = React__default.forwardRef(({ icon, indicatorClassName, timestamp, children, className, _as = "li", ...props }, ref) => {
|
|
36
|
+
const inner = (jsx(FeedItemInner, { icon: icon, indicatorClassName: indicatorClassName, timestamp: timestamp, children: children }));
|
|
37
|
+
if (_as === "div") {
|
|
38
|
+
return (jsx("div", { className: className, ...props, children: inner }));
|
|
39
|
+
}
|
|
40
|
+
return (jsx("li", { ref: ref, className: className, ...props, children: inner }));
|
|
79
41
|
});
|
|
80
42
|
FeedItem.displayName = "Feed.Item";
|
|
81
43
|
// ---------------------------------------------------------------------------
|
|
44
|
+
// Feed.Collapse
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
/**
|
|
47
|
+
* SVG curved connector for the collapsed state.
|
|
48
|
+
* Draws a smooth parenthesis ) shape from (1,0) → (APEX,MID) → (1,H).
|
|
49
|
+
* Cubic beziers with vertical tangents at every junction so the curve
|
|
50
|
+
* connects seamlessly to the straight Feed connector above/below.
|
|
51
|
+
*
|
|
52
|
+
* Both CURVE_PATH and STRAIGHT_PATH use identical command structure
|
|
53
|
+
* (M, C, C) so framer-motion interpolates all numeric values smoothly.
|
|
54
|
+
*/
|
|
55
|
+
const COLLAPSED_HEIGHT = 72;
|
|
56
|
+
const CURVE_APEX_X = 24;
|
|
57
|
+
const STROKE_WIDTH = 2;
|
|
58
|
+
const SVG_WIDTH = CURVE_APEX_X + STROKE_WIDTH;
|
|
59
|
+
const MID_Y = COLLAPSED_HEIGHT / 2;
|
|
60
|
+
const CURVE_PATH = `M 1 0 C 1 20, ${CURVE_APEX_X} 16, ${CURVE_APEX_X} ${MID_Y} C ${CURVE_APEX_X} 56, 1 52, 1 ${COLLAPSED_HEIGHT}`;
|
|
61
|
+
const STRAIGHT_PATH = `M 1 0 C 1 12, 1 24, 1 ${MID_Y} C 1 48, 1 60, 1 ${COLLAPSED_HEIGHT}`;
|
|
62
|
+
const FeedCollapse = ({ label = "Show {count} more", icon, defaultExpanded = false, expanded: controlledExpanded, onToggle, children, className, }) => {
|
|
63
|
+
const { theme } = useFeedContext();
|
|
64
|
+
const shouldReduceMotion = useReducedMotion();
|
|
65
|
+
const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);
|
|
66
|
+
const isControlled = controlledExpanded !== undefined;
|
|
67
|
+
const expanded = isControlled ? controlledExpanded : internalExpanded;
|
|
68
|
+
const count = React__default.Children.count(children);
|
|
69
|
+
const resolvedLabel = label.replace("{count}", String(count));
|
|
70
|
+
const handleToggle = useCallback(() => {
|
|
71
|
+
const next = !expanded;
|
|
72
|
+
if (!isControlled)
|
|
73
|
+
setInternalExpanded(next);
|
|
74
|
+
onToggle === null || onToggle === void 0 ? void 0 : onToggle(next);
|
|
75
|
+
}, [expanded, isControlled, onToggle]);
|
|
76
|
+
// Clone children with _as="div" to avoid nested <li>
|
|
77
|
+
const clonedChildren = React__default.Children.map(children, (child) => {
|
|
78
|
+
if (React__default.isValidElement(child)) {
|
|
79
|
+
return React__default.cloneElement(child, {
|
|
80
|
+
_as: "div",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return child;
|
|
84
|
+
});
|
|
85
|
+
const collapseIcon = icon !== null && icon !== void 0 ? icon : (jsx(ChevronUpDownIcon, { className: "size-4 text-[var(--color-primary)]" }));
|
|
86
|
+
/* ---- Reduced motion: instant toggle, no staged animations ---- */
|
|
87
|
+
if (shouldReduceMotion) {
|
|
88
|
+
return (jsxs("li", { className: cn(theme.collapseStyle, className), children: [expanded && (jsx("span", { "aria-hidden": "true", className: "absolute left-5 -translate-x-1/2 top-0 h-full w-0.5 bg-[var(--color-border)]/60" })), !expanded ? (jsxs("div", { className: "relative", style: { height: COLLAPSED_HEIGHT }, children: [jsx("svg", { "aria-hidden": "true", className: theme.collapseSvgStyle, style: { left: "calc(1.25rem - 1px)" }, width: SVG_WIDTH, height: COLLAPSED_HEIGHT, fill: "none", children: jsx("path", { d: CURVE_PATH, stroke: "var(--color-border)", strokeOpacity: "0.6", strokeWidth: STROKE_WIDTH }) }), jsxs("button", { type: "button", className: "absolute top-1/2 -translate-y-1/2 flex items-center gap-2.5 cursor-pointer bg-transparent border-none p-0", style: {
|
|
89
|
+
left: `calc(1.25rem - 1px + ${CURVE_APEX_X + 12}px)`,
|
|
90
|
+
}, onClick: handleToggle, "aria-expanded": false, children: [jsx("div", { className: "flex size-5 shrink-0 items-center justify-center rounded-full bg-[var(--color-surface)] ", children: collapseIcon }), jsx("span", { className: theme.collapseButtonStyle, children: resolvedLabel })] })] })) : (jsxs("div", { children: [clonedChildren, jsx("div", { className: "relative pb-8", children: jsxs("div", { className: theme.itemContentStyle, children: [jsx("div", { className: "flex size-8 ml-1 shrink-0 items-center justify-center rounded-full bg-[var(--color-background-secondary)] ring-2 ring-[var(--color-background)]/50", children: collapseIcon }), jsx("div", { className: theme.contentStyle, children: jsx("button", { type: "button", className: theme.collapseButtonStyle, onClick: handleToggle, "aria-expanded": true, children: "Show less" }) })] }) })] }))] }));
|
|
91
|
+
}
|
|
92
|
+
/* ---- Full multi-stage animation ---- */
|
|
93
|
+
return (jsxs("li", { className: cn(theme.collapseStyle, className), children: [jsx(motion.span, { "aria-hidden": "true", className: "absolute left-5 -translate-x-1/2 top-0 h-full w-0.5 bg-[var(--color-border)]/60", animate: { opacity: expanded ? 1 : 0 }, transition: { duration: 0.2 } }), jsx(motion.div, { animate: {
|
|
94
|
+
height: expanded ? 0 : COLLAPSED_HEIGHT,
|
|
95
|
+
opacity: expanded ? 0 : 1,
|
|
96
|
+
}, transition: expanded ? collapseLayerExitTiming : collapseLayerEnterTiming, style: { overflow: "hidden", position: "relative" }, children: jsxs("div", { className: "relative", style: { height: COLLAPSED_HEIGHT }, children: [jsx("svg", { "aria-hidden": "true", className: theme.collapseSvgStyle, style: { left: "calc(1.25rem - 1px)" }, width: SVG_WIDTH, height: COLLAPSED_HEIGHT, fill: "none", children: jsx(motion.path, { animate: { d: expanded ? STRAIGHT_PATH : CURVE_PATH }, transition: { duration: 0.3, ease: EASE }, stroke: "var(--color-border)", strokeOpacity: "0.6", strokeWidth: STROKE_WIDTH }) }), jsxs(motion.button, { type: "button", className: "absolute top-1/2 -translate-y-1/2 flex items-center gap-2.5 cursor-pointer bg-transparent border-none p-0", style: {
|
|
97
|
+
left: `calc(1.25rem - 1px + ${CURVE_APEX_X + 12}px)`,
|
|
98
|
+
}, animate: { opacity: expanded ? 0 : 1 }, transition: { duration: 0.2, delay: expanded ? 0 : 0.2 }, onClick: handleToggle, "aria-expanded": false, children: [jsx("div", { className: "flex size-5 shrink-0 items-center justify-center rounded-full bg-[var(--color-surface)] border border-[var(--color-border)] shadow-sm", children: collapseIcon }), jsx("span", { className: theme.collapseButtonStyle, children: resolvedLabel })] })] }) }), jsxs(motion.div, { animate: { height: expanded ? "auto" : 0 }, transition: expanded ? expandLayerEnterTiming : expandLayerExitTiming, style: { overflow: "hidden" }, children: [React__default.Children.map(clonedChildren, (child, i) => (jsx(motion.div, { animate: {
|
|
99
|
+
opacity: expanded ? 1 : 0,
|
|
100
|
+
y: expanded ? 0 : 8,
|
|
101
|
+
}, transition: {
|
|
102
|
+
duration: 0.25,
|
|
103
|
+
delay: expanded
|
|
104
|
+
? STAGGER_BASE_DELAY + i * STAGGER_IN
|
|
105
|
+
: (count - i) * STAGGER_OUT,
|
|
106
|
+
}, children: child }, i))), jsx(motion.div, { animate: {
|
|
107
|
+
opacity: expanded ? 1 : 0,
|
|
108
|
+
y: expanded ? 0 : 8,
|
|
109
|
+
}, transition: {
|
|
110
|
+
duration: 0.25,
|
|
111
|
+
delay: expanded ? STAGGER_BASE_DELAY + count * STAGGER_IN : 0,
|
|
112
|
+
}, children: jsx("div", { className: "relative pb-8", children: jsxs("div", { className: theme.itemContentStyle, children: [jsx("div", { className: "flex size-8 ml-1 shrink-0 items-center justify-center rounded-full bg-[var(--color-background-secondary)] ring-2 ring-[var(--color-background)]/50", children: collapseIcon }), jsx("div", { className: theme.contentStyle, children: jsx("button", { type: "button", className: theme.collapseButtonStyle, onClick: handleToggle, "aria-expanded": true, children: "Show less" }) })] }) }) })] })] }));
|
|
113
|
+
};
|
|
114
|
+
FeedCollapse.displayName = "Feed.Collapse";
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
82
116
|
// Compound export
|
|
83
117
|
// ---------------------------------------------------------------------------
|
|
84
118
|
const Feed = Object.assign(FeedRoot, {
|
|
85
119
|
Item: FeedItem,
|
|
120
|
+
Collapse: FeedCollapse,
|
|
86
121
|
});
|
|
87
122
|
|
|
88
|
-
export { Feed };
|
|
123
|
+
export { Feed, useFeedContext };
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
const feedTheme = {
|
|
2
2
|
// Structural
|
|
3
3
|
baseStyle: "flow-root",
|
|
4
|
-
listStyle: "-mb-8 [&>li:last-
|
|
4
|
+
listStyle: "-mb-8 [&>li:last-child>div>.feed-connector]:hidden",
|
|
5
5
|
itemInnerStyle: "relative pb-8",
|
|
6
|
-
itemContentStyle: "relative flex items-start space-x-
|
|
7
|
-
connectorStyle: "feed-connector absolute top-5 left-
|
|
6
|
+
itemContentStyle: "relative flex items-start space-x-4",
|
|
7
|
+
connectorStyle: "feed-connector absolute top-5 left-5 -translate-x-1/2 h-full w-0.5 bg-[var(--color-border)]",
|
|
8
8
|
// Indicators
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
avatarIndicatorStyle: "relative flex-shrink-0",
|
|
9
|
+
indicatorStyle: "relative flex size-8 ml-1 shrink-0 items-center justify-center bg-[var(--color-background-secondary)] rounded-full ring-2 ring-[var(--color-background)]/50",
|
|
10
|
+
dotIndicatorStyle: "relative flex size-10 items-center justify-center",
|
|
12
11
|
// Content
|
|
13
|
-
contentStyle: "min-w-0 flex-1",
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
commentInputFooterStyle: "flex justify-end",
|
|
12
|
+
contentStyle: "min-w-0 flex-1 pt-1",
|
|
13
|
+
timestampStyle: "mt-1 text-xs text-[var(--color-text-muted)]/80 whitespace-nowrap",
|
|
14
|
+
// Collapse
|
|
15
|
+
collapseStyle: "relative",
|
|
16
|
+
collapseButtonStyle: "flex items-center gap-1.5 text-sm font-medium text-[var(--color-primary)] hover:text-[var(--color-primary-700)] transition-colors cursor-pointer bg-transparent border-none p-0",
|
|
17
|
+
collapseSvgStyle: "absolute top-0",
|
|
20
18
|
};
|
|
21
19
|
|
|
22
20
|
export { feedTheme };
|
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
-
export type FeedItemVariant = "default" | "icon" | "avatar" | "comment-input";
|
|
3
|
-
export interface FeedAvatarConfig {
|
|
4
|
-
src?: string;
|
|
5
|
-
alt: string;
|
|
6
|
-
}
|
|
7
2
|
export interface FeedTheme {
|
|
8
3
|
baseStyle: string;
|
|
9
4
|
listStyle: string;
|
|
10
5
|
itemInnerStyle: string;
|
|
11
6
|
itemContentStyle: string;
|
|
12
7
|
connectorStyle: string;
|
|
8
|
+
indicatorStyle: string;
|
|
13
9
|
dotIndicatorStyle: string;
|
|
14
|
-
iconIndicatorStyle: string;
|
|
15
|
-
avatarIndicatorStyle: string;
|
|
16
10
|
contentStyle: string;
|
|
17
|
-
titleStyle: string;
|
|
18
|
-
actionTextStyle: string;
|
|
19
11
|
timestampStyle: string;
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
collapseStyle: string;
|
|
13
|
+
collapseButtonStyle: string;
|
|
14
|
+
collapseSvgStyle: string;
|
|
22
15
|
}
|
|
23
16
|
export interface FeedThemeOverrides {
|
|
24
17
|
baseStyle?: string;
|
|
@@ -26,39 +19,47 @@ export interface FeedThemeOverrides {
|
|
|
26
19
|
itemInnerStyle?: string;
|
|
27
20
|
itemContentStyle?: string;
|
|
28
21
|
connectorStyle?: string;
|
|
22
|
+
indicatorStyle?: string;
|
|
29
23
|
dotIndicatorStyle?: string;
|
|
30
|
-
iconIndicatorStyle?: string;
|
|
31
|
-
avatarIndicatorStyle?: string;
|
|
32
24
|
contentStyle?: string;
|
|
33
|
-
titleStyle?: string;
|
|
34
|
-
actionTextStyle?: string;
|
|
35
25
|
timestampStyle?: string;
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
collapseStyle?: string;
|
|
27
|
+
collapseButtonStyle?: string;
|
|
28
|
+
collapseSvgStyle?: string;
|
|
38
29
|
}
|
|
39
30
|
export interface FeedProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
40
31
|
children: ReactNode;
|
|
41
32
|
theme?: FeedThemeOverrides;
|
|
42
33
|
className?: string;
|
|
43
34
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
timestamp?: string;
|
|
51
|
-
/** Icon element for the "icon" variant indicator */
|
|
35
|
+
/** @internal Injected by Feed.Collapse via cloneElement */
|
|
36
|
+
export interface FeedItemInternalProps {
|
|
37
|
+
_as?: "li" | "div";
|
|
38
|
+
}
|
|
39
|
+
export interface FeedItemProps extends React.HTMLAttributes<HTMLLIElement>, FeedItemInternalProps {
|
|
40
|
+
/** Icon or avatar element rendered as the indicator */
|
|
52
41
|
icon?: ReactNode;
|
|
53
|
-
/**
|
|
54
|
-
|
|
55
|
-
/**
|
|
42
|
+
/** Custom className for the indicator wrapper (icon background circle) */
|
|
43
|
+
indicatorClassName?: string;
|
|
44
|
+
/** Timestamp label (e.g. "6d ago") */
|
|
45
|
+
timestamp?: ReactNode;
|
|
46
|
+
/** Body content */
|
|
56
47
|
children?: ReactNode;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
className?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface FeedCollapseProps {
|
|
51
|
+
/** Template string with `{count}` placeholder for the number of hidden items */
|
|
52
|
+
label?: string;
|
|
53
|
+
/** Icon rendered next to the label */
|
|
54
|
+
icon?: ReactNode;
|
|
55
|
+
/** Uncontrolled initial expanded state */
|
|
56
|
+
defaultExpanded?: boolean;
|
|
57
|
+
/** Controlled expanded state */
|
|
58
|
+
expanded?: boolean;
|
|
59
|
+
/** Callback fired when the toggle is clicked */
|
|
60
|
+
onToggle?: (expanded: boolean) => void;
|
|
61
|
+
/** Feed.Item children to hide/reveal */
|
|
62
|
+
children: ReactNode;
|
|
63
|
+
/** Override className on the wrapper <li> */
|
|
63
64
|
className?: string;
|
|
64
65
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Feed } from "./Feed";
|
|
2
|
-
export type { FeedProps, FeedItemProps,
|
|
2
|
+
export type { FeedProps, FeedItemProps, FeedCollapseProps, FeedItemInternalProps, FeedTheme, FeedThemeOverrides, } from "./Feed.types";
|
|
@@ -11,10 +11,10 @@ import { taskBarVariants } from './GanttChart.animations.js';
|
|
|
11
11
|
import { useGanttDrag } from './hooks/useGanttDrag.js';
|
|
12
12
|
import { getDaysBetween, addDays, toDate } from '../../../utils/dateUtils.js';
|
|
13
13
|
|
|
14
|
-
const GanttTaskBar = React__default.memo(({ task, group, top
|
|
14
|
+
const GanttTaskBar = React__default.memo(({ task, group, top }) => {
|
|
15
15
|
var _a;
|
|
16
16
|
const { theme, dayWidth, rangeStart, rowHeight, readonly, readonlyDates, readonlyProgress, onTaskUpdate, onTaskClick, tasks, } = useGanttContext();
|
|
17
|
-
const { hoveredTaskId, setHoveredTaskId, focusedTaskId, setActiveDrag
|
|
17
|
+
const { hoveredTaskId, setHoveredTaskId, focusedTaskId, setActiveDrag } = useGanttInteraction();
|
|
18
18
|
const [tooltipPos, setTooltipPos] = useState(null);
|
|
19
19
|
const offset = getDayOffset(task.startDate, rangeStart);
|
|
20
20
|
const span = getDaysBetween(task.startDate, task.endDate);
|
|
@@ -66,7 +66,9 @@ const GanttTaskBar = React__default.memo(({ task, group, top, }) => {
|
|
|
66
66
|
disabled: !canDragDates,
|
|
67
67
|
onDragEnd: handleResizeLeftEnd,
|
|
68
68
|
onDragStateChange: useCallback((isDragging, deltaX) => {
|
|
69
|
-
setActiveDrag(isDragging
|
|
69
|
+
setActiveDrag(isDragging
|
|
70
|
+
? { taskId: task.id, mode: "resize-left", deltaX }
|
|
71
|
+
: null);
|
|
70
72
|
}, [setActiveDrag, task.id]),
|
|
71
73
|
});
|
|
72
74
|
// ----- Drag: Resize right -----
|
|
@@ -87,7 +89,9 @@ const GanttTaskBar = React__default.memo(({ task, group, top, }) => {
|
|
|
87
89
|
disabled: !canDragDates,
|
|
88
90
|
onDragEnd: handleResizeRightEnd,
|
|
89
91
|
onDragStateChange: useCallback((isDragging, deltaX) => {
|
|
90
|
-
setActiveDrag(isDragging
|
|
92
|
+
setActiveDrag(isDragging
|
|
93
|
+
? { taskId: task.id, mode: "resize-right", deltaX }
|
|
94
|
+
: null);
|
|
91
95
|
}, [setActiveDrag, task.id]),
|
|
92
96
|
});
|
|
93
97
|
// ----- Drag: Progress -----
|
|
@@ -151,9 +155,7 @@ const GanttTaskBar = React__default.memo(({ task, group, top, }) => {
|
|
|
151
155
|
const hoveredTask = tasks.find((t) => t.id === hoveredTaskId);
|
|
152
156
|
return (_c = (_b = hoveredTask === null || hoveredTask === void 0 ? void 0 : hoveredTask.dependencies) === null || _b === void 0 ? void 0 : _b.includes(task.id)) !== null && _c !== void 0 ? _c : false;
|
|
153
157
|
}, [hoveredTaskId, task.id, task.dependencies, tasks]);
|
|
154
|
-
const isFaded = hoveredTaskId !== null &&
|
|
155
|
-
hoveredTaskId !== task.id &&
|
|
156
|
-
!isHighlighted;
|
|
158
|
+
const isFaded = hoveredTaskId !== null && hoveredTaskId !== task.id && !isHighlighted;
|
|
157
159
|
const isFocused = focusedTaskId === task.id;
|
|
158
160
|
// ----- Click handler -----
|
|
159
161
|
const handleClick = (e) => {
|
|
@@ -165,7 +167,7 @@ const GanttTaskBar = React__default.memo(({ task, group, top, }) => {
|
|
|
165
167
|
const tooltipContent = (jsxs("div", { className: "text-sm space-y-2 min-w-[180px]", children: [jsx("div", { className: "font-semibold text-base", children: task.title }), jsxs("div", { className: "flex items-center gap-1.5 opacity-70", children: [jsx("span", { className: "inline-block size-2 rounded-full shrink-0", style: { backgroundColor: group.color } }), group.title] }), jsxs("div", { className: "space-y-0.5", children: [jsxs("div", { children: [formatDateShort(task.startDate), " \u2014 ", formatDateShort(task.endDate)] }), jsx("div", { className: "opacity-70", children: formatDuration(task.startDate, task.endDate) })] }), jsxs("div", { children: [jsxs("div", { className: "flex justify-between mb-1", children: [jsx("span", { children: "Progress" }), jsxs("span", { className: "font-medium", children: [task.progress, "%"] })] }), jsx("div", { className: "h-1.5 rounded-full bg-white/20 overflow-hidden", children: jsx("div", { className: "h-full rounded-full", style: {
|
|
166
168
|
width: `${task.progress}%`,
|
|
167
169
|
backgroundColor: barColor,
|
|
168
|
-
} }) })] }), task.assignee && (jsxs("div", { className: "flex items-center gap-1.5 pt-0.5", children: [jsx(Avatar, { src: task.assignee.avatar,
|
|
170
|
+
} }) })] }), task.assignee && (jsxs("div", { className: "flex items-center gap-1.5 pt-0.5", children: [jsx(Avatar, { src: task.assignee.avatar, name: task.assignee.name, size: "xs" }), jsx("span", { children: task.assignee.name })] })), isBehindSchedule && (jsxs("div", { className: "text-[var(--color-warning)] text-[10px]", children: ["Behind schedule (expected ", expectedProgress, "%)"] }))] }));
|
|
169
171
|
return (jsxs(Fragment, { children: [jsx(GanttTaskContextMenu, { task: task, children: jsxs("div", { className: "absolute", style: {
|
|
170
172
|
left: visualLeft,
|
|
171
173
|
top: top + (rowHeight - barHeight) / 2,
|
|
@@ -195,7 +197,7 @@ const GanttTaskBar = React__default.memo(({ task, group, top, }) => {
|
|
|
195
197
|
} }), isBehindSchedule && (jsx("div", { className: "absolute top-0 bottom-0 w-px", style: {
|
|
196
198
|
left: `${expectedProgress}%`,
|
|
197
199
|
borderLeft: "2px dashed rgba(255,255,255,0.5)",
|
|
198
|
-
} })), task.completed && (jsx("div", { className: "absolute top-1/2 left-2 right-2 h-px bg-white/60", style: { transform: "translateY(-0.5px)" } })), canDragDates && (jsx("div", { className: "absolute left-0 top-0 bottom-0 w-2 cursor-ew-resize z-20 rounded-l-full opacity-0 group-hover:opacity-100 transition-opacity hover:bg-black/10", onPointerDown: resizeLeftDrag.handlePointerDown })), canDragDates && (jsx("div", { className: "absolute right-0 top-0 bottom-0 w-2 cursor-ew-resize z-20 rounded-r-full opacity-0 group-hover:opacity-100 transition-opacity hover:bg-black/10", onPointerDown: resizeRightDrag.handlePointerDown })), canDragProgress && !isNarrow && (jsx("div", { className: "absolute top-0 bottom-0 w-3 cursor-ew-resize z-20 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity", style: { left: `calc(${displayProgress}% - 6px)` }, onPointerDown: progressDrag.handlePointerDown, children: jsx("div", { className: "w-0.5 h-3 rounded-full bg-white/80 shadow" }) })), !isNarrow && (jsxs("div", { className: "relative flex items-center gap-1.5 px-1 z-10 min-w-0 pointer-events-none", children: [task.assignee && (jsx(Avatar, { src: task.assignee.avatar,
|
|
200
|
+
} })), task.completed && (jsx("div", { className: "absolute top-1/2 left-2 right-2 h-px bg-white/60", style: { transform: "translateY(-0.5px)" } })), canDragDates && (jsx("div", { className: "absolute left-0 top-0 bottom-0 w-2 cursor-ew-resize z-20 rounded-l-full opacity-0 group-hover:opacity-100 transition-opacity hover:bg-black/10", onPointerDown: resizeLeftDrag.handlePointerDown })), canDragDates && (jsx("div", { className: "absolute right-0 top-0 bottom-0 w-2 cursor-ew-resize z-20 rounded-r-full opacity-0 group-hover:opacity-100 transition-opacity hover:bg-black/10", onPointerDown: resizeRightDrag.handlePointerDown })), canDragProgress && !isNarrow && (jsx("div", { className: "absolute top-0 bottom-0 w-3 cursor-ew-resize z-20 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity", style: { left: `calc(${displayProgress}% - 6px)` }, onPointerDown: progressDrag.handlePointerDown, children: jsx("div", { className: "w-0.5 h-3 rounded-full bg-white/80 shadow" }) })), !isNarrow && (jsxs("div", { className: "relative flex items-center gap-1.5 px-1 z-10 min-w-0 pointer-events-none", children: [task.assignee && (jsx(Avatar, { src: task.assignee.avatar, name: task.assignee.name, size: "xs" })), jsx("span", { className: "truncate text-sm text-[var(--color-text-inverse)] font-medium", children: task.title })] }))] }), isNarrow && (jsx("span", { className: "absolute text-sm font-medium whitespace-nowrap pointer-events-none", style: {
|
|
199
201
|
left: visualWidth + 6,
|
|
200
202
|
top: barHeight / 2,
|
|
201
203
|
transform: "translateY(-50%)",
|
|
@@ -11,7 +11,7 @@ const GanttTaskContextMenu = ({ task, children, }) => {
|
|
|
11
11
|
if (readonly || (!onTaskUpdate && !onTaskDuplicate && !onTaskDelete)) {
|
|
12
12
|
return jsx(Fragment, { children: children });
|
|
13
13
|
}
|
|
14
|
-
return (jsxs(ContextMenu, { children: [jsx(ContextMenu.Trigger, { children: children }), jsxs(ContextMenu.
|
|
14
|
+
return (jsxs(ContextMenu, { children: [jsx(ContextMenu.Trigger, { children: children }), jsxs(ContextMenu.Body, { children: [onTaskUpdate && (jsxs(ContextMenu.Item, { onSelect: () => onTaskUpdate(task.id, { completed: !task.completed, progress: task.completed ? 0 : 100 }), children: [jsx(CheckCircleIcon, { className: "size-4 mr-2" }), task.completed ? "Mark as incomplete" : "Mark as done"] })), onTaskUpdate && (jsxs(ContextMenu.Sub, { children: [jsx(ContextMenu.SubTrigger, { children: "Progress" }), jsx(ContextMenu.SubBody, { children: PROGRESS_STEPS.map((val) => (jsxs(ContextMenu.Item, { onSelect: () => onTaskUpdate(task.id, { progress: val, completed: val === 100 }), children: [val, "%"] }, val))) })] })), (onTaskDuplicate || onTaskDelete) && jsx(ContextMenu.Separator, {}), onTaskDuplicate && (jsxs(ContextMenu.Item, { onSelect: () => onTaskDuplicate(task.id), children: [jsx(DocumentDuplicateIcon, { className: "size-4 mr-2" }), "Duplicate"] })), onTaskDelete && (jsxs(ContextMenu.Item, { onSelect: () => onTaskDelete(task.id), className: "text-[var(--color-danger)]", children: [jsx(TrashIcon, { className: "size-4 mr-2" }), "Delete"] }))] })] }));
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export { GanttTaskContextMenu };
|
|
@@ -32,7 +32,7 @@ const KPI = React__default.forwardRef(({ value, label, trend, trendLabel, progre
|
|
|
32
32
|
return Math.round((Math.min(Math.max(progress, 0), 100) / 100) * barCount);
|
|
33
33
|
}, [progress, barCount]);
|
|
34
34
|
const barSize = kpiTheme.barSizes[size];
|
|
35
|
-
return (jsxs("div", { ref: ref, className: cn(theme.baseStyle, className), ...props, children: [jsxs("div", { className: "flex items-start justify-between", children: [jsxs("div", { className: "flex items-baseline gap-2", children: [jsx("span", { className: cn(theme.valueSizes[size]), children: value }), label && (jsxs("span", { className: cn(theme.labelStyle, theme.labelSizes[size]), children: [icon && (jsx("span", { className: "inline-flex items-center mr-1", children: icon })), label] }))] }), formattedTrend && trendDirection && (jsxs("span", { className: cn("inline-flex items-center gap-0.5 font-medium", theme.trendSizes[size], trendDirection === "up" && theme.trendPositive, trendDirection === "down" && theme.trendNegative, trendDirection === "neutral" && theme.trendNeutral), children: [formattedTrend, trendDirection === "up" && jsx(ArrowUpRightIcon, { className: "size-4" }), trendDirection === "down" && jsx(ArrowDownRightIcon, { className: "size-4" })] }))] }), progress !== undefined && (jsx("div", { className: cn("flex items-end", barSize.gap), role: "img", "aria-label": `Progress: ${progress}%`, children: Array.from({ length: barCount }, (_, i) => {
|
|
35
|
+
return (jsxs("div", { ref: ref, className: cn(theme.baseStyle, className), ...props, children: [jsxs("div", { className: "flex items-start justify-between", children: [jsxs("div", { className: "flex items-baseline gap-2", children: [jsx("span", { className: cn(theme.valueSizes[size]), children: value }), label && (typeof label === 'string' ? (jsxs("span", { className: cn(theme.labelStyle, theme.labelSizes[size]), children: [icon && (jsx("span", { className: "inline-flex items-center mr-1", children: icon })), label] })) : label)] }), formattedTrend && trendDirection && (typeof formattedTrend === 'string' ? (jsxs("span", { className: cn("inline-flex items-center gap-0.5 font-medium", theme.trendSizes[size], trendDirection === "up" && theme.trendPositive, trendDirection === "down" && theme.trendNegative, trendDirection === "neutral" && theme.trendNeutral), children: [formattedTrend, trendDirection === "up" && jsx(ArrowUpRightIcon, { className: "size-4" }), trendDirection === "down" && jsx(ArrowDownRightIcon, { className: "size-4" })] })) : formattedTrend)] }), progress !== undefined && (jsx("div", { className: cn("flex items-end", barSize.gap), role: "img", "aria-label": `Progress: ${progress}%`, children: Array.from({ length: barCount }, (_, i) => {
|
|
36
36
|
const isFilled = i < filledBars;
|
|
37
37
|
const fadeDistance = filledBars - i;
|
|
38
38
|
const fillOpacity = isFilled && fadeDistance <= 3
|
|
@@ -43,7 +43,7 @@ const KPI = React__default.forwardRef(({ value, label, trend, trendLabel, progre
|
|
|
43
43
|
ease: "easeOut",
|
|
44
44
|
delay: i * 0.03,
|
|
45
45
|
} })) }, i));
|
|
46
|
-
}) })), subtitle && (jsx("span", { className: cn(theme.subtitleStyle, size === "sm" ? "text-sm" : "text-base"), children: subtitle }))] }));
|
|
46
|
+
}) })), subtitle && (typeof subtitle === 'string' ? (jsx("span", { className: cn(theme.subtitleStyle, size === "sm" ? "text-sm" : "text-base"), children: subtitle })) : subtitle)] }));
|
|
47
47
|
});
|
|
48
48
|
KPI.displayName = "KPI";
|
|
49
49
|
|