@flikk/ui 1.0.0-beta.27 → 1.0.0-beta.29
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/bg/1.webp +0 -0
- package/dist/bg/10.webp +0 -0
- package/dist/bg/11.webp +0 -0
- package/dist/bg/12.webp +0 -0
- package/dist/bg/13.webp +0 -0
- package/dist/bg/14.webp +0 -0
- package/dist/bg/15.webp +0 -0
- package/dist/bg/16.webp +0 -0
- package/dist/bg/17.webp +0 -0
- package/dist/bg/18.webp +0 -0
- package/dist/bg/19.webp +0 -0
- package/dist/bg/2.webp +0 -0
- package/dist/bg/20.webp +0 -0
- package/dist/bg/21.webp +0 -0
- package/dist/bg/22.webp +0 -0
- package/dist/bg/3.webp +0 -0
- package/dist/bg/4.webp +0 -0
- package/dist/bg/5.webp +0 -0
- package/dist/bg/6.webp +0 -0
- package/dist/bg/7.webp +0 -0
- package/dist/bg/8.webp +0 -0
- package/dist/bg/9.webp +0 -0
- package/dist/components/ai/CodeBlock/CodeBlock.theme.js +1 -1
- package/dist/components/ai/PromptInput/PromptInput.js +7 -143
- package/dist/components/ai/PromptInput/VoiceRecorder.js +0 -88
- package/dist/components/ai/TokenCounter/TokenCounter.theme.js +1 -1
- package/dist/components/canvas/Background.d.ts +19 -0
- package/dist/components/canvas/Background.js +23 -0
- package/dist/components/canvas/BaseNode.d.ts +15 -0
- package/dist/components/canvas/BaseNode.js +20 -0
- package/dist/components/canvas/CanvasToolbar.d.ts +34 -0
- package/dist/components/canvas/CanvasToolbar.js +34 -0
- package/dist/components/canvas/Edge.d.ts +35 -0
- package/dist/components/canvas/Edge.js +97 -0
- package/dist/components/canvas/EdgeLayer.d.ts +18 -0
- package/dist/components/canvas/EdgeLayer.js +111 -0
- package/dist/components/canvas/Handle.d.ts +11 -0
- package/dist/components/canvas/Handle.js +63 -0
- package/dist/components/canvas/MiniMap.d.ts +22 -0
- package/dist/components/canvas/MiniMap.js +105 -0
- package/dist/components/canvas/NodeCanvas.d.ts +10 -0
- package/dist/components/canvas/NodeCanvas.js +477 -0
- package/dist/components/canvas/NodeCanvas.theme.d.ts +7 -0
- package/dist/components/canvas/NodeCanvas.theme.js +9 -0
- package/dist/components/canvas/NodeCanvas.types.d.ts +187 -0
- package/dist/components/canvas/NodeControls.d.ts +25 -0
- package/dist/components/canvas/NodeControls.js +40 -0
- package/dist/components/canvas/NodeRenderer.d.ts +19 -0
- package/dist/components/canvas/NodeRenderer.js +117 -0
- package/dist/components/canvas/changes.d.ts +11 -0
- package/dist/components/canvas/changes.js +76 -0
- package/dist/components/canvas/context/CanvasContext.d.ts +32 -0
- package/dist/components/canvas/context/CanvasContext.js +14 -0
- package/dist/components/canvas/context/ConnectionContext.d.ts +33 -0
- package/dist/components/canvas/context/ConnectionContext.js +13 -0
- package/dist/components/canvas/context/HandleRegistry.d.ts +24 -0
- package/dist/components/canvas/context/HandleRegistry.js +15 -0
- package/dist/components/canvas/context/InteractionContext.d.ts +18 -0
- package/dist/components/canvas/context/InteractionContext.js +14 -0
- package/dist/components/canvas/context/NodeIdContext.d.ts +3 -0
- package/dist/components/canvas/context/NodeIdContext.js +15 -0
- package/dist/components/canvas/hooks/useConnection.d.ts +17 -0
- package/dist/components/canvas/hooks/useConnection.js +29 -0
- package/dist/components/canvas/hooks/useMarquee.d.ts +25 -0
- package/dist/components/canvas/hooks/useMarquee.js +91 -0
- package/dist/components/canvas/hooks/useNodeDrag.d.ts +23 -0
- package/dist/components/canvas/hooks/useNodeDrag.js +110 -0
- package/dist/components/canvas/hooks/usePanZoom.d.ts +30 -0
- package/dist/components/canvas/hooks/usePanZoom.js +189 -0
- package/dist/components/canvas/hooks/useViewport.d.ts +21 -0
- package/dist/components/canvas/hooks/useViewport.js +35 -0
- package/dist/components/canvas/index.d.ts +14 -0
- package/dist/components/canvas/index.js +12 -0
- package/dist/components/canvas/layout.d.ts +22 -0
- package/dist/components/canvas/layout.js +67 -0
- package/dist/components/canvas/utils.d.ts +4 -0
- package/dist/components/canvas/utils.js +16 -0
- package/dist/components/charts/AreaChart/AreaChart.js +136 -101
- package/dist/components/charts/AreaChart/AreaChart.types.d.ts +5 -5
- package/dist/components/charts/AreaChart/AreaChart.types.js +1 -0
- package/dist/components/charts/BarChart/BarChart.js +207 -143
- package/dist/components/charts/BarChart/BarChart.types.d.ts +4 -4
- package/dist/components/charts/BarChart/BarChart.types.js +1 -0
- package/dist/components/charts/ComboChart/ComboChart.types.d.ts +2 -2
- package/dist/components/charts/LineChart/LineChart.js +88 -72
- package/dist/components/charts/LineChart/LineChart.types.d.ts +3 -3
- package/dist/components/charts/RadarChart/RadarChart.js +1 -1
- package/dist/components/charts/RadarChart/RadarChart.theme.js +5 -2
- package/dist/components/charts/ScatterPlot/ScatterPlot.js +62 -72
- package/dist/components/charts/ScatterPlot/ScatterPlot.theme.js +10 -1
- package/dist/components/charts/ScatterPlot/ScatterPlot.types.d.ts +3 -9
- package/dist/components/charts/StackedBarChart/StackedBarChart.js +33 -33
- package/dist/components/charts/StackedBarChart/StackedBarChart.types.d.ts +2 -2
- package/dist/components/charts/hooks/index.d.ts +2 -0
- package/dist/components/charts/hooks/useChartDimensions.d.ts +29 -0
- package/dist/components/charts/hooks/useChartDimensions.js +42 -0
- package/dist/components/charts/shared/ChartTooltip/ChartTooltip.theme.js +1 -1
- package/dist/components/charts/types/chart.types.d.ts +11 -2
- package/dist/components/charts/types/chart.types.js +10 -3
- package/dist/components/core/Avatar/Avatar.js +5 -1
- package/dist/components/core/AvatarGroup/AvatarGroup.js +5 -1
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +4 -2
- package/dist/components/core/Badge/Badge.js +1 -1
- package/dist/components/core/Badge/Badge.theme.js +16 -15
- package/dist/components/core/Button/Button.js +1 -1
- package/dist/components/core/Button/Button.theme.js +2 -2
- package/dist/components/core/Calendar/Calendar.theme.js +1 -1
- package/dist/components/core/Card/Card.js +7 -3
- package/dist/components/core/Card/Card.theme.js +3 -3
- package/dist/components/core/Card/Card.types.d.ts +27 -2
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +2 -2
- package/dist/components/core/ContextMenu/ContextMenu.theme.js +2 -2
- package/dist/components/core/ContextMenu/ContextMenuItem.js +1 -1
- package/dist/components/core/ContextMenu/ContextMenuSubTrigger.js +1 -1
- package/dist/components/core/Dropdown/Dropdown.theme.js +3 -3
- package/dist/components/core/Dropdown/DropdownMenu.js +57 -29
- package/dist/components/core/HeroCard/HeroCard.d.ts +5 -0
- package/dist/components/core/HeroCard/HeroCard.js +99 -0
- package/dist/components/core/HeroCard/HeroCard.theme.d.ts +3 -0
- package/dist/components/core/HeroCard/HeroCard.theme.js +8 -0
- package/dist/components/core/HeroCard/HeroCard.types.d.ts +70 -0
- package/dist/components/core/HeroCard/index.d.ts +4 -0
- package/dist/components/core/Kbd/Kbd.theme.js +1 -1
- package/dist/components/core/Modal/Modal.d.ts +1 -1
- package/dist/components/core/Modal/Modal.js +2 -7
- package/dist/components/core/Modal/Modal.theme.js +4 -8
- package/dist/components/core/Modal/Modal.types.d.ts +0 -10
- package/dist/components/core/Modal/index.d.ts +1 -1
- package/dist/components/core/ModalStack/ModalStack.d.ts +1 -1
- package/dist/components/core/ModalStack/ModalStack.types.d.ts +1 -2
- package/dist/components/core/ModalStack/ModalStackModal.d.ts +1 -1
- package/dist/components/core/ModalStack/ModalStackModal.js +2 -7
- package/dist/components/core/PageHeading/PageHeading.theme.js +2 -2
- package/dist/components/core/Popover/Popover.theme.js +1 -1
- package/dist/components/core/ScrollArea/ScrollArea.js +242 -4
- package/dist/components/core/ScrollArea/ScrollArea.types.d.ts +12 -1
- package/dist/components/core/ScrollArea/smooth/SmoothScrollEngine.d.ts +4 -0
- package/dist/components/core/ScrollArea/smooth/SmoothScrollEngine.js +23 -0
- package/dist/components/core/ScrollArea/smooth/useSmoothScroll.js +4 -0
- package/dist/components/core/ScrollArea/smooth/useSmoothScroll.types.d.ts +5 -0
- package/dist/components/core/Segmented/Segmented.theme.js +2 -2
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
- package/dist/components/core/index.d.ts +1 -0
- package/dist/components/core/index.js +2 -0
- package/dist/components/data-display/DescriptionList/DescriptionList.js +23 -7
- package/dist/components/data-display/DescriptionList/DescriptionList.theme.js +10 -3
- package/dist/components/data-display/DescriptionList/DescriptionList.types.d.ts +49 -10
- package/dist/components/data-display/DescriptionList/index.d.ts +1 -1
- package/dist/components/data-display/Feed/Feed.js +28 -5
- package/dist/components/data-display/Feed/Feed.theme.js +1 -1
- package/dist/components/data-display/Feed/Feed.types.d.ts +32 -1
- package/dist/components/data-display/Feed/index.d.ts +1 -1
- package/dist/components/data-display/Metric/Metric.js +8 -8
- package/dist/components/data-display/Metric/Metric.theme.d.ts +3 -2
- package/dist/components/data-display/Metric/Metric.theme.js +50 -68
- package/dist/components/data-display/Metric/Metric.types.d.ts +19 -21
- package/dist/components/data-display/Table/Table.js +2 -2
- package/dist/components/data-display/Table/Table.theme.js +24 -4
- package/dist/components/data-display/Table/Table.types.d.ts +8 -0
- package/dist/components/data-display/Table/TableBody.js +2 -2
- package/dist/components/data-display/Table/TableCell.js +1 -1
- package/dist/components/data-display/Table/TableRow.d.ts +1 -1
- package/dist/components/data-display/Table/TableRow.js +9 -2
- package/dist/components/data-display/Timeline/Timeline.js +27 -5
- package/dist/components/data-display/Timeline/Timeline.theme.d.ts +10 -2
- package/dist/components/data-display/Timeline/Timeline.theme.js +14 -8
- package/dist/components/data-display/Timeline/Timeline.types.d.ts +48 -16
- package/dist/components/data-display/Timeline/Timeline.utils.d.ts +6 -0
- package/dist/components/data-display/Timeline/Timeline.utils.js +11 -0
- package/dist/components/data-display/Timeline/TimelineItem.js +13 -20
- package/dist/components/data-display/Timeline/TimelineMarker.js +10 -8
- package/dist/components/data-display/Timeline/index.d.ts +2 -2
- package/dist/components/effects/3d/index.d.ts +0 -2
- package/dist/components/effects/3d/index.js +0 -1
- package/dist/components/effects/DotPattern/DotPattern.js +1 -1
- package/dist/components/effects/Overlay/Overlay.theme.js +1 -2
- package/dist/components/effects/Preloader/Preloader.animations.d.ts +23 -0
- package/dist/components/effects/Preloader/Preloader.animations.js +150 -0
- package/dist/components/effects/Preloader/Preloader.d.ts +3 -0
- package/dist/components/effects/Preloader/Preloader.js +119 -0
- package/dist/components/effects/Preloader/Preloader.types.d.ts +63 -0
- package/dist/components/effects/Preloader/index.d.ts +2 -0
- package/dist/components/effects/ProgressiveBlur/ProgressiveBlur.js +25 -14
- package/dist/components/effects/ProgressiveBlur/ProgressiveBlur.types.d.ts +2 -0
- package/dist/components/effects/TiltCard/TiltCard.d.ts +12 -0
- package/dist/components/effects/TiltCard/TiltCard.glow.d.ts +28 -0
- package/dist/components/effects/TiltCard/TiltCard.glow.js +114 -0
- package/dist/components/effects/TiltCard/TiltCard.js +177 -0
- package/dist/components/effects/{SpotlightBorder/SpotlightBorder.shaders.d.ts → TiltCard/TiltCard.shaders.d.ts} +1 -1
- package/dist/components/effects/{SpotlightBorder/SpotlightBorder.shaders.js → TiltCard/TiltCard.shaders.js} +1 -1
- package/dist/components/effects/TiltCard/TiltCard.types.d.ts +88 -0
- package/dist/components/effects/TiltCard/index.d.ts +2 -0
- package/dist/components/effects/index.d.ts +4 -12
- package/dist/components/effects/index.js +2 -6
- package/dist/components/forms/Checkbox/Checkbox.js +7 -1
- package/dist/components/forms/DatePicker/DatePicker.theme.js +2 -2
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +1 -1
- package/dist/components/forms/FileUpload/FileUpload.js +1 -89
- package/dist/components/forms/FormLabel/FormLabel.theme.js +1 -1
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +2 -2
- package/dist/components/forms/Slider/Slider.theme.js +1 -1
- package/dist/components/forms/Switch/Switch.js +27 -15
- package/dist/components/forms/Switch/Switch.theme.d.ts +36 -6
- package/dist/components/forms/Switch/Switch.theme.js +33 -4
- package/dist/components/forms/Switch/Switch.types.d.ts +12 -2
- package/dist/components/forms/TimePicker/TimePicker.theme.js +1 -2
- package/dist/components/forms/TimePicker/TimePickerContent.js +1 -90
- package/dist/components/forms/forms.theme.js +1 -1
- package/dist/components/forms/index.d.ts +0 -4
- package/dist/components/forms/index.js +0 -92
- package/dist/components/generative/GenerativeView.d.ts +21 -0
- package/dist/components/generative/GenerativeView.js +116 -0
- package/dist/components/generative/actions.d.ts +26 -0
- package/dist/components/generative/actions.js +51 -0
- package/dist/components/generative/index.d.ts +11 -0
- package/dist/components/generative/index.js +9 -0
- package/dist/components/generative/registry.d.ts +43 -0
- package/dist/components/generative/registry.js +114 -0
- package/dist/components/generative/resolvers.d.ts +35 -0
- package/dist/components/generative/resolvers.js +93 -0
- package/dist/components/generative/schema.generated.d.ts +2 -0
- package/dist/components/generative/schema.generated.js +1639 -0
- package/dist/components/generative/schemaTypes.d.ts +30 -0
- package/dist/components/generative/streaming.d.ts +39 -0
- package/dist/components/generative/streaming.js +283 -0
- package/dist/components/generative/tools.d.ts +21 -0
- package/dist/components/generative/tools.js +54 -0
- package/dist/components/generative/types.d.ts +41 -0
- package/dist/components/generative/useGenerativeStream.d.ts +37 -0
- package/dist/components/generative/useGenerativeStream.js +36 -0
- package/dist/components/generative/validate.d.ts +24 -0
- package/dist/components/generative/validate.js +259 -0
- package/dist/components/layout/AppShell/AppShell.theme.js +2 -2
- package/dist/components/layout/FormLayout/FormLayout.js +1 -90
- package/dist/components/layout/Grid/Grid.d.ts +3 -0
- package/dist/components/layout/Grid/Grid.js +50 -0
- package/dist/components/layout/Grid/Grid.theme.d.ts +2 -0
- package/dist/components/layout/Grid/Grid.theme.js +35 -0
- package/dist/components/layout/Grid/Grid.types.d.ts +57 -0
- package/dist/components/layout/Grid/index.d.ts +3 -0
- package/dist/components/layout/Section/Section.d.ts +3 -0
- package/dist/components/layout/Section/Section.js +18 -0
- package/dist/components/layout/Section/Section.theme.d.ts +2 -0
- package/dist/components/layout/Section/Section.theme.js +10 -0
- package/dist/components/layout/Section/Section.types.d.ts +34 -0
- package/dist/components/layout/Section/index.d.ts +3 -0
- package/dist/components/layout/Stack/Stack.d.ts +3 -0
- package/dist/components/layout/Stack/Stack.js +19 -0
- package/dist/components/layout/Stack/Stack.theme.d.ts +2 -0
- package/dist/components/layout/Stack/Stack.theme.js +10 -0
- package/dist/components/layout/Stack/Stack.types.d.ts +39 -0
- package/dist/components/layout/Stack/index.d.ts +3 -0
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.js +6 -0
- package/dist/generative.schema.json +1637 -0
- package/dist/index.js +180 -180
- package/dist/registry.json +648 -464
- package/dist/styles.css +1 -1
- package/dist/tools.json +1731 -0
- package/package.json +17 -4
- package/src/global.scss +53 -101
- package/src/styles/theme.css +687 -493
- package/dist/bg/1.jpg +0 -0
- package/dist/bg/10.jpg +0 -0
- package/dist/bg/11.jpg +0 -0
- package/dist/bg/14.jpg +0 -0
- package/dist/bg/15.jpg +0 -0
- package/dist/bg/16.jpg +0 -0
- package/dist/bg/17.jpg +0 -0
- package/dist/bg/18.jpg +0 -0
- package/dist/bg/19.jpg +0 -0
- package/dist/bg/2.jpg +0 -0
- package/dist/bg/20.jpg +0 -0
- package/dist/bg/21.jpg +0 -0
- package/dist/bg/22.jpg +0 -0
- package/dist/bg/23.jpg +0 -0
- package/dist/bg/24.jpg +0 -0
- package/dist/bg/3.jpg +0 -0
- package/dist/bg/4.jpg +0 -0
- package/dist/bg/5.jpg +0 -0
- package/dist/bg/6.jpg +0 -0
- package/dist/bg/7.jpg +0 -0
- package/dist/bg/8.jpg +0 -0
- package/dist/bg/9.jpg +0 -0
- package/dist/components/effects/MorphingText/MorphingText.d.ts +0 -17
- package/dist/components/effects/MorphingText/MorphingText.js +0 -125
- package/dist/components/effects/MorphingText/MorphingText.types.d.ts +0 -18
- package/dist/components/effects/MorphingText/index.d.ts +0 -2
- package/dist/components/effects/PageTransition/PageTransition.animations.d.ts +0 -8
- package/dist/components/effects/PageTransition/PageTransition.animations.js +0 -53
- package/dist/components/effects/PageTransition/PageTransition.d.ts +0 -3
- package/dist/components/effects/PageTransition/PageTransition.js +0 -82
- package/dist/components/effects/PageTransition/PageTransition.types.d.ts +0 -15
- package/dist/components/effects/PageTransition/index.d.ts +0 -2
- package/dist/components/effects/ParallaxSection/ParallaxSection.d.ts +0 -26
- package/dist/components/effects/ParallaxSection/ParallaxSection.js +0 -71
- package/dist/components/effects/ParallaxSection/ParallaxSection.types.d.ts +0 -11
- package/dist/components/effects/ParallaxSection/index.d.ts +0 -2
- package/dist/components/effects/Spotlight/Spotlight.d.ts +0 -36
- package/dist/components/effects/Spotlight/Spotlight.js +0 -112
- package/dist/components/effects/Spotlight/Spotlight.types.d.ts +0 -29
- package/dist/components/effects/Spotlight/index.d.ts +0 -2
- package/dist/components/effects/SpotlightBorder/SpotlightBorder.d.ts +0 -18
- package/dist/components/effects/SpotlightBorder/SpotlightBorder.js +0 -213
- package/dist/components/effects/SpotlightBorder/SpotlightBorder.types.d.ts +0 -61
- package/dist/components/effects/SpotlightBorder/index.d.ts +0 -2
- package/dist/components/effects/StickyScroll/StickyScroll.d.ts +0 -30
- package/dist/components/effects/StickyScroll/StickyScroll.js +0 -128
- package/dist/components/effects/StickyScroll/StickyScroll.types.d.ts +0 -19
- package/dist/components/effects/StickyScroll/index.d.ts +0 -2
- package/dist/components/forms/CronInput/CronInput.d.ts +0 -3
- package/dist/components/forms/CronInput/CronInput.js +0 -113
- package/dist/components/forms/CronInput/CronInput.theme.d.ts +0 -6
- package/dist/components/forms/CronInput/CronInput.theme.js +0 -75
- package/dist/components/forms/CronInput/CronInput.types.d.ts +0 -109
- package/dist/components/forms/CronInput/CronInput.utils.d.ts +0 -67
- package/dist/components/forms/CronInput/CronInput.utils.js +0 -505
- package/dist/components/forms/CronInput/index.d.ts +0 -4
- /package/dist/components/effects/{SpotlightBorder/SpotlightBorder.types.js → TiltCard/TiltCard.types.js} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { TimelineTheme } from "./Timeline.theme";
|
|
2
3
|
/**
|
|
3
4
|
* Layout orientation for the Timeline
|
|
4
5
|
*/
|
|
@@ -18,12 +19,44 @@ export interface TimelineThemeOverrides {
|
|
|
18
19
|
baseStyleHorizontal?: string;
|
|
19
20
|
itemStyle?: string;
|
|
20
21
|
itemStyleHorizontal?: string;
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
connectorStyle?: string;
|
|
23
|
+
connectorStyleHorizontal?: string;
|
|
24
|
+
connectorCompletedStyle?: string;
|
|
23
25
|
markerStyle?: string;
|
|
24
26
|
markerStatuses?: Partial<Record<TimelineItemStatus, string>>;
|
|
25
27
|
contentStyle?: string;
|
|
26
28
|
contentStyleHorizontal?: string;
|
|
29
|
+
titleStyle?: string;
|
|
30
|
+
descriptionStyle?: string;
|
|
31
|
+
timestampStyle?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A single timeline item for the data-driven (`items`) API.
|
|
35
|
+
* Maps internally to `Timeline.Item` → `Timeline.Marker` + `Timeline.Content`,
|
|
36
|
+
* so it stays fully serializable (no JSX composition required). This is the
|
|
37
|
+
* generative-UI / model-friendly entry path; the compound API remains for
|
|
38
|
+
* hand-authored timelines that need full control.
|
|
39
|
+
*/
|
|
40
|
+
export interface TimelineItemData {
|
|
41
|
+
/** @default 'pending' */
|
|
42
|
+
status?: TimelineItemStatus;
|
|
43
|
+
/** Heading line (rendered with the theme's `titleStyle`) */
|
|
44
|
+
title?: React.ReactNode;
|
|
45
|
+
/** Body line (rendered with the theme's `descriptionStyle`) */
|
|
46
|
+
description?: React.ReactNode;
|
|
47
|
+
/** Trailing meta line, e.g. a date (rendered with the theme's `timestampStyle`) */
|
|
48
|
+
timestamp?: React.ReactNode;
|
|
49
|
+
/** Icon element shown inside the marker. Pass a ReactNode (resolve name→icon upstream). */
|
|
50
|
+
icon?: React.ReactNode;
|
|
51
|
+
/**
|
|
52
|
+
* Escape hatch — when provided, replaces the default title/description/timestamp
|
|
53
|
+
* rendering with arbitrary content (matches the compound `Timeline.Content` body).
|
|
54
|
+
*/
|
|
55
|
+
content?: React.ReactNode;
|
|
56
|
+
/** Optional className forwarded to the item wrapper */
|
|
57
|
+
className?: string;
|
|
58
|
+
/** Stable React key (falls back to the array index) */
|
|
59
|
+
key?: string | number;
|
|
27
60
|
}
|
|
28
61
|
/**
|
|
29
62
|
* Timeline root component props
|
|
@@ -34,32 +67,26 @@ export interface TimelineProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
34
67
|
* @default 'vertical'
|
|
35
68
|
*/
|
|
36
69
|
layout?: TimelineLayout;
|
|
70
|
+
/**
|
|
71
|
+
* Data-driven items. When provided, the timeline renders from this array and
|
|
72
|
+
* any `children` are ignored (dev-warns). Omit it to use the compound API.
|
|
73
|
+
*/
|
|
74
|
+
items?: TimelineItemData[];
|
|
37
75
|
/**
|
|
38
76
|
* Theme overrides for customizing styles
|
|
39
77
|
*/
|
|
40
78
|
theme?: TimelineThemeOverrides;
|
|
41
79
|
/**
|
|
42
|
-
* Children
|
|
80
|
+
* Children — `Timeline.Item` components (compound API). Optional when `items` is used.
|
|
43
81
|
*/
|
|
44
|
-
children
|
|
82
|
+
children?: React.ReactNode;
|
|
45
83
|
}
|
|
46
84
|
/**
|
|
47
85
|
* Context value shared between Timeline compound components
|
|
48
86
|
*/
|
|
49
87
|
export interface TimelineContextValue {
|
|
50
88
|
layout: TimelineLayout;
|
|
51
|
-
theme:
|
|
52
|
-
baseStyle: string;
|
|
53
|
-
baseStyleHorizontal: string;
|
|
54
|
-
itemStyle: string;
|
|
55
|
-
itemStyleHorizontal: string;
|
|
56
|
-
lineStyle: string;
|
|
57
|
-
lineStyleHorizontal: string;
|
|
58
|
-
markerStyle: string;
|
|
59
|
-
markerStatuses: Record<TimelineItemStatus, string>;
|
|
60
|
-
contentStyle: string;
|
|
61
|
-
contentStyleHorizontal: string;
|
|
62
|
-
};
|
|
89
|
+
theme: TimelineTheme;
|
|
63
90
|
totalItems: number;
|
|
64
91
|
}
|
|
65
92
|
/**
|
|
@@ -79,6 +106,11 @@ export interface TimelineItemProps extends React.HTMLAttributes<HTMLDivElement>
|
|
|
79
106
|
* Item content - should include Timeline.Marker and Timeline.Content
|
|
80
107
|
*/
|
|
81
108
|
children: React.ReactNode;
|
|
109
|
+
/**
|
|
110
|
+
* @internal Index within the timeline, injected by the root via cloneElement.
|
|
111
|
+
* Do not set this manually.
|
|
112
|
+
*/
|
|
113
|
+
_index?: number;
|
|
82
114
|
}
|
|
83
115
|
/**
|
|
84
116
|
* Context value for individual Timeline items
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip the DOM drag/animation handlers that collide with `motion.*` element
|
|
3
|
+
* props, so the remaining `...rest` can be safely spread onto a motion element.
|
|
4
|
+
* Shared by TimelineItem and TimelineMarker (both render a `motion.div`).
|
|
5
|
+
*/
|
|
6
|
+
export declare function stripMotionConflicts<T extends Record<string, unknown>>(props: T): Omit<T, "onDrag" | "onDragEnd" | "onDragStart" | "onAnimationStart" | "onAnimationEnd">;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip the DOM drag/animation handlers that collide with `motion.*` element
|
|
3
|
+
* props, so the remaining `...rest` can be safely spread onto a motion element.
|
|
4
|
+
* Shared by TimelineItem and TimelineMarker (both render a `motion.div`).
|
|
5
|
+
*/
|
|
6
|
+
function stripMotionConflicts(props) {
|
|
7
|
+
const { onDrag: _onDrag, onDragEnd: _onDragEnd, onDragStart: _onDragStart, onAnimationStart: _onAnimationStart, onAnimationEnd: _onAnimationEnd, ...rest } = props;
|
|
8
|
+
return rest;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { stripMotionConflicts };
|
|
@@ -4,6 +4,7 @@ import { useReducedMotion, motion } from 'motion/react';
|
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
5
|
import { useTimelineContext } from './Timeline.js';
|
|
6
6
|
import { timelineHorizontalItemVariants, timelineItemVariants } from './Timeline.animations.js';
|
|
7
|
+
import { stripMotionConflicts } from './Timeline.utils.js';
|
|
7
8
|
|
|
8
9
|
// Create context for TimelineItem
|
|
9
10
|
const TimelineItemContext = createContext(undefined);
|
|
@@ -14,26 +15,22 @@ const useTimelineItemContext = () => {
|
|
|
14
15
|
throw new Error("Timeline.Marker and Timeline.Content must be used within Timeline.Item");
|
|
15
16
|
return ctx;
|
|
16
17
|
};
|
|
17
|
-
const TimelineItem = React__default.forwardRef(({ children, className, status = "pending", ...props }, ref) => {
|
|
18
|
+
const TimelineItem = React__default.forwardRef(({ children, className, status = "pending", _index = 0, ...props }, ref) => {
|
|
18
19
|
const { layout, theme, totalItems } = useTimelineContext();
|
|
19
20
|
const shouldReduceMotion = useReducedMotion();
|
|
20
21
|
const itemRef = useRef(null);
|
|
21
22
|
const [isVisible, setIsVisible] = useState(false);
|
|
22
|
-
//
|
|
23
|
+
// Index/first/last come from the root (single source of truth), not the DOM.
|
|
24
|
+
const index = _index;
|
|
25
|
+
const isFirst = index === 0;
|
|
26
|
+
const isLast = index === totalItems - 1;
|
|
27
|
+
const isHorizontal = layout === "horizontal";
|
|
23
28
|
const resolvedRef = ref || itemRef;
|
|
24
|
-
//
|
|
25
|
-
const [index, setIndex] = useState(0);
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
const element = resolvedRef && "current" in resolvedRef ? resolvedRef.current : itemRef.current;
|
|
28
|
-
if (element === null || element === void 0 ? void 0 : element.parentElement) {
|
|
29
|
-
const siblings = Array.from(element.parentElement.children);
|
|
30
|
-
const idx = siblings.indexOf(element);
|
|
31
|
-
setIndex(idx);
|
|
32
|
-
}
|
|
33
|
-
}, [resolvedRef]);
|
|
34
|
-
// IntersectionObserver for scroll-triggered animation
|
|
29
|
+
// IntersectionObserver for scroll-triggered entry animation
|
|
35
30
|
useEffect(() => {
|
|
36
|
-
const element = resolvedRef && "current" in resolvedRef
|
|
31
|
+
const element = resolvedRef && "current" in resolvedRef
|
|
32
|
+
? resolvedRef.current
|
|
33
|
+
: itemRef.current;
|
|
37
34
|
if (!element)
|
|
38
35
|
return;
|
|
39
36
|
const observer = new IntersectionObserver(([entry]) => {
|
|
@@ -45,9 +42,6 @@ const TimelineItem = React__default.forwardRef(({ children, className, status =
|
|
|
45
42
|
observer.observe(element);
|
|
46
43
|
return () => observer.disconnect();
|
|
47
44
|
}, [resolvedRef]);
|
|
48
|
-
const isFirst = index === 0;
|
|
49
|
-
const isLast = index === totalItems - 1;
|
|
50
|
-
const isHorizontal = layout === "horizontal";
|
|
51
45
|
// Select animation variants based on layout
|
|
52
46
|
const getVariants = () => {
|
|
53
47
|
if (shouldReduceMotion)
|
|
@@ -63,10 +57,9 @@ const TimelineItem = React__default.forwardRef(({ children, className, status =
|
|
|
63
57
|
isFirst,
|
|
64
58
|
isLast,
|
|
65
59
|
};
|
|
66
|
-
|
|
67
|
-
const { onDrag, onDragEnd, onDragStart, onAnimationStart, onAnimationEnd, ...safeProps } = props;
|
|
60
|
+
const safeProps = stripMotionConflicts(props);
|
|
68
61
|
const variants = getVariants();
|
|
69
|
-
return (jsx(TimelineItemContext.Provider, { value: contextValue, children: jsx(motion.div, { ref: ref || itemRef, className: cn(isHorizontal ? theme.itemStyleHorizontal : theme.itemStyle, className), "data-status": status, "data-layout": layout, role: "listitem", initial: variants ? "hidden" : undefined, animate: variants && isVisible ? "visible" : variants ? "hidden" : undefined, variants: variants, ...safeProps, children: children }) }));
|
|
62
|
+
return (jsx(TimelineItemContext.Provider, { value: contextValue, children: jsx(motion.div, { ref: ref || itemRef, className: cn(isHorizontal ? theme.itemStyleHorizontal : theme.itemStyle, className), "data-status": status, "data-layout": layout, role: "listitem", "aria-current": status === "active" ? "step" : undefined, initial: variants ? "hidden" : undefined, animate: variants && isVisible ? "visible" : variants ? "hidden" : undefined, variants: variants, ...safeProps, children: children }) }));
|
|
70
63
|
});
|
|
71
64
|
TimelineItem.displayName = "TimelineItem";
|
|
72
65
|
|
|
@@ -6,7 +6,14 @@ import { cn } from '../../../utils/cn.js';
|
|
|
6
6
|
import { useTimelineContext } from './Timeline.js';
|
|
7
7
|
import { useTimelineItemContext } from './TimelineItem.js';
|
|
8
8
|
import { timelineMarkerVariants } from './Timeline.animations.js';
|
|
9
|
+
import { stripMotionConflicts } from './Timeline.utils.js';
|
|
9
10
|
|
|
11
|
+
// Screen-reader status text so status isn't conveyed by color/icon alone.
|
|
12
|
+
const STATUS_LABEL = {
|
|
13
|
+
completed: "Completed",
|
|
14
|
+
active: "In progress",
|
|
15
|
+
pending: "Pending",
|
|
16
|
+
};
|
|
10
17
|
const TimelineMarker = React__default.forwardRef(({ icon, className, ...props }, ref) => {
|
|
11
18
|
const { theme, layout } = useTimelineContext();
|
|
12
19
|
const { status, isLast } = useTimelineItemContext();
|
|
@@ -19,20 +26,15 @@ const TimelineMarker = React__default.forwardRef(({ icon, className, ...props },
|
|
|
19
26
|
return jsx(CheckIcon, { className: "w-4 h-4" });
|
|
20
27
|
}
|
|
21
28
|
if (status === "active") {
|
|
22
|
-
return jsx("span", { className: "w-2 h-2 rounded-full bg-
|
|
29
|
+
return (jsx("span", { className: "w-2 h-2 rounded-full bg-[var(--color-primary)]" }));
|
|
23
30
|
}
|
|
24
31
|
// Pending: small neutral dot
|
|
25
32
|
return (jsx("span", { className: "w-2 h-2 rounded-full bg-[var(--color-text-muted)]" }));
|
|
26
33
|
};
|
|
27
34
|
const isHorizontal = layout === "horizontal";
|
|
28
35
|
const variants = shouldReduceMotion ? undefined : timelineMarkerVariants;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return (jsxs("div", { className: cn("relative flex flex-col items-center", isHorizontal && "w-full"), children: [jsx(motion.div, { ref: ref, className: cn(theme.markerStyle, theme.markerStatuses[status], className), "data-status": status, "aria-label": `${status} step`, initial: variants ? "hidden" : undefined, animate: variants ? "visible" : undefined, variants: variants, ...safeProps, children: renderIcon() }), !isLast && !isHorizontal && (jsx("div", { className: cn("w-0.5 flex-1 min-h-4", status === "completed"
|
|
32
|
-
? "bg-[var(--color-success)]"
|
|
33
|
-
: "bg-[var(--color-border)]"), "aria-hidden": "true" })), !isLast && isHorizontal && (jsx("div", { className: cn("absolute top-1/2 -translate-y-1/2 left-1/2 h-0.5 w-full", status === "completed"
|
|
34
|
-
? "bg-[var(--color-success)]"
|
|
35
|
-
: "bg-[var(--color-border)]"), "aria-hidden": "true" }))] }));
|
|
36
|
+
const safeProps = stripMotionConflicts(props);
|
|
37
|
+
return (jsxs("div", { className: cn("relative flex flex-col items-center", isHorizontal && "w-full"), children: [jsxs(motion.div, { ref: ref, className: cn(theme.markerStyle, theme.markerStatuses[status], className), "data-status": status, initial: variants ? "hidden" : undefined, animate: variants ? "visible" : undefined, variants: variants, ...safeProps, children: [jsx("span", { className: "sr-only", children: STATUS_LABEL[status] }), jsx("span", { "aria-hidden": "true", className: "flex items-center justify-center", children: renderIcon() })] }), !isLast && !isHorizontal && (jsx("div", { className: cn(theme.connectorStyle, status === "completed" && theme.connectorCompletedStyle), "aria-hidden": "true" })), !isLast && isHorizontal && (jsx("div", { className: cn(theme.connectorStyleHorizontal, status === "completed" && theme.connectorCompletedStyle), "aria-hidden": "true" }))] }));
|
|
36
38
|
});
|
|
37
39
|
TimelineMarker.displayName = "TimelineMarker";
|
|
38
40
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Timeline } from "./Timeline";
|
|
2
|
-
import { TimelineProps, TimelineItemProps, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineItemStatus } from "./Timeline.types";
|
|
2
|
+
import { TimelineProps, TimelineItemProps, TimelineItemData, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineItemStatus } from "./Timeline.types";
|
|
3
3
|
export { Timeline };
|
|
4
|
-
export type { TimelineProps, TimelineItemProps, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineItemStatus, };
|
|
4
|
+
export type { TimelineProps, TimelineItemProps, TimelineItemData, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineItemStatus, };
|
|
@@ -2,5 +2,3 @@ export { AIOrb } from "../AIOrb";
|
|
|
2
2
|
export type { AIOrbProps, OrbState, DotSphereProps, LiquidProps, AuraProps } from "../AIOrb";
|
|
3
3
|
export { Particles } from "../Particles";
|
|
4
4
|
export type { ParticlesProps } from "../Particles";
|
|
5
|
-
export { SpotlightBorder } from "../SpotlightBorder";
|
|
6
|
-
export type { SpotlightBorderProps, SpotlightBorderVariation, } from "../SpotlightBorder";
|
|
@@ -34,7 +34,7 @@ function buildMaskImage(direction, fadeSize) {
|
|
|
34
34
|
* </div>
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
|
-
const DotPattern = React__default.forwardRef(({ spacing = 20, dotSize = 1, color = "var(--color-border)", fade = true, fadeDirection = "radial", fadeSize = 50, animated = false, className, style, ...rest }, ref) => {
|
|
37
|
+
const DotPattern = React__default.forwardRef(({ spacing = 20, dotSize = 1, color = "var(--color-border-secondary)", fade = true, fadeDirection = "radial", fadeSize = 50, animated = false, className, style, ...rest }, ref) => {
|
|
38
38
|
const patternId = useId();
|
|
39
39
|
const shouldReduceMotion = useReducedMotion();
|
|
40
40
|
const enableAnimation = animated && !shouldReduceMotion;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const overlayTheme = {
|
|
2
2
|
/** Full-screen backdrop with blur */
|
|
3
|
-
backdrop: "fixed inset-0 bg-[var(--overlay-bg)] z-50 ",
|
|
4
|
-
// backdrop-blur-[var(--overlay-blur)]
|
|
3
|
+
backdrop: "fixed inset-0 bg-[var(--overlay-bg)] z-50 backdrop-blur-[var(--overlay-blur)] ",
|
|
5
4
|
/** Dots / pattern layer behind content */
|
|
6
5
|
pattern: "absolute inset-0 w-full h-full z-0 pointer-events-none",
|
|
7
6
|
/** Content wrapper (sits above pattern) */
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { PreloaderDirection, PreloaderType } from './Preloader.types';
|
|
3
|
+
import type { Variants } from 'motion/react';
|
|
4
|
+
export declare const CURTAIN_EASE: readonly [0.76, 0, 0.24, 1];
|
|
5
|
+
export declare const buildCurtainVariants: (direction: PreloaderDirection, duration: number) => Variants;
|
|
6
|
+
export declare const buildLogoParallaxVariants: (direction: PreloaderDirection, duration: number) => Variants;
|
|
7
|
+
export declare const buildLogoFadeVariants: (duration: number) => Variants;
|
|
8
|
+
export interface PanelDescriptor {
|
|
9
|
+
key: string;
|
|
10
|
+
style: React.CSSProperties;
|
|
11
|
+
variants: Variants;
|
|
12
|
+
/** Resolved fill for this panel (layers color ladder). Falls back to the `color` prop, then the default class. */
|
|
13
|
+
backgroundColor?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface PanelEngineOptions {
|
|
16
|
+
type: PreloaderType;
|
|
17
|
+
direction: PreloaderDirection;
|
|
18
|
+
duration: number;
|
|
19
|
+
panels: number;
|
|
20
|
+
stagger: number;
|
|
21
|
+
color?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const buildPanelDescriptors: (opts: PanelEngineOptions) => PanelDescriptor[];
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const CURTAIN_EASE = [0.76, 0, 0.24, 1];
|
|
2
|
+
const exitTransition = (duration, delay = 0) => ({
|
|
3
|
+
duration,
|
|
4
|
+
ease: CURTAIN_EASE,
|
|
5
|
+
delay,
|
|
6
|
+
});
|
|
7
|
+
const exitMap = {
|
|
8
|
+
up: { y: '-100%', x: 0 },
|
|
9
|
+
down: { y: '100%', x: 0 },
|
|
10
|
+
left: { x: '-100%', y: 0 },
|
|
11
|
+
right: { x: '100%', y: 0 },
|
|
12
|
+
};
|
|
13
|
+
const buildCurtainVariants = (direction, duration) => ({
|
|
14
|
+
covered: { y: 0, x: 0 },
|
|
15
|
+
exit: {
|
|
16
|
+
...exitMap[direction],
|
|
17
|
+
transition: exitTransition(duration),
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
// Logo is rendered INSIDE the curtain. These are relative offsets that
|
|
21
|
+
// counteract ~30% of the curtain's motion, making the logo appear to
|
|
22
|
+
// move at ~70% of the curtain's speed (parallax lag effect). It also
|
|
23
|
+
// fades out so the mark dissolves while lagging instead of riding the
|
|
24
|
+
// curtain edge off-screen.
|
|
25
|
+
const logoInnerOffsetMap = {
|
|
26
|
+
up: { y: '30vh', x: 0 },
|
|
27
|
+
down: { y: '-30vh', x: 0 },
|
|
28
|
+
left: { x: '30vw', y: 0 },
|
|
29
|
+
right: { x: '-30vw', y: 0 },
|
|
30
|
+
};
|
|
31
|
+
const buildLogoParallaxVariants = (direction, duration) => ({
|
|
32
|
+
covered: { y: 0, x: 0, opacity: 1 },
|
|
33
|
+
exit: {
|
|
34
|
+
...logoInnerOffsetMap[direction],
|
|
35
|
+
opacity: 0,
|
|
36
|
+
transition: exitTransition(duration),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
// Plain fade-out for logos that don't translate on their own: every
|
|
40
|
+
// non-slide type renders the logo in a static centered layer over the
|
|
41
|
+
// panels, so it must fade or it would linger over the revealed page.
|
|
42
|
+
// Slightly faster than the panels so the mark is gone before the
|
|
43
|
+
// reveal completes.
|
|
44
|
+
const buildLogoFadeVariants = (duration) => ({
|
|
45
|
+
covered: { opacity: 1 },
|
|
46
|
+
exit: {
|
|
47
|
+
opacity: 0,
|
|
48
|
+
transition: { duration: duration * 0.5, ease: CURTAIN_EASE },
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
// Strips travel slightly past their own span so sub-pixel rounding never
|
|
52
|
+
// leaves a hairline of curtain at the edge.
|
|
53
|
+
const STRIP_EXIT = 102;
|
|
54
|
+
const buildStripDescriptors = ({ type, direction, duration, panels, stagger, }) => {
|
|
55
|
+
// Strips orient perpendicular to the exit axis: up/down → vertical strips
|
|
56
|
+
// translating Y; left/right → horizontal strips translating X.
|
|
57
|
+
const axis = direction === 'left' || direction === 'right' ? 'x' : 'y';
|
|
58
|
+
const sign = direction === 'up' || direction === 'left' ? -1 : 1;
|
|
59
|
+
const size = 100 / panels;
|
|
60
|
+
return Array.from({ length: panels }, (_, i) => {
|
|
61
|
+
// +0.4% overlap so adjacent strips never show a seam between them
|
|
62
|
+
const span = `${size + (i < panels - 1 ? 0.4 : 0)}%`;
|
|
63
|
+
const offset = `${i * size}%`;
|
|
64
|
+
const panelSign = type === 'shutters' && i % 2 === 1 ? -sign : sign;
|
|
65
|
+
return {
|
|
66
|
+
key: `strip-${i}`,
|
|
67
|
+
style: axis === 'y'
|
|
68
|
+
? { top: 0, bottom: 0, left: offset, width: span, willChange: 'transform' }
|
|
69
|
+
: { left: 0, right: 0, top: offset, height: span, willChange: 'transform' },
|
|
70
|
+
variants: {
|
|
71
|
+
covered: { x: 0, y: 0 },
|
|
72
|
+
exit: {
|
|
73
|
+
[axis]: `${panelSign * STRIP_EXIT}%`,
|
|
74
|
+
transition: exitTransition(duration, i * stagger),
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
const buildLayerDescriptors = ({ direction, duration, panels, stagger, color, }) => {
|
|
81
|
+
const base = color !== null && color !== void 0 ? color : 'var(--color-primary)';
|
|
82
|
+
return Array.from({ length: panels }, (_, i) => ({
|
|
83
|
+
key: `layer-${i}`,
|
|
84
|
+
// First-leaving layer sits on top; deeper layers get progressively lighter
|
|
85
|
+
style: { inset: 0, zIndex: panels - i, willChange: 'transform' },
|
|
86
|
+
backgroundColor: i === 0 ? color : `color-mix(in oklab, ${base}, white ${Math.min(i * 30, 75)}%)`,
|
|
87
|
+
variants: {
|
|
88
|
+
covered: { x: 0, y: 0 },
|
|
89
|
+
exit: {
|
|
90
|
+
...exitMap[direction],
|
|
91
|
+
transition: exitTransition(duration, i * stagger),
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
}));
|
|
95
|
+
};
|
|
96
|
+
const buildSplitDescriptors = ({ direction, duration, }) => {
|
|
97
|
+
const make = (key, place, exit) => ({
|
|
98
|
+
key,
|
|
99
|
+
style: { ...place, willChange: 'transform' },
|
|
100
|
+
variants: {
|
|
101
|
+
covered: {},
|
|
102
|
+
exit: { ...exit, transition: exitTransition(duration) },
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
return direction === 'up' || direction === 'down'
|
|
106
|
+
? [
|
|
107
|
+
make('split-1', { top: 0, left: 0, right: 0, height: '50%' }, { y: '-100%' }),
|
|
108
|
+
make('split-2', { bottom: 0, left: 0, right: 0, height: '50%' }, { y: '100%' }),
|
|
109
|
+
]
|
|
110
|
+
: [
|
|
111
|
+
make('split-1', { top: 0, bottom: 0, left: 0, width: '50%' }, { x: '-100%' }),
|
|
112
|
+
make('split-2', { top: 0, bottom: 0, right: 0, width: '50%' }, { x: '100%' }),
|
|
113
|
+
];
|
|
114
|
+
};
|
|
115
|
+
const buildPanelDescriptors = (opts) => {
|
|
116
|
+
switch (opts.type) {
|
|
117
|
+
case 'blinds':
|
|
118
|
+
case 'shutters':
|
|
119
|
+
return buildStripDescriptors(opts);
|
|
120
|
+
case 'layers':
|
|
121
|
+
return buildLayerDescriptors(opts);
|
|
122
|
+
case 'iris':
|
|
123
|
+
return [
|
|
124
|
+
{
|
|
125
|
+
key: 'iris',
|
|
126
|
+
style: { inset: 0 },
|
|
127
|
+
variants: {
|
|
128
|
+
covered: { clipPath: 'circle(125% at 50% 50%)' },
|
|
129
|
+
exit: {
|
|
130
|
+
clipPath: 'circle(0% at 50% 50%)',
|
|
131
|
+
transition: exitTransition(opts.duration),
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
case 'split':
|
|
137
|
+
return buildSplitDescriptors(opts);
|
|
138
|
+
case 'slide':
|
|
139
|
+
default:
|
|
140
|
+
return [
|
|
141
|
+
{
|
|
142
|
+
key: 'curtain',
|
|
143
|
+
style: { inset: 0, willChange: 'transform' },
|
|
144
|
+
variants: buildCurtainVariants(opts.direction, opts.duration),
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export { CURTAIN_EASE, buildCurtainVariants, buildLogoFadeVariants, buildLogoParallaxVariants, buildPanelDescriptors };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useRef, useEffect } from 'react';
|
|
3
|
+
import { useReducedMotion, motion } from 'motion/react';
|
|
4
|
+
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
import { buildPanelDescriptors, buildLogoParallaxVariants, buildLogoFadeVariants } from './Preloader.animations.js';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_COLOR_CLASS = "bg-[var(--color-primary)]";
|
|
8
|
+
const PANEL_DEFAULTS = {
|
|
9
|
+
blinds: 5,
|
|
10
|
+
shutters: 4,
|
|
11
|
+
layers: 3,
|
|
12
|
+
};
|
|
13
|
+
const STAGGER_DEFAULTS = {
|
|
14
|
+
blinds: 0.08,
|
|
15
|
+
shutters: 0.08,
|
|
16
|
+
layers: 0.14,
|
|
17
|
+
};
|
|
18
|
+
const Preloader = ({ children, logo, type = "slide", direction = "up", duration = 0.8, delay = 0.8, color, className, parallax = true, contained = false, panels, stagger, onStart, onComplete, }) => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
const [phase, setPhase] = useState("covered");
|
|
21
|
+
const [completedPanels, setCompletedPanels] = useState(0);
|
|
22
|
+
const shouldReduceMotion = useReducedMotion();
|
|
23
|
+
const isMultiPanel = type === "blinds" || type === "shutters" || type === "layers";
|
|
24
|
+
let panelCount = (_a = PANEL_DEFAULTS[type]) !== null && _a !== void 0 ? _a : (type === "split" ? 2 : 1);
|
|
25
|
+
if (isMultiPanel && panels !== undefined) {
|
|
26
|
+
if (process.env.NODE_ENV !== "production" && (panels < 2 || panels > 12)) {
|
|
27
|
+
console.warn("[Preloader]: panels must be between 2 and 12; clamping.");
|
|
28
|
+
}
|
|
29
|
+
panelCount = Math.min(12, Math.max(2, Math.round(panels)));
|
|
30
|
+
}
|
|
31
|
+
const resolvedStagger = isMultiPanel ? (_b = stagger !== null && stagger !== void 0 ? stagger : STAGGER_DEFAULTS[type]) !== null && _b !== void 0 ? _b : 0 : 0;
|
|
32
|
+
// Stable refs for callbacks/reduced-motion to avoid stale closures without re-running the effect
|
|
33
|
+
const onStartRef = useRef(onStart);
|
|
34
|
+
const onCompleteRef = useRef(onComplete);
|
|
35
|
+
const reducedMotionRef = useRef(shouldReduceMotion);
|
|
36
|
+
// Guards against re-triggering the exit if the effect re-runs (e.g. `delay` change)
|
|
37
|
+
const startedRef = useRef(false);
|
|
38
|
+
useEffect(() => { onStartRef.current = onStart; }, [onStart]);
|
|
39
|
+
useEffect(() => { onCompleteRef.current = onComplete; }, [onComplete]);
|
|
40
|
+
useEffect(() => { reducedMotionRef.current = shouldReduceMotion; }, [shouldReduceMotion]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (typeof window === "undefined" || typeof document === "undefined")
|
|
43
|
+
return;
|
|
44
|
+
let cancelled = false;
|
|
45
|
+
let delayTimer;
|
|
46
|
+
let loadListener;
|
|
47
|
+
const loadPromise = new Promise((resolve) => {
|
|
48
|
+
if (document.readyState === "complete") {
|
|
49
|
+
resolve();
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
loadListener = () => resolve();
|
|
53
|
+
window.addEventListener("load", loadListener, { once: true });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const delayPromise = new Promise((resolve) => {
|
|
57
|
+
delayTimer = setTimeout(resolve, delay * 1000);
|
|
58
|
+
});
|
|
59
|
+
Promise.all([loadPromise, delayPromise]).then(() => {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
if (cancelled || startedRef.current)
|
|
62
|
+
return;
|
|
63
|
+
startedRef.current = true;
|
|
64
|
+
if (reducedMotionRef.current) {
|
|
65
|
+
// Skip the animation entirely but keep the callback contract
|
|
66
|
+
(_a = onStartRef.current) === null || _a === void 0 ? void 0 : _a.call(onStartRef);
|
|
67
|
+
setPhase("done");
|
|
68
|
+
(_b = onCompleteRef.current) === null || _b === void 0 ? void 0 : _b.call(onCompleteRef);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
setPhase("exit");
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return () => {
|
|
75
|
+
cancelled = true;
|
|
76
|
+
if (delayTimer !== undefined)
|
|
77
|
+
clearTimeout(delayTimer);
|
|
78
|
+
if (loadListener)
|
|
79
|
+
window.removeEventListener("load", loadListener);
|
|
80
|
+
};
|
|
81
|
+
}, [delay]);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
var _a;
|
|
84
|
+
if (completedPanels >= panelCount) {
|
|
85
|
+
setPhase("done");
|
|
86
|
+
(_a = onCompleteRef.current) === null || _a === void 0 ? void 0 : _a.call(onCompleteRef);
|
|
87
|
+
}
|
|
88
|
+
}, [completedPanels, panelCount]);
|
|
89
|
+
if (phase === "done") {
|
|
90
|
+
return jsx(Fragment, { children: children });
|
|
91
|
+
}
|
|
92
|
+
const positionClass = contained ? "absolute inset-0" : "fixed inset-0";
|
|
93
|
+
const descriptors = buildPanelDescriptors({
|
|
94
|
+
type,
|
|
95
|
+
direction,
|
|
96
|
+
duration,
|
|
97
|
+
panels: panelCount,
|
|
98
|
+
stagger: resolvedStagger,
|
|
99
|
+
color,
|
|
100
|
+
});
|
|
101
|
+
const handleExitStart = (def) => {
|
|
102
|
+
var _a;
|
|
103
|
+
if (def === "exit")
|
|
104
|
+
(_a = onStartRef.current) === null || _a === void 0 ? void 0 : _a.call(onStartRef);
|
|
105
|
+
};
|
|
106
|
+
// Slide carries its logo inside the curtain (parallax lag or plain fade);
|
|
107
|
+
// every other type renders it in the static centered layer below.
|
|
108
|
+
const slideLogoNode = type === "slide" && logo ? (parallax ? (jsx(motion.div, { className: "relative z-10 select-none", variants: buildLogoParallaxVariants(direction, duration), initial: "covered", animate: phase, children: logo })) : (jsx(motion.div, { className: "relative z-10 select-none", variants: buildLogoFadeVariants(duration), initial: "covered", animate: phase, children: logo }))) : null;
|
|
109
|
+
return (jsxs(Fragment, { children: [children, jsxs("div", { "aria-hidden": "true", className: cn(positionClass, "z-[9999] pointer-events-none"), children: [descriptors.map((d, i) => {
|
|
110
|
+
var _a;
|
|
111
|
+
const bg = (_a = d.backgroundColor) !== null && _a !== void 0 ? _a : color;
|
|
112
|
+
return (jsx(motion.div, { className: cn("absolute pointer-events-auto", type === "slide" && "flex items-center justify-center", !bg && DEFAULT_COLOR_CLASS, className), style: { ...d.style, ...(bg ? { backgroundColor: bg } : undefined) }, variants: d.variants, initial: "covered", animate: phase, onAnimationStart: i === 0 ? handleExitStart : undefined, onAnimationComplete: (def) => {
|
|
113
|
+
if (def === "exit")
|
|
114
|
+
setCompletedPanels((n) => n + 1);
|
|
115
|
+
}, children: slideLogoNode }, d.key));
|
|
116
|
+
}), type !== "slide" && logo && (jsx(motion.div, { className: "absolute inset-0 flex items-center justify-center select-none", style: { zIndex: 50 }, variants: buildLogoFadeVariants(duration), initial: "covered", animate: phase, children: logo }))] })] }));
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export { Preloader };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export type PreloaderDirection = 'up' | 'down' | 'left' | 'right';
|
|
2
|
+
export type PreloaderType = 'slide' | 'split' | 'blinds' | 'shutters' | 'layers' | 'iris';
|
|
3
|
+
export interface PreloaderProps {
|
|
4
|
+
/** Page content revealed once the curtain exits. */
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
/** Decorative mark centered on the curtain (hidden from assistive tech). */
|
|
7
|
+
logo?: React.ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* `slide` = one full curtain exits; `split` = two half panels part in
|
|
10
|
+
* opposite directions; `blinds` = staggered strips sweep the same way;
|
|
11
|
+
* `shutters` = strips alternate directions; `layers` = stacked curtains
|
|
12
|
+
* trail each other in lightening shades; `iris` = a circular mask closes
|
|
13
|
+
* on the curtain from the edges to the center.
|
|
14
|
+
*/
|
|
15
|
+
type?: PreloaderType;
|
|
16
|
+
/**
|
|
17
|
+
* Exit direction. For `split`, `up`/`down` split along the horizontal seam
|
|
18
|
+
* and `left`/`right` along the vertical seam (the two are equivalent per axis).
|
|
19
|
+
* For `blinds`/`shutters`, strips orient perpendicular to the exit axis.
|
|
20
|
+
* Ignored by `iris` (always closes to center).
|
|
21
|
+
*/
|
|
22
|
+
direction?: PreloaderDirection;
|
|
23
|
+
/**
|
|
24
|
+
* Exit animation duration in seconds (not ms), per panel. For staggered
|
|
25
|
+
* types the total exit time is `duration + (panels - 1) * stagger`.
|
|
26
|
+
*/
|
|
27
|
+
duration?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Minimum hold time in seconds (not ms). The curtain exits once BOTH the
|
|
30
|
+
* window `load` event has fired and this delay has elapsed.
|
|
31
|
+
*/
|
|
32
|
+
delay?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Curtain fill as a CSS color value (e.g. `"var(--color-primary-900)"`, `"#0a0a0a"`).
|
|
35
|
+
* Applied as an inline `background-color`, so it wins over `className`.
|
|
36
|
+
* When omitted, the curtain uses `bg-[var(--color-primary)]` as a class,
|
|
37
|
+
* which `className` background utilities can override.
|
|
38
|
+
*/
|
|
39
|
+
color?: string;
|
|
40
|
+
className?: string;
|
|
41
|
+
/** Slide only: the logo lags behind the curtain for a depth effect. */
|
|
42
|
+
parallax?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Position the overlay `absolute` within the nearest positioned ancestor
|
|
45
|
+
* instead of `fixed` to the viewport. Use when embedding the transition in
|
|
46
|
+
* a container (demos, hero sections) rather than covering the whole page.
|
|
47
|
+
*/
|
|
48
|
+
contained?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Strip/slat/layer count for `blinds` (default 5), `shutters` (default 4),
|
|
51
|
+
* and `layers` (default 3). Clamped to 2–12. Ignored by other types.
|
|
52
|
+
*/
|
|
53
|
+
panels?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Seconds between successive panels for `blinds`/`shutters` (default 0.08)
|
|
56
|
+
* and `layers` (default 0.14). Ignored by other types.
|
|
57
|
+
*/
|
|
58
|
+
stagger?: number;
|
|
59
|
+
/** Fires when the exit animation starts (immediately if reduced motion is on). */
|
|
60
|
+
onStart?: () => void;
|
|
61
|
+
/** Fires once the reveal finishes; the overlay unmounts from the DOM. */
|
|
62
|
+
onComplete?: () => void;
|
|
63
|
+
}
|