@mks2508/mks-ui 0.5.4 → 0.5.8
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/react-ui/primitives/waapi/Gooey/Gooey.types.d.ts +23 -4
- package/dist/react-ui/primitives/waapi/Gooey/Gooey.types.d.ts.map +1 -1
- package/dist/react-ui/primitives/waapi/Gooey/GooeyCanvas.d.ts +2 -2
- package/dist/react-ui/primitives/waapi/Gooey/GooeyCanvas.d.ts.map +1 -1
- package/dist/react-ui/primitives/waapi/Gooey/GooeyCanvas.js +292 -31
- package/dist/react-ui/primitives/waapi/Gooey/gooey-utils.d.ts +7 -0
- package/dist/react-ui/primitives/waapi/Gooey/gooey-utils.d.ts.map +1 -1
- package/dist/react-ui/primitives/waapi/Gooey/gooey-utils.js +6 -1
- package/dist/react-ui/ui/DynamicToggle/{DynamicToggle-Cm6-VceQ.css → DynamicToggle-DJLwEkHr.css} +116 -51
- package/dist/react-ui/ui/DynamicToggle/DynamicToggle.css +116 -51
- package/dist/react-ui/ui/DynamicToggle/DynamicToggle.styles.d.ts +1 -0
- package/dist/react-ui/ui/DynamicToggle/DynamicToggle.styles.d.ts.map +1 -1
- package/dist/react-ui/ui/DynamicToggle/DynamicToggle.styles.js +9 -3
- package/dist/react-ui/ui/DynamicToggle/DynamicToggle.types.d.ts +61 -31
- package/dist/react-ui/ui/DynamicToggle/DynamicToggle.types.d.ts.map +1 -1
- package/dist/react-ui/ui/DynamicToggle/index.d.ts +9 -3
- package/dist/react-ui/ui/DynamicToggle/index.d.ts.map +1 -1
- package/dist/react-ui/ui/DynamicToggle/index.js +68 -37
- package/package.json +52 -13
- package/src/assets/react.svg +0 -1
- package/src/core/index.ts +0 -7
- package/src/core/types.ts +0 -82
- package/src/css.d.ts +0 -7
- package/src/index.css +0 -129
- package/src/index.ts +0 -29
- package/src/react-ui/blocks/Terminal/ResttyAdapter.ts +0 -278
- package/src/react-ui/blocks/Terminal/Terminal.adapter.ts +0 -97
- package/src/react-ui/blocks/Terminal/Terminal.theme.restty.ts +0 -155
- package/src/react-ui/blocks/Terminal/Terminal.theme.ts +0 -80
- package/src/react-ui/blocks/Terminal/Terminal.types.ts +0 -438
- package/src/react-ui/blocks/Terminal/TerminalDisplay.styles.ts +0 -38
- package/src/react-ui/blocks/Terminal/TerminalDisplay.tsx +0 -254
- package/src/react-ui/blocks/Terminal/TerminalDisplay.types.ts +0 -73
- package/src/react-ui/blocks/Terminal/TerminalPanel.tsx +0 -269
- package/src/react-ui/blocks/Terminal/TerminalRestty.tsx +0 -326
- package/src/react-ui/blocks/Terminal/TerminalXterm.tsx +0 -230
- package/src/react-ui/blocks/Terminal/XTermAdapter.ts +0 -163
- package/src/react-ui/blocks/Terminal/chrome.ts +0 -25
- package/src/react-ui/blocks/Terminal/components/LogLineBadges.tsx +0 -316
- package/src/react-ui/blocks/Terminal/components/SpecializedSyntaxHighlighter.tsx +0 -218
- package/src/react-ui/blocks/Terminal/components/SyntaxHighlight.tsx +0 -386
- package/src/react-ui/blocks/Terminal/components/TerminalLogBadge.tsx +0 -67
- package/src/react-ui/blocks/Terminal/components/index.ts +0 -10
- package/src/react-ui/blocks/Terminal/display.ts +0 -46
- package/src/react-ui/blocks/Terminal/hooks/index.ts +0 -22
- package/src/react-ui/blocks/Terminal/hooks/useTerminalSettings.ts +0 -229
- package/src/react-ui/blocks/Terminal/hooks/useTerminalWebSocket.ts +0 -292
- package/src/react-ui/blocks/Terminal/index.ts +0 -111
- package/src/react-ui/blocks/Terminal/panel/LogLinesViewer.tsx +0 -330
- package/src/react-ui/blocks/Terminal/panel/TerminalDebugPanel.tsx +0 -242
- package/src/react-ui/blocks/Terminal/panel/TerminalFilterDropdown.tsx +0 -202
- package/src/react-ui/blocks/Terminal/panel/TerminalFilterTabs.tsx +0 -140
- package/src/react-ui/blocks/Terminal/panel/TerminalInteractivePanel.tsx +0 -68
- package/src/react-ui/blocks/Terminal/panel/TerminalInteractivePanel.types.ts +0 -85
- package/src/react-ui/blocks/Terminal/panel/TerminalInteractivePanelRestty.tsx +0 -383
- package/src/react-ui/blocks/Terminal/panel/TerminalInteractivePanelXterm.tsx +0 -439
- package/src/react-ui/blocks/Terminal/panel/TerminalLogsPanel.tsx +0 -550
- package/src/react-ui/blocks/Terminal/panel/TerminalLogsPanel.types.ts +0 -259
- package/src/react-ui/blocks/Terminal/panel/TerminalPanelChrome.styles.ts +0 -75
- package/src/react-ui/blocks/Terminal/panel/TerminalPanelChrome.tsx +0 -266
- package/src/react-ui/blocks/Terminal/panel/TerminalPanelChrome.types.ts +0 -82
- package/src/react-ui/blocks/Terminal/panel/TerminalPanelFooter.tsx +0 -112
- package/src/react-ui/blocks/Terminal/panel/TerminalPanelHeader.tsx +0 -178
- package/src/react-ui/blocks/Terminal/panel/TerminalPanelToolbar.tsx +0 -203
- package/src/react-ui/blocks/Terminal/panel/TerminalSessionControl.tsx +0 -252
- package/src/react-ui/blocks/Terminal/panel/TerminalSessionTabs.tsx +0 -334
- package/src/react-ui/blocks/Terminal/panel/TerminalSettingsPopover.tsx +0 -261
- package/src/react-ui/blocks/Terminal/panel/TerminalThemeSelector.tsx +0 -248
- package/src/react-ui/blocks/Terminal/panel/index.ts +0 -72
- package/src/react-ui/blocks/Terminal/panel/terminal-filter-dropdown.module.css +0 -59
- package/src/react-ui/blocks/Terminal/panel/terminal-session-tabs.module.css +0 -59
- package/src/react-ui/blocks/Terminal/parsing/BadgeFormatter.ts +0 -180
- package/src/react-ui/blocks/Terminal/parsing/HttpLogParser.ts +0 -248
- package/src/react-ui/blocks/Terminal/parsing/LogParser.types.ts +0 -283
- package/src/react-ui/blocks/Terminal/parsing/LogParserService.ts +0 -686
- package/src/react-ui/blocks/Terminal/parsing/MultilineAggregator.ts +0 -466
- package/src/react-ui/blocks/Terminal/parsing/PersistentLogBuffer.ts +0 -343
- package/src/react-ui/blocks/Terminal/parsing/SyntaxHighlighter.ts +0 -167
- package/src/react-ui/blocks/Terminal/parsing/TableParser.ts +0 -348
- package/src/react-ui/blocks/Terminal/parsing/ansi/AnsiColorMapper.ts +0 -251
- package/src/react-ui/blocks/Terminal/parsing/ansi/AnsiParser.ts +0 -390
- package/src/react-ui/blocks/Terminal/parsing/ansi/ansi.constants.ts +0 -320
- package/src/react-ui/blocks/Terminal/parsing/ansi/index.ts +0 -20
- package/src/react-ui/blocks/Terminal/parsing/index.ts +0 -69
- package/src/react-ui/blocks/Terminal/parsing/levels/LogLevel.types.ts +0 -68
- package/src/react-ui/blocks/Terminal/parsing/levels/LogLevelDetector.ts +0 -436
- package/src/react-ui/blocks/Terminal/parsing/levels/index.ts +0 -14
- package/src/react-ui/blocks/index.ts +0 -11
- package/src/react-ui/components/MorphingPopover/MorphingPopover.types.ts +0 -49
- package/src/react-ui/components/MorphingPopover/index.tsx +0 -186
- package/src/react-ui/components/MorphingPopover/morphing-popover.module.css +0 -153
- package/src/react-ui/components/index.ts +0 -9
- package/src/react-ui/hooks/Animation/UseAutoHeight.tsx +0 -123
- package/src/react-ui/hooks/DOM/UseIsInView.tsx +0 -44
- package/src/react-ui/hooks/Formatting/UseListFormat.ts +0 -134
- package/src/react-ui/hooks/State/UseControlledState.tsx +0 -57
- package/src/react-ui/hooks/State/UseDataState.tsx +0 -76
- package/src/react-ui/hooks/index.ts +0 -20
- package/src/react-ui/icons/index.ts +0 -12
- package/src/react-ui/icons/lucide-animated/activity.tsx +0 -109
- package/src/react-ui/icons/lucide-animated/arrow-down-to-line.tsx +0 -51
- package/src/react-ui/icons/lucide-animated/arrow-up.tsx +0 -50
- package/src/react-ui/icons/lucide-animated/bell-electric.tsx +0 -124
- package/src/react-ui/icons/lucide-animated/bell.tsx +0 -93
- package/src/react-ui/icons/lucide-animated/bot.tsx +0 -122
- package/src/react-ui/icons/lucide-animated/box.tsx +0 -117
- package/src/react-ui/icons/lucide-animated/check.tsx +0 -21
- package/src/react-ui/icons/lucide-animated/circle-check.tsx +0 -107
- package/src/react-ui/icons/lucide-animated/delete.tsx +0 -133
- package/src/react-ui/icons/lucide-animated/download.tsx +0 -99
- package/src/react-ui/icons/lucide-animated/edit-2.tsx +0 -21
- package/src/react-ui/icons/lucide-animated/globe.tsx +0 -23
- package/src/react-ui/icons/lucide-animated/home.tsx +0 -103
- package/src/react-ui/icons/lucide-animated/index.ts +0 -38
- package/src/react-ui/icons/lucide-animated/layers.tsx +0 -23
- package/src/react-ui/icons/lucide-animated/layout-panel-top.tsx +0 -143
- package/src/react-ui/icons/lucide-animated/list.tsx +0 -54
- package/src/react-ui/icons/lucide-animated/package.tsx +0 -24
- package/src/react-ui/icons/lucide-animated/palette.tsx +0 -25
- package/src/react-ui/icons/lucide-animated/plus.tsx +0 -92
- package/src/react-ui/icons/lucide-animated/refresh-cw.tsx +0 -24
- package/src/react-ui/icons/lucide-animated/rocket.tsx +0 -24
- package/src/react-ui/icons/lucide-animated/save.tsx +0 -23
- package/src/react-ui/icons/lucide-animated/search.tsx +0 -94
- package/src/react-ui/icons/lucide-animated/settings.tsx +0 -92
- package/src/react-ui/icons/lucide-animated/terminal.tsx +0 -46
- package/src/react-ui/icons/lucide-animated/trash-2.tsx +0 -25
- package/src/react-ui/icons/lucide-animated/trending-down.tsx +0 -151
- package/src/react-ui/icons/lucide-animated/trending-up.tsx +0 -150
- package/src/react-ui/icons/lucide-animated/type.tsx +0 -23
- package/src/react-ui/icons/lucide-animated/upload.tsx +0 -23
- package/src/react-ui/icons/lucide-animated/x.tsx +0 -102
- package/src/react-ui/index.ts +0 -30
- package/src/react-ui/lib/get-strict-context.tsx +0 -56
- package/src/react-ui/lib/icon-wrapper.tsx +0 -70
- package/src/react-ui/lib/index.ts +0 -9
- package/src/react-ui/lib/utils.ts +0 -24
- package/src/react-ui/primitives/AutoHeight/index.tsx +0 -74
- package/src/react-ui/primitives/CountingNumber/index.tsx +0 -147
- package/src/react-ui/primitives/Highlight/Highlight.types.ts +0 -136
- package/src/react-ui/primitives/Highlight/index.tsx +0 -577
- package/src/react-ui/primitives/Slot/index.tsx +0 -128
- package/src/react-ui/primitives/index.ts +0 -16
- package/src/react-ui/primitives/waapi/Gooey/Gooey.types.ts +0 -123
- package/src/react-ui/primitives/waapi/Gooey/GooeyCanvas.tsx +0 -80
- package/src/react-ui/primitives/waapi/Gooey/GooeyFilter.tsx +0 -77
- package/src/react-ui/primitives/waapi/Gooey/MorphPath.tsx +0 -58
- package/src/react-ui/primitives/waapi/Gooey/gooey-utils.ts +0 -244
- package/src/react-ui/primitives/waapi/Gooey/index.ts +0 -50
- package/src/react-ui/primitives/waapi/Gooey/useMorphPath.ts +0 -48
- package/src/react-ui/primitives/waapi/Morph/Morph.types.ts +0 -106
- package/src/react-ui/primitives/waapi/Morph/MorphContext.tsx +0 -21
- package/src/react-ui/primitives/waapi/Morph/index.tsx +0 -56
- package/src/react-ui/primitives/waapi/Morph/techniques/index.ts +0 -12
- package/src/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.ts +0 -89
- package/src/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.ts +0 -176
- package/src/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.ts +0 -87
- package/src/react-ui/primitives/waapi/Morph/useMorph.ts +0 -101
- package/src/react-ui/primitives/waapi/Reorder/Reorder.types.ts +0 -177
- package/src/react-ui/primitives/waapi/Reorder/index.tsx +0 -260
- package/src/react-ui/primitives/waapi/Reorder/useReorder.ts +0 -47
- package/src/react-ui/primitives/waapi/Reorder/useReorderPresence.ts +0 -209
- package/src/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.ts +0 -104
- package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.ts +0 -14
- package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.ts +0 -84
- package/src/react-ui/primitives/waapi/SlidingNumber/index.tsx +0 -474
- package/src/react-ui/primitives/waapi/SlidingText/SlidingText.styles.ts +0 -32
- package/src/react-ui/primitives/waapi/SlidingText/SlidingText.types.ts +0 -69
- package/src/react-ui/primitives/waapi/SlidingText/index.tsx +0 -140
- package/src/react-ui/primitives/waapi/core/animationConstants.ts +0 -215
- package/src/react-ui/primitives/waapi/core/index.ts +0 -53
- package/src/react-ui/primitives/waapi/core/types.ts +0 -200
- package/src/react-ui/primitives/waapi/core/useAnimationOrchestrator.ts +0 -430
- package/src/react-ui/primitives/waapi/core/useElementRegistry.ts +0 -81
- package/src/react-ui/primitives/waapi/core/useFLIPAnimation.ts +0 -138
- package/src/react-ui/primitives/waapi/core/usePositionCapture.ts +0 -106
- package/src/react-ui/primitives/waapi/index.ts +0 -139
- package/src/react-ui/styles/animations.css +0 -369
- package/src/react-ui/ui/Accordion/Accordion.styles.ts +0 -72
- package/src/react-ui/ui/Accordion/Accordion.types.ts +0 -199
- package/src/react-ui/ui/Accordion/index.tsx +0 -362
- package/src/react-ui/ui/AlertDialog/AlertDialog.styles.ts +0 -38
- package/src/react-ui/ui/AlertDialog/AlertDialog.types.ts +0 -296
- package/src/react-ui/ui/AlertDialog/index.tsx +0 -540
- package/src/react-ui/ui/Badge/Badge.styles.ts +0 -43
- package/src/react-ui/ui/Badge/Badge.types.ts +0 -26
- package/src/react-ui/ui/Badge/index.tsx +0 -34
- package/src/react-ui/ui/Button/Button.styles.ts +0 -57
- package/src/react-ui/ui/Button/Button.types.ts +0 -63
- package/src/react-ui/ui/Button/index.tsx +0 -155
- package/src/react-ui/ui/Card/Card.styles.ts +0 -32
- package/src/react-ui/ui/Card/Card.types.ts +0 -39
- package/src/react-ui/ui/Card/index.tsx +0 -130
- package/src/react-ui/ui/Checkbox/Checkbox.styles.ts +0 -40
- package/src/react-ui/ui/Checkbox/Checkbox.types.ts +0 -98
- package/src/react-ui/ui/Checkbox/index.tsx +0 -233
- package/src/react-ui/ui/Combobox/Combobox.styles.ts +0 -34
- package/src/react-ui/ui/Combobox/Combobox.types.ts +0 -89
- package/src/react-ui/ui/Combobox/index.tsx +0 -331
- package/src/react-ui/ui/CornerBracket/CornerBracket.styles.ts +0 -38
- package/src/react-ui/ui/CornerBracket/CornerBracket.types.ts +0 -15
- package/src/react-ui/ui/CornerBracket/index.tsx +0 -49
- package/src/react-ui/ui/DataCard/DataCard.styles.ts +0 -94
- package/src/react-ui/ui/DataCard/DataCard.types.ts +0 -125
- package/src/react-ui/ui/DataCard/index.tsx +0 -340
- package/src/react-ui/ui/Dialog/Dialog.styles.ts +0 -59
- package/src/react-ui/ui/Dialog/Dialog.types.ts +0 -284
- package/src/react-ui/ui/Dialog/index.tsx +0 -452
- package/src/react-ui/ui/DropdownMenu/DropdownMenu.styles.ts +0 -35
- package/src/react-ui/ui/DropdownMenu/DropdownMenu.types.ts +0 -81
- package/src/react-ui/ui/DropdownMenu/index.tsx +0 -300
- package/src/react-ui/ui/DynamicToggle/DynamicToggle.css +0 -303
- package/src/react-ui/ui/DynamicToggle/DynamicToggle.styles.ts +0 -85
- package/src/react-ui/ui/DynamicToggle/DynamicToggle.types.ts +0 -174
- package/src/react-ui/ui/DynamicToggle/index.tsx +0 -294
- package/src/react-ui/ui/DynamicToggle/prototype-v7.html +0 -615
- package/src/react-ui/ui/DynamicToggle/prototype.html +0 -419
- package/src/react-ui/ui/Field/Field.styles.ts +0 -47
- package/src/react-ui/ui/Field/Field.types.ts +0 -60
- package/src/react-ui/ui/Field/index.tsx +0 -254
- package/src/react-ui/ui/Input/Input.styles.ts +0 -11
- package/src/react-ui/ui/Input/Input.types.ts +0 -10
- package/src/react-ui/ui/Input/index.tsx +0 -32
- package/src/react-ui/ui/InputGroup/InputGroup.styles.ts +0 -53
- package/src/react-ui/ui/InputGroup/InputGroup.types.ts +0 -44
- package/src/react-ui/ui/InputGroup/index.tsx +0 -149
- package/src/react-ui/ui/Label/Label.styles.ts +0 -10
- package/src/react-ui/ui/Label/Label.types.ts +0 -9
- package/src/react-ui/ui/Label/index.tsx +0 -27
- package/src/react-ui/ui/Menu/Menu.styles.ts +0 -71
- package/src/react-ui/ui/Menu/Menu.types.ts +0 -425
- package/src/react-ui/ui/Menu/index.tsx +0 -900
- package/src/react-ui/ui/Popover/Popover.styles.ts +0 -55
- package/src/react-ui/ui/Popover/Popover.types.ts +0 -261
- package/src/react-ui/ui/Popover/index.tsx +0 -422
- package/src/react-ui/ui/Progress/Progress.styles.ts +0 -36
- package/src/react-ui/ui/Progress/Progress.types.ts +0 -162
- package/src/react-ui/ui/Progress/index.tsx +0 -254
- package/src/react-ui/ui/Select/Select.styles.ts +0 -30
- package/src/react-ui/ui/Select/Select.types.ts +0 -51
- package/src/react-ui/ui/Select/index.tsx +0 -225
- package/src/react-ui/ui/Separator/Separator.styles.ts +0 -10
- package/src/react-ui/ui/Separator/Separator.types.ts +0 -10
- package/src/react-ui/ui/Separator/index.tsx +0 -37
- package/src/react-ui/ui/Switch/Switch.styles.ts +0 -50
- package/src/react-ui/ui/Switch/Switch.types.ts +0 -155
- package/src/react-ui/ui/Switch/index.tsx +0 -253
- package/src/react-ui/ui/Tabs/Tabs.css +0 -39
- package/src/react-ui/ui/Tabs/Tabs.styles.ts +0 -148
- package/src/react-ui/ui/Tabs/Tabs.types.ts +0 -255
- package/src/react-ui/ui/Tabs/index.tsx +0 -529
- package/src/react-ui/ui/TextFlow/TextFlow.styles.ts +0 -36
- package/src/react-ui/ui/TextFlow/TextFlow.types.ts +0 -118
- package/src/react-ui/ui/TextFlow/index.tsx +0 -276
- package/src/react-ui/ui/Textarea/Textarea.styles.ts +0 -10
- package/src/react-ui/ui/Textarea/Textarea.types.ts +0 -9
- package/src/react-ui/ui/Textarea/index.tsx +0 -27
- package/src/react-ui/ui/Tooltip/Tooltip.styles.ts +0 -43
- package/src/react-ui/ui/Tooltip/Tooltip.types.ts +0 -253
- package/src/react-ui/ui/Tooltip/index.tsx +0 -394
- package/src/react-ui/ui/index.ts +0 -41
- package/src/types/css-modules.d.ts +0 -18
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import type { ReactNode, ElementType } from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
IAnimationOrchestratorAPI,
|
|
4
|
-
FLIPBehavior,
|
|
5
|
-
ExitPositionStrategy
|
|
6
|
-
} from '../core/types';
|
|
7
|
-
|
|
8
|
-
// Re-export core types used by consumers
|
|
9
|
-
export type { FLIPBehavior, ExitPositionStrategy } from '../core/types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Layout direction for reorder items.
|
|
13
|
-
*
|
|
14
|
-
* - `auto`: No layout applied (consumer handles positioning)
|
|
15
|
-
* - `horizontal`: Flexbox row layout with wrapping
|
|
16
|
-
* - `inline-horizontal`: Inline-flexbox row layout without wrapping
|
|
17
|
-
* - `vertical`: Flexbox column layout
|
|
18
|
-
* - `grid`: CSS Grid with auto-fill columns
|
|
19
|
-
*/
|
|
20
|
-
export type ReorderLayout = 'auto' | 'horizontal' | 'inline-horizontal' | 'vertical' | 'grid';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Stagger configuration for animations.
|
|
24
|
-
* A single number applies to both enter/exit; an object allows separate values.
|
|
25
|
-
*/
|
|
26
|
-
export type StaggerConfig = number | { enter: number; exit: number };
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Duration configuration for animations.
|
|
30
|
-
* A single number applies to both enter/exit; an object allows separate values.
|
|
31
|
-
*/
|
|
32
|
-
export type DurationConfig = number | { enter: number; exit: number };
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Animation state for individual reorder items.
|
|
36
|
-
*/
|
|
37
|
-
export interface IReorderItemState {
|
|
38
|
-
/** True when the item is currently animating out */
|
|
39
|
-
isExiting: boolean;
|
|
40
|
-
/** True when the item is currently animating in */
|
|
41
|
-
isEntering: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Props for Reorder container component.
|
|
46
|
-
* Agnostic primitive for animated list reordering using FLIP technique.
|
|
47
|
-
*/
|
|
48
|
-
export interface IReorderProps {
|
|
49
|
-
/** Child elements to be animated. Each child should have a unique `key` prop */
|
|
50
|
-
children: ReactNode;
|
|
51
|
-
/** Layout arrangement for child elements */
|
|
52
|
-
layout?: ReorderLayout;
|
|
53
|
-
/** Stagger delay between item animations */
|
|
54
|
-
stagger?: StaggerConfig;
|
|
55
|
-
/** Animation duration in milliseconds */
|
|
56
|
-
duration?: DurationConfig;
|
|
57
|
-
/** Additional CSS class name for the container */
|
|
58
|
-
className?: string;
|
|
59
|
-
/** FLIP animation behavior strategy */
|
|
60
|
-
flipBehavior?: FLIPBehavior;
|
|
61
|
-
/** Strategy for positioning elements during exit animation */
|
|
62
|
-
exitPositionStrategy?: ExitPositionStrategy;
|
|
63
|
-
/** Callback fired when an item starts its exit animation */
|
|
64
|
-
onItemExit?: (id: string) => void;
|
|
65
|
-
/** Callback fired when an item completes its enter animation */
|
|
66
|
-
onItemEnter?: (id: string) => void;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Configuration options for useReorder hook.
|
|
71
|
-
* All timing values are in milliseconds.
|
|
72
|
-
*/
|
|
73
|
-
export interface IUseReorderConfig {
|
|
74
|
-
/** Duration of enter animation in milliseconds. @default 200 */
|
|
75
|
-
enterDuration?: number;
|
|
76
|
-
/** Duration of exit animation in milliseconds. @default 180 */
|
|
77
|
-
exitDuration?: number;
|
|
78
|
-
/** Duration of FLIP animation in milliseconds. @default 300 */
|
|
79
|
-
flipDuration?: number;
|
|
80
|
-
/** Easing function for enter animation */
|
|
81
|
-
enterEasing?: string;
|
|
82
|
-
/** Easing function for exit animation */
|
|
83
|
-
exitEasing?: string;
|
|
84
|
-
/** Easing function for FLIP animation */
|
|
85
|
-
flipEasing?: string;
|
|
86
|
-
/** FLIP animation behavior strategy. @default 'all' */
|
|
87
|
-
flipBehavior?: FLIPBehavior;
|
|
88
|
-
/** Strategy for positioning elements during exit animation. @default 'absolute-fixed' */
|
|
89
|
-
exitPositionStrategy?: ExitPositionStrategy;
|
|
90
|
-
/** Callback called when an item's exit animation completes */
|
|
91
|
-
onComplete?: (id: string) => void;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Return type for useReorder hook.
|
|
96
|
-
* Extends the full AnimationOrchestratorAPI with semantic aliases.
|
|
97
|
-
*/
|
|
98
|
-
export interface IUseReorderReturn extends IAnimationOrchestratorAPI {
|
|
99
|
-
/** Start exit animation for an item (alias for startExit) */
|
|
100
|
-
startItemExit: (id: string) => Promise<void>;
|
|
101
|
-
/** Start enter animation for an item (alias for startEnter) */
|
|
102
|
-
startItemEnter: (id: string) => Promise<void>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Context value passed to Reorder children.
|
|
107
|
-
* @internal Consumed by ReorderItem component.
|
|
108
|
-
*/
|
|
109
|
-
export interface IReorderContextValue {
|
|
110
|
-
/** Reorder instance with animation methods */
|
|
111
|
-
reorder: IUseReorderReturn;
|
|
112
|
-
/** Current layout setting */
|
|
113
|
-
layout: ReorderLayout;
|
|
114
|
-
/** Check if an item is currently exiting */
|
|
115
|
-
isExiting: (id: string) => boolean;
|
|
116
|
-
/** Check if an item is currently entering */
|
|
117
|
-
isEntering: (id: string) => boolean;
|
|
118
|
-
/** Array of item IDs currently exiting */
|
|
119
|
-
exitingIds: string[];
|
|
120
|
-
/** Array of item IDs currently entering */
|
|
121
|
-
enteringIds: string[];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Configuration for useReorderPresence hook.
|
|
126
|
-
* An alternative to the Reorder component giving full control
|
|
127
|
-
* over rendering while handling animation orchestration.
|
|
128
|
-
*/
|
|
129
|
-
export interface IUseReorderPresenceConfig {
|
|
130
|
-
/** Enable automatic enter animations for new children. @default true */
|
|
131
|
-
autoAnimate?: boolean;
|
|
132
|
-
/** Stagger delay between item animations */
|
|
133
|
-
stagger?: StaggerConfig;
|
|
134
|
-
/** Duration of enter animation in milliseconds */
|
|
135
|
-
enterDuration?: number;
|
|
136
|
-
/** Duration of exit animation in milliseconds */
|
|
137
|
-
exitDuration?: number;
|
|
138
|
-
/** Duration of FLIP animation in milliseconds */
|
|
139
|
-
flipDuration?: number;
|
|
140
|
-
/** Easing function for enter animation */
|
|
141
|
-
enterEasing?: string;
|
|
142
|
-
/** Easing function for exit animation */
|
|
143
|
-
exitEasing?: string;
|
|
144
|
-
/** Easing function for FLIP animation */
|
|
145
|
-
flipEasing?: string;
|
|
146
|
-
/** FLIP animation behavior strategy */
|
|
147
|
-
flipBehavior?: FLIPBehavior;
|
|
148
|
-
/** Strategy for positioning elements during exit animation */
|
|
149
|
-
exitPositionStrategy?: ExitPositionStrategy;
|
|
150
|
-
/** Callback fired when an item starts its exit animation */
|
|
151
|
-
onItemExit?: (id: string) => void;
|
|
152
|
-
/** Callback fired when an item completes its enter animation */
|
|
153
|
-
onItemEnter?: (id: string) => void;
|
|
154
|
-
/** Callback fired when an item's exit animation completes */
|
|
155
|
-
onAnimationComplete?: (id: string) => void;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Return type for useReorderPresence hook.
|
|
160
|
-
* Provides rendered children and methods for triggering animations.
|
|
161
|
-
*/
|
|
162
|
-
export interface IUseReorderPresenceReturn {
|
|
163
|
-
/** Rendered children with animation data attributes applied */
|
|
164
|
-
presentChildren: ReactNode;
|
|
165
|
-
/** Trigger exit animation for an item */
|
|
166
|
-
triggerExit: (id: string) => void;
|
|
167
|
-
/** Check if an item is currently exiting */
|
|
168
|
-
isExiting: (id: string) => boolean;
|
|
169
|
-
/** Check if an item is currently entering */
|
|
170
|
-
isEntering: (id: string) => boolean;
|
|
171
|
-
/** Array of item IDs currently exiting */
|
|
172
|
-
exitingIds: string[];
|
|
173
|
-
/** Array of item IDs currently entering */
|
|
174
|
-
enteringIds: string[];
|
|
175
|
-
/** Underlying reorder instance */
|
|
176
|
-
reorder: IUseReorderReturn;
|
|
177
|
-
}
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React, { useMemo, useState, useEffect, useRef, useCallback, useImperativeHandle, Children, isValidElement, cloneElement, forwardRef, type CSSProperties, type ReactNode, type ReactElement } from 'react';
|
|
4
|
-
import { useReorder } from './useReorder';
|
|
5
|
-
import type { IReorderProps, ReorderLayout, DurationConfig } from './Reorder.types';
|
|
6
|
-
import { cn } from '@/react-ui/lib/utils';
|
|
7
|
-
|
|
8
|
-
function getDuration(config: DurationConfig | undefined, type: 'enter' | 'exit'): number | undefined {
|
|
9
|
-
if (config === undefined) return undefined;
|
|
10
|
-
if (typeof config === 'number') return config;
|
|
11
|
-
return config[type];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const layoutStyles: Record<ReorderLayout, CSSProperties> = {
|
|
15
|
-
auto: { position: 'relative' },
|
|
16
|
-
horizontal: { display: 'flex', flexDirection: 'row', flexWrap: 'wrap', alignItems: 'center', position: 'relative' },
|
|
17
|
-
'inline-horizontal': { display: 'inline-flex', flexDirection: 'row', flexWrap: 'nowrap', alignItems: 'center', position: 'relative' },
|
|
18
|
-
vertical: { display: 'flex', flexDirection: 'column', position: 'relative' },
|
|
19
|
-
grid: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(100px, 1fr))', gap: '8px', position: 'relative' }
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
interface IChildRecord {
|
|
23
|
-
key: string;
|
|
24
|
-
element: ReactElement;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Reorder - Agnostic container for reorderable items with FLIP animations
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```tsx
|
|
32
|
-
* <Reorder
|
|
33
|
-
* layout="horizontal"
|
|
34
|
-
* onItemExit={(id) => handleRemove(id)}
|
|
35
|
-
* >
|
|
36
|
-
* {items.map(item => (
|
|
37
|
-
* <div key={item.id}>{item.name}</div>
|
|
38
|
-
* ))}
|
|
39
|
-
* </Reorder>
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
const ReorderRoot = forwardRef<{
|
|
43
|
-
startItemExit: (id: string) => Promise<void>;
|
|
44
|
-
startItemEnter: (id: string) => Promise<void>;
|
|
45
|
-
isAnimating: (id?: string) => boolean;
|
|
46
|
-
}, IReorderProps>(({
|
|
47
|
-
children,
|
|
48
|
-
stagger,
|
|
49
|
-
duration,
|
|
50
|
-
layout = 'auto',
|
|
51
|
-
className = '',
|
|
52
|
-
flipBehavior,
|
|
53
|
-
exitPositionStrategy,
|
|
54
|
-
onItemExit,
|
|
55
|
-
onItemEnter
|
|
56
|
-
}, ref) => {
|
|
57
|
-
// Completion handler - removes from displayChildren
|
|
58
|
-
const handleAnimationComplete = useCallback((id: string) => {
|
|
59
|
-
setDisplayChildren(prev => prev.filter(child => child.key !== id));
|
|
60
|
-
}, []);
|
|
61
|
-
|
|
62
|
-
// Reorder hook — delegates to full FLIP orchestrator
|
|
63
|
-
const reorder = useReorder({
|
|
64
|
-
enterDuration: getDuration(duration, 'enter'),
|
|
65
|
-
exitDuration: getDuration(duration, 'exit'),
|
|
66
|
-
flipBehavior,
|
|
67
|
-
exitPositionStrategy,
|
|
68
|
-
onComplete: handleAnimationComplete
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Expose reorder methods via ref
|
|
72
|
-
useImperativeHandle(ref, () => ({
|
|
73
|
-
startItemExit: reorder.startItemExit,
|
|
74
|
-
startItemEnter: reorder.startItemEnter,
|
|
75
|
-
isAnimating: reorder.isAnimating
|
|
76
|
-
}), [reorder.startItemExit, reorder.startItemEnter, reorder.isAnimating]);
|
|
77
|
-
|
|
78
|
-
// Store reorder functions in refs for stable callbacks
|
|
79
|
-
const startExitRef = useRef(reorder.startItemExit);
|
|
80
|
-
const startEnterRef = useRef(reorder.startItemEnter);
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
startExitRef.current = reorder.startItemExit;
|
|
83
|
-
startEnterRef.current = reorder.startItemEnter;
|
|
84
|
-
}, [reorder.startItemExit, reorder.startItemEnter]);
|
|
85
|
-
|
|
86
|
-
// Extract current children as records
|
|
87
|
-
const currentChildren = useMemo<IChildRecord[]>(() => {
|
|
88
|
-
const records: IChildRecord[] = [];
|
|
89
|
-
Children.forEach(children, child => {
|
|
90
|
-
if (isValidElement(child) && child.key != null) {
|
|
91
|
-
records.push({
|
|
92
|
-
key: String(child.key),
|
|
93
|
-
element: child as ReactElement
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
return records;
|
|
98
|
-
}, [children]);
|
|
99
|
-
|
|
100
|
-
// Internal display state
|
|
101
|
-
const [displayChildren, setDisplayChildren] = useState<IChildRecord[]>(currentChildren);
|
|
102
|
-
|
|
103
|
-
// Track which keys are currently exiting
|
|
104
|
-
const exitingKeysRef = useRef<Set<string>>(new Set());
|
|
105
|
-
|
|
106
|
-
// Calculate stagger delay
|
|
107
|
-
const getStaggerDelay = useCallback((index: number, type: 'enter' | 'exit'): number => {
|
|
108
|
-
if (!stagger) return 0;
|
|
109
|
-
if (typeof stagger === 'number') return stagger * index;
|
|
110
|
-
return (stagger[type] ?? 0) * index;
|
|
111
|
-
}, [stagger]);
|
|
112
|
-
|
|
113
|
-
// Detect changes and sync displayChildren
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
const currentKeys = new Set(currentChildren.map(c => c.key));
|
|
116
|
-
const displayKeys = new Set(displayChildren.map(c => c.key));
|
|
117
|
-
|
|
118
|
-
// Removals: in display but not in current, and not already exiting
|
|
119
|
-
const removed = displayChildren.filter(c =>
|
|
120
|
-
!currentKeys.has(c.key) && !exitingKeysRef.current.has(c.key)
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
// Additions: in current but not in display
|
|
124
|
-
const added = currentChildren.filter(c => !displayKeys.has(c.key));
|
|
125
|
-
|
|
126
|
-
// No structural changes
|
|
127
|
-
if (removed.length === 0 && added.length === 0) {
|
|
128
|
-
const hasUpdates = currentChildren.some((c) => {
|
|
129
|
-
const displayChild = displayChildren.find(dc => dc.key === c.key);
|
|
130
|
-
return displayChild && displayChild.element !== c.element;
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
if (hasUpdates) {
|
|
134
|
-
setDisplayChildren(prev => prev.map(dc => {
|
|
135
|
-
if (exitingKeysRef.current.has(dc.key)) return dc;
|
|
136
|
-
const currentChild = currentChildren.find(c => c.key === dc.key);
|
|
137
|
-
return currentChild ?? dc;
|
|
138
|
-
}));
|
|
139
|
-
}
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Handle removals - start exit animations
|
|
144
|
-
removed.forEach((child, index) => {
|
|
145
|
-
const delay = getStaggerDelay(index, 'exit');
|
|
146
|
-
exitingKeysRef.current.add(child.key);
|
|
147
|
-
|
|
148
|
-
const processExit = () => {
|
|
149
|
-
onItemExit?.(child.key);
|
|
150
|
-
|
|
151
|
-
// Start exit animation
|
|
152
|
-
startExitRef.current(child.key).finally(() => {
|
|
153
|
-
exitingKeysRef.current.delete(child.key);
|
|
154
|
-
});
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
if (delay > 0) {
|
|
158
|
-
setTimeout(processExit, delay);
|
|
159
|
-
} else {
|
|
160
|
-
processExit();
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// Handle additions - merge into display
|
|
165
|
-
if (added.length > 0) {
|
|
166
|
-
const exitingChildren = displayChildren.filter(c => !currentKeys.has(c.key));
|
|
167
|
-
let result = [...currentChildren];
|
|
168
|
-
|
|
169
|
-
exitingChildren.forEach(ec => {
|
|
170
|
-
const oldIdx = displayChildren.findIndex(c => c.key === ec.key);
|
|
171
|
-
if (oldIdx !== -1 && oldIdx <= result.length) {
|
|
172
|
-
result.splice(oldIdx, 0, ec);
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
setDisplayChildren(result);
|
|
177
|
-
|
|
178
|
-
added.forEach((child, index) => {
|
|
179
|
-
const delay = getStaggerDelay(index, 'enter');
|
|
180
|
-
|
|
181
|
-
const processEnter = () => {
|
|
182
|
-
onItemEnter?.(child.key);
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
if (delay > 0) {
|
|
186
|
-
setTimeout(processEnter, delay);
|
|
187
|
-
} else {
|
|
188
|
-
processEnter();
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}, [currentChildren, displayChildren, getStaggerDelay, onItemExit, onItemEnter]);
|
|
193
|
-
|
|
194
|
-
// Build present children with data attributes and ref registration
|
|
195
|
-
const presentChildren = useMemo<ReactNode[]>(() => {
|
|
196
|
-
const currentKeys = new Set(currentChildren.map(c => c.key));
|
|
197
|
-
|
|
198
|
-
return displayChildren.map(({ key, element }) => {
|
|
199
|
-
const isNewElement = currentKeys.has(key);
|
|
200
|
-
const isExiting = exitingKeysRef.current.has(key);
|
|
201
|
-
|
|
202
|
-
const elementWithRef = cloneElement(element as ReactElement<any>, {
|
|
203
|
-
ref: (el: HTMLElement | null) => {
|
|
204
|
-
if (el) {
|
|
205
|
-
reorder.registerElement(key, el);
|
|
206
|
-
|
|
207
|
-
const currentState = el.dataset.reorderState;
|
|
208
|
-
|
|
209
|
-
if (!currentState && isNewElement && !isExiting) {
|
|
210
|
-
el.dataset.reorderState = 'entering';
|
|
211
|
-
startEnterRef.current(key);
|
|
212
|
-
}
|
|
213
|
-
} else {
|
|
214
|
-
reorder.registerElement(key, null);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Preserve original ref
|
|
218
|
-
const originalRef = (element as any).ref;
|
|
219
|
-
if (typeof originalRef === 'function') {
|
|
220
|
-
originalRef(el);
|
|
221
|
-
} else if (originalRef && typeof originalRef === 'object') {
|
|
222
|
-
(originalRef as React.MutableRefObject<HTMLElement | null>).current = el;
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
'data-reorder-id': key
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
return elementWithRef;
|
|
229
|
-
});
|
|
230
|
-
}, [displayChildren, currentChildren, reorder.registerElement]);
|
|
231
|
-
|
|
232
|
-
const layoutClass = layout !== 'auto' ? `reorder--${layout}` : '';
|
|
233
|
-
|
|
234
|
-
return (
|
|
235
|
-
<div
|
|
236
|
-
className={cn('waapi-reorder-container', 'reorder', layoutClass, className)}
|
|
237
|
-
style={layoutStyles[layout]}
|
|
238
|
-
>
|
|
239
|
-
{presentChildren}
|
|
240
|
-
</div>
|
|
241
|
-
);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
ReorderRoot.displayName = 'Reorder';
|
|
245
|
-
|
|
246
|
-
export { ReorderRoot as Reorder };
|
|
247
|
-
export type {
|
|
248
|
-
IReorderProps,
|
|
249
|
-
ReorderLayout,
|
|
250
|
-
DurationConfig,
|
|
251
|
-
StaggerConfig,
|
|
252
|
-
IUseReorderReturn,
|
|
253
|
-
IUseReorderConfig,
|
|
254
|
-
IReorderItemState,
|
|
255
|
-
IReorderContextValue,
|
|
256
|
-
IUseReorderPresenceConfig,
|
|
257
|
-
IUseReorderPresenceReturn,
|
|
258
|
-
FLIPBehavior,
|
|
259
|
-
ExitPositionStrategy,
|
|
260
|
-
} from './Reorder.types';
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { useAnimationOrchestrator } from '../core/useAnimationOrchestrator';
|
|
3
|
-
import type { IUseReorderReturn, IUseReorderConfig } from './Reorder.types';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hook for managing reorderable lists with FLIP animations.
|
|
7
|
-
*
|
|
8
|
-
* Architecture: Thin wrapper around useAnimationOrchestrator.
|
|
9
|
-
* Delegates all animation logic to the orchestrator and provides
|
|
10
|
-
* a stable API surface for the Reorder component.
|
|
11
|
-
*
|
|
12
|
-
* @param config - Optional reorder configuration (timing, easing, callbacks)
|
|
13
|
-
* @returns Reorder API with register, exit, enter, and query methods
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```tsx
|
|
17
|
-
* const reorder = useReorder({
|
|
18
|
-
* onComplete: (id) => removeFromList(id)
|
|
19
|
-
* });
|
|
20
|
-
*
|
|
21
|
-
* <div ref={el => reorder.registerElement('item-1', el)}>
|
|
22
|
-
* Item 1
|
|
23
|
-
* </div>
|
|
24
|
-
*
|
|
25
|
-
* await reorder.startItemExit('item-1');
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export function useReorder(config?: IUseReorderConfig): IUseReorderReturn {
|
|
29
|
-
const orchestrator = useAnimationOrchestrator({
|
|
30
|
-
enterDuration: config?.enterDuration,
|
|
31
|
-
exitDuration: config?.exitDuration,
|
|
32
|
-
flipDuration: config?.flipDuration,
|
|
33
|
-
enterEasing: config?.enterEasing,
|
|
34
|
-
exitEasing: config?.exitEasing,
|
|
35
|
-
flipEasing: config?.flipEasing,
|
|
36
|
-
flipBehavior: config?.flipBehavior,
|
|
37
|
-
exitPositionStrategy: config?.exitPositionStrategy,
|
|
38
|
-
onExitComplete: config?.onComplete
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
...orchestrator,
|
|
43
|
-
registerElement: orchestrator.registerElement,
|
|
44
|
-
startItemExit: orchestrator.startExit,
|
|
45
|
-
startItemEnter: orchestrator.startEnter
|
|
46
|
-
};
|
|
47
|
-
}
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import {
|
|
3
|
-
useRef,
|
|
4
|
-
useCallback,
|
|
5
|
-
useMemo,
|
|
6
|
-
useLayoutEffect,
|
|
7
|
-
useEffect,
|
|
8
|
-
Children,
|
|
9
|
-
isValidElement,
|
|
10
|
-
cloneElement,
|
|
11
|
-
type ReactNode,
|
|
12
|
-
type ReactElement
|
|
13
|
-
} from 'react';
|
|
14
|
-
import { useReorder } from './useReorder';
|
|
15
|
-
import type {
|
|
16
|
-
IUseReorderPresenceConfig,
|
|
17
|
-
IUseReorderPresenceReturn
|
|
18
|
-
} from './Reorder.types';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Hook for managing presence animations in reorderable lists.
|
|
22
|
-
*
|
|
23
|
-
* Follows the pattern where elements stay in DOM until animation completes.
|
|
24
|
-
* Consumer must keep items in their state until onAnimationComplete fires.
|
|
25
|
-
* No "ghost" cloning — animations run on actual DOM elements.
|
|
26
|
-
*
|
|
27
|
-
* @param children - React children with unique keys
|
|
28
|
-
* @param config - Presence animation configuration
|
|
29
|
-
* @returns Presence API with presentChildren, triggerExit, and state queries
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```tsx
|
|
33
|
-
* const [items, setItems] = useState(INITIAL_ITEMS);
|
|
34
|
-
*
|
|
35
|
-
* const { presentChildren, triggerExit } = useReorderPresence(
|
|
36
|
-
* items.map(item => <div key={item.id}>{item.name}</div>),
|
|
37
|
-
* {
|
|
38
|
-
* onAnimationComplete: (id) => {
|
|
39
|
-
* setItems(prev => prev.filter(item => item.id !== id));
|
|
40
|
-
* }
|
|
41
|
-
* }
|
|
42
|
-
* );
|
|
43
|
-
*
|
|
44
|
-
* const handleDelete = (id: string) => {
|
|
45
|
-
* triggerExit(id);
|
|
46
|
-
* };
|
|
47
|
-
* ```
|
|
48
|
-
*/
|
|
49
|
-
export function useReorderPresence(
|
|
50
|
-
children: ReactNode,
|
|
51
|
-
config: IUseReorderPresenceConfig = {}
|
|
52
|
-
): IUseReorderPresenceReturn {
|
|
53
|
-
const {
|
|
54
|
-
autoAnimate = true,
|
|
55
|
-
stagger,
|
|
56
|
-
enterDuration,
|
|
57
|
-
exitDuration,
|
|
58
|
-
flipDuration,
|
|
59
|
-
enterEasing,
|
|
60
|
-
exitEasing,
|
|
61
|
-
flipEasing
|
|
62
|
-
} = config;
|
|
63
|
-
|
|
64
|
-
const configRef = useRef(config);
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
configRef.current = config;
|
|
67
|
-
}, [config]);
|
|
68
|
-
|
|
69
|
-
// Track animating IDs via REF (not state) — like AnimatedTokens
|
|
70
|
-
const exitingIdsRef = useRef<Set<string>>(new Set());
|
|
71
|
-
const enteringIdsRef = useRef<Set<string>>(new Set());
|
|
72
|
-
|
|
73
|
-
// Track previous children keys for change detection
|
|
74
|
-
const prevKeysRef = useRef<Set<string>>(new Set());
|
|
75
|
-
|
|
76
|
-
const getStaggerDelay = useCallback((index: number, type: 'enter' | 'exit'): number => {
|
|
77
|
-
if (!stagger) return 0;
|
|
78
|
-
if (typeof stagger === 'number') return stagger * index;
|
|
79
|
-
return (stagger[type] ?? 0) * index;
|
|
80
|
-
}, [stagger]);
|
|
81
|
-
|
|
82
|
-
const handleAnimationComplete = useCallback((id: string) => {
|
|
83
|
-
exitingIdsRef.current.delete(id);
|
|
84
|
-
configRef.current.onAnimationComplete?.(id);
|
|
85
|
-
}, []);
|
|
86
|
-
|
|
87
|
-
const reorder = useReorder({
|
|
88
|
-
enterDuration,
|
|
89
|
-
exitDuration,
|
|
90
|
-
flipDuration,
|
|
91
|
-
enterEasing,
|
|
92
|
-
exitEasing,
|
|
93
|
-
flipEasing,
|
|
94
|
-
onComplete: handleAnimationComplete
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const currentKeys = useMemo(() => {
|
|
98
|
-
const keys = new Set<string>();
|
|
99
|
-
Children.forEach(children, child => {
|
|
100
|
-
if (isValidElement(child) && child.key != null) {
|
|
101
|
-
keys.add(String(child.key));
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
return keys;
|
|
105
|
-
}, [children]);
|
|
106
|
-
|
|
107
|
-
// Detect and process changes
|
|
108
|
-
useLayoutEffect(() => {
|
|
109
|
-
const prevKeys = prevKeysRef.current;
|
|
110
|
-
|
|
111
|
-
// Detect additions (in current but not in prev)
|
|
112
|
-
const added: string[] = [];
|
|
113
|
-
currentKeys.forEach(key => {
|
|
114
|
-
if (!prevKeys.has(key) && !enteringIdsRef.current.has(key)) {
|
|
115
|
-
added.push(key);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// Process additions
|
|
120
|
-
if (added.length > 0) {
|
|
121
|
-
added.forEach((key, index) => {
|
|
122
|
-
const delay = getStaggerDelay(index, 'enter');
|
|
123
|
-
|
|
124
|
-
const processEnter = () => {
|
|
125
|
-
enteringIdsRef.current.add(key);
|
|
126
|
-
configRef.current.onItemEnter?.(key);
|
|
127
|
-
|
|
128
|
-
requestAnimationFrame(() => {
|
|
129
|
-
reorder.startItemEnter(key).then(() => {
|
|
130
|
-
enteringIdsRef.current.delete(key);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
if (delay > 0) {
|
|
136
|
-
setTimeout(processEnter, delay);
|
|
137
|
-
} else {
|
|
138
|
-
processEnter();
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
prevKeysRef.current = new Set(currentKeys);
|
|
144
|
-
}, [currentKeys, autoAnimate, reorder, getStaggerDelay]);
|
|
145
|
-
|
|
146
|
-
// Manual exit trigger
|
|
147
|
-
const triggerExit = useCallback((id: string) => {
|
|
148
|
-
if (exitingIdsRef.current.has(id)) return;
|
|
149
|
-
if (!reorder.registry.has(id)) return;
|
|
150
|
-
|
|
151
|
-
exitingIdsRef.current.add(id);
|
|
152
|
-
configRef.current.onItemExit?.(id);
|
|
153
|
-
|
|
154
|
-
reorder.startItemExit(id);
|
|
155
|
-
}, [reorder]);
|
|
156
|
-
|
|
157
|
-
const isExiting = useCallback((id: string): boolean => {
|
|
158
|
-
return exitingIdsRef.current.has(id);
|
|
159
|
-
}, []);
|
|
160
|
-
|
|
161
|
-
const isEntering = useCallback((id: string): boolean => {
|
|
162
|
-
return enteringIdsRef.current.has(id);
|
|
163
|
-
}, []);
|
|
164
|
-
|
|
165
|
-
const getExitingIds = useCallback((): string[] => {
|
|
166
|
-
return Array.from(exitingIdsRef.current);
|
|
167
|
-
}, []);
|
|
168
|
-
|
|
169
|
-
const getEnteringIds = useCallback((): string[] => {
|
|
170
|
-
return Array.from(enteringIdsRef.current);
|
|
171
|
-
}, []);
|
|
172
|
-
|
|
173
|
-
// presentChildren — children as-is with data attribute for exiting
|
|
174
|
-
const presentChildren = useMemo(() => {
|
|
175
|
-
const result: ReactNode[] = [];
|
|
176
|
-
|
|
177
|
-
Children.forEach(children, child => {
|
|
178
|
-
if (!isValidElement(child)) {
|
|
179
|
-
result.push(child);
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const key = child.key != null ? String(child.key) : null;
|
|
184
|
-
const isCurrentlyExiting = key != null && exitingIdsRef.current.has(key);
|
|
185
|
-
|
|
186
|
-
if (isCurrentlyExiting) {
|
|
187
|
-
result.push(
|
|
188
|
-
cloneElement(child as ReactElement<{ 'data-reorder-state'?: string }>, {
|
|
189
|
-
'data-reorder-state': 'exiting'
|
|
190
|
-
})
|
|
191
|
-
);
|
|
192
|
-
} else {
|
|
193
|
-
result.push(child);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
return result;
|
|
198
|
-
}, [children]);
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
presentChildren,
|
|
202
|
-
triggerExit,
|
|
203
|
-
isExiting,
|
|
204
|
-
isEntering,
|
|
205
|
-
exitingIds: getExitingIds(),
|
|
206
|
-
enteringIds: getEnteringIds(),
|
|
207
|
-
reorder
|
|
208
|
-
};
|
|
209
|
-
}
|