@hanzo/ui 3.6.5 → 3.7.22
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/blocks/components/cta-block.tsx +3 -3
- package/package.json +30 -22
- package/primitives/action-button.tsx +12 -11
- package/primitives/button.tsx +0 -7
- package/primitives/drawer.tsx +39 -19
- package/primitives/index.ts +3 -2
- package/primitives/link-element.tsx +16 -11
- package/style/drawer.css +163 -0
- package/tailwind/tailwind.config.hanzo-preset.js +0 -5
- package/tsconfig.json +1 -1
- package/types/image-def.ts +1 -2
- package/types/link-def.ts +3 -5
- package/util/index-client.ts +3 -0
- package/util/index.ts +6 -1
- package/util/step-animation.ts +90 -0
- package/util/two-way-map.ts +19 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
|
|
3
3
|
import type { LinkDef, ButtonDef} from '../../types'
|
|
4
|
-
import {
|
|
4
|
+
import { buttonVariants, ActionButton, LinkElement } from '../../primitives'
|
|
5
5
|
import type { CTABlock } from '../def'
|
|
6
|
-
import { cn, containsToken } from '../../util'
|
|
6
|
+
import { cn, containsToken, type VariantProps } from '../../util'
|
|
7
7
|
|
|
8
8
|
import type BlockComponentProps from './block-component-props'
|
|
9
9
|
|
|
10
10
|
const CtaBlockComponent: React.FC<BlockComponentProps & {
|
|
11
11
|
itemClasses?: string
|
|
12
|
-
itemSize?:
|
|
12
|
+
itemSize?: VariantProps<typeof buttonVariants>['size'],
|
|
13
13
|
renderLink?: (def: LinkDef, key: any) => JSX.Element
|
|
14
14
|
renderButton?: (def: ButtonDef, key: any) => JSX.Element
|
|
15
15
|
}> = ({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.22",
|
|
4
4
|
"description": "Library that contains shared UI primitives, support for a common design system, and other boilerplate support.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -31,9 +31,16 @@
|
|
|
31
31
|
"scripts": {
|
|
32
32
|
"lat": "npm show @hanzo/ui version",
|
|
33
33
|
"pub": "npm publish",
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
"tc": "tsc"
|
|
35
|
+
},
|
|
36
|
+
"exports": {
|
|
37
|
+
"./blocks": "./blocks/index.ts",
|
|
38
|
+
"./primitives": "./primitives/index.ts",
|
|
39
|
+
"./style/": "./style/*",
|
|
40
|
+
"./tailwind": "./tailwind/index.ts",
|
|
41
|
+
"./types": "./types/index.ts",
|
|
42
|
+
"./util": "./util/index.ts",
|
|
43
|
+
"./util-client": "./util/index-client.ts"
|
|
37
44
|
},
|
|
38
45
|
"dependencies": {
|
|
39
46
|
"@next/third-parties": "^14.1.0",
|
|
@@ -63,32 +70,33 @@
|
|
|
63
70
|
"class-variance-authority": "^0.7.0",
|
|
64
71
|
"clsx": "^2.1.0",
|
|
65
72
|
"cmdk": "^0.2.0",
|
|
66
|
-
"embla-carousel-react": "8.0.
|
|
73
|
+
"embla-carousel-react": "8.0.2",
|
|
67
74
|
"input-otp": "^1.0.1",
|
|
68
75
|
"lodash.castarray": "^4.4.0",
|
|
69
76
|
"lodash.isplainobject": "^4.0.6",
|
|
70
77
|
"lodash.merge": "^4.6.2",
|
|
71
|
-
"markdown-to-jsx": "^7.
|
|
72
|
-
"postcss-selector-parser": "^6.0.
|
|
73
|
-
"react-day-picker": "^8.
|
|
74
|
-
"react-intersection-observer": "^9.
|
|
75
|
-
"sonner": "^1.
|
|
76
|
-
"tailwind-merge": "^2.
|
|
78
|
+
"markdown-to-jsx": "^7.4.7",
|
|
79
|
+
"postcss-selector-parser": "^6.0.16",
|
|
80
|
+
"react-day-picker": "^8.10.1",
|
|
81
|
+
"react-intersection-observer": "^9.8.2",
|
|
82
|
+
"sonner": "^1.4.41",
|
|
83
|
+
"tailwind-merge": "^2.3.0",
|
|
77
84
|
"tailwindcss-animate": "^1.0.7",
|
|
78
85
|
"tailwindcss-interaction-media": "^0.1.0",
|
|
79
|
-
"
|
|
86
|
+
"@hanzo/react-drawer": "0.9.1"
|
|
80
87
|
},
|
|
81
88
|
"peerDependencies": {
|
|
82
89
|
"@hookform/resolvers": "^3.3.2",
|
|
83
|
-
"embla-carousel": "^8.0.
|
|
90
|
+
"embla-carousel": "^8.0.2",
|
|
84
91
|
"lucide-react": "^0.344.0",
|
|
92
|
+
"mobx": "^6.12.0",
|
|
85
93
|
"next": "14.1.3",
|
|
86
94
|
"next-themes": "^0.2.1",
|
|
87
|
-
"react": "^18.
|
|
88
|
-
"react-dom": "^18.
|
|
89
|
-
"react-hook-form": "^7.
|
|
95
|
+
"react": "^18.3.1",
|
|
96
|
+
"react-dom": "^18.3.1",
|
|
97
|
+
"react-hook-form": "^7.51.4",
|
|
90
98
|
"validator": "^13.11.0",
|
|
91
|
-
"zod": "3.
|
|
99
|
+
"zod": "3.23.8"
|
|
92
100
|
},
|
|
93
101
|
"devDependencies": {
|
|
94
102
|
"@mdx-js/loader": "^3.0.0",
|
|
@@ -96,11 +104,11 @@
|
|
|
96
104
|
"@types/facebook-pixel": "^0.0.30",
|
|
97
105
|
"@types/gtag.js": "^0.0.19",
|
|
98
106
|
"@types/lodash.merge": "^4.6.9",
|
|
99
|
-
"@types/mdx": "^2.0.
|
|
100
|
-
"@types/react": "^18.
|
|
101
|
-
"@types/react-dom": "^18.
|
|
102
|
-
"embla-carousel": "^8.0.
|
|
103
|
-
"tailwindcss": "^3.4.
|
|
107
|
+
"@types/mdx": "^2.0.13",
|
|
108
|
+
"@types/react": "^18.3.1",
|
|
109
|
+
"@types/react-dom": "^18.3.0",
|
|
110
|
+
"embla-carousel": "^8.0.2",
|
|
111
|
+
"tailwindcss": "^3.4.3",
|
|
104
112
|
"typescript": "5.3.3"
|
|
105
113
|
}
|
|
106
114
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import dynamic from 'next/dynamic'
|
|
3
3
|
|
|
4
|
-
import { cn } from '../util'
|
|
4
|
+
import { cn, type VariantProps } from '../util'
|
|
5
5
|
|
|
6
6
|
import type { ButtonDef, ButtonModalDef } from '../types'
|
|
7
|
-
import type {
|
|
7
|
+
import type { buttonVariants } from './button'
|
|
8
8
|
|
|
9
9
|
// The DVC must be rendered client-side since it accesses the DOM directly.
|
|
10
10
|
// There is no need for a loading UI since the dialog only opens
|
|
@@ -12,26 +12,27 @@ import type { ButtonSizes } from './button'
|
|
|
12
12
|
// https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading
|
|
13
13
|
const DynamicDVC = dynamic(() => (import('./dialog-video-controller')), {ssr: false})
|
|
14
14
|
|
|
15
|
-
const ActionButton: React.FC<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const ActionButton: React.FC<
|
|
16
|
+
VariantProps<typeof buttonVariants> &
|
|
17
|
+
{
|
|
18
|
+
def: ButtonDef
|
|
19
|
+
className?: string
|
|
20
|
+
}
|
|
21
|
+
> = ({
|
|
20
22
|
def,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
className='',
|
|
24
|
+
...rest
|
|
23
25
|
}) => {
|
|
24
26
|
if (def.action.type === 'modal') {
|
|
25
27
|
const m = def.action.def as ButtonModalDef
|
|
26
28
|
const Modal = m.Comp
|
|
27
|
-
const sizeToSpread = size ? {size} : {}
|
|
28
29
|
return (
|
|
29
30
|
<DynamicDVC>
|
|
30
31
|
<Modal
|
|
31
32
|
title={m.title}
|
|
32
33
|
byline={m.byline}
|
|
33
34
|
buttonText={def.text}
|
|
34
|
-
buttonProps={{...def.props, ...
|
|
35
|
+
buttonProps={{...def.props, ...rest, className: cn((def.props?.className ?? ''), className)}}
|
|
35
36
|
action={m.action}
|
|
36
37
|
actionEnclosure={m.actionEnclosure}
|
|
37
38
|
{...m.props}
|
package/primitives/button.tsx
CHANGED
|
@@ -52,10 +52,6 @@ const buttonVariants = cva(
|
|
|
52
52
|
}
|
|
53
53
|
)
|
|
54
54
|
|
|
55
|
-
type ButtonVariants = keyof typeof variant
|
|
56
|
-
type ButtonSizes = keyof typeof size
|
|
57
|
-
type ButtonRoundedValue = keyof typeof rounded
|
|
58
|
-
|
|
59
55
|
interface ButtonProps extends
|
|
60
56
|
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
61
57
|
VariantProps<typeof buttonVariants>
|
|
@@ -81,8 +77,5 @@ Button.displayName = "Button"
|
|
|
81
77
|
export {
|
|
82
78
|
Button as default,
|
|
83
79
|
type ButtonProps,
|
|
84
|
-
type ButtonVariants,
|
|
85
|
-
type ButtonSizes,
|
|
86
|
-
type ButtonRoundedValue,
|
|
87
80
|
buttonVariants,
|
|
88
81
|
}
|
package/primitives/drawer.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
|
-
import { Drawer as DrawerPrimitive } from '
|
|
4
|
+
import { Drawer as DrawerPrimitive, useDrawerContext } from '@hanzo/react-drawer'
|
|
5
5
|
|
|
6
6
|
import { cn } from '../util'
|
|
7
7
|
|
|
8
8
|
const Drawer = ({
|
|
9
|
-
shouldScaleBackground =
|
|
9
|
+
shouldScaleBackground = false,
|
|
10
10
|
...props
|
|
11
11
|
}: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
|
|
12
12
|
<DrawerPrimitive.Root
|
|
@@ -18,6 +18,7 @@ Drawer.displayName = 'Drawer'
|
|
|
18
18
|
|
|
19
19
|
const DrawerTrigger = DrawerPrimitive.Trigger
|
|
20
20
|
const DrawerPortal = DrawerPrimitive.Portal
|
|
21
|
+
const DrawerHandle = DrawerPrimitive.Handle
|
|
21
22
|
const DrawerClose = DrawerPrimitive.Close
|
|
22
23
|
|
|
23
24
|
const DrawerOverlay = React.forwardRef<
|
|
@@ -36,24 +37,38 @@ const DrawerContent = React.forwardRef<
|
|
|
36
37
|
React.ElementRef<typeof DrawerPrimitive.Content>,
|
|
37
38
|
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content> & {
|
|
38
39
|
overlayClx?: string
|
|
40
|
+
defaultHandle?: boolean
|
|
39
41
|
}
|
|
40
|
-
>(({
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
>(({
|
|
43
|
+
className,
|
|
44
|
+
children,
|
|
45
|
+
overlayClx='',
|
|
46
|
+
defaultHandle=true,
|
|
47
|
+
...props
|
|
48
|
+
}, ref) => {
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<DrawerPortal>
|
|
52
|
+
{/* If no or same z index, overlay should precede content */}
|
|
53
|
+
<DrawerOverlay className={cn('z-below-modal', overlayClx)}/>
|
|
54
|
+
<DrawerPrimitive.Content
|
|
55
|
+
ref={ref}
|
|
56
|
+
className={cn('fixed left-0 right-0 bottom-0 z-modal',
|
|
57
|
+
'mt-24 flex flex-col rounded-t-[10px] pt-6 border bg-background',
|
|
58
|
+
// 'h-[80%]'
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{defaultHandle && (
|
|
64
|
+
<div className='absolute left-0 right-0 mx-auto top-2 h-2 w-[100px] rounded-full bg-level-3 shrink-0' />
|
|
65
|
+
)}
|
|
66
|
+
{children}
|
|
67
|
+
</DrawerPrimitive.Content>
|
|
68
|
+
</DrawerPortal>
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
|
|
57
72
|
DrawerContent.displayName = 'DrawerContent'
|
|
58
73
|
|
|
59
74
|
const DrawerHeader = ({
|
|
@@ -105,15 +120,20 @@ const DrawerDescription = React.forwardRef<
|
|
|
105
120
|
))
|
|
106
121
|
DrawerDescription.displayName = DrawerPrimitive.Description.displayName
|
|
107
122
|
|
|
123
|
+
type DrawerProps = React.ComponentProps<typeof DrawerPrimitive.Root>
|
|
124
|
+
|
|
108
125
|
export {
|
|
126
|
+
type DrawerProps,
|
|
109
127
|
Drawer,
|
|
110
128
|
DrawerPortal,
|
|
111
129
|
DrawerOverlay,
|
|
112
130
|
DrawerTrigger,
|
|
113
131
|
DrawerClose,
|
|
114
132
|
DrawerContent,
|
|
133
|
+
DrawerHandle,
|
|
115
134
|
DrawerHeader,
|
|
116
135
|
DrawerFooter,
|
|
117
136
|
DrawerTitle,
|
|
118
137
|
DrawerDescription,
|
|
138
|
+
useDrawerContext
|
|
119
139
|
}
|
package/primitives/index.ts
CHANGED
|
@@ -24,8 +24,6 @@ export {
|
|
|
24
24
|
export {
|
|
25
25
|
default as Button,
|
|
26
26
|
type ButtonProps,
|
|
27
|
-
type ButtonVariants,
|
|
28
|
-
type ButtonSizes,
|
|
29
27
|
buttonVariants,
|
|
30
28
|
} from './button'
|
|
31
29
|
|
|
@@ -61,16 +59,19 @@ export {
|
|
|
61
59
|
} from './command'
|
|
62
60
|
|
|
63
61
|
export {
|
|
62
|
+
type DrawerProps,
|
|
64
63
|
Drawer,
|
|
65
64
|
DrawerPortal,
|
|
66
65
|
DrawerOverlay,
|
|
67
66
|
DrawerTrigger,
|
|
68
67
|
DrawerClose,
|
|
69
68
|
DrawerContent,
|
|
69
|
+
DrawerHandle,
|
|
70
70
|
DrawerHeader,
|
|
71
71
|
DrawerFooter,
|
|
72
72
|
DrawerTitle,
|
|
73
73
|
DrawerDescription,
|
|
74
|
+
useDrawerContext
|
|
74
75
|
} from './drawer'
|
|
75
76
|
|
|
76
77
|
export {
|
|
@@ -2,24 +2,26 @@ import React, { type PropsWithChildren } from 'react'
|
|
|
2
2
|
import Link from 'next/link'
|
|
3
3
|
|
|
4
4
|
import type { LinkDef, Icon } from '../types'
|
|
5
|
-
import { buttonVariants
|
|
6
|
-
import { cn } from '../util'
|
|
5
|
+
import { buttonVariants } from './button'
|
|
6
|
+
import { cn, type VariantProps } from '../util'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* If this is rendered directly (and not auto generated in a Block)
|
|
10
10
|
* and it has any children, title, icon, and iconAfter
|
|
11
11
|
* are ignore.
|
|
12
12
|
*/
|
|
13
|
-
const LinkElement: React.FC<
|
|
13
|
+
const LinkElement: React.FC<
|
|
14
|
+
PropsWithChildren &
|
|
15
|
+
VariantProps<typeof buttonVariants> &
|
|
16
|
+
{
|
|
14
17
|
def: LinkDef,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/** To trigger other events in addition to the
|
|
20
|
-
* link action itself. (eg, to also close a drawer menu)
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Use to trigger other events in addition to the
|
|
21
|
+
* link action itself. For example, to also close a drawer menu.
|
|
21
22
|
*/
|
|
22
23
|
onClick?: () => void
|
|
24
|
+
|
|
23
25
|
/** overrides def (eg, for title area)*/
|
|
24
26
|
icon?: Icon
|
|
25
27
|
/** overrides def */
|
|
@@ -28,9 +30,10 @@ const LinkElement: React.FC<PropsWithChildren & {
|
|
|
28
30
|
}> = ({
|
|
29
31
|
def,
|
|
30
32
|
// DO NOT provide a default to any of the props that also appear in def!
|
|
31
|
-
size,
|
|
32
33
|
onClick,
|
|
34
|
+
size,
|
|
33
35
|
variant,
|
|
36
|
+
rounded,
|
|
34
37
|
icon,
|
|
35
38
|
iconAfter,
|
|
36
39
|
className = '',
|
|
@@ -42,6 +45,7 @@ const LinkElement: React.FC<PropsWithChildren & {
|
|
|
42
45
|
newTab,
|
|
43
46
|
variant: defVariant,
|
|
44
47
|
size: defSize,
|
|
48
|
+
rounded: defRounded,
|
|
45
49
|
title
|
|
46
50
|
} = def
|
|
47
51
|
|
|
@@ -88,7 +92,8 @@ const LinkElement: React.FC<PropsWithChildren & {
|
|
|
88
92
|
size: (!defVariant || defVariant.includes('link') || variant?.includes('link')) ?
|
|
89
93
|
'link'
|
|
90
94
|
:
|
|
91
|
-
(size ? size : defSize)
|
|
95
|
+
(size ? size : defSize),
|
|
96
|
+
rounded: rounded ? rounded : (defRounded ? defRounded : 'md'),
|
|
92
97
|
}),
|
|
93
98
|
// This is a "label only" LinkDef. cf: footer"
|
|
94
99
|
((href.length > 0 || onClick) ? '' : 'pointer-events-none'),
|
package/style/drawer.css
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/* This is a copy of vaul/src/style.css */
|
|
2
|
+
|
|
3
|
+
[vaul-drawer] {
|
|
4
|
+
touch-action: none;
|
|
5
|
+
transition: transform 0.5s cubic-bezier(0.32, 0.72, 0, 1);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
[vaul-drawer][vaul-drawer-direction='bottom'] {
|
|
9
|
+
transform: translate3d(0, 100%, 0);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
[vaul-drawer][vaul-drawer-direction='top'] {
|
|
13
|
+
transform: translate3d(0, -100%, 0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
[vaul-drawer][vaul-drawer-direction='left'] {
|
|
17
|
+
transform: translate3d(-100%, 0, 0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
[vaul-drawer][vaul-drawer-direction='right'] {
|
|
21
|
+
transform: translate3d(100%, 0, 0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.vaul-dragging .vaul-scrollable [vault-drawer-direction='top'] {
|
|
25
|
+
overflow-y: hidden !important;
|
|
26
|
+
}
|
|
27
|
+
.vaul-dragging .vaul-scrollable [vault-drawer-direction='bottom'] {
|
|
28
|
+
overflow-y: hidden !important;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.vaul-dragging .vaul-scrollable [vault-drawer-direction='left'] {
|
|
32
|
+
overflow-x: hidden !important;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.vaul-dragging .vaul-scrollable [vault-drawer-direction='right'] {
|
|
36
|
+
overflow-x: hidden !important;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='top'] {
|
|
40
|
+
transform: translate3d(0, var(--snap-point-height, 0), 0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='bottom'] {
|
|
44
|
+
transform: translate3d(0, var(--snap-point-height, 0), 0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='left'] {
|
|
48
|
+
transform: translate3d(var(--snap-point-height, 0), 0, 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='right'] {
|
|
52
|
+
transform: translate3d(var(--snap-point-height, 0), 0, 0);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
[vaul-overlay] {
|
|
56
|
+
opacity: 0;
|
|
57
|
+
transition: opacity 0.5s cubic-bezier(0.32, 0.72, 0, 1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
[vaul-overlay][vaul-drawer-visible='true'] {
|
|
61
|
+
opacity: 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
[vaul-drawer]::after {
|
|
65
|
+
content: '';
|
|
66
|
+
position: absolute;
|
|
67
|
+
background: inherit;
|
|
68
|
+
background-color: inherit;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[vaul-drawer][vaul-drawer-direction='top']::after {
|
|
72
|
+
top: initial;
|
|
73
|
+
bottom: 100%;
|
|
74
|
+
left: 0;
|
|
75
|
+
right: 0;
|
|
76
|
+
height: 200%;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
[vaul-drawer][vaul-drawer-direction='bottom']::after {
|
|
80
|
+
top: 100%;
|
|
81
|
+
bottom: initial;
|
|
82
|
+
left: 0;
|
|
83
|
+
right: 0;
|
|
84
|
+
height: 200%;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
[vaul-drawer][vaul-drawer-direction='left']::after {
|
|
88
|
+
left: initial;
|
|
89
|
+
right: 100%;
|
|
90
|
+
top: 0;
|
|
91
|
+
bottom: 0;
|
|
92
|
+
width: 200%;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[vaul-drawer][vaul-drawer-direction='right']::after {
|
|
96
|
+
left: 100%;
|
|
97
|
+
right: initial;
|
|
98
|
+
top: 0;
|
|
99
|
+
bottom: 0;
|
|
100
|
+
width: 200%;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
[vaul-handle] {
|
|
104
|
+
display: block;
|
|
105
|
+
position: relative;
|
|
106
|
+
opacity: 0.8;
|
|
107
|
+
margin-left: auto;
|
|
108
|
+
margin-right: auto;
|
|
109
|
+
height: 5px;
|
|
110
|
+
width: 56px;
|
|
111
|
+
border-radius: 1rem;
|
|
112
|
+
touch-action: pan-y;
|
|
113
|
+
cursor: grab;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
[vaul-handle]:hover,
|
|
117
|
+
[vaul-handle]:active {
|
|
118
|
+
opacity: 1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[vaul-handle]:active {
|
|
122
|
+
cursor: grabbing;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
[vaul-handle-hitarea] {
|
|
126
|
+
position: absolute;
|
|
127
|
+
left: 50%;
|
|
128
|
+
top: 50%;
|
|
129
|
+
transform: translate(-50%, -50%);
|
|
130
|
+
width: max(100%, 2.75rem); /* 44px */
|
|
131
|
+
height: max(100%, 2.75rem); /* 44px */
|
|
132
|
+
touch-action: inherit;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
[vaul-overlay][vaul-snap-points='true']:not([vaul-snap-points-overlay='true']):not([data-state='closed']) {
|
|
136
|
+
opacity: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
[vaul-overlay][vaul-snap-points-overlay='true']:not([vaul-drawer-visible='false']) {
|
|
140
|
+
opacity: 1;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* This will allow us to not animate via animation, but still benefit from delaying unmount via Radix. */
|
|
144
|
+
@keyframes fake-animation {
|
|
145
|
+
from {
|
|
146
|
+
}
|
|
147
|
+
to {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@media (pointer: fine) {
|
|
152
|
+
[vaul-handle-hitarea] {
|
|
153
|
+
width: 100%;
|
|
154
|
+
height: 100%;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@media (hover: hover) and (pointer: fine) {
|
|
159
|
+
[vaul-drawer] {
|
|
160
|
+
user-select: none;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
@@ -107,11 +107,6 @@ export default {
|
|
|
107
107
|
}),
|
|
108
108
|
borderOpacity: ({ theme }) => theme('opacity'),
|
|
109
109
|
borderRadius: {
|
|
110
|
-
/* shadcn's:
|
|
111
|
-
lg: `var(--radius)`,
|
|
112
|
-
md: `calc(var(--radius) - 2px)`,
|
|
113
|
-
sm: "calc(var(--radius) - 4px)",
|
|
114
|
-
*/
|
|
115
110
|
none: '0px',
|
|
116
111
|
sm: '0.25rem',
|
|
117
112
|
DEFAULT: '0.5rem',
|
package/tsconfig.json
CHANGED
package/types/image-def.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ButtonRoundedValue } from '../primitives/button'
|
|
2
1
|
import type Dimensions from './dimensions'
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -25,7 +24,7 @@ interface ImageDef {
|
|
|
25
24
|
*/
|
|
26
25
|
dim: Dimensions
|
|
27
26
|
|
|
28
|
-
rounded?:
|
|
27
|
+
rounded?: string // any key from tailwind.config.borderRadius
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
export {
|
package/types/link-def.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { VariantProps } from 'class-variance-authority'
|
|
2
|
+
import type { buttonVariants } from '../primitives/button'
|
|
2
3
|
import type Icon from './icon'
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -6,7 +7,7 @@ import type Icon from './icon'
|
|
|
6
7
|
*
|
|
7
8
|
*
|
|
8
9
|
*/
|
|
9
|
-
interface LinkDef {
|
|
10
|
+
interface LinkDef extends VariantProps<typeof buttonVariants> {
|
|
10
11
|
/**
|
|
11
12
|
* If the LinkElement is rendered directly and has children,
|
|
12
13
|
* the title, icon, iconAfter fields in the supplied LinkDef
|
|
@@ -49,9 +50,6 @@ interface LinkDef {
|
|
|
49
50
|
* rendered as a disabled link, shows default cursor, and eats pointer events.
|
|
50
51
|
*/
|
|
51
52
|
disabled?: boolean
|
|
52
|
-
|
|
53
|
-
variant?: ButtonVariants
|
|
54
|
-
size?: ButtonSizes
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
export {
|
package/util/index.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { compiler as mdCompiler } from 'markdown-to-jsx'
|
|
|
2
2
|
|
|
3
3
|
import { clsx, type ClassValue } from 'clsx'
|
|
4
4
|
import { twMerge } from 'tailwind-merge'
|
|
5
|
+
export { cva, type VariantProps } from 'class-variance-authority'
|
|
6
|
+
|
|
5
7
|
import type { Dimensions } from '../types'
|
|
6
8
|
|
|
7
9
|
// @ts-ignore
|
|
@@ -71,4 +73,7 @@ export const capitalize = (str: string): string => (
|
|
|
71
73
|
str.charAt(0).toUpperCase() + str.slice(1)
|
|
72
74
|
)
|
|
73
75
|
|
|
74
|
-
export { default as spreadToTransform } from './spread-to-transform'
|
|
76
|
+
export { default as spreadToTransform } from './spread-to-transform'
|
|
77
|
+
// Must be imported from 'use client'
|
|
78
|
+
// export * from './step-animation'
|
|
79
|
+
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react'
|
|
2
|
+
import { makeObservable, reaction, computed, type IReactionDisposer, observable, action } from 'mobx'
|
|
3
|
+
|
|
4
|
+
interface StepAnimation {
|
|
5
|
+
notPast(step: number): boolean
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
class MyStepAnimation implements StepAnimation {
|
|
9
|
+
|
|
10
|
+
_step: number = -1
|
|
11
|
+
_reactionDisposer: IReactionDisposer | undefined = undefined
|
|
12
|
+
|
|
13
|
+
_initialStep: () => boolean
|
|
14
|
+
_intervals: number[]
|
|
15
|
+
|
|
16
|
+
/** initialStep: false -> true: step 0
|
|
17
|
+
true -> false: step 1
|
|
18
|
+
after intervals[0] : step 2
|
|
19
|
+
after intervals[1] : step 3
|
|
20
|
+
|
|
21
|
+
initialStep must contain at least one mobx observable and return boolean
|
|
22
|
+
see: https://mobx.js.org/reactions.html#reaction
|
|
23
|
+
*/
|
|
24
|
+
constructor(initialStep: () => boolean, intervals: number[]) {
|
|
25
|
+
|
|
26
|
+
this._initialStep = initialStep
|
|
27
|
+
this._intervals = intervals
|
|
28
|
+
|
|
29
|
+
makeObservable(this, {
|
|
30
|
+
_step: observable,
|
|
31
|
+
_setStep: action
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// This is separated out because reactions have to be created
|
|
36
|
+
// once we have a valid doc / window etc. (mobx internals)
|
|
37
|
+
// Can't just do it in constructor and assign to ref
|
|
38
|
+
initialize = () => {
|
|
39
|
+
|
|
40
|
+
const fireNext = () => {
|
|
41
|
+
this._setStep(this._step + 1)
|
|
42
|
+
if (this._step <= this._intervals.length) {
|
|
43
|
+
// No need to call clearTimeout(): https://stackoverflow.com/a/7391588/11645689
|
|
44
|
+
setTimeout(() => { fireNext() }, this._intervals[this._step - 1])
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this._reactionDisposer = reaction(
|
|
49
|
+
this._initialStep,
|
|
50
|
+
(triggered: boolean) => {
|
|
51
|
+
if (triggered && this._step === -1) {
|
|
52
|
+
this._setStep(0)
|
|
53
|
+
}
|
|
54
|
+
// extra safe
|
|
55
|
+
else if (this._step === 0) {
|
|
56
|
+
fireNext()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
_setStep = (v: number): void => {this._step = v}
|
|
63
|
+
|
|
64
|
+
dispose = () => {
|
|
65
|
+
if (this._reactionDisposer) {
|
|
66
|
+
this._reactionDisposer()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// https://mobx.js.org/computeds-with-args.html#2-close-over-the-arguments
|
|
71
|
+
notPast = (step: number): boolean => (
|
|
72
|
+
computed(() => (this._step > -1 && this._step <= step)).get()
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const useStepAnimation = (initialStep: () => boolean, intervals: number[]): StepAnimation => {
|
|
77
|
+
|
|
78
|
+
const animRef = useRef<MyStepAnimation>(new MyStepAnimation(initialStep, intervals))
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
animRef.current.initialize()
|
|
81
|
+
return animRef.current.dispose
|
|
82
|
+
}, [])
|
|
83
|
+
|
|
84
|
+
return animRef.current
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
type StepAnimation,
|
|
89
|
+
useStepAnimation
|
|
90
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class TwoWayReadonlyMap<T, K> {
|
|
2
|
+
map: Map<T, K>;
|
|
3
|
+
reverseMap: Map<K, T>;
|
|
4
|
+
constructor(map: Map<T, K>) {
|
|
5
|
+
this.map = map;
|
|
6
|
+
this.reverseMap = new Map<K, T>();
|
|
7
|
+
map.forEach((value, key) => {
|
|
8
|
+
this.reverseMap.set(value, key);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
get(key: T) {
|
|
12
|
+
return this.map.get(key);
|
|
13
|
+
}
|
|
14
|
+
revGet(key: K) {
|
|
15
|
+
return this.reverseMap.get(key);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default TwoWayReadonlyMap
|