@speakeasy-api/moonshine 2.0.0-alpha.1 → 2.0.0-alpha.3
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/LICENSE +21 -0
- package/README.md +49 -23
- package/package.json +33 -50
- package/scripts/generate-utility-docs.js +324 -0
- package/src/assets/icons/external/github.svg +3 -0
- package/src/assets/icons/external/maven.svg +152 -0
- package/src/assets/icons/external/npm.svg +4 -0
- package/src/assets/icons/external/nuget.svg +5 -0
- package/src/assets/icons/external/packagist.svg +1 -0
- package/src/assets/icons/external/pypi.svg +182 -0
- package/src/assets/icons/external/rubygems.svg +14 -0
- package/src/assets/icons/external/terraform.svg +1 -0
- package/src/assets/icons/languages/csharp.svg +1 -0
- package/src/assets/icons/languages/go.svg +1 -0
- package/src/assets/icons/languages/java.svg +1 -0
- package/src/assets/icons/languages/json.svg +2 -0
- package/src/assets/icons/languages/php.svg +1 -0
- package/src/assets/icons/languages/postman.svg +3 -0
- package/src/assets/icons/languages/python.svg +1 -0
- package/src/assets/icons/languages/ruby.svg +1 -0
- package/src/assets/icons/languages/swift.svg +1 -0
- package/src/assets/icons/languages/terraform.svg +1 -0
- package/src/assets/icons/languages/typescript.svg +1 -0
- package/src/assets/icons/languages/unity.svg +1 -0
- package/src/base.css +12 -12
- package/src/components/AIChat/AIChatContainer.tsx +71 -0
- package/src/components/AIChat/AIChatMessage.tsx +135 -0
- package/src/components/AIChat/AIChatMessageComposer.tsx +175 -0
- package/src/components/AIChat/AIChatMessageList.tsx +34 -0
- package/src/components/AIChat/AIChatModelSelector.tsx +159 -0
- package/src/components/AIChat/componentsTypes.ts +36 -0
- package/src/components/AIChat/context.ts +15 -0
- package/src/components/AIChat/index.ts +12 -0
- package/src/components/AIChat/parts/AIChatMessageFilePart.tsx +129 -0
- package/src/components/AIChat/parts/AIChatMessageReasoningPart.tsx +23 -0
- package/src/components/AIChat/parts/AIChatMessageSourcePart.tsx +58 -0
- package/src/components/AIChat/parts/AIChatMessageTextPart.tsx +33 -0
- package/src/components/AIChat/parts/AIChatMessageToolInvocationPart.tsx +53 -0
- package/src/components/AIChat/parts/AIChatMessageToolPart.tsx +395 -0
- package/src/components/AIChat/parts/AIChatMessageToolResultPart.tsx +46 -0
- package/src/components/AIChat/toolCallApproval.ts +61 -0
- package/src/components/AIChat/types.ts +97 -0
- package/src/components/ActionBar/index.tsx +184 -0
- package/src/components/Alert/index.tsx +118 -0
- package/src/components/Alert/types.ts +12 -0
- package/src/components/AppLayout/context.tsx +31 -0
- package/src/components/AppLayout/index.tsx +550 -0
- package/src/components/AppLayout/provider.tsx +40 -0
- package/src/components/AppLayout/useAppLayoutKeys.ts +26 -0
- package/src/components/Badge/index.tsx +227 -0
- package/src/components/Button/index.tsx +531 -0
- package/src/components/Card/index.tsx +193 -0
- package/src/components/CodeEditorLayout/index.tsx +394 -0
- package/src/components/CodeEditorLayout/styles.module.css +8 -0
- package/src/components/CodeHighlight/Pre.tsx +63 -0
- package/src/components/CodePlayground/index.tsx +411 -0
- package/src/components/CodeSnippet/codeSnippet.css +97 -0
- package/src/components/CodeSnippet/index.tsx +224 -0
- package/src/components/Combobox/index.tsx +193 -0
- package/src/components/Command/index.tsx +152 -0
- package/src/components/Container/index.tsx +31 -0
- package/src/components/ContextDropdown/index.tsx +150 -0
- package/src/components/Dialog/index.tsx +123 -0
- package/src/components/DragNDrop/DragNDropArea.tsx +30 -0
- package/src/components/DragNDrop/DragOverlay.tsx +4 -0
- package/src/components/DragNDrop/Draggable.tsx +97 -0
- package/src/components/DragNDrop/Droppable.tsx +51 -0
- package/src/components/Dropdown/index.tsx +201 -0
- package/src/components/ExternalPill/index.tsx +58 -0
- package/src/components/Facepile/index.tsx +309 -0
- package/src/components/GradientCircle/gradientCircle.css +34 -0
- package/src/components/GradientCircle/index.tsx +143 -0
- package/src/components/Grid/index.tsx +150 -0
- package/src/components/Heading/index.tsx +54 -0
- package/src/components/HighlightedText/index.tsx +152 -0
- package/src/components/Icon/customIcons/createCustomLucideIcon.ts +25 -0
- package/src/components/Icon/customIcons/gems.ts +26 -0
- package/{dist/go-CiWl_aXI.mjs → src/components/Icon/customIcons/go.ts} +21 -19
- package/src/components/Icon/customIcons/index.ts +11 -0
- package/{dist/maven-DhmnGXoB.mjs → src/components/Icon/customIcons/maven.ts} +17 -15
- package/src/components/Icon/customIcons/npm.ts +19 -0
- package/{dist/nuget-5a2icRS2.mjs → src/components/Icon/customIcons/nuget.ts} +17 -15
- package/src/components/Icon/customIcons/packagist.ts +124 -0
- package/{dist/pypi-DsuRYjdK.mjs → src/components/Icon/customIcons/pypi.ts} +16 -14
- package/src/components/Icon/index.tsx +83 -0
- package/src/components/Icon/isIconName.ts +10 -0
- package/src/components/Icon/names.ts +14 -0
- package/src/components/IconButton/index.tsx +51 -0
- package/src/components/Input/index.tsx +98 -0
- package/src/components/KeyHint/index.tsx +118 -0
- package/src/components/LanguageIndicator/index.tsx +68 -0
- package/src/components/Link/index.tsx +153 -0
- package/src/components/LoggedInUserMenu/index.tsx +116 -0
- package/src/components/Logo/Animated.tsx +191 -0
- package/src/components/Logo/index.tsx +17 -0
- package/src/components/Logo/speakeasy-logo.riv +0 -0
- package/src/components/Logo/svgs/index.tsx +126 -0
- package/src/components/Modal/index.tsx +104 -0
- package/src/components/PageHeader/index.tsx +227 -0
- package/src/components/PageHeader/styles.module.css +27 -0
- package/src/components/Popover/index.tsx +35 -0
- package/src/components/PromptInput/index.tsx +372 -0
- package/src/components/PullRequestLink/index.tsx +64 -0
- package/src/components/ResizablePanel/index.tsx +119 -0
- package/src/components/Score/index.module.css +32 -0
- package/src/components/Score/index.tsx +268 -0
- package/src/components/ScrollArea/index.tsx +48 -0
- package/src/components/SegmentedButton/index.module.css +19 -0
- package/src/components/SegmentedButton/index.tsx +101 -0
- package/src/components/Select/index.tsx +159 -0
- package/src/components/Separator/index.tsx +23 -0
- package/src/components/Skeleton/index.tsx +61 -0
- package/src/components/Skeleton/skeleton.css +52 -0
- package/src/components/Stack/index.tsx +137 -0
- package/src/components/Subnav/index.tsx +315 -0
- package/src/components/Switch/index.tsx +29 -0
- package/src/components/Table/context/context.tsx +19 -0
- package/src/components/Table/context/tableProvider.tsx +39 -0
- package/src/components/Table/index.tsx +707 -0
- package/src/components/Table/styles.module.css +25 -0
- package/src/components/Tabs/index.tsx +87 -0
- package/src/components/TargetLanguageIcon/index.tsx +84 -0
- package/src/components/Text/index.tsx +59 -0
- package/src/components/ThemeSwitcher/index.tsx +118 -0
- package/src/components/Timeline/index.tsx +290 -0
- package/src/components/Tooltip/index.tsx +41 -0
- package/src/components/UserAvatar/index.tsx +87 -0
- package/src/components/UserAvatar/sizeMap.ts +12 -0
- package/src/components/Wizard/index.tsx +208 -0
- package/src/components/Wizard/types.ts +17 -0
- package/src/components/WorkspaceSelector/CreateOrg.tsx +95 -0
- package/src/components/WorkspaceSelector/CreateWorkspace.tsx +196 -0
- package/src/components/WorkspaceSelector/OrgList.tsx +115 -0
- package/src/components/WorkspaceSelector/OrgSelector.tsx +207 -0
- package/src/components/WorkspaceSelector/RecentWorkspaces.tsx +83 -0
- package/src/components/WorkspaceSelector/ScrollingList.tsx +84 -0
- package/src/components/WorkspaceSelector/SearchBox.tsx +40 -0
- package/src/components/WorkspaceSelector/WorkspaceItem.tsx +37 -0
- package/src/components/WorkspaceSelector/WorkspaceList.tsx +107 -0
- package/src/components/WorkspaceSelector/index.tsx +400 -0
- package/src/components/WorkspaceSelector/styles.css +74 -0
- package/src/components/__beta__/CLIWizard/index.tsx +357 -0
- package/src/components/__beta__/CLIWizard/terminal-command.tsx +108 -0
- package/src/components/__beta__/CLIWizard/terminal.tsx +83 -0
- package/src/components/__beta__/README.md +3 -0
- package/src/components/index.mdx +38 -0
- package/src/context/ConfigContext.tsx +43 -0
- package/src/context/ModalContext.tsx +118 -0
- package/src/context/theme.ts +1 -0
- package/src/hooks/useAppLayout.ts +10 -0
- package/src/hooks/useConfig.ts +10 -0
- package/src/hooks/useIsMounted.ts +13 -0
- package/src/hooks/useModal.tsx +10 -0
- package/src/hooks/useTailwindBreakpoint.ts +47 -0
- package/src/hooks/useTheme.ts +13 -0
- package/src/index.ts +234 -0
- package/src/lib/assert.ts +9 -0
- package/src/lib/codeUtils.ts +177 -0
- package/src/lib/debounce.ts +9 -0
- package/src/lib/responsiveMappers.ts +69 -0
- package/src/lib/responsiveUtils.ts +23 -0
- package/src/lib/storybookUtils.tsx +26 -0
- package/src/lib/typeUtils.ts +109 -0
- package/src/lib/utils.ts +85 -0
- package/src/styles/codeSyntax.css +59 -0
- package/src/styles/globals.css +51 -0
- package/src/types.ts +200 -0
- package/src/utilities.css +347 -6
- package/src/vite-env.d.ts +6 -0
- package/types/utilities.d.ts +43 -1
- package/dist/components/AIChat/AIChatContainer.d.ts +0 -25
- package/dist/components/AIChat/AIChatMessage.d.ts +0 -19
- package/dist/components/AIChat/AIChatMessageComposer.d.ts +0 -22
- package/dist/components/AIChat/AIChatMessageList.d.ts +0 -6
- package/dist/components/AIChat/AIChatModelSelector.d.ts +0 -14
- package/dist/components/AIChat/componentsTypes.d.ts +0 -11
- package/dist/components/AIChat/context.d.ts +0 -3
- package/dist/components/AIChat/index.d.ts +0 -12
- package/dist/components/AIChat/parts/AIChatMessageFilePart.d.ts +0 -7
- package/dist/components/AIChat/parts/AIChatMessageReasoningPart.d.ts +0 -5
- package/dist/components/AIChat/parts/AIChatMessageSourcePart.d.ts +0 -9
- package/dist/components/AIChat/parts/AIChatMessageTextPart.d.ts +0 -5
- package/dist/components/AIChat/parts/AIChatMessageToolInvocationPart.d.ts +0 -6
- package/dist/components/AIChat/parts/AIChatMessageToolPart.d.ts +0 -33
- package/dist/components/AIChat/parts/AIChatMessageToolResultPart.d.ts +0 -5
- package/dist/components/AIChat/toolCallApproval.d.ts +0 -15
- package/dist/components/AIChat/types.d.ts +0 -78
- package/dist/components/ActionBar/index.d.ts +0 -36
- package/dist/components/Alert/index.d.ts +0 -18
- package/dist/components/Alert/types.d.ts +0 -4
- package/dist/components/Badge/index.d.ts +0 -10
- package/dist/components/Button/index.d.ts +0 -11
- package/dist/components/Card/index.d.ts +0 -47
- package/dist/components/CodeEditorLayout/index.d.ts +0 -101
- package/dist/components/CodePlayground/index.d.ts +0 -108
- package/dist/components/CodePlayground/lineNumbers.d.ts +0 -2
- package/dist/components/CodePlayground/tokenTransitions.d.ts +0 -2
- package/dist/components/CodePlayground/wordWrap.d.ts +0 -2
- package/dist/components/CodeSnippet/index.d.ts +0 -50
- package/dist/components/Combobox/index.d.ts +0 -35
- package/dist/components/Command/index.d.ts +0 -80
- package/dist/components/Container/index.d.ts +0 -9
- package/dist/components/ContextDropdown/index.d.ts +0 -7
- package/dist/components/ContextDropdown/provider.d.ts +0 -22
- package/dist/components/ContextDropdown/useModal.d.ts +0 -11
- package/dist/components/Dialog/index.d.ts +0 -19
- package/dist/components/DragNDrop/DragNDropArea.d.ts +0 -8
- package/dist/components/DragNDrop/DragOverlay.d.ts +0 -1
- package/dist/components/DragNDrop/Draggable.d.ts +0 -29
- package/dist/components/DragNDrop/Droppable.d.ts +0 -28
- package/dist/components/Dropdown/index.d.ts +0 -27
- package/dist/components/ExternalPill/index.d.ts +0 -12
- package/dist/components/Facepile/index.d.ts +0 -16
- package/dist/components/GradientCircle/index.d.ts +0 -10
- package/dist/components/Grid/index.d.ts +0 -80
- package/dist/components/Heading/index.d.ts +0 -12
- package/dist/components/HighlightedText/index.d.ts +0 -19
- package/dist/components/Icon/customIcons/createCustomLucideIcon.d.ts +0 -3
- package/dist/components/Icon/customIcons/gems.d.ts +0 -2
- package/dist/components/Icon/customIcons/go.d.ts +0 -2
- package/dist/components/Icon/customIcons/index.d.ts +0 -10
- package/dist/components/Icon/customIcons/maven.d.ts +0 -2
- package/dist/components/Icon/customIcons/npm.d.ts +0 -2
- package/dist/components/Icon/customIcons/nuget.d.ts +0 -2
- package/dist/components/Icon/customIcons/packagist.d.ts +0 -2
- package/dist/components/Icon/customIcons/pypi.d.ts +0 -2
- package/dist/components/Icon/index.d.ts +0 -10
- package/dist/components/Icon/isIconName.d.ts +0 -2
- package/dist/components/Icon/names.d.ts +0 -6
- package/dist/components/Input/index.d.ts +0 -8
- package/dist/components/KeyHint/index.d.ts +0 -16
- package/dist/components/LanguageIndicator/index.d.ts +0 -7
- package/dist/components/Link/index.d.ts +0 -19
- package/dist/components/LoggedInUserMenu/index.d.ts +0 -17
- package/dist/components/Logo/Animated.d.ts +0 -7
- package/dist/components/Logo/index.d.ts +0 -7
- package/dist/components/Logo/svgs/index.d.ts +0 -6
- package/dist/components/Navbar/Slim.d.ts +0 -33
- package/dist/components/Navbar/index.d.ts +0 -15
- package/dist/components/PageHeader/index.d.ts +0 -45
- package/dist/components/Popover/index.d.ts +0 -8
- package/dist/components/PromptInput/index.d.ts +0 -55
- package/dist/components/PullRequestLink/index.d.ts +0 -10
- package/dist/components/ResizablePanel/index.d.ts +0 -26
- package/dist/components/Score/index.d.ts +0 -37
- package/dist/components/ScrollArea/index.d.ts +0 -5
- package/dist/components/Select/index.d.ts +0 -13
- package/dist/components/Separator/index.d.ts +0 -6
- package/dist/components/Skeleton/index.d.ts +0 -27
- package/dist/components/Stack/index.d.ts +0 -33
- package/dist/components/Subnav/index.d.ts +0 -12
- package/dist/components/Switch/index.d.ts +0 -4
- package/dist/components/Table/context/context.d.ts +0 -8
- package/dist/components/Table/context/tableProvider.d.ts +0 -6
- package/dist/components/Table/index.d.ts +0 -94
- package/dist/components/Tabs/index.d.ts +0 -21
- package/dist/components/TargetLanguageIcon/index.d.ts +0 -7
- package/dist/components/Text/index.d.ts +0 -19
- package/dist/components/ThemeSwitcher/index.d.ts +0 -5
- package/dist/components/Tooltip/index.d.ts +0 -8
- package/dist/components/UserAvatar/index.d.ts +0 -9
- package/dist/components/UserAvatar/sizeMap.d.ts +0 -3
- package/dist/components/Wizard/index.d.ts +0 -19
- package/dist/components/Wizard/types.d.ts +0 -15
- package/dist/components/WorkspaceSelector/CreateOrg.d.ts +0 -6
- package/dist/components/WorkspaceSelector/CreateWorkspace.d.ts +0 -17
- package/dist/components/WorkspaceSelector/OrgList.d.ts +0 -11
- package/dist/components/WorkspaceSelector/OrgSelector.d.ts +0 -13
- package/dist/components/WorkspaceSelector/RecentWorkspaces.d.ts +0 -11
- package/dist/components/WorkspaceSelector/ScrollingList.d.ts +0 -21
- package/dist/components/WorkspaceSelector/SearchBox.d.ts +0 -9
- package/dist/components/WorkspaceSelector/WorkspaceItem.d.ts +0 -9
- package/dist/components/WorkspaceSelector/WorkspaceList.d.ts +0 -10
- package/dist/components/WorkspaceSelector/index.d.ts +0 -34
- package/dist/components/__beta__/CLIWizard/index.d.ts +0 -21
- package/dist/components/__beta__/CLIWizard/terminal-command.d.ts +0 -19
- package/dist/components/__beta__/CLIWizard/terminal.d.ts +0 -26
- package/dist/context/ConfigContext.d.ts +0 -18
- package/dist/context/theme.d.ts +0 -1
- package/dist/createCustomLucideIcon-YlrRX5h9.mjs +0 -19
- package/dist/createCustomLucideIcon-YlrRX5h9.mjs.map +0 -1
- package/dist/gems-BcsO9cXq.mjs +0 -24
- package/dist/gems-BcsO9cXq.mjs.map +0 -1
- package/dist/github-kgjMtfE7.mjs +0 -11
- package/dist/github-kgjMtfE7.mjs.map +0 -1
- package/dist/go-CiWl_aXI.mjs.map +0 -1
- package/dist/hooks/useConfig.d.ts +0 -2
- package/dist/hooks/useIsMounted.d.ts +0 -1
- package/dist/hooks/useTailwindBreakpoint.d.ts +0 -3
- package/dist/hooks/useTheme.d.ts +0 -6
- package/dist/index-COXZ9O-g.mjs +0 -50882
- package/dist/index-COXZ9O-g.mjs.map +0 -1
- package/dist/index.d.ts +0 -73
- package/dist/lib/assert.d.ts +0 -2
- package/dist/lib/codeUtils.d.ts +0 -35
- package/dist/lib/debounce.d.ts +0 -1
- package/dist/lib/responsiveMappers.d.ts +0 -10
- package/dist/lib/responsiveUtils.d.ts +0 -3
- package/dist/lib/storybookUtils.d.ts +0 -5
- package/dist/lib/typeUtils.d.ts +0 -24
- package/dist/lib/utils.d.ts +0 -23
- package/dist/lucide-icons-BDw0imyx.mjs +0 -28054
- package/dist/lucide-icons-BDw0imyx.mjs.map +0 -1
- package/dist/maven-DhmnGXoB.mjs.map +0 -1
- package/dist/maven-W_nkSDNW.mjs +0 -107
- package/dist/maven-W_nkSDNW.mjs.map +0 -1
- package/dist/moonshine.es.js +0 -114
- package/dist/moonshine.es.js.map +0 -1
- package/dist/npm-BWTcVvFH.mjs +0 -11
- package/dist/npm-BWTcVvFH.mjs.map +0 -1
- package/dist/npm-CvQ4GKW4.mjs +0 -17
- package/dist/npm-CvQ4GKW4.mjs.map +0 -1
- package/dist/nuget-5a2icRS2.mjs.map +0 -1
- package/dist/nuget-CV5HU1JR.mjs +0 -11
- package/dist/nuget-CV5HU1JR.mjs.map +0 -1
- package/dist/packagist-CET6q9hi.mjs +0 -118
- package/dist/packagist-CET6q9hi.mjs.map +0 -1
- package/dist/packagist-D01fn9N_.mjs +0 -11
- package/dist/packagist-D01fn9N_.mjs.map +0 -1
- package/dist/pypi-DLh6kIJe.mjs +0 -11
- package/dist/pypi-DLh6kIJe.mjs.map +0 -1
- package/dist/pypi-DsuRYjdK.mjs.map +0 -1
- package/dist/rubygems-DeiNjcDV.mjs +0 -11
- package/dist/rubygems-DeiNjcDV.mjs.map +0 -1
- package/dist/speakeasy-logo-ByBTXLWb.mjs +0 -5
- package/dist/speakeasy-logo-ByBTXLWb.mjs.map +0 -1
- package/dist/style.css +0 -1
- package/dist/terraform-C4aktQ0o.mjs +0 -11
- package/dist/terraform-C4aktQ0o.mjs.map +0 -1
- package/dist/types.d.ts +0 -80
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react'
|
|
4
|
+
import { motion, AnimatePresence } from 'motion/react'
|
|
5
|
+
import { Icon } from '../Icon'
|
|
6
|
+
import { assert } from '../../lib/typeUtils'
|
|
7
|
+
import { Heading } from '../Heading'
|
|
8
|
+
import React from 'react'
|
|
9
|
+
import { useModal } from '../../hooks/useModal'
|
|
10
|
+
import { Screen } from '../../context/ModalContext'
|
|
11
|
+
|
|
12
|
+
const MotionHeading = motion.create(Heading)
|
|
13
|
+
|
|
14
|
+
const animationDuration = 0.15
|
|
15
|
+
|
|
16
|
+
interface ContextDropdownProps {
|
|
17
|
+
renderTitle?: (screen: Screen, index: number) => React.ReactNode
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function ContextDropdown({ renderTitle }: ContextDropdownProps) {
|
|
21
|
+
const {
|
|
22
|
+
screens,
|
|
23
|
+
currentIndex,
|
|
24
|
+
isOpen,
|
|
25
|
+
close,
|
|
26
|
+
popScreen,
|
|
27
|
+
navigationDirection,
|
|
28
|
+
} = useModal()
|
|
29
|
+
|
|
30
|
+
// Animation variants for title and content
|
|
31
|
+
const slideVariants = {
|
|
32
|
+
enter: (isForward: boolean) => ({
|
|
33
|
+
x: isForward ? '100%' : '-100%',
|
|
34
|
+
opacity: 0,
|
|
35
|
+
width: '100%',
|
|
36
|
+
}),
|
|
37
|
+
center: {
|
|
38
|
+
x: 0,
|
|
39
|
+
opacity: 1,
|
|
40
|
+
width: '100%',
|
|
41
|
+
},
|
|
42
|
+
exit: (isForward: boolean) => ({
|
|
43
|
+
x: isForward ? '-100%' : '100%',
|
|
44
|
+
opacity: 0,
|
|
45
|
+
width: '100%',
|
|
46
|
+
}),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Handle escape key to close modal
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const handleEscape = (e: KeyboardEvent) => {
|
|
52
|
+
if (e.key === 'Escape') {
|
|
53
|
+
close()
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (isOpen) {
|
|
58
|
+
document.addEventListener('keydown', handleEscape)
|
|
59
|
+
// Prevent body scrolling when modal is open
|
|
60
|
+
document.body.style.overflow = 'hidden'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return () => {
|
|
64
|
+
document.removeEventListener('keydown', handleEscape)
|
|
65
|
+
document.body.style.overflow = 'auto'
|
|
66
|
+
}
|
|
67
|
+
}, [isOpen, close])
|
|
68
|
+
|
|
69
|
+
if (!isOpen) return null
|
|
70
|
+
|
|
71
|
+
const currentScreen = screens[currentIndex]
|
|
72
|
+
assert(currentScreen, 'No current screen')
|
|
73
|
+
const isForward = navigationDirection === 'forward'
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<AnimatePresence>
|
|
77
|
+
{isOpen && (
|
|
78
|
+
<motion.div
|
|
79
|
+
className="fixed inset-0 z-50 flex flex-col bg-transparent"
|
|
80
|
+
initial={{ opacity: 0 }}
|
|
81
|
+
animate={{ opacity: 1 }}
|
|
82
|
+
exit={{ opacity: 0 }}
|
|
83
|
+
transition={{ duration: animationDuration }}
|
|
84
|
+
>
|
|
85
|
+
<div className="flex h-16 items-center justify-between border-b px-4">
|
|
86
|
+
<div className="flex items-center gap-2">
|
|
87
|
+
{currentIndex > 0 && (
|
|
88
|
+
<button
|
|
89
|
+
onClick={popScreen}
|
|
90
|
+
className="hover:bg-muted mr-2 rounded-full border p-2 disabled:opacity-50 disabled:hover:bg-transparent"
|
|
91
|
+
aria-label="Go back"
|
|
92
|
+
>
|
|
93
|
+
<Icon name="chevron-left" className="size-4" />
|
|
94
|
+
</button>
|
|
95
|
+
)}
|
|
96
|
+
|
|
97
|
+
{/* Animated title */}
|
|
98
|
+
<div className="relative h-7 w-fit min-w-xs overflow-x-hidden">
|
|
99
|
+
<AnimatePresence initial={false} mode="sync" custom={isForward}>
|
|
100
|
+
<MotionHeading
|
|
101
|
+
key={`title-${currentIndex}`}
|
|
102
|
+
className="text-md absolute !leading-6 font-medium"
|
|
103
|
+
custom={isForward}
|
|
104
|
+
variants={slideVariants}
|
|
105
|
+
initial="enter"
|
|
106
|
+
animate="center"
|
|
107
|
+
exit="exit"
|
|
108
|
+
variant="sm"
|
|
109
|
+
transition={{ type: 'tween', duration: animationDuration }}
|
|
110
|
+
>
|
|
111
|
+
{renderTitle
|
|
112
|
+
? renderTitle(currentScreen, currentIndex)
|
|
113
|
+
: currentScreen.title}
|
|
114
|
+
</MotionHeading>
|
|
115
|
+
</AnimatePresence>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
{/* Static right side with close button */}
|
|
120
|
+
<button
|
|
121
|
+
onClick={close}
|
|
122
|
+
className="hover:bg-muted rounded-full border p-2"
|
|
123
|
+
aria-label="Close modal"
|
|
124
|
+
>
|
|
125
|
+
<Icon name="x" className="size-4" />
|
|
126
|
+
</button>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
{/* Modal Content with Animation */}
|
|
130
|
+
<div className="relative flex-1 overflow-hidden">
|
|
131
|
+
<AnimatePresence initial={false} mode="wait" custom={isForward}>
|
|
132
|
+
<motion.div
|
|
133
|
+
key={currentIndex}
|
|
134
|
+
className="absolute inset-0 overflow-auto"
|
|
135
|
+
custom={isForward}
|
|
136
|
+
variants={slideVariants}
|
|
137
|
+
initial="enter"
|
|
138
|
+
animate="center"
|
|
139
|
+
exit="exit"
|
|
140
|
+
transition={{ type: 'tween', duration: animationDuration }}
|
|
141
|
+
>
|
|
142
|
+
{currentScreen.component}
|
|
143
|
+
</motion.div>
|
|
144
|
+
</AnimatePresence>
|
|
145
|
+
</div>
|
|
146
|
+
</motion.div>
|
|
147
|
+
)}
|
|
148
|
+
</AnimatePresence>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog'
|
|
5
|
+
import { X } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
import { cn } from '../../lib/utils'
|
|
8
|
+
|
|
9
|
+
const DialogTrigger = DialogPrimitive.Trigger
|
|
10
|
+
|
|
11
|
+
const DialogPortal = DialogPrimitive.Portal
|
|
12
|
+
|
|
13
|
+
const DialogClose = DialogPrimitive.Close
|
|
14
|
+
|
|
15
|
+
const DialogOverlay = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
17
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
18
|
+
>(({ className, ...props }, ref) => (
|
|
19
|
+
<DialogPrimitive.Overlay
|
|
20
|
+
ref={ref}
|
|
21
|
+
className={cn(
|
|
22
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
))
|
|
28
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
|
29
|
+
|
|
30
|
+
const DialogContent = React.forwardRef<
|
|
31
|
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
32
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
|
|
33
|
+
closeable?: boolean
|
|
34
|
+
}
|
|
35
|
+
>(({ className, children, closeable = true, ...props }, ref) => (
|
|
36
|
+
<DialogPortal>
|
|
37
|
+
<DialogOverlay />
|
|
38
|
+
<DialogPrimitive.Content
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={cn(
|
|
41
|
+
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
{closeable && (
|
|
48
|
+
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none">
|
|
49
|
+
<X className="h-4 w-4" />
|
|
50
|
+
<span className="sr-only">Close</span>
|
|
51
|
+
</DialogPrimitive.Close>
|
|
52
|
+
)}
|
|
53
|
+
</DialogPrimitive.Content>
|
|
54
|
+
</DialogPortal>
|
|
55
|
+
))
|
|
56
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName
|
|
57
|
+
|
|
58
|
+
const DialogHeader = ({
|
|
59
|
+
className,
|
|
60
|
+
...props
|
|
61
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
62
|
+
<div
|
|
63
|
+
className={cn(
|
|
64
|
+
'flex flex-col space-y-1.5 text-center sm:text-left',
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
DialogHeader.displayName = 'DialogHeader'
|
|
71
|
+
|
|
72
|
+
const DialogFooter = ({
|
|
73
|
+
className,
|
|
74
|
+
...props
|
|
75
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
76
|
+
<div
|
|
77
|
+
className={cn(
|
|
78
|
+
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
|
79
|
+
className
|
|
80
|
+
)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
)
|
|
84
|
+
DialogFooter.displayName = 'DialogFooter'
|
|
85
|
+
|
|
86
|
+
const DialogTitle = React.forwardRef<
|
|
87
|
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
88
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
89
|
+
>(({ className, ...props }, ref) => (
|
|
90
|
+
<DialogPrimitive.Title
|
|
91
|
+
ref={ref}
|
|
92
|
+
className={cn(
|
|
93
|
+
'text-lg leading-none font-semibold tracking-tight',
|
|
94
|
+
className
|
|
95
|
+
)}
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
))
|
|
99
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
|
100
|
+
|
|
101
|
+
const DialogDescription = React.forwardRef<
|
|
102
|
+
React.ElementRef<typeof DialogPrimitive.Description>,
|
|
103
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
104
|
+
>(({ className, ...props }, ref) => (
|
|
105
|
+
<DialogPrimitive.Description
|
|
106
|
+
ref={ref}
|
|
107
|
+
className={cn('text-muted-foreground text-sm', className)}
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
))
|
|
111
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
|
112
|
+
|
|
113
|
+
export const Dialog = Object.assign(DialogPrimitive.Root, {
|
|
114
|
+
Portal: DialogPortal,
|
|
115
|
+
Overlay: DialogOverlay,
|
|
116
|
+
Close: DialogClose,
|
|
117
|
+
Trigger: DialogTrigger,
|
|
118
|
+
Content: DialogContent,
|
|
119
|
+
Header: DialogHeader,
|
|
120
|
+
Footer: DialogFooter,
|
|
121
|
+
Title: DialogTitle,
|
|
122
|
+
Description: DialogDescription,
|
|
123
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CollisionDetection, DndContext, Modifier } from '@dnd-kit/core'
|
|
2
|
+
import { restrictToWindowEdges } from '@dnd-kit/modifiers'
|
|
3
|
+
|
|
4
|
+
export interface DragNDropAreaProps {
|
|
5
|
+
children: React.ReactNode
|
|
6
|
+
|
|
7
|
+
modifiers?: Modifier[]
|
|
8
|
+
|
|
9
|
+
className?: string
|
|
10
|
+
|
|
11
|
+
collisionDetectionAlgo?: CollisionDetection
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const defaultModifiers: Modifier[] = [restrictToWindowEdges]
|
|
15
|
+
|
|
16
|
+
export function DragNDropArea({
|
|
17
|
+
children,
|
|
18
|
+
modifiers = defaultModifiers,
|
|
19
|
+
className,
|
|
20
|
+
collisionDetectionAlgo,
|
|
21
|
+
}: DragNDropAreaProps) {
|
|
22
|
+
return (
|
|
23
|
+
<DndContext
|
|
24
|
+
collisionDetection={collisionDetectionAlgo}
|
|
25
|
+
modifiers={modifiers}
|
|
26
|
+
>
|
|
27
|
+
<div className={className}>{children}</div>
|
|
28
|
+
</DndContext>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Active,
|
|
3
|
+
DndMonitorListener,
|
|
4
|
+
useDndMonitor,
|
|
5
|
+
useDraggable,
|
|
6
|
+
Over,
|
|
7
|
+
Data,
|
|
8
|
+
UniqueIdentifier,
|
|
9
|
+
} from '@dnd-kit/core'
|
|
10
|
+
import type { ClientRect } from '@dnd-kit/core/dist/types/rect'
|
|
11
|
+
import { CSS } from '@dnd-kit/utilities'
|
|
12
|
+
import { MutableRefObject } from 'react'
|
|
13
|
+
|
|
14
|
+
export interface DraggableChildrenProps {
|
|
15
|
+
over: Over | null
|
|
16
|
+
active: Active | null
|
|
17
|
+
activeNodeRect: ClientRect | null
|
|
18
|
+
isDragging: boolean
|
|
19
|
+
node: MutableRefObject<HTMLElement | null> | null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DraggableProps<TData> extends DndMonitorListener {
|
|
23
|
+
/**
|
|
24
|
+
* The children to render.
|
|
25
|
+
*
|
|
26
|
+
* If a function is provided, it will be called with the current state of the draggable.
|
|
27
|
+
*/
|
|
28
|
+
children:
|
|
29
|
+
| React.ReactNode
|
|
30
|
+
| ((props: DraggableChildrenProps) => React.ReactNode)
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The unique identifier for the draggable.
|
|
34
|
+
*/
|
|
35
|
+
id: UniqueIdentifier
|
|
36
|
+
|
|
37
|
+
className?: string
|
|
38
|
+
|
|
39
|
+
disabled?: boolean
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The data to pass to the draggable of generic type TData.
|
|
43
|
+
*/
|
|
44
|
+
data?: TData
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function Draggable<TData extends Data>({
|
|
48
|
+
children,
|
|
49
|
+
id,
|
|
50
|
+
onDragEnd,
|
|
51
|
+
onDragStart,
|
|
52
|
+
onDragCancel,
|
|
53
|
+
onDragOver,
|
|
54
|
+
className,
|
|
55
|
+
disabled,
|
|
56
|
+
data,
|
|
57
|
+
}: DraggableProps<TData>) {
|
|
58
|
+
const {
|
|
59
|
+
attributes,
|
|
60
|
+
listeners,
|
|
61
|
+
setNodeRef,
|
|
62
|
+
over,
|
|
63
|
+
transform,
|
|
64
|
+
active,
|
|
65
|
+
isDragging,
|
|
66
|
+
activeNodeRect,
|
|
67
|
+
node,
|
|
68
|
+
} = useDraggable({
|
|
69
|
+
id,
|
|
70
|
+
data,
|
|
71
|
+
disabled,
|
|
72
|
+
})
|
|
73
|
+
useDndMonitor({
|
|
74
|
+
onDragEnd,
|
|
75
|
+
onDragStart,
|
|
76
|
+
onDragCancel,
|
|
77
|
+
onDragOver,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const style: React.CSSProperties = {
|
|
81
|
+
transform: CSS.Translate.toString(transform),
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div
|
|
86
|
+
ref={setNodeRef}
|
|
87
|
+
style={style}
|
|
88
|
+
{...attributes}
|
|
89
|
+
{...listeners}
|
|
90
|
+
className={className}
|
|
91
|
+
>
|
|
92
|
+
{typeof children === 'function'
|
|
93
|
+
? children({ over, active, activeNodeRect, isDragging, node })
|
|
94
|
+
: children}
|
|
95
|
+
</div>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Over, UniqueIdentifier, useDroppable } from '@dnd-kit/core'
|
|
2
|
+
import type { ClientRect } from '@dnd-kit/core/dist/types/rect'
|
|
3
|
+
import type { MutableRefObject, ReactNode } from 'react'
|
|
4
|
+
|
|
5
|
+
interface DroppableData {
|
|
6
|
+
isOver: boolean
|
|
7
|
+
over: Over | null
|
|
8
|
+
rect: MutableRefObject<ClientRect | null>
|
|
9
|
+
node: MutableRefObject<HTMLElement | null>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DroppableProps<TData extends Record<string, unknown>> {
|
|
13
|
+
/**
|
|
14
|
+
* A function that returns a React node or a React node.
|
|
15
|
+
* If a function is provided, it will be called with the droppable data.
|
|
16
|
+
*/
|
|
17
|
+
children: ReactNode | ((props: DroppableData) => ReactNode)
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The unique identifier for the droppable container.
|
|
21
|
+
*/
|
|
22
|
+
id: UniqueIdentifier
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The data to pass to the droppable container.
|
|
26
|
+
* Will be returned in any dragOver events for draggables that are over this droppable.
|
|
27
|
+
*/
|
|
28
|
+
data?: TData
|
|
29
|
+
|
|
30
|
+
className?: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function Droppable<TData extends Record<string, unknown>>({
|
|
34
|
+
children,
|
|
35
|
+
id,
|
|
36
|
+
data,
|
|
37
|
+
className,
|
|
38
|
+
}: DroppableProps<TData>) {
|
|
39
|
+
const { setNodeRef, isOver, over, rect, node } = useDroppable({
|
|
40
|
+
id,
|
|
41
|
+
data,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div ref={setNodeRef} className={className}>
|
|
46
|
+
{typeof children === 'function'
|
|
47
|
+
? children({ isOver, over, rect, node })
|
|
48
|
+
: children}
|
|
49
|
+
</div>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
|
|
5
|
+
import { Check, ChevronRight, Circle } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
import { cn } from '../../lib/utils'
|
|
8
|
+
|
|
9
|
+
const DropdownMenu = DropdownMenuPrimitive.Root
|
|
10
|
+
|
|
11
|
+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
|
12
|
+
|
|
13
|
+
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
|
14
|
+
|
|
15
|
+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
|
16
|
+
|
|
17
|
+
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
|
18
|
+
|
|
19
|
+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
|
20
|
+
|
|
21
|
+
const DropdownMenuSubTrigger = React.forwardRef<
|
|
22
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
|
23
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
24
|
+
inset?: boolean
|
|
25
|
+
}
|
|
26
|
+
>(({ className, inset, children, ...props }, ref) => (
|
|
27
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cn(
|
|
30
|
+
'focus:bg-accent data-[state=open]:bg-accent flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
|
31
|
+
inset && 'pl-8',
|
|
32
|
+
className
|
|
33
|
+
)}
|
|
34
|
+
{...props}
|
|
35
|
+
>
|
|
36
|
+
{children}
|
|
37
|
+
<ChevronRight className="ml-auto" />
|
|
38
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
39
|
+
))
|
|
40
|
+
DropdownMenuSubTrigger.displayName =
|
|
41
|
+
DropdownMenuPrimitive.SubTrigger.displayName
|
|
42
|
+
|
|
43
|
+
const DropdownMenuSubContent = React.forwardRef<
|
|
44
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
|
45
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
|
46
|
+
>(({ className, ...props }, ref) => (
|
|
47
|
+
<DropdownMenuPrimitive.SubContent
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={cn(
|
|
50
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
))
|
|
56
|
+
DropdownMenuSubContent.displayName =
|
|
57
|
+
DropdownMenuPrimitive.SubContent.displayName
|
|
58
|
+
|
|
59
|
+
const DropdownMenuContent = React.forwardRef<
|
|
60
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
61
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
62
|
+
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
63
|
+
<DropdownMenuPrimitive.Portal>
|
|
64
|
+
<DropdownMenuPrimitive.Content
|
|
65
|
+
ref={ref}
|
|
66
|
+
sideOffset={sideOffset}
|
|
67
|
+
className={cn(
|
|
68
|
+
'bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md',
|
|
69
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
</DropdownMenuPrimitive.Portal>
|
|
75
|
+
))
|
|
76
|
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
|
77
|
+
|
|
78
|
+
const DropdownMenuItem = React.forwardRef<
|
|
79
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
80
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
81
|
+
inset?: boolean
|
|
82
|
+
}
|
|
83
|
+
>(({ className, inset, ...props }, ref) => (
|
|
84
|
+
<DropdownMenuPrimitive.Item
|
|
85
|
+
ref={ref}
|
|
86
|
+
className={cn(
|
|
87
|
+
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
|
|
88
|
+
inset && 'pl-8',
|
|
89
|
+
className
|
|
90
|
+
)}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
))
|
|
94
|
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
|
95
|
+
|
|
96
|
+
const DropdownMenuCheckboxItem = React.forwardRef<
|
|
97
|
+
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
|
98
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
|
99
|
+
>(({ className, children, checked, ...props }, ref) => (
|
|
100
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
101
|
+
ref={ref}
|
|
102
|
+
className={cn(
|
|
103
|
+
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
104
|
+
className
|
|
105
|
+
)}
|
|
106
|
+
checked={checked}
|
|
107
|
+
{...props}
|
|
108
|
+
>
|
|
109
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
110
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
111
|
+
<Check className="h-4 w-4" />
|
|
112
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
113
|
+
</span>
|
|
114
|
+
{children}
|
|
115
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
116
|
+
))
|
|
117
|
+
DropdownMenuCheckboxItem.displayName =
|
|
118
|
+
DropdownMenuPrimitive.CheckboxItem.displayName
|
|
119
|
+
|
|
120
|
+
const DropdownMenuRadioItem = React.forwardRef<
|
|
121
|
+
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
|
122
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
|
123
|
+
>(({ className, children, ...props }, ref) => (
|
|
124
|
+
<DropdownMenuPrimitive.RadioItem
|
|
125
|
+
ref={ref}
|
|
126
|
+
className={cn(
|
|
127
|
+
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
128
|
+
className
|
|
129
|
+
)}
|
|
130
|
+
{...props}
|
|
131
|
+
>
|
|
132
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
133
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
134
|
+
<Circle className="h-2 w-2 fill-current" />
|
|
135
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
136
|
+
</span>
|
|
137
|
+
{children}
|
|
138
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
139
|
+
))
|
|
140
|
+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
|
141
|
+
|
|
142
|
+
const DropdownMenuLabel = React.forwardRef<
|
|
143
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
144
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
145
|
+
inset?: boolean
|
|
146
|
+
}
|
|
147
|
+
>(({ className, inset, ...props }, ref) => (
|
|
148
|
+
<DropdownMenuPrimitive.Label
|
|
149
|
+
ref={ref}
|
|
150
|
+
className={cn(
|
|
151
|
+
'px-2 py-1.5 text-sm font-semibold',
|
|
152
|
+
inset && 'pl-8',
|
|
153
|
+
className
|
|
154
|
+
)}
|
|
155
|
+
{...props}
|
|
156
|
+
/>
|
|
157
|
+
))
|
|
158
|
+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
|
159
|
+
|
|
160
|
+
const DropdownMenuSeparator = React.forwardRef<
|
|
161
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
162
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
163
|
+
>(({ className, ...props }, ref) => (
|
|
164
|
+
<DropdownMenuPrimitive.Separator
|
|
165
|
+
ref={ref}
|
|
166
|
+
className={cn('bg-muted -mx-1 my-1 h-px', className)}
|
|
167
|
+
{...props}
|
|
168
|
+
/>
|
|
169
|
+
))
|
|
170
|
+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
|
171
|
+
|
|
172
|
+
const DropdownMenuShortcut = ({
|
|
173
|
+
className,
|
|
174
|
+
...props
|
|
175
|
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
176
|
+
return (
|
|
177
|
+
<span
|
|
178
|
+
className={cn('ml-auto text-xs tracking-widest opacity-60', className)}
|
|
179
|
+
{...props}
|
|
180
|
+
/>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'
|
|
184
|
+
|
|
185
|
+
export {
|
|
186
|
+
DropdownMenu,
|
|
187
|
+
DropdownMenuTrigger,
|
|
188
|
+
DropdownMenuContent,
|
|
189
|
+
DropdownMenuItem,
|
|
190
|
+
DropdownMenuCheckboxItem,
|
|
191
|
+
DropdownMenuRadioItem,
|
|
192
|
+
DropdownMenuLabel,
|
|
193
|
+
DropdownMenuSeparator,
|
|
194
|
+
DropdownMenuShortcut,
|
|
195
|
+
DropdownMenuGroup,
|
|
196
|
+
DropdownMenuPortal,
|
|
197
|
+
DropdownMenuSub,
|
|
198
|
+
DropdownMenuSubContent,
|
|
199
|
+
DropdownMenuSubTrigger,
|
|
200
|
+
DropdownMenuRadioGroup,
|
|
201
|
+
}
|