@flikk/ui 1.0.0-beta.13 → 1.0.0-beta.15
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/CodeBlock/CodeBlock.theme.js +1 -1
- package/dist/components/ai/PromptInput/PromptInput.js +4 -2
- package/dist/components/ai/PromptInput/VoiceRecorder.js +1 -1
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +4 -4
- package/dist/components/ai/StreamingResponse/StreamingResponse.js +6 -0
- package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.js +3 -14
- package/dist/components/ai/index.d.ts +0 -5
- package/dist/components/ai/index.js +8 -4
- package/dist/components/charts/DonutChart/DonutChart.js +1 -1
- package/dist/components/charts/DonutChart/MultiSegmentDonutChart.js +1 -1
- package/dist/components/charts/FunnelChart/FunnelChart.js +2 -2
- package/dist/components/charts/shared/ChartLegend/ChartLegend.types.d.ts +13 -1
- package/dist/components/charts/shared/ChartLegend/ChartLegendContent.js +1 -1
- package/dist/components/charts/shared/ChartTooltip/ChartTooltip.types.d.ts +13 -2
- package/dist/components/core/Accordion/AccordionItem.js +1 -1
- package/dist/components/core/Accordion/AccordionTrigger.js +1 -1
- package/dist/components/core/Alert/Alert.animations.d.ts +11 -0
- package/dist/components/core/Alert/Alert.animations.js +44 -0
- package/dist/components/core/Alert/Alert.js +16 -3
- package/dist/components/core/Avatar/Avatar.js +12 -7
- package/dist/components/core/Avatar/Avatar.theme.d.ts +4 -6
- package/dist/components/core/Avatar/Avatar.theme.js +22 -12
- package/dist/components/core/Avatar/Avatar.types.d.ts +9 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.animations.js +2 -2
- package/dist/components/core/AvatarGroup/AvatarGroup.js +1 -2
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +1 -1
- package/dist/components/core/Badge/Badge.animations.js +1 -1
- package/dist/components/core/Badge/Badge.js +26 -50
- package/dist/components/core/Badge/Badge.theme.js +49 -63
- package/dist/components/core/Badge/Badge.types.d.ts +6 -30
- package/dist/components/core/Button/Button.js +2 -2
- package/dist/components/core/Button/Button.ripple.js +1 -1
- package/dist/components/core/Button/Button.theme.d.ts +1 -1
- package/dist/components/core/Button/Button.theme.js +5 -5
- package/dist/components/core/Button/Button.types.d.ts +1 -1
- package/dist/components/core/ButtonGroup/ButtonGroup.theme.js +6 -6
- package/dist/components/core/ButtonGroup/ButtonGroupText.js +1 -3
- package/dist/components/core/Calendar/Calendar.js +29 -3
- package/dist/components/core/Calendar/Calendar.theme.js +11 -7
- package/dist/components/core/Calendar/Calendar.types.d.ts +3 -0
- package/dist/components/core/Calendar/CalendarMini/CalendarMini.js +2 -2
- package/dist/components/core/Carousel/CarouselBody.js +0 -1
- package/dist/components/core/CommandPalette/CommandItem.js +1 -1
- package/dist/components/core/CommandPalette/CommandPalette.js +6 -4
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +1 -0
- package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +6 -0
- package/dist/components/core/ContextMenu/ContextMenu.js +5 -4
- package/dist/components/core/ContextMenu/ContextMenuTrigger.js +5 -6
- package/dist/components/core/Drawer/Drawer.d.ts +1 -1
- package/dist/components/core/Drawer/Drawer.js +25 -2
- package/dist/components/core/Drawer/Drawer.theme.js +2 -2
- package/dist/components/core/Drawer/Drawer.types.d.ts +6 -0
- package/dist/components/core/Drawer/DrawerHeader.js +1 -1
- package/dist/components/core/Dropdown/Dropdown.d.ts +1 -1
- package/dist/components/core/Dropdown/Dropdown.js +5 -1
- package/dist/components/core/Dropdown/Dropdown.types.d.ts +1 -0
- package/dist/components/core/Dropdown/DropdownItem.js +1 -1
- package/dist/components/core/Dropdown/DropdownMenu.js +4 -4
- package/dist/components/core/Dropdown/DropdownSection.js +1 -1
- package/dist/components/core/Dropdown/DropdownSeparator.js +1 -1
- package/dist/components/core/Dropdown/DropdownTrigger.d.ts +6 -1
- package/dist/components/core/Dropdown/DropdownTrigger.js +10 -8
- package/dist/components/core/Kbd/Kbd.theme.js +3 -3
- package/dist/components/core/Link/Link.js +4 -2
- package/dist/components/core/Message/Message.d.ts +9 -0
- package/dist/components/core/Message/Message.js +44 -3
- package/dist/components/core/Message/Message.theme.js +22 -0
- package/dist/components/core/Message/Message.types.d.ts +115 -0
- package/dist/components/core/Message/MessageAudio.d.ts +8 -0
- package/dist/components/core/Message/MessageAudio.js +11 -0
- package/dist/components/core/Message/MessageContext.d.ts +3 -1
- package/dist/components/core/Message/MessageDateDivider.d.ts +6 -0
- package/dist/components/core/Message/MessageDateDivider.js +10 -0
- package/dist/components/core/Message/MessageFile.d.ts +9 -0
- package/dist/components/core/Message/MessageFile.js +15 -0
- package/dist/components/core/Message/MessageImage.d.ts +11 -0
- package/dist/components/core/Message/MessageImage.js +13 -0
- package/dist/components/core/Message/MessageLink.d.ts +10 -0
- package/dist/components/core/Message/MessageLink.js +15 -0
- package/dist/components/core/Message/MessageReactions.d.ts +8 -0
- package/dist/components/core/Message/MessageReactions.js +12 -0
- package/dist/components/core/Message/MessageReply.d.ts +8 -0
- package/dist/components/core/Message/MessageReply.js +10 -0
- package/dist/components/core/Message/MessageSenderName.d.ts +6 -0
- package/dist/components/core/Message/MessageSenderName.js +10 -0
- package/dist/components/core/Message/MessageStatusIndicator.d.ts +9 -0
- package/dist/components/core/Message/MessageStatusIndicator.js +45 -0
- package/dist/components/core/Message/index.d.ts +19 -1
- package/dist/components/core/Modal/Modal.animations.d.ts +1 -0
- package/dist/components/core/Modal/Modal.animations.js +14 -11
- package/dist/components/core/Modal/ModalHeader.js +1 -1
- package/dist/components/core/NavItem/NavItem.js +100 -52
- package/dist/components/core/NavItem/NavItem.theme.js +6 -3
- package/dist/components/core/NavItem/NavItem.types.d.ts +44 -30
- package/dist/components/core/NavItem/index.d.ts +1 -1
- package/dist/components/core/Pagination/Pagination.theme.js +1 -1
- package/dist/components/core/Pill/Pill.theme.js +1 -1
- package/dist/components/core/Popover/Popover.d.ts +1 -1
- package/dist/components/core/Popover/PopoverBody.js +2 -2
- package/dist/components/core/Popover/PopoverTrigger.d.ts +1 -1
- package/dist/components/core/Popover/PopoverTrigger.js +11 -11
- package/dist/components/core/Progress/Progress.d.ts +9 -8
- package/dist/components/core/Progress/Progress.js +16 -16
- package/dist/components/core/Progress/Progress.theme.js +5 -16
- package/dist/components/core/Progress/Progress.types.d.ts +2 -20
- package/dist/components/core/Progress/index.d.ts +1 -1
- package/dist/components/core/ScrollArea/ScrollArea.js +49 -7
- package/dist/components/core/ScrollArea/ScrollArea.types.d.ts +12 -3
- package/dist/components/core/ScrollArea/index.d.ts +1 -1
- package/dist/components/core/Segmented/SegmentedItem.js +1 -1
- package/dist/components/core/Sidebar/Sidebar.d.ts +11 -1
- package/dist/components/core/Sidebar/Sidebar.js +51 -17
- package/dist/components/core/Sidebar/Sidebar.theme.js +9 -7
- package/dist/components/core/Sidebar/Sidebar.types.d.ts +57 -0
- package/dist/components/core/Sidebar/SidebarContent.js +3 -1
- package/dist/components/core/Sidebar/SidebarContext.d.ts +14 -0
- package/dist/components/core/Sidebar/SidebarContext.js +63 -11
- package/dist/components/core/Sidebar/SidebarFooter.js +3 -1
- package/dist/components/core/Sidebar/SidebarHeader.js +6 -2
- package/dist/components/core/Sidebar/SidebarMobileTrigger.d.ts +3 -0
- package/dist/components/core/Sidebar/SidebarMobileTrigger.js +29 -0
- package/dist/components/core/Sidebar/SidebarNav.js +3 -2
- package/dist/components/core/Sidebar/SidebarNavGroup.js +4 -2
- package/dist/components/core/Sidebar/SidebarToggle.js +2 -1
- package/dist/components/core/Sidebar/SidebarUserProfile.d.ts +3 -0
- package/dist/components/core/Sidebar/SidebarUserProfile.js +35 -0
- package/dist/components/core/Sidebar/index.d.ts +3 -1
- package/dist/components/core/SocialIcon/SocialIcon.js +1 -1
- package/dist/components/core/Sortable/Sortable.js +2 -2
- package/dist/components/core/Sortable/Sortable.theme.js +1 -1
- package/dist/components/core/Sortable/Sortable.types.d.ts +7 -5
- package/dist/components/core/Tabs/Tabs.theme.d.ts +1 -1
- package/dist/components/core/Tabs/Tabs.theme.js +3 -3
- package/dist/components/core/Tabs/TabsBody.js +1 -1
- package/dist/components/core/Tabs/TabsTrigger.js +1 -1
- package/dist/components/core/Tag/Tag.js +2 -2
- package/dist/components/core/Toast/Toast.d.ts +2 -2
- package/dist/components/core/Toast/Toast.js +30 -21
- package/dist/components/core/Toast/Toast.theme.js +4 -9
- package/dist/components/core/Toast/Toast.types.d.ts +4 -21
- package/dist/components/core/Toast/index.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.js +1 -1
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
- package/dist/components/core/index.js +11 -0
- package/dist/components/data-display/GanttChart/GanttChart.types.d.ts +2 -2
- package/dist/components/data-display/GanttChart/GanttToolbar.js +1 -1
- package/dist/components/data-display/Table/Table.types.d.ts +8 -8
- package/dist/components/effects/CustomCursor/CustomCursor.js +2 -2
- package/dist/components/effects/GlassSurface/GlassSurface.d.ts +1 -1
- package/dist/components/effects/GlassSurface/GlassSurface.js +12 -4
- package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.animations.d.ts +39 -0
- package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.animations.js +98 -0
- package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.d.ts +3 -0
- package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.js +104 -0
- package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.types.d.ts +30 -0
- package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.d.ts +3 -0
- package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.js +36 -0
- package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.d.ts +3 -0
- package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.js +36 -0
- package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.d.ts +3 -0
- package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.js +37 -0
- package/dist/components/effects/InteractiveCharacters/hooks/useBlink.d.ts +14 -0
- package/dist/components/effects/InteractiveCharacters/hooks/useBlink.js +41 -0
- package/dist/components/effects/InteractiveCharacters/hooks/useIdleAnimation.d.ts +25 -0
- package/dist/components/effects/InteractiveCharacters/hooks/useIdleAnimation.js +84 -0
- package/dist/components/effects/InteractiveCharacters/hooks/useMouseTracking.d.ts +18 -0
- package/dist/components/effects/InteractiveCharacters/hooks/useMouseTracking.js +35 -0
- package/dist/components/effects/InteractiveCharacters/index.d.ts +2 -0
- package/dist/components/effects/MorphingText/MorphingText.d.ts +1 -1
- package/dist/components/effects/MorphingText/MorphingText.js +6 -5
- package/dist/components/effects/Neumorphic/InsetCircleButton.d.ts +9 -0
- package/dist/components/effects/Neumorphic/InsetCircleButton.js +10 -0
- package/dist/components/effects/Neumorphic/InsetPill.d.ts +7 -0
- package/dist/components/effects/Neumorphic/InsetPill.js +7 -0
- package/dist/components/effects/Neumorphic/index.d.ts +4 -0
- package/dist/components/effects/NoiseOverlay/NoiseOverlay.d.ts +1 -1
- package/dist/components/effects/NoiseOverlay/NoiseOverlay.js +4 -4
- package/dist/components/effects/Overlay/Overlay.js +6 -4
- package/dist/components/effects/PageTransition/PageTransition.animations.d.ts +8 -0
- package/dist/components/effects/PageTransition/PageTransition.animations.js +53 -0
- package/dist/components/effects/PageTransition/PageTransition.d.ts +3 -0
- package/dist/components/effects/PageTransition/PageTransition.js +71 -0
- package/dist/components/effects/PageTransition/PageTransition.types.d.ts +15 -0
- package/dist/components/effects/PageTransition/index.d.ts +2 -0
- package/dist/components/effects/index.d.ts +6 -0
- package/dist/components/effects/index.js +4 -0
- package/dist/components/forms/Checkbox/Checkbox.animations.d.ts +14 -0
- package/dist/components/forms/Checkbox/Checkbox.animations.js +53 -0
- package/dist/components/forms/Checkbox/Checkbox.js +4 -2
- package/dist/components/forms/Checkbox/Checkbox.theme.js +3 -3
- package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerBody.js +3 -3
- package/dist/components/forms/Combobox/Combobox.js +5 -3
- package/dist/components/forms/DatePicker/DatePickerBody.js +1 -1
- package/dist/components/forms/DateRangePicker/DateRangePicker.animations.d.ts +1 -0
- package/dist/components/forms/DateRangePicker/DateRangePicker.d.ts +37 -0
- package/dist/components/forms/DateRangePicker/DateRangePicker.js +110 -0
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.d.ts +5 -0
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +52 -0
- package/dist/components/forms/DateRangePicker/DateRangePicker.types.d.ts +154 -0
- package/dist/components/forms/DateRangePicker/DateRangePickerBody.d.ts +6 -0
- package/dist/components/forms/DateRangePicker/DateRangePickerBody.js +208 -0
- package/dist/components/forms/DateRangePicker/DateRangePickerPresets.d.ts +6 -0
- package/dist/components/forms/DateRangePicker/DateRangePickerPresets.js +41 -0
- package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.d.ts +6 -0
- package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +32 -0
- package/dist/components/forms/DateRangePicker/dateRangePresets.d.ts +5 -0
- package/dist/components/forms/DateRangePicker/dateRangePresets.js +59 -0
- package/dist/components/forms/DateRangePicker/index.d.ts +4 -0
- package/dist/components/forms/FileUpload/FileUploadProgress.animations.d.ts +36 -0
- package/dist/components/forms/FileUpload/FileUploadProgress.animations.js +22 -0
- package/dist/components/forms/FileUpload/FileUploadProgress.d.ts +3 -0
- package/dist/components/forms/FileUpload/FileUploadProgress.js +111 -0
- package/dist/components/forms/FileUpload/FileUploadProgress.theme.d.ts +19 -0
- package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +27 -0
- package/dist/components/forms/FileUpload/FileUploadProgress.types.d.ts +33 -0
- package/dist/components/forms/FileUpload/index.d.ts +3 -0
- package/dist/components/forms/Input/Input.js +8 -13
- package/dist/components/forms/Input/Input.types.d.ts +6 -0
- package/dist/components/forms/InputAddress/InputAddress.theme.js +1 -1
- package/dist/components/forms/InputCounter/InputCounter.js +1 -1
- package/dist/components/forms/InputCreditCard/InputCreditCard.theme.js +1 -1
- package/dist/components/forms/InputOTP/InputOTP.theme.js +1 -1
- package/dist/components/forms/Radio/Radio.animations.d.ts +10 -0
- package/dist/components/forms/Radio/Radio.animations.js +33 -0
- package/dist/components/forms/Radio/Radio.js +11 -2
- package/dist/components/forms/Radio/Radio.theme.js +3 -3
- package/dist/components/forms/RichTextEditor/RichTextEditor.js +23 -14
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +2 -2
- package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +11 -0
- package/dist/components/forms/Select/Select.d.ts +1 -1
- package/dist/components/forms/Select/Select.js +7 -7
- package/dist/components/forms/Select/Select.types.d.ts +3 -3
- package/dist/components/forms/SelectableCard/SelectableCard.js +1 -1
- package/dist/components/forms/Slider/Slider.theme.js +1 -1
- package/dist/components/forms/Switch/Switch.theme.js +3 -3
- package/dist/components/forms/forms.theme.js +1 -1
- package/dist/components/forms/index.d.ts +6 -0
- package/dist/components/forms/index.js +8 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useMediaQuery.d.ts +5 -0
- package/dist/hooks/useMediaQuery.js +21 -0
- package/dist/index.js +23 -0
- package/dist/styles.css +1 -1
- package/dist/utils/dateUtils.js +56 -5
- package/dist/utils/formatUtils.d.ts +10 -0
- package/dist/utils/formatUtils.js +24 -0
- package/dist/utils/index.d.ts +1 -1
- package/package.json +12 -4
- package/src/global.scss +320 -39
- package/src/styles/theme.css +151 -62
- package/src/theme-plugin.css +13 -0
- package/dist/components/ai/ApprovalCard/ApprovalCard.d.ts +0 -3
- package/dist/components/ai/ApprovalCard/ApprovalCard.js +0 -16
- package/dist/components/ai/ApprovalCard/ApprovalCard.theme.d.ts +0 -13
- package/dist/components/ai/ApprovalCard/ApprovalCard.theme.js +0 -15
- package/dist/components/ai/ApprovalCard/ApprovalCard.types.d.ts +0 -43
- package/dist/components/ai/ApprovalCard/index.d.ts +0 -2
- package/dist/components/ai/MessageHistory/MessageHistory.d.ts +0 -18
- package/dist/components/ai/MessageHistory/MessageHistory.js +0 -98
- package/dist/components/ai/MessageHistory/MessageHistory.theme.d.ts +0 -2
- package/dist/components/ai/MessageHistory/MessageHistory.theme.js +0 -8
- package/dist/components/ai/MessageHistory/MessageHistory.types.d.ts +0 -94
- package/dist/components/ai/MessageHistory/index.d.ts +0 -3
- package/dist/icons/Icon.d.ts +0 -24
- package/dist/icons/Icon.js +0 -30
- package/dist/icons/Index.d.ts +0 -16
- package/dist/icons/core/ChevronUpDown.d.ts +0 -1
- package/dist/icons/core/ChevronUpDown.js +0 -7
- package/dist/icons/core/DollarIcon.d.ts +0 -1
- package/dist/icons/core/DollarIcon.js +0 -5
- package/dist/icons/core/LockIcon.d.ts +0 -1
- package/dist/icons/core/LockIcon.js +0 -5
- package/dist/icons/core/MinusIcon.d.ts +0 -1
- package/dist/icons/core/MinusIcon.js +0 -7
- package/dist/icons/core/PlusIcon.d.ts +0 -1
- package/dist/icons/core/PlusIcon.js +0 -7
- package/dist/icons/core/SearchIcon.d.ts +0 -1
- package/dist/icons/core/SearchIcon.js +0 -7
- package/dist/icons/core/TickIcon.d.ts +0 -1
- package/dist/icons/core/TickIcon.js +0 -5
- package/dist/icons/core/User.d.ts +0 -1
- package/dist/utils/useClickOutside.d.ts +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const tooltipTheme = {
|
|
2
2
|
// Base style for the tooltip - using fixed positioning for portal rendering
|
|
3
3
|
baseStyle: "fixed z-[99] rounded-[var(--tooltip-radius)] py-1 px-2 text-sm text-[var(--color-text-primary)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 pointer-events-none bg-white/60 backdrop-blur-md outline outline-[var(--color-border)] shadow-lg border-t-[1px] border-white " +
|
|
4
|
-
"dark:bg-neutral-800/80 dark:outline-[var(--color-border)]/80 dark:border-[var(--color-border)]",
|
|
4
|
+
"dark:bg-[var(--color-neutral-800)]/80 dark:outline-[var(--color-border)]/80 dark:border-[var(--color-border)]",
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
export { tooltipTheme };
|
|
@@ -74,6 +74,15 @@ export { messageTheme } from './Message/Message.theme.js';
|
|
|
74
74
|
export { messageListTheme } from './Message/MessageList.theme.js';
|
|
75
75
|
export { TypeWriter } from './Message/TypeWriter.js';
|
|
76
76
|
export { MessageBody } from './Message/MessageBody.js';
|
|
77
|
+
export { MessageStatusIndicator } from './Message/MessageStatusIndicator.js';
|
|
78
|
+
export { MessageSenderName } from './Message/MessageSenderName.js';
|
|
79
|
+
export { MessageFile } from './Message/MessageFile.js';
|
|
80
|
+
export { MessageImage } from './Message/MessageImage.js';
|
|
81
|
+
export { MessageAudio } from './Message/MessageAudio.js';
|
|
82
|
+
export { MessageLink } from './Message/MessageLink.js';
|
|
83
|
+
export { MessageReply } from './Message/MessageReply.js';
|
|
84
|
+
export { MessageReactions } from './Message/MessageReactions.js';
|
|
85
|
+
export { MessageDateDivider } from './Message/MessageDateDivider.js';
|
|
77
86
|
export { Empty } from './Empty/Empty.js';
|
|
78
87
|
export { emptyTheme } from './Empty/Empty.theme.js';
|
|
79
88
|
export { Masonry } from './Masonry/Masonry.js';
|
|
@@ -89,6 +98,8 @@ export { SidebarNav } from './Sidebar/SidebarNav.js';
|
|
|
89
98
|
export { SidebarNavGroup } from './Sidebar/SidebarNavGroup.js';
|
|
90
99
|
export { SidebarSubmenu } from './Sidebar/SidebarSubmenu.js';
|
|
91
100
|
export { SidebarToggle } from './Sidebar/SidebarToggle.js';
|
|
101
|
+
export { SidebarMobileTrigger } from './Sidebar/SidebarMobileTrigger.js';
|
|
102
|
+
export { SidebarUserProfile } from './Sidebar/SidebarUserProfile.js';
|
|
92
103
|
export { useSidebarContext } from './Sidebar/SidebarContext.js';
|
|
93
104
|
export { OfflineIndicator } from './OfflineIndicator/OfflineIndicator.js';
|
|
94
105
|
export { offlineIndicatorTheme } from './OfflineIndicator/OfflineIndicator.theme.js';
|
|
@@ -14,7 +14,7 @@ export interface GanttTask {
|
|
|
14
14
|
completed?: boolean;
|
|
15
15
|
dependencies?: string[];
|
|
16
16
|
milestone?: boolean;
|
|
17
|
-
[key: string]:
|
|
17
|
+
[key: string]: unknown;
|
|
18
18
|
}
|
|
19
19
|
export interface GanttHoliday {
|
|
20
20
|
date: Date | string;
|
|
@@ -30,7 +30,7 @@ export interface GanttGroup {
|
|
|
30
30
|
export interface GanttColumn<T extends GanttTask = GanttTask> {
|
|
31
31
|
id: string;
|
|
32
32
|
header: string;
|
|
33
|
-
accessor: keyof T | ((task: T) =>
|
|
33
|
+
accessor: keyof T | ((task: T) => ReactNode | string | number | boolean | null | undefined);
|
|
34
34
|
cell?: (task: T, group: GanttGroup) => ReactNode;
|
|
35
35
|
width?: number;
|
|
36
36
|
align?: "left" | "center" | "right";
|
|
@@ -23,7 +23,7 @@ const GanttToolbar = () => {
|
|
|
23
23
|
const targetScroll = todayOffset * dayWidth - container.clientWidth / 2;
|
|
24
24
|
container.scrollTo({ left: targetScroll, behavior: "smooth" });
|
|
25
25
|
};
|
|
26
|
-
return (jsxs("div", { className: cn(theme.toolbarStyle), children: [jsxs("div", { className: "flex items-center gap-3", children: [todayOffset !== null && (jsxs(Button, { variant: "outline", color: "neutral", size: "sm", onClick: handleScrollToToday, children: [jsx(CalendarIcon, { className: "size-4" }), "Today"] })), jsx(Segmented, { value: zoom, onChange: (val) => setZoom(val), size: "sm", children: ZOOM_OPTIONS.map((opt) => (jsx(Segmented.Item, { value: opt.value, children: opt.label }, opt.value))) }), jsx(Checkbox, { id: "gantt-hide-completed", name: "hideCompleted", value: "hideCompleted", checked: hideCompleted, onChange: (checked) => setHideCompleted(checked), label: "Hide completed", size: "sm" })] }), jsx("div", { className: "flex items-center gap-2", children: onGroupAdd && !readonly && (jsxs(Button, { variant: "
|
|
26
|
+
return (jsxs("div", { className: cn(theme.toolbarStyle), children: [jsxs("div", { className: "flex items-center gap-3", children: [todayOffset !== null && (jsxs(Button, { variant: "outline", color: "neutral", size: "sm", onClick: handleScrollToToday, children: [jsx(CalendarIcon, { className: "size-4" }), "Today"] })), jsx(Segmented, { value: zoom, onChange: (val) => setZoom(val), size: "sm", children: ZOOM_OPTIONS.map((opt) => (jsx(Segmented.Item, { value: opt.value, children: opt.label }, opt.value))) }), jsx(Checkbox, { id: "gantt-hide-completed", name: "hideCompleted", value: "hideCompleted", checked: hideCompleted, onChange: (checked) => setHideCompleted(checked), label: "Hide completed", size: "sm" })] }), jsx("div", { className: "flex items-center gap-2", children: onGroupAdd && !readonly && (jsxs(Button, { variant: "soft", size: "sm", onClick: onGroupAdd, children: [jsx(PlusIcon, { className: "size-3.5" }), "Add group"] })) })] }));
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
export { GanttToolbar };
|
|
@@ -38,13 +38,13 @@ export interface FilterOption {
|
|
|
38
38
|
/**
|
|
39
39
|
* Column definition for table data display and behavior
|
|
40
40
|
*/
|
|
41
|
-
export interface Column<T =
|
|
41
|
+
export interface Column<T = unknown> {
|
|
42
42
|
/** Unique identifier for the column */
|
|
43
43
|
id: string;
|
|
44
44
|
/** Header content - can be string or React element */
|
|
45
45
|
header: string | ReactNode;
|
|
46
46
|
/** Property key or function to extract cell data from row object */
|
|
47
|
-
accessor: keyof T | ((row: T) =>
|
|
47
|
+
accessor: keyof T | ((row: T) => ReactNode | string | number | boolean | null | undefined);
|
|
48
48
|
/** Optional custom renderer for cell content */
|
|
49
49
|
cell?: (row: T) => ReactNode;
|
|
50
50
|
/** Enable sorting for this column */
|
|
@@ -134,7 +134,7 @@ export interface TableContextType {
|
|
|
134
134
|
*
|
|
135
135
|
* @template T The type of data objects in each table row
|
|
136
136
|
*/
|
|
137
|
-
export interface TableProps<T =
|
|
137
|
+
export interface TableProps<T = unknown> {
|
|
138
138
|
/** Array of data objects to display - required for data-driven API */
|
|
139
139
|
data?: T[];
|
|
140
140
|
/** Column definitions for data display and behavior - required for data-driven API */
|
|
@@ -287,7 +287,7 @@ export interface InternalTableCellProps<T> {
|
|
|
287
287
|
}
|
|
288
288
|
export type ActionVariant = 'default' | 'danger';
|
|
289
289
|
export type ActionPriority = 'high' | 'normal';
|
|
290
|
-
export interface ActionItem<T =
|
|
290
|
+
export interface ActionItem<T = unknown> {
|
|
291
291
|
/** Unique identifier for the action */
|
|
292
292
|
id: string;
|
|
293
293
|
/** Display label for the action */
|
|
@@ -305,7 +305,7 @@ export interface ActionItem<T = any> {
|
|
|
305
305
|
/** Function to determine if action should be disabled */
|
|
306
306
|
disabled?: (row: T) => boolean;
|
|
307
307
|
}
|
|
308
|
-
export interface TableActionsProps<T =
|
|
308
|
+
export interface TableActionsProps<T = unknown> {
|
|
309
309
|
/** Array of action items to display */
|
|
310
310
|
actions: ActionItem<T>[];
|
|
311
311
|
/** Row data to pass to action handlers */
|
|
@@ -315,7 +315,7 @@ export interface TableActionsProps<T = any> {
|
|
|
315
315
|
/** Additional CSS class name */
|
|
316
316
|
className?: string;
|
|
317
317
|
}
|
|
318
|
-
export interface TableActionsMenuProps<T =
|
|
318
|
+
export interface TableActionsMenuProps<T = unknown> {
|
|
319
319
|
/** Array of action items to display in menu */
|
|
320
320
|
actions: ActionItem<T>[];
|
|
321
321
|
/** Row data to pass to action handlers */
|
|
@@ -351,7 +351,7 @@ export interface TableSelectionHeaderProps {
|
|
|
351
351
|
onClearSelection: () => void;
|
|
352
352
|
className?: string;
|
|
353
353
|
}
|
|
354
|
-
export interface TableColumnManagerProps<T =
|
|
354
|
+
export interface TableColumnManagerProps<T = unknown> {
|
|
355
355
|
columns: Column<T>[];
|
|
356
356
|
visibleColumns: string[];
|
|
357
357
|
columnOrder: string[];
|
|
@@ -359,7 +359,7 @@ export interface TableColumnManagerProps<T = any> {
|
|
|
359
359
|
onResetToDefault: () => void;
|
|
360
360
|
onColumnReorder?: (fromIndex: number, toIndex: number) => void;
|
|
361
361
|
}
|
|
362
|
-
export interface TableFilterProps<T =
|
|
362
|
+
export interface TableFilterProps<T = unknown> {
|
|
363
363
|
columns: Column<T>[];
|
|
364
364
|
filterConfig: FilterConfig[];
|
|
365
365
|
onFilterChange: (filterConfig: FilterConfig[]) => void;
|
|
@@ -125,7 +125,7 @@ CustomCursorProvider.displayName = "CustomCursorProvider";
|
|
|
125
125
|
* </CustomCursor>
|
|
126
126
|
* ```
|
|
127
127
|
*/
|
|
128
|
-
const CustomCursor = React.forwardRef(({ children, size = "md", color = "primary", variant = "default", shape = "arrow", className, style, ...props }, ref) => {
|
|
128
|
+
const CustomCursor = React.forwardRef(({ children, size = "md", color = "primary", variant = "default", shape = "arrow", className, style, onAnimationStart: _onAnimationStart, onAnimationEnd: _onAnimationEnd, onDrag: _onDrag, onDragStart: _onDragStart, onDragEnd: _onDragEnd, ...props }, ref) => {
|
|
129
129
|
const { cursorPos, isActive, containerRef, cursorRef } = useCustomCursor();
|
|
130
130
|
React.useImperativeHandle(ref, () => cursorRef.current);
|
|
131
131
|
const x = useMotionValue(0);
|
|
@@ -200,7 +200,7 @@ const userVariantColors = [
|
|
|
200
200
|
"warning",
|
|
201
201
|
"danger",
|
|
202
202
|
];
|
|
203
|
-
const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align = "bottom-right", transition, variant = "default", avatar, name, color, className, style, ...props }, ref) => {
|
|
203
|
+
const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align = "bottom-right", transition, variant = "default", avatar, name, color, className, style, onAnimationStart: _onAnimationStart2, onAnimationEnd: _onAnimationEnd2, onDrag: _onDrag2, onDragStart: _onDragStart2, onDragEnd: _onDragEnd2, ...props }, ref) => {
|
|
204
204
|
const { cursorPos, isActive, cursorRef } = useCustomCursor();
|
|
205
205
|
const cursorFollowRef = React.useRef(null);
|
|
206
206
|
const shouldReduceMotion = useReducedMotion();
|
|
@@ -5,4 +5,4 @@ import { GlassSurfaceProps } from "./GlassSurface.types";
|
|
|
5
5
|
* Creates a realistic chromatic aberration glass effect using SVG filters.
|
|
6
6
|
* Works as a wrapper for any content.
|
|
7
7
|
*/
|
|
8
|
-
export declare const GlassSurface: React.
|
|
8
|
+
export declare const GlassSurface: React.ForwardRefExoticComponent<GlassSurfaceProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useId, useState, useRef, useMemo, useEffect } from 'react';
|
|
2
|
+
import React__default, { useId, useState, useRef, useMemo, useEffect, useCallback } from 'react';
|
|
3
3
|
import { cn } from '../../../utils/cn.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -23,7 +23,7 @@ const useDarkMode = () => {
|
|
|
23
23
|
* Creates a realistic chromatic aberration glass effect using SVG filters.
|
|
24
24
|
* Works as a wrapper for any content.
|
|
25
25
|
*/
|
|
26
|
-
const GlassSurface = ({ children, width, height, borderRadius = 20, borderWidth = 0.07, brightness: brightnessProp, opacity: opacityProp, blur: blurProp, displace: displaceProp, backgroundOpacity: backgroundOpacityProp, backgroundColor, saturation: saturationProp, distortionScale: distortionScaleProp, redOffset = 0, greenOffset = 10, blueOffset = 20, xChannel = "R", yChannel = "G", mixBlendMode: mixBlendModeProp, colorScheme = "auto", frosted = false, className = "", style = {}, }) => {
|
|
26
|
+
const GlassSurface = React__default.forwardRef(({ children, width, height, borderRadius = 20, borderWidth = 0.07, brightness: brightnessProp, opacity: opacityProp, blur: blurProp, displace: displaceProp, backgroundOpacity: backgroundOpacityProp, backgroundColor, saturation: saturationProp, distortionScale: distortionScaleProp, redOffset = 0, greenOffset = 10, blueOffset = 20, xChannel = "R", yChannel = "G", mixBlendMode: mixBlendModeProp, colorScheme = "auto", frosted = false, className = "", style = {}, }, forwardedRef) => {
|
|
27
27
|
const uniqueId = useId().replace(/:/g, "-");
|
|
28
28
|
const filterId = `glass-filter-${uniqueId}`;
|
|
29
29
|
const redGradId = `red-grad-${uniqueId}`;
|
|
@@ -250,7 +250,15 @@ const GlassSurface = ({ children, width, height, borderRadius = 20, borderWidth
|
|
|
250
250
|
const focusVisibleClasses = resolvedDark
|
|
251
251
|
? "focus-visible:outline-2 focus-visible:outline-[#0A84FF] focus-visible:outline-offset-2"
|
|
252
252
|
: "focus-visible:outline-2 focus-visible:outline-[#007AFF] focus-visible:outline-offset-2";
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
const mergedRef = useCallback((node) => {
|
|
254
|
+
containerRef.current = node;
|
|
255
|
+
if (typeof forwardedRef === "function")
|
|
256
|
+
forwardedRef(node);
|
|
257
|
+
else if (forwardedRef)
|
|
258
|
+
forwardedRef.current = node;
|
|
259
|
+
}, [forwardedRef]);
|
|
260
|
+
return (jsxs("div", { ref: mergedRef, className: cn("relative transition-opacity duration-[260ms] ease-out", focusVisibleClasses, className), style: containerStyles, children: [jsx("svg", { className: "w-full h-full pointer-events-none absolute inset-0 opacity-0 -z-10", xmlns: "http://www.w3.org/2000/svg", children: jsxs("defs", { children: [jsxs("filter", { id: filterId, colorInterpolationFilters: "sRGB", x: "0%", y: "0%", width: "100%", height: "100%", children: [jsx("feImage", { ref: feImageRef, x: "0", y: "0", width: "100%", height: "100%", preserveAspectRatio: "none", result: "map" }), jsx("feDisplacementMap", { ref: redChannelRef, in: "SourceGraphic", in2: "map", id: "redchannel", result: "dispRed" }), jsx("feColorMatrix", { in: "dispRed", type: "matrix", values: "1 0 0 0 0\n 0 0 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0", result: "red" }), jsx("feDisplacementMap", { ref: greenChannelRef, in: "SourceGraphic", in2: "map", id: "greenchannel", result: "dispGreen" }), jsx("feColorMatrix", { in: "dispGreen", type: "matrix", values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0", result: "green" }), jsx("feDisplacementMap", { ref: blueChannelRef, in: "SourceGraphic", in2: "map", id: "bluechannel", result: "dispBlue" }), jsx("feColorMatrix", { in: "dispBlue", type: "matrix", values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0", result: "blue" }), jsx("feBlend", { in: "red", in2: "green", mode: "screen", result: "rg" }), jsx("feBlend", { in: "rg", in2: "blue", mode: "screen", result: "output" }), jsx("feGaussianBlur", { ref: gaussianBlurRef, in: "output", stdDeviation: "0.7" })] }), jsx("filter", { id: noiseFilterId, x: "0%", y: "0%", width: "100%", height: "100%", children: jsx("feTurbulence", { type: "fractalNoise", baseFrequency: "0.65", numOctaves: "3", stitchTiles: "stitch" }) })] }) }), jsx("div", { className: "relative z-10 h-full rounded-[inherit]", children: children }), jsx("div", { className: "absolute inset-0 pointer-events-none rounded-[inherit] overflow-hidden z-20", children: frosted && (jsx("div", { className: "absolute inset-0 opacity-10 mix-blend-overlay", style: { filter: `url(#${noiseFilterId})` } })) })] }));
|
|
261
|
+
});
|
|
262
|
+
GlassSurface.displayName = "GlassSurface";
|
|
255
263
|
|
|
256
264
|
export { GlassSurface };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Variants } from 'motion/react';
|
|
2
|
+
import type { CharacterState } from './InteractiveCharacters.types';
|
|
3
|
+
export declare const eyelidVariants: Record<CharacterState, {
|
|
4
|
+
scaleY: number;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const blobBodyVariants: Variants;
|
|
7
|
+
export declare const tallBodyVariants: Variants;
|
|
8
|
+
export declare const smallBodyVariants: Variants;
|
|
9
|
+
export declare const blobMouthPaths: Record<CharacterState, string>;
|
|
10
|
+
export declare const tallMouthPaths: Record<CharacterState, string>;
|
|
11
|
+
export declare const smallMouthPaths: Record<CharacterState, string>;
|
|
12
|
+
export declare const eyebrowVariants: Record<CharacterState, {
|
|
13
|
+
rotate: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const springConfigs: {
|
|
17
|
+
readonly small: {
|
|
18
|
+
readonly stiffness: 300;
|
|
19
|
+
readonly damping: 20;
|
|
20
|
+
};
|
|
21
|
+
readonly blob: {
|
|
22
|
+
readonly stiffness: 150;
|
|
23
|
+
readonly damping: 25;
|
|
24
|
+
};
|
|
25
|
+
readonly tall: {
|
|
26
|
+
readonly stiffness: 80;
|
|
27
|
+
readonly damping: 30;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export declare const bodyTransition: {
|
|
31
|
+
type: "spring";
|
|
32
|
+
stiffness: number;
|
|
33
|
+
damping: number;
|
|
34
|
+
};
|
|
35
|
+
export declare const clickTransition: {
|
|
36
|
+
type: "spring";
|
|
37
|
+
stiffness: number;
|
|
38
|
+
damping: number;
|
|
39
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Eyelid variants — controls how much the eye is covered
|
|
2
|
+
// scaleY: 0 = fully open, 1 = fully closed
|
|
3
|
+
const eyelidVariants = {
|
|
4
|
+
idle: { scaleY: 0 },
|
|
5
|
+
email: { scaleY: 0 },
|
|
6
|
+
password: { scaleY: 1 },
|
|
7
|
+
peek: { scaleY: 0.6 },
|
|
8
|
+
surprised: { scaleY: 0 }, // wide open
|
|
9
|
+
love: { scaleY: 0.65 }, // happy squint ^_^
|
|
10
|
+
excited: { scaleY: 0 }, // wide open
|
|
11
|
+
};
|
|
12
|
+
// Body sway variants per character
|
|
13
|
+
const blobBodyVariants = {
|
|
14
|
+
idle: { rotate: 0, y: 0 },
|
|
15
|
+
email: { rotate: 2, y: -2 },
|
|
16
|
+
password: { rotate: -1, y: 2, scale: 0.97 },
|
|
17
|
+
peek: { rotate: 3, y: -1 },
|
|
18
|
+
surprised: { rotate: 0, y: -8, scale: 1.05 }, // jump up, puff out
|
|
19
|
+
love: { rotate: 0, y: 0 },
|
|
20
|
+
excited: { rotate: 0, y: 0 },
|
|
21
|
+
};
|
|
22
|
+
const tallBodyVariants = {
|
|
23
|
+
idle: { rotate: 0, y: 0 },
|
|
24
|
+
email: { rotate: -1.5, y: 0 },
|
|
25
|
+
password: { rotate: 0, y: 3, scale: 0.96 },
|
|
26
|
+
peek: { rotate: 2, y: -2 },
|
|
27
|
+
surprised: { rotate: 0, y: 0 },
|
|
28
|
+
love: { rotate: -2, y: -3, scale: 1.03 }, // slight lean, puff up
|
|
29
|
+
excited: { rotate: 0, y: 0 },
|
|
30
|
+
};
|
|
31
|
+
const smallBodyVariants = {
|
|
32
|
+
idle: { rotate: 0, y: 0 },
|
|
33
|
+
email: { rotate: 3, y: -3 },
|
|
34
|
+
password: { rotate: -2, y: 1, scale: 0.95 },
|
|
35
|
+
peek: { rotate: -3, y: -2 },
|
|
36
|
+
surprised: { rotate: 0, y: 0 },
|
|
37
|
+
love: { rotate: 0, y: 0 },
|
|
38
|
+
excited: { rotate: 5, y: -10, scale: 1.08 }, // big bounce, spin
|
|
39
|
+
};
|
|
40
|
+
// Mouth paths for each character per state
|
|
41
|
+
// All paths use M + Q for smooth interpolation between states
|
|
42
|
+
const blobMouthPaths = {
|
|
43
|
+
idle: 'M -10 0 Q 0 8 10 0', // wide gentle smile
|
|
44
|
+
email: 'M -12 -2 Q 0 12 12 -2', // big happy smile
|
|
45
|
+
password: 'M -6 0 Q 0 2 6 0', // flat/neutral
|
|
46
|
+
peek: 'M -8 0 Q 0 5 8 0', // small smirk
|
|
47
|
+
surprised: 'M -5 -4 Q 0 10 5 -4', // round "O" mouth
|
|
48
|
+
love: 'M -10 0 Q 0 8 10 0', // gentle smile
|
|
49
|
+
excited: 'M -12 -2 Q 0 12 12 -2', // big grin
|
|
50
|
+
};
|
|
51
|
+
const tallMouthPaths = {
|
|
52
|
+
idle: 'M -6 0 Q 0 3 6 0', // subtle relaxed smile
|
|
53
|
+
email: 'M -10 -1 Q 0 10 10 -1', // big happy smile
|
|
54
|
+
password: 'M -5 0 Q 0 0 5 0', // flat line (Q-based for animation)
|
|
55
|
+
peek: 'M -5 0 Q 2 6 7 -1', // asymmetric smirk
|
|
56
|
+
surprised: 'M -5 -3 Q 0 8 5 -3', // small O
|
|
57
|
+
love: 'M -10 -2 Q 0 12 10 -2', // wide beaming smile
|
|
58
|
+
excited: 'M -8 -1 Q 0 10 8 -1', // happy grin
|
|
59
|
+
};
|
|
60
|
+
const smallMouthPaths = {
|
|
61
|
+
idle: 'M -7 0 Q 0 6 7 0', // sweet smile
|
|
62
|
+
email: 'M -9 -1 Q 0 9 9 -1', // big grin
|
|
63
|
+
password: 'M -4 0 Q 0 1 4 0', // tiny neutral
|
|
64
|
+
peek: 'M -4 1 Q 1 6 6 0', // cheeky smirk
|
|
65
|
+
surprised: 'M -4 -3 Q 0 8 4 -3', // little O
|
|
66
|
+
love: 'M -7 0 Q 0 6 7 0', // sweet smile
|
|
67
|
+
excited: 'M -10 -3 Q 0 14 10 -3', // huge open grin
|
|
68
|
+
};
|
|
69
|
+
// Eyebrow angles for Tall character
|
|
70
|
+
const eyebrowVariants = {
|
|
71
|
+
idle: { rotate: 0, y: 0 },
|
|
72
|
+
email: { rotate: -5, y: -2 },
|
|
73
|
+
password: { rotate: 8, y: 2 },
|
|
74
|
+
peek: { rotate: -10, y: -1 },
|
|
75
|
+
surprised: { rotate: -12, y: -4 }, // raised high
|
|
76
|
+
love: { rotate: -6, y: -2 }, // gently raised
|
|
77
|
+
excited: { rotate: -8, y: -3 }, // raised
|
|
78
|
+
};
|
|
79
|
+
// Spring configs per character for mouse tracking
|
|
80
|
+
const springConfigs = {
|
|
81
|
+
small: { stiffness: 300, damping: 20 },
|
|
82
|
+
blob: { stiffness: 150, damping: 25 },
|
|
83
|
+
tall: { stiffness: 80, damping: 30 },
|
|
84
|
+
};
|
|
85
|
+
// Body spring for state transitions
|
|
86
|
+
const bodyTransition = {
|
|
87
|
+
type: 'spring',
|
|
88
|
+
stiffness: 200,
|
|
89
|
+
damping: 20,
|
|
90
|
+
};
|
|
91
|
+
// Bouncier transition for click reactions
|
|
92
|
+
const clickTransition = {
|
|
93
|
+
type: 'spring',
|
|
94
|
+
stiffness: 300,
|
|
95
|
+
damping: 15,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export { blobBodyVariants, blobMouthPaths, bodyTransition, clickTransition, eyebrowVariants, eyelidVariants, smallBodyVariants, smallMouthPaths, springConfigs, tallBodyVariants, tallMouthPaths };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useState, useCallback, useEffect } from 'react';
|
|
3
|
+
import { useReducedMotion } from 'motion/react';
|
|
4
|
+
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
import { springConfigs } from './InteractiveCharacters.animations.js';
|
|
6
|
+
import { useMouseTracking } from './hooks/useMouseTracking.js';
|
|
7
|
+
import { useIdleAnimation } from './hooks/useIdleAnimation.js';
|
|
8
|
+
import { useBlink } from './hooks/useBlink.js';
|
|
9
|
+
import { BlobCharacter } from './characters/BlobCharacter.js';
|
|
10
|
+
import { TallCharacter } from './characters/TallCharacter.js';
|
|
11
|
+
import { SmallCharacter } from './characters/SmallCharacter.js';
|
|
12
|
+
|
|
13
|
+
const sizeMap = {
|
|
14
|
+
sm: 'w-[200px]',
|
|
15
|
+
md: 'w-[320px]',
|
|
16
|
+
lg: 'w-[400px]',
|
|
17
|
+
};
|
|
18
|
+
/** Click reaction states per character */
|
|
19
|
+
const CLICK_REACTIONS = {
|
|
20
|
+
blob: 'surprised',
|
|
21
|
+
tall: 'love',
|
|
22
|
+
small: 'excited',
|
|
23
|
+
};
|
|
24
|
+
/** How long click reactions last (ms) */
|
|
25
|
+
const CLICK_DURATION = 1500;
|
|
26
|
+
const InteractiveCharacters = ({ state = 'idle', trackMouse = true, size = 'md', className, }) => {
|
|
27
|
+
const svgRef = useRef(null);
|
|
28
|
+
const shouldReduceMotion = useReducedMotion();
|
|
29
|
+
const clickTimeoutRef = useRef(null);
|
|
30
|
+
const [clickedChar, setClickedChar] = useState(null);
|
|
31
|
+
const handleCharacterClick = useCallback((character) => {
|
|
32
|
+
if (clickTimeoutRef.current)
|
|
33
|
+
clearTimeout(clickTimeoutRef.current);
|
|
34
|
+
setClickedChar(character);
|
|
35
|
+
clickTimeoutRef.current = setTimeout(() => setClickedChar(null), CLICK_DURATION);
|
|
36
|
+
}, []);
|
|
37
|
+
// Cleanup timeout on unmount
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
return () => {
|
|
40
|
+
if (clickTimeoutRef.current)
|
|
41
|
+
clearTimeout(clickTimeoutRef.current);
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
// Determine effective state per character (click overrides form state)
|
|
45
|
+
const blobState = clickedChar === 'blob' ? CLICK_REACTIONS.blob : state;
|
|
46
|
+
const tallState = clickedChar === 'tall' ? CLICK_REACTIONS.tall : state;
|
|
47
|
+
const smallState = clickedChar === 'small' ? CLICK_REACTIONS.small : state;
|
|
48
|
+
const isTrackingEnabled = trackMouse && state !== 'password' && !shouldReduceMotion;
|
|
49
|
+
const isIdleAnimated = !shouldReduceMotion;
|
|
50
|
+
// Mouse tracking — different spring configs per character
|
|
51
|
+
const blobEye = useMouseTracking({
|
|
52
|
+
containerRef: svgRef,
|
|
53
|
+
enabled: isTrackingEnabled,
|
|
54
|
+
...springConfigs.blob,
|
|
55
|
+
});
|
|
56
|
+
const tallEye = useMouseTracking({
|
|
57
|
+
containerRef: svgRef,
|
|
58
|
+
enabled: isTrackingEnabled,
|
|
59
|
+
...springConfigs.tall,
|
|
60
|
+
});
|
|
61
|
+
const smallEye = useMouseTracking({
|
|
62
|
+
containerRef: svgRef,
|
|
63
|
+
enabled: isTrackingEnabled,
|
|
64
|
+
...springConfigs.small,
|
|
65
|
+
});
|
|
66
|
+
// Idle sway/breathing/head — each character at different rates & phase offsets
|
|
67
|
+
const blobIdle = useIdleAnimation({
|
|
68
|
+
enabled: isIdleAnimated,
|
|
69
|
+
swayAmount: 1.5,
|
|
70
|
+
swaySpeed: 0.8,
|
|
71
|
+
breathAmount: 0.008,
|
|
72
|
+
headTiltAmount: 3,
|
|
73
|
+
headNudgeAmount: 1.5,
|
|
74
|
+
phaseOffset: 0,
|
|
75
|
+
});
|
|
76
|
+
const tallIdle = useIdleAnimation({
|
|
77
|
+
enabled: isIdleAnimated,
|
|
78
|
+
swayAmount: 1,
|
|
79
|
+
swaySpeed: 0.6,
|
|
80
|
+
breathAmount: 0.006,
|
|
81
|
+
headTiltAmount: 2,
|
|
82
|
+
headNudgeAmount: 1,
|
|
83
|
+
phaseOffset: 2.5,
|
|
84
|
+
});
|
|
85
|
+
const smallIdle = useIdleAnimation({
|
|
86
|
+
enabled: isIdleAnimated,
|
|
87
|
+
swayAmount: 2.5,
|
|
88
|
+
swaySpeed: 1.2,
|
|
89
|
+
breathAmount: 0.012,
|
|
90
|
+
headTiltAmount: 4,
|
|
91
|
+
headNudgeAmount: 2,
|
|
92
|
+
phaseOffset: 5,
|
|
93
|
+
});
|
|
94
|
+
// Blink — disable during password/peek and click reactions
|
|
95
|
+
const canBlinkBlob = blobState === 'idle' || blobState === 'email';
|
|
96
|
+
const canBlinkTall = tallState === 'idle' || tallState === 'email';
|
|
97
|
+
const canBlinkSmall = smallState === 'idle' || smallState === 'email';
|
|
98
|
+
const blobBlink = useBlink({ enabled: canBlinkBlob, minInterval: 2500, maxInterval: 5000 });
|
|
99
|
+
const tallBlink = useBlink({ enabled: canBlinkTall, minInterval: 3000, maxInterval: 6000 });
|
|
100
|
+
const smallBlink = useBlink({ enabled: canBlinkSmall, minInterval: 1800, maxInterval: 4000 });
|
|
101
|
+
return (jsx("div", { className: cn(sizeMap[size], className), "data-state": state, children: jsxs("svg", { ref: svgRef, viewBox: "0 0 400 180", xmlns: "http://www.w3.org/2000/svg", className: "w-full h-auto", role: "img", "aria-label": "Interactive characters that react to form input", children: [jsx("g", { transform: "translate(200, 170)", className: "cursor-pointer", children: jsx(TallCharacter, { state: tallState, eyeOffset: { x: tallEye.x, y: tallEye.y }, idle: tallIdle, blinkAmount: tallBlink, onClick: () => handleCharacterClick('tall') }) }), jsx("g", { transform: "translate(100, 170)", className: "cursor-pointer", children: jsx(BlobCharacter, { state: blobState, eyeOffset: { x: blobEye.x, y: blobEye.y }, idle: blobIdle, blinkAmount: blobBlink, onClick: () => handleCharacterClick('blob') }) }), jsx("g", { transform: "translate(310, 170)", className: "cursor-pointer", children: jsx(SmallCharacter, { state: smallState, eyeOffset: { x: smallEye.x, y: smallEye.y }, idle: smallIdle, blinkAmount: smallBlink, onClick: () => handleCharacterClick('small') }) })] }) }));
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export { InteractiveCharacters };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MotionValue } from 'motion/react';
|
|
2
|
+
export type CharacterState = 'idle' | 'email' | 'password' | 'peek' | 'surprised' | 'love' | 'excited';
|
|
3
|
+
export type CharacterSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
export interface InteractiveCharactersProps {
|
|
5
|
+
/** Current character state — controls expressions and animations */
|
|
6
|
+
state?: CharacterState;
|
|
7
|
+
/** Enable mouse/cursor tracking for eye movement (default: true) */
|
|
8
|
+
trackMouse?: boolean;
|
|
9
|
+
/** Size preset (default: 'md') */
|
|
10
|
+
size?: CharacterSize;
|
|
11
|
+
/** Additional class names for the container */
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface CharacterProps {
|
|
15
|
+
state: CharacterState;
|
|
16
|
+
eyeOffset: {
|
|
17
|
+
x: MotionValue<number>;
|
|
18
|
+
y: MotionValue<number>;
|
|
19
|
+
};
|
|
20
|
+
idle: {
|
|
21
|
+
sway: MotionValue<number>;
|
|
22
|
+
bob: MotionValue<number>;
|
|
23
|
+
breath: MotionValue<number>;
|
|
24
|
+
headTilt: MotionValue<number>;
|
|
25
|
+
headX: MotionValue<number>;
|
|
26
|
+
headY: MotionValue<number>;
|
|
27
|
+
};
|
|
28
|
+
blinkAmount: MotionValue<number>;
|
|
29
|
+
onClick?: () => void;
|
|
30
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useTransform, motion } from 'motion/react';
|
|
3
|
+
import { eyelidVariants, clickTransition, bodyTransition, blobBodyVariants, blobMouthPaths } from '../InteractiveCharacters.animations.js';
|
|
4
|
+
|
|
5
|
+
const LEFT_EYE = { cx: 32, cy: -50 };
|
|
6
|
+
const RIGHT_EYE = { cx: 68, cy: -50 };
|
|
7
|
+
const CLICK_STATES = new Set(['surprised', 'love', 'excited']);
|
|
8
|
+
const BlobCharacter = ({ state, eyeOffset, idle, blinkAmount, onClick, }) => {
|
|
9
|
+
const leftPupilX = useTransform(eyeOffset.x, (v) => LEFT_EYE.cx + v);
|
|
10
|
+
const leftPupilY = useTransform(eyeOffset.y, (v) => LEFT_EYE.cy + v);
|
|
11
|
+
const rightPupilX = useTransform(eyeOffset.x, (v) => RIGHT_EYE.cx + v);
|
|
12
|
+
const rightPupilY = useTransform(eyeOffset.y, (v) => RIGHT_EYE.cy + v);
|
|
13
|
+
// Combine idle head movement with cursor tracking for head turning
|
|
14
|
+
const combinedHeadX = useTransform([idle.headX, eyeOffset.x], ([idleX, cursorX]) => idleX + cursorX * 0.5);
|
|
15
|
+
const combinedHeadY = useTransform([idle.headY, eyeOffset.y], ([idleY, cursorY]) => idleY + cursorY * 0.3);
|
|
16
|
+
const combinedHeadRotate = useTransform([idle.headTilt, eyeOffset.x], ([tilt, cursorX]) => tilt + cursorX * 0.5);
|
|
17
|
+
const stateEyelid = eyelidVariants[state].scaleY;
|
|
18
|
+
const eyelidScale = useTransform(blinkAmount, (blink) => Math.max(stateEyelid, blink));
|
|
19
|
+
const isClickReaction = CLICK_STATES.has(state);
|
|
20
|
+
const transition = isClickReaction ? clickTransition : bodyTransition;
|
|
21
|
+
return (jsxs(motion.g, { animate: state, variants: blobBodyVariants, transition: transition, style: {
|
|
22
|
+
originX: '50%',
|
|
23
|
+
originY: '100%',
|
|
24
|
+
x: idle.sway,
|
|
25
|
+
y: idle.bob,
|
|
26
|
+
scale: idle.breath,
|
|
27
|
+
}, onClick: onClick, children: [jsx("path", { d: "M 0 0 Q 0 -95 65 -95 Q 100 -95 100 -50 Q 100 0 100 0 Z", fill: "#F97316" }), jsxs(motion.g, { style: {
|
|
28
|
+
originX: '50px',
|
|
29
|
+
originY: '-50px',
|
|
30
|
+
rotate: combinedHeadRotate,
|
|
31
|
+
x: combinedHeadX,
|
|
32
|
+
y: combinedHeadY,
|
|
33
|
+
}, children: [jsxs("g", { children: [jsx("clipPath", { id: "blob-eye-l", children: jsx("ellipse", { cx: LEFT_EYE.cx, cy: LEFT_EYE.cy, rx: 14, ry: 16 }) }), jsx("ellipse", { cx: LEFT_EYE.cx, cy: LEFT_EYE.cy, rx: 14, ry: 16, fill: "white" }), jsx(motion.circle, { cx: leftPupilX, cy: leftPupilY, r: 8.5, fill: "#1E293B", clipPath: "url(#blob-eye-l)" }), jsx("circle", { cx: LEFT_EYE.cx + 4, cy: LEFT_EYE.cy - 5.5, r: 3, fill: "white", opacity: 0.95 }), jsx("circle", { cx: LEFT_EYE.cx - 3, cy: LEFT_EYE.cy + 4, r: 1.5, fill: "white", opacity: 0.7 }), jsx(motion.rect, { x: LEFT_EYE.cx - 14, y: LEFT_EYE.cy - 16, width: 28, height: 32, fill: "#F97316", rx: 2, style: { scaleY: eyelidScale, originX: '50%', originY: '0%', transformBox: 'fill-box' } })] }), jsxs("g", { children: [jsx("clipPath", { id: "blob-eye-r", children: jsx("ellipse", { cx: RIGHT_EYE.cx, cy: RIGHT_EYE.cy, rx: 14, ry: 16 }) }), jsx("ellipse", { cx: RIGHT_EYE.cx, cy: RIGHT_EYE.cy, rx: 14, ry: 16, fill: "white" }), jsx(motion.circle, { cx: rightPupilX, cy: rightPupilY, r: 8.5, fill: "#1E293B", clipPath: "url(#blob-eye-r)" }), jsx("circle", { cx: RIGHT_EYE.cx + 4, cy: RIGHT_EYE.cy - 5.5, r: 3, fill: "white", opacity: 0.95 }), jsx("circle", { cx: RIGHT_EYE.cx - 3, cy: RIGHT_EYE.cy + 4, r: 1.5, fill: "white", opacity: 0.7 }), jsx(motion.rect, { x: RIGHT_EYE.cx - 14, y: RIGHT_EYE.cy - 16, width: 28, height: 32, fill: "#F97316", rx: 2, style: { scaleY: eyelidScale, originX: '50%', originY: '0%', transformBox: 'fill-box' } })] }), jsx("ellipse", { cx: 18, cy: -28, rx: 8, ry: 5.5, fill: "#FB923C", opacity: state === 'surprised' ? 0.7 : 0.5 }), jsx("ellipse", { cx: 82, cy: -28, rx: 8, ry: 5.5, fill: "#FB923C", opacity: state === 'surprised' ? 0.7 : 0.5 }), jsx(motion.path, { d: blobMouthPaths[state], fill: "none", stroke: "#1E293B", strokeWidth: 2.5, strokeLinecap: "round", animate: { d: blobMouthPaths[state] }, transition: transition, transform: "translate(50, -24)" })] })] }));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { BlobCharacter };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useTransform, motion } from 'motion/react';
|
|
3
|
+
import { eyelidVariants, clickTransition, bodyTransition, smallBodyVariants, smallMouthPaths } from '../InteractiveCharacters.animations.js';
|
|
4
|
+
|
|
5
|
+
const LEFT_EYE = { cx: -14, cy: -32 };
|
|
6
|
+
const RIGHT_EYE = { cx: 14, cy: -32 };
|
|
7
|
+
const CLICK_STATES = new Set(['surprised', 'love', 'excited']);
|
|
8
|
+
const SmallCharacter = ({ state, eyeOffset, idle, blinkAmount, onClick, }) => {
|
|
9
|
+
const leftPupilX = useTransform(eyeOffset.x, (v) => LEFT_EYE.cx + v);
|
|
10
|
+
const leftPupilY = useTransform(eyeOffset.y, (v) => LEFT_EYE.cy + v);
|
|
11
|
+
const rightPupilX = useTransform(eyeOffset.x, (v) => RIGHT_EYE.cx + v);
|
|
12
|
+
const rightPupilY = useTransform(eyeOffset.y, (v) => RIGHT_EYE.cy + v);
|
|
13
|
+
// Combine idle head movement with cursor tracking for head turning
|
|
14
|
+
const combinedHeadX = useTransform([idle.headX, eyeOffset.x], ([idleX, cursorX]) => idleX + cursorX * 0.6);
|
|
15
|
+
const combinedHeadY = useTransform([idle.headY, eyeOffset.y], ([idleY, cursorY]) => idleY + cursorY * 0.35);
|
|
16
|
+
const combinedHeadRotate = useTransform([idle.headTilt, eyeOffset.x], ([tilt, cursorX]) => tilt + cursorX * 0.6);
|
|
17
|
+
const stateEyelid = eyelidVariants[state].scaleY;
|
|
18
|
+
const eyelidScale = useTransform(blinkAmount, (blink) => Math.max(stateEyelid, blink));
|
|
19
|
+
const isClickReaction = CLICK_STATES.has(state);
|
|
20
|
+
const transition = isClickReaction ? clickTransition : bodyTransition;
|
|
21
|
+
return (jsxs(motion.g, { animate: state, variants: smallBodyVariants, transition: transition, style: {
|
|
22
|
+
originX: '50%',
|
|
23
|
+
originY: '100%',
|
|
24
|
+
x: idle.sway,
|
|
25
|
+
y: idle.bob,
|
|
26
|
+
scale: idle.breath,
|
|
27
|
+
}, onClick: onClick, children: [jsx("path", { d: "M -45 0 Q -45 -60 0 -60 Q 45 -60 45 0 Z", fill: "#FACC15" }), jsxs(motion.g, { style: {
|
|
28
|
+
originX: '0px',
|
|
29
|
+
originY: '-30px',
|
|
30
|
+
rotate: combinedHeadRotate,
|
|
31
|
+
x: combinedHeadX,
|
|
32
|
+
y: combinedHeadY,
|
|
33
|
+
}, children: [jsxs("g", { children: [jsx("clipPath", { id: "small-eye-l", children: jsx("circle", { cx: LEFT_EYE.cx, cy: LEFT_EYE.cy, r: 10 }) }), jsx("circle", { cx: LEFT_EYE.cx, cy: LEFT_EYE.cy, r: 10, fill: "white" }), jsx(motion.circle, { cx: leftPupilX, cy: leftPupilY, r: 6, fill: "#1E293B", clipPath: "url(#small-eye-l)" }), jsx("circle", { cx: LEFT_EYE.cx + 3, cy: LEFT_EYE.cy - 4, r: 2.2, fill: "white", opacity: 0.95 }), jsx("circle", { cx: LEFT_EYE.cx - 2, cy: LEFT_EYE.cy + 3, r: 1.1, fill: "white", opacity: 0.7 }), jsx(motion.rect, { x: LEFT_EYE.cx - 10, y: LEFT_EYE.cy - 10, width: 20, height: 20, fill: "#FACC15", rx: 2, style: { scaleY: eyelidScale, originX: '50%', originY: '0%', transformBox: 'fill-box' } })] }), jsxs("g", { children: [jsx("clipPath", { id: "small-eye-r", children: jsx("circle", { cx: RIGHT_EYE.cx, cy: RIGHT_EYE.cy, r: 10 }) }), jsx("circle", { cx: RIGHT_EYE.cx, cy: RIGHT_EYE.cy, r: 10, fill: "white" }), jsx(motion.circle, { cx: rightPupilX, cy: rightPupilY, r: 6, fill: "#1E293B", clipPath: "url(#small-eye-r)" }), jsx("circle", { cx: RIGHT_EYE.cx + 3, cy: RIGHT_EYE.cy - 4, r: 2.2, fill: "white", opacity: 0.95 }), jsx("circle", { cx: RIGHT_EYE.cx - 2, cy: RIGHT_EYE.cy + 3, r: 1.1, fill: "white", opacity: 0.7 }), jsx(motion.rect, { x: RIGHT_EYE.cx - 10, y: RIGHT_EYE.cy - 10, width: 20, height: 20, fill: "#FACC15", rx: 2, style: { scaleY: eyelidScale, originX: '50%', originY: '0%', transformBox: 'fill-box' } })] }), jsx("ellipse", { cx: -22, cy: -18, rx: 6, ry: 4, fill: "#FDE68A", opacity: state === 'excited' ? 0.85 : 0.6 }), jsx("ellipse", { cx: 22, cy: -18, rx: 6, ry: 4, fill: "#FDE68A", opacity: state === 'excited' ? 0.85 : 0.6 }), jsx(motion.path, { d: smallMouthPaths[state], fill: "none", stroke: "#1E293B", strokeWidth: 2, strokeLinecap: "round", animate: { d: smallMouthPaths[state] }, transition: transition, transform: "translate(0, -14)" })] })] }));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { SmallCharacter };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useTransform, motion } from 'motion/react';
|
|
3
|
+
import { eyelidVariants, clickTransition, bodyTransition, tallBodyVariants, eyebrowVariants, tallMouthPaths } from '../InteractiveCharacters.animations.js';
|
|
4
|
+
|
|
5
|
+
const LEFT_EYE = { cx: -12, cy: -82 };
|
|
6
|
+
const RIGHT_EYE = { cx: 12, cy: -82 };
|
|
7
|
+
const CLICK_STATES = new Set(['surprised', 'love', 'excited']);
|
|
8
|
+
const TallCharacter = ({ state, eyeOffset, idle, blinkAmount, onClick, }) => {
|
|
9
|
+
const leftPupilX = useTransform(eyeOffset.x, (v) => LEFT_EYE.cx + v);
|
|
10
|
+
const leftPupilY = useTransform(eyeOffset.y, (v) => LEFT_EYE.cy + v);
|
|
11
|
+
const rightPupilX = useTransform(eyeOffset.x, (v) => RIGHT_EYE.cx + v);
|
|
12
|
+
const rightPupilY = useTransform(eyeOffset.y, (v) => RIGHT_EYE.cy + v);
|
|
13
|
+
// Combine idle head movement with cursor tracking for head turning
|
|
14
|
+
const combinedHeadX = useTransform([idle.headX, eyeOffset.x], ([idleX, cursorX]) => idleX + cursorX * 0.4);
|
|
15
|
+
const combinedHeadY = useTransform([idle.headY, eyeOffset.y], ([idleY, cursorY]) => idleY + cursorY * 0.25);
|
|
16
|
+
const combinedHeadRotate = useTransform([idle.headTilt, eyeOffset.x], ([tilt, cursorX]) => tilt + cursorX * 0.4);
|
|
17
|
+
const stateEyelid = eyelidVariants[state].scaleY;
|
|
18
|
+
const eyelidScale = useTransform(blinkAmount, (blink) => Math.max(stateEyelid, blink));
|
|
19
|
+
const eyebrow = eyebrowVariants[state];
|
|
20
|
+
const isClickReaction = CLICK_STATES.has(state);
|
|
21
|
+
const transition = isClickReaction ? clickTransition : bodyTransition;
|
|
22
|
+
return (jsxs(motion.g, { animate: state, variants: tallBodyVariants, transition: transition, style: {
|
|
23
|
+
originX: '50%',
|
|
24
|
+
originY: '100%',
|
|
25
|
+
x: idle.sway,
|
|
26
|
+
y: idle.bob,
|
|
27
|
+
scale: idle.breath,
|
|
28
|
+
}, onClick: onClick, children: [jsx("rect", { x: -30, y: -140, width: 60, height: 140, rx: 22, fill: "#8B5CF6" }), jsxs(motion.g, { style: {
|
|
29
|
+
originX: '0px',
|
|
30
|
+
originY: '-70px',
|
|
31
|
+
rotate: combinedHeadRotate,
|
|
32
|
+
x: combinedHeadX,
|
|
33
|
+
y: combinedHeadY,
|
|
34
|
+
}, children: [jsx(motion.line, { x1: -22, y1: -103, x2: -4, y2: -103, stroke: "#1E293B", strokeWidth: 2.5, strokeLinecap: "round", animate: { rotate: eyebrow.rotate, y: eyebrow.y }, transition: transition, style: { originX: '50%', originY: '50%', transformBox: 'fill-box' } }), jsx(motion.line, { x1: 4, y1: -103, x2: 22, y2: -103, stroke: "#1E293B", strokeWidth: 2.5, strokeLinecap: "round", animate: { rotate: -eyebrow.rotate, y: eyebrow.y }, transition: transition, style: { originX: '50%', originY: '50%', transformBox: 'fill-box' } }), jsxs("g", { children: [jsx("clipPath", { id: "tall-eye-l", children: jsx("ellipse", { cx: LEFT_EYE.cx, cy: LEFT_EYE.cy, rx: 11, ry: 14 }) }), jsx("ellipse", { cx: LEFT_EYE.cx, cy: LEFT_EYE.cy, rx: 11, ry: 14, fill: "white" }), jsx(motion.circle, { cx: leftPupilX, cy: leftPupilY, r: 6.5, fill: "#1E293B", clipPath: "url(#tall-eye-l)" }), jsx("circle", { cx: LEFT_EYE.cx + 3.5, cy: LEFT_EYE.cy - 5, r: 2.5, fill: "white", opacity: 0.95 }), jsx("circle", { cx: LEFT_EYE.cx - 2.5, cy: LEFT_EYE.cy + 3, r: 1.2, fill: "white", opacity: 0.7 }), jsx(motion.rect, { x: LEFT_EYE.cx - 11, y: LEFT_EYE.cy - 14, width: 22, height: 28, fill: "#8B5CF6", rx: 2, style: { scaleY: eyelidScale, originX: '50%', originY: '0%', transformBox: 'fill-box' } })] }), jsxs("g", { children: [jsx("clipPath", { id: "tall-eye-r", children: jsx("ellipse", { cx: RIGHT_EYE.cx, cy: RIGHT_EYE.cy, rx: 11, ry: 14 }) }), jsx("ellipse", { cx: RIGHT_EYE.cx, cy: RIGHT_EYE.cy, rx: 11, ry: 14, fill: "white" }), jsx(motion.circle, { cx: rightPupilX, cy: rightPupilY, r: 6.5, fill: "#1E293B", clipPath: "url(#tall-eye-r)" }), jsx("circle", { cx: RIGHT_EYE.cx + 3.5, cy: RIGHT_EYE.cy - 5, r: 2.5, fill: "white", opacity: 0.95 }), jsx("circle", { cx: RIGHT_EYE.cx - 2.5, cy: RIGHT_EYE.cy + 3, r: 1.2, fill: "white", opacity: 0.7 }), jsx(motion.rect, { x: RIGHT_EYE.cx - 11, y: RIGHT_EYE.cy - 14, width: 22, height: 28, fill: "#8B5CF6", rx: 2, style: { scaleY: eyelidScale, originX: '50%', originY: '0%', transformBox: 'fill-box' } })] }), jsx("ellipse", { cx: -22, cy: -62, rx: 7, ry: 5, fill: "#F9A8D4", opacity: state === 'love' ? 0.65 : 0.45 }), jsx("ellipse", { cx: 22, cy: -62, rx: 7, ry: 5, fill: "#F9A8D4", opacity: state === 'love' ? 0.65 : 0.45 }), jsx(motion.path, { d: tallMouthPaths[state], fill: "none", stroke: "#1E293B", strokeWidth: 2, strokeLinecap: "round", animate: { d: tallMouthPaths[state] }, transition: transition, transform: "translate(0, -55)" })] })] }));
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { TallCharacter };
|