@luxfi/core 5.2.6 → 5.2.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,6 +19,13 @@ import type { CommerceDrawer, SelectAndBuy, RecentActivity } from './store'
19
19
  import { CommerceUIStore } from './store'
20
20
  import conf from './conf'
21
21
 
22
+ const LOG = false ////////////////////
23
+ const log = (s: string) => {
24
+ if (LOG) {
25
+ console.log('CMMC UI CONTEXT ' + s)
26
+ }
27
+ }
28
+
22
29
  // https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
23
30
  enableStaticRendering(typeof window === "undefined")
24
31
 
@@ -41,13 +48,9 @@ const CommerceUIProvider: React.FC<PropsWithChildren> = ({
41
48
  }) => {
42
49
 
43
50
  const cmmc = useCommerce()
44
- const pathName = usePathname()
45
- const isCheckout = pathName === '/checkout'
46
- const ref = useRef<CommerceUIStore>(new CommerceUIStore(cmmc, conf))
47
-
48
- if (ref.current.checkingOut != isCheckout) {
49
- ref.current.setCheckingOut(isCheckout)
50
- }
51
+ const pathname = usePathname()
52
+ const storeRef = useRef<CommerceUIStore>(new CommerceUIStore(cmmc, conf))
53
+ const prevPathRef = useRef<string>('initial')
51
54
 
52
55
  const onResize = () => {
53
56
  const width = window.innerWidth
@@ -58,36 +61,57 @@ const CommerceUIProvider: React.FC<PropsWithChildren> = ({
58
61
  desktopMin = parseInt(twConfig.theme?.screens.md)
59
62
  }
60
63
  if (width < desktopMin) {
61
- if (!ref.current.isMobile) {
62
- ref.current.setMobile(true)
64
+ if (!storeRef.current.isMobile) {
65
+ storeRef.current.setMobile(true)
63
66
  }
64
67
  }
65
- else if (ref.current.isMobile) {
66
- ref.current.setMobile(false)
68
+ else if (storeRef.current.isMobile) {
69
+ storeRef.current.setMobile(false)
67
70
  }
68
71
  }
69
- ref.current.setViewportHeight(window.innerHeight)
72
+ storeRef.current.setViewportHeight(window.innerHeight)
70
73
  }
71
74
 
72
75
  const onResize_debounced = useDebounceCallback(onResize, 500)
73
76
 
74
77
  useLayoutEffect(() => {
75
- ref.current.initialize()
78
+ storeRef.current.initialize()
76
79
  onResize()
77
80
  window.addEventListener('resize', onResize_debounced);
78
81
  return () => {
79
82
  window.removeEventListener('resize', onResize_debounced)
80
- ref.current.dispose()
83
+ storeRef.current.dispose()
81
84
  }
82
85
  }, [])
83
86
 
84
87
  useEffect(() => {
85
- ref.current.reset()
86
- }, [pathName])
88
+ const checkingOut = (pathname === '/checkout')
89
+
90
+ /////////////////////////////////////
91
+ log("useEffect: pathname: " + pathname)
92
+ log("useEffect: prev pathname: " + prevPathRef.current)
93
+
94
+ if (storeRef.current.checkingOut === undefined || storeRef.current._checkingOut!== checkingOut) {
95
+ log("useEffect: setting checkingOut to: " + checkingOut) /////////////////////////////////////
96
+ storeRef.current.setCheckingOut(checkingOut)
97
+ }
98
+ if ( prevPathRef.current === 'initial') {
99
+ prevPathRef.current = pathname
100
+ // no need to reset
101
+ }
102
+ else if (
103
+ !checkingOut
104
+ &&
105
+ prevPathRef.current !== pathname
106
+ ) {
107
+ storeRef.current.reset()
108
+ prevPathRef.current = pathname
109
+ }
110
+ }, [pathname])
87
111
 
88
112
 
89
113
  return (
90
- <CommerceUIContext.Provider value={ref.current}>
114
+ <CommerceUIContext.Provider value={storeRef.current}>
91
115
  {children}
92
116
  </CommerceUIContext.Provider>
93
117
  )
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  action,
3
+ autorun,
3
4
  computed,
4
5
  makeObservable,
5
6
  observable,
@@ -9,9 +10,10 @@ import {
9
10
 
10
11
  import type { CommerceService, LineItem, ObsLineItemRef } from '@hanzo/commerce/types'
11
12
 
12
- const logOn = false
13
+ const LOG = false ////////////////////
14
+
13
15
  const log = (s: string) => {
14
- if (logOn) {
16
+ if (LOG) {
15
17
  console.log('COMMERCE_UI ' + s)
16
18
  }
17
19
  }
@@ -69,7 +71,7 @@ class CommerceUIStore implements
69
71
 
70
72
  _currentSkuPath: string | undefined = undefined
71
73
  _closedByUser: boolean = false
72
- _checkingOut: boolean = false
74
+ _checkingOut: boolean | undefined = undefined
73
75
  _ignoreStateChange: boolean = false
74
76
  _activePoint: SnapPoint | null = null
75
77
 
@@ -116,6 +118,7 @@ class CommerceUIStore implements
116
118
  showCheckout: computed,
117
119
  snapPointPx: computed,
118
120
  state: computed,
121
+ open: computed
119
122
  })
120
123
  }
121
124
 
@@ -135,6 +138,16 @@ class CommerceUIStore implements
135
138
  }
136
139
  }
137
140
  ))
141
+ this._reactionDisposers.push(autorun(() => {
142
+ log('AUTORUN: OPEN: ' + this.open)
143
+ log('AUTORUN:' + // ===============
144
+ '[showCheckout: ' + this.showCheckout +
145
+ '], [showAdded: ' + this.showAdded +
146
+ '], [showBuy: ' + this.showBuy +
147
+ '], [closedByUser: ' + this._closedByUser +
148
+ '], [checkingOut: ' + this._checkingOut + ']'
149
+ ) // ===========
150
+ }))
138
151
  }
139
152
 
140
153
  reset = () => {
@@ -191,7 +204,7 @@ class CommerceUIStore implements
191
204
  get ignoreStateChange(): boolean { return this._ignoreStateChange }
192
205
  setIgnoreStateChange = (b: boolean): void => { this._ignoreStateChange = b}
193
206
 
194
- get checkingOut(): boolean { return this._checkingOut }
207
+ get checkingOut(): boolean | undefined { return this._checkingOut }
195
208
  setCheckingOut = (b: boolean): void => { this._checkingOut = b }
196
209
 
197
210
  get activePoint(): SnapPoint | null { return this._activePoint }
@@ -218,26 +231,41 @@ class CommerceUIStore implements
218
231
  }
219
232
 
220
233
  get open(): boolean {
234
+
235
+ log('open():' + // ===============
236
+ ' showCheckout: ' + this.showCheckout +
237
+ ' showAdded: ' + this.showAdded +
238
+ ' showBuy: ' + this.showBuy
239
+ ) // ===========
240
+
241
+
242
+
221
243
  return (
222
- !this.closedByUser
244
+ this._checkingOut !== undefined
245
+ &&
246
+ !this._checkingOut
247
+ &&
248
+ !this.closedByUser
223
249
  &&
224
250
  (this.showCheckout || this.showAdded || this.showBuy)
225
251
  )
226
252
  }
227
253
 
228
254
  get state(): DrawerState {
229
- if (this.showBuy) {
230
- return 'full'
231
- }
232
- else if (!this.closedByUser && (this.showAdded || this.showCheckout)) {
233
- return 'micro'
255
+ if (!this.closedByUser && !this._checkingOut) {
256
+ if (this.showBuy) {
257
+ return 'full'
258
+ }
259
+ else if (this.showAdded || this.showCheckout) {
260
+ return 'micro'
261
+ }
234
262
  }
235
263
  return 'closed'
236
264
  }
237
265
 
238
266
  get showBuy(): boolean {return !!this.currentSkuPath}
239
- get showAdded(): boolean { return !this._checkingOut && !!this.item}
240
- get showCheckout(): boolean { return !this._checkingOut && !this._service.cartEmpty}
267
+ get showAdded(): boolean { return !!this.item}
268
+ get showCheckout(): boolean { return !this._service.cartEmpty}
241
269
  get modal(): boolean { return this.state !== 'micro'}
242
270
 
243
271
  get microHeight(): SnapPoint {
@@ -58,7 +58,7 @@ const LoginPanel: React.FC<{
58
58
  onClick={close}
59
59
  className='w-fit !min-w-0 p-2'
60
60
  >
61
- <Logo size='md' spanClassName='!cursor-pointer' layout='text-only'/>
61
+ <Logo size='md' textClx='!cursor-pointer' variant='text-only'/>
62
62
  </Button>
63
63
  <Carousel
64
64
  options={{ align: 'center', loop: true }}
@@ -0,0 +1,42 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import { useRouter } from 'next/navigation'
4
+
5
+ import { ChevronLeft } from 'lucide-react'
6
+
7
+
8
+ import {
9
+ Button,
10
+ buttonVariants,
11
+ } from '@hanzo/ui/primitives'
12
+
13
+ import type { VariantProps } from '@hanzo/ui/util'
14
+
15
+ const BackButton: React.FC<{
16
+ variant?: VariantProps<typeof buttonVariants>['variant']
17
+ size?: VariantProps<typeof buttonVariants>['size']
18
+ clx?: string
19
+ iconClx?: string
20
+ }> = ({
21
+ variant='ghost',
22
+ size='default',
23
+ clx='',
24
+ iconClx='',
25
+ }) => {
26
+
27
+ const router = useRouter()
28
+ const back = () => {router.back()}
29
+
30
+ return (
31
+ <Button
32
+ variant={variant}
33
+ size={size}
34
+ onClick={back}
35
+ className={clx}
36
+ >
37
+ <ChevronLeft className={iconClx}/>
38
+ </Button>
39
+ )
40
+ }
41
+
42
+ export default BackButton
@@ -1,56 +1,73 @@
1
1
  'use client'
2
2
  import React, { type PropsWithChildren } from 'react'
3
+ import { observer } from 'mobx-react-lite'
3
4
 
4
5
  import { ScrollArea, StepIndicator } from '@hanzo/ui/primitives'
5
6
  import { AuthWidget } from '@hanzo/auth/components'
6
- import { CartPanel } from '@hanzo/commerce'
7
+ import { CartPanel, useCommerce } from '@hanzo/commerce'
8
+ import { cn } from '@hanzo/ui/util'
7
9
 
8
- import * as Icons from '../../icons'
10
+ import { BackButton, Logo, Tooltip } from '../..'
9
11
  import DesktopBagCarousel from './dt-bag-carousel'
10
- import CloseButton from './close-button'
11
- import { cn } from '@hanzo/ui/util'
12
12
  import LinksRow from './links-row'
13
13
 
14
14
  const DesktopCheckoutPanel: React.FC<PropsWithChildren & {
15
15
  index: number
16
16
  stepNames: string[]
17
- close:() => void
17
+ close: () => void
18
18
  className?: string
19
- }> = ({
19
+ }> = observer(({
20
20
  index,
21
21
  stepNames,
22
22
  close,
23
23
  className='',
24
24
  children
25
- }) => (
25
+ }) => {
26
26
 
27
+ const cmmc = useCommerce()
28
+
29
+ return (
27
30
  <div /* id='CHECKOUT_PANEL' */ className={cn('grid grid-cols-2', className)}>
28
- <div className='w-full h-full bg-background flex flex-row items-start justify-end'>
29
- <div className='w-full max-w-[750px] relative flex flex-col items-center justify-start p-8'>
30
- <CloseButton close={close} size='md'/>
31
- <div className='w-full max-w-[550px] mx-auto flex flex-col gap-3'>
32
- <DesktopBagCarousel className='h-[260px] w-[360px] lg:w-[420px] mx-auto -mt-8' constrainTo={{w: 250, h: 250}}/>
31
+ <div key={1} className='w-full h-full bg-background flex flex-row items-start justify-end'>
32
+ <div className='w-full h-full max-w-[750px] relative flex flex-col items-stretch justify-start px-8 pb-8'>
33
+ <div key={1} className='h-[80px] grow-0 flex flex-row items-center z-10' >
34
+ <Logo onClick={close} size='md' href='/' variant='text-only' outerClx='logo-outer-tooltip-class' />
35
+ <Tooltip select='.logo-outer-tooltip-class' text='home' position='right' offset={6}/>
36
+ </div>
37
+ <BackButton size='sm' clx={
38
+ 'z-10 absolute top-14 left-6 !px-0 aspect-square ' +
39
+ 'rounded-full hover:!bg-level-3 ' +
40
+ //'border border-transparent hover:border-muted-2 ' +
41
+ 'back-button-tooltip-class '
42
+ }/>
43
+ <Tooltip select='.back-button-tooltip-class' text='back' position='right' offset={5}/>
44
+ <div key={2} className={cn(
45
+ 'w-full grow min-h-0 max-w-[550px] mx-auto flex flex-col gap-3',
46
+ (cmmc.cartItems.length > 4 ? 'justify-between' : 'justify-start gap-10 pt-10')
47
+ )}>
48
+ <DesktopBagCarousel className='grow-0 h-[260px] w-[360px] lg:w-[420px] mx-auto -mt-8' constrainTo={{w: 250, h: 250}}/>
33
49
  <CartPanel
34
50
  className='w-full border-none p-0'
35
- itemClx='mb-3'
36
- totalClx='sticky -bottom-1 p-1 bg-background'
51
+ itemClx='mb-2'
52
+ totalClx='sticky bottom-0 bg-background'
37
53
  listClx='pr-3'
38
54
  scrollAfter={5}
39
- scrollHeightClx='h-[50vh]'
55
+ scrollHeightClx='min-h-[50vh] grow'
40
56
  showPromoCode
41
57
  showShipping
58
+ selectItems
42
59
  />
43
60
  </div>
44
61
  </div>
45
62
  </div>
46
- <div className='w-full h-full flex flex-col bg-level-1 min-h-screen justify-between'>
63
+ <div key={2} className='w-full h-full flex flex-col bg-level-1 min-h-screen justify-between'>
47
64
  <ScrollArea className='w-full flex flex-row items-start justify-start overflow-y-auto'>
48
65
  <div className='h-full w-full max-w-[750px] relative flex flex-col items-center px-8 pt-0'>
49
- <div className='bg-level-1 sticky h-30 pb-8 w-full top-0 flex justify-center items-end'>
66
+ <div key={1} className='bg-level-1 sticky h-30 pb-8 w-full top-0 flex justify-center items-end'>
50
67
  <AuthWidget noLogin className='hidden md:flex absolute top-4 right-4 '/>
51
68
  <StepIndicator dotSizeRem={1.5} steps={stepNames} currentStep={index} className='gap-2 text-base w-pr-70' />
52
69
  </div>
53
- <div className='w-full max-w-[550px] mx-auto pb-10'>
70
+ <div key={2} className='w-full max-w-[550px] mx-auto pb-10'>
54
71
  {children}
55
72
  </div>
56
73
  </div>
@@ -63,5 +80,6 @@ const DesktopCheckoutPanel: React.FC<PropsWithChildren & {
63
80
  </div>
64
81
  </div>
65
82
  )
83
+ })
66
84
 
67
85
  export default DesktopCheckoutPanel
@@ -6,7 +6,7 @@ import { cn } from '@hanzo/ui/util'
6
6
  import { AuthWidget } from '@hanzo/auth/components'
7
7
  import { CartAccordian } from '@hanzo/commerce'
8
8
 
9
- import CloseButton from './close-button'
9
+ import { Logo } from '../..'
10
10
  import BagButton from '../bag-button'
11
11
  import LinksRow from './links-row'
12
12
 
@@ -25,7 +25,7 @@ const MobileCheckoutPanel: React.FC<PropsWithChildren & {
25
25
 
26
26
  <div /* id='MOBILE_GRID' */ className={cn('bg-background flex flex-col justify-start px-4', className)}>
27
27
  <div className='sticky top-0 w-full flex flex-row justify-between items-center bg-background'>
28
- <CloseButton close={close} size='xs' />
28
+ <Logo onClick={close} size='xs' href='/' />
29
29
  {/* Need wrapper div since 'noLogin' returns null if no logged in user */}
30
30
  <div className='w-10 h-10 flex items-center justify-center'><AuthWidget noLogin className=''/></div>
31
31
  </div>
@@ -17,111 +17,6 @@ import {
17
17
  } from '@hanzo/ui/primitives'
18
18
  import Warpcast from "../icons/warpcast"
19
19
 
20
- // const components: { title: string; href: string; description: string }[] = [
21
- // {
22
- // title: "Alert Dialog",
23
- // href: "/docs/primitives/alert-dialog",
24
- // description:
25
- // "A modal dialog that interrupts the user with important content and expects a response.",
26
- // },
27
- // {
28
- // title: "Hover Card",
29
- // href: "/docs/primitives/hover-card",
30
- // description:
31
- // "For sighted users to preview content available behind a link.",
32
- // },
33
- // {
34
- // title: "Progress",
35
- // href: "/docs/primitives/progress",
36
- // description:
37
- // "Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.",
38
- // },
39
- // {
40
- // title: "Scroll-area",
41
- // href: "/docs/primitives/scroll-area",
42
- // description: "Visually or semantically separates content.",
43
- // },
44
- // {
45
- // title: "Tabs",
46
- // href: "/docs/primitives/tabs",
47
- // description:
48
- // "A set of layered sections of content—known as tab panels—that are displayed one at a time.",
49
- // },
50
- // {
51
- // title: "Tooltip",
52
- // href: "/docs/primitives/tooltip",
53
- // description:
54
- // "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.",
55
- // },
56
- // ]
57
-
58
- // export function NavigationMenuDemo() {
59
- // return (
60
- // <NavigationMenu>
61
- // <NavigationMenuList>
62
- // <NavigationMenuItem>
63
- // <NavigationMenuTrigger>Getting started</NavigationMenuTrigger>
64
- // <NavigationMenuContent>
65
- // <ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
66
- // <li className="row-span-3">
67
- // <NavigationMenuLink asChild>
68
- // <a
69
- // className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
70
- // href="/"
71
- // >
72
- // {/* <Icons.logo className="h-6 w-6" /> */}
73
- // <div className="mb-2 mt-4 text-lg font-medium">
74
- // shadcn/ui
75
- // </div>
76
- // <p className="text-sm leading-tight text-muted-foreground">
77
- // Beautifully designed components that you can copy and
78
- // paste into your apps. Accessible. Customizable. Open
79
- // Source.
80
- // </p>
81
- // </a>
82
- // </NavigationMenuLink>
83
- // </li>
84
- // <ListItem href="/docs" title="Introduction">
85
- // Re-usable components built using Radix UI and Tailwind CSS.
86
- // </ListItem>
87
- // <ListItem href="/docs/installation" title="Installation">
88
- // How to install dependencies and structure your app.
89
- // </ListItem>
90
- // <ListItem href="/docs/primitives/typography" title="Typography">
91
- // Styles for headings, paragraphs, lists...etc
92
- // </ListItem>
93
- // </ul>
94
- // </NavigationMenuContent>
95
- // </NavigationMenuItem>
96
- // <NavigationMenuItem>
97
- // <NavigationMenuTrigger>Components</NavigationMenuTrigger>
98
- // <NavigationMenuContent>
99
- // <ul className="w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-1 lg:w-[600px] ">
100
- // {components.map((component) => (
101
- // <ListItem
102
- // key={component.title}
103
- // title={component.title}
104
- // href={component.href}
105
- // >
106
- // {component.description}
107
- // </ListItem>
108
- // ))}
109
- // </ul>
110
- // </NavigationMenuContent>
111
- // </NavigationMenuItem>
112
- // <NavigationMenuItem>
113
- // <Link href="/docs" legacyBehavior passHref>
114
- // <NavigationMenuLink className={navigationMenuTriggerStyle()}>
115
- // Documentation
116
- // </NavigationMenuLink>
117
- // </Link>
118
- // </NavigationMenuItem>
119
- // </NavigationMenuList>
120
- // </NavigationMenu>
121
- // )
122
- // }
123
-
124
-
125
20
  const DesktopNav: React.FC<{
126
21
  links: LinkDefExtended[],
127
22
  }> = ({
@@ -135,7 +30,7 @@ const DesktopNav: React.FC<{
135
30
 
136
31
  if (el.isAIMenu) {
137
32
  return (
138
- <NavigationMenuItem>
33
+ <NavigationMenuItem key={index}>
139
34
  <Link href={el.href} legacyBehavior passHref>
140
35
  <NavigationMenuLink className={navigationMenuTriggerStyle()}>
141
36
  {el.title}
@@ -145,11 +40,11 @@ const DesktopNav: React.FC<{
145
40
  )
146
41
  } else if (el.title == 'Community') {
147
42
  return (
148
- <NavigationMenuItem>
43
+ <NavigationMenuItem key={index}>
149
44
  <NavigationMenuTrigger>{el.title}</NavigationMenuTrigger>
150
45
  <NavigationMenuContent>
151
- <ul className="grid md:grid-cols-2 gap-3 p-6 md:w-[400px] lg:w-[500px]">
152
- <li className="row-span-3">
46
+ <ul className="grid md:grid-cols-2 gap-3 p-6 md:w-[400px] lg:w-[500px]" key={index}>
47
+ <li className="row-span-3" key='0'>
153
48
  <NavigationMenuLink asChild>
154
49
  <a
155
50
  className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
@@ -165,12 +60,12 @@ const DesktopNav: React.FC<{
165
60
  </a>
166
61
  </NavigationMenuLink>
167
62
  </li>
168
- {el.childMenu?.map((component) => (
169
- <div className="relative flex items-center my-2">
63
+ {el.childMenu?.map((component, index) => (
64
+ <div className="relative flex items-center my-2" key={index}>
170
65
  <div className="mr-2 mt-0">
171
66
  {component.icon}
172
67
  </div>
173
- <ListItem href={component.href} title={component.title}>
68
+ <ListItem href={component.href} title={component.title} key={index}>
174
69
  {component.contents}
175
70
  </ListItem>
176
71
  </div>
@@ -182,13 +77,13 @@ const DesktopNav: React.FC<{
182
77
  )
183
78
  } else {
184
79
  return (
185
- <NavigationMenuItem>
80
+ <NavigationMenuItem key={index}>
186
81
  <NavigationMenuTrigger>{el.title}</NavigationMenuTrigger>
187
82
  <NavigationMenuContent>
188
- <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[500px] ">
189
- {el.childMenu?.map((component) => (
83
+ <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[500px] " key={index}>
84
+ {el.childMenu?.map((component, index) => (
190
85
  <ListItem
191
- key={component.title}
86
+ key={index}
192
87
  title={component.title}
193
88
  href={component.href}
194
89
  >
@@ -211,9 +106,9 @@ export default DesktopNav
211
106
  const ListItem = React.forwardRef<
212
107
  React.ElementRef<"a">,
213
108
  React.ComponentPropsWithoutRef<"a">
214
- >(({ className, title, children, ...props }, ref) => {
109
+ >(({ className, title, children, key, ...props }, ref) => {
215
110
  return (
216
- <li>
111
+ <li key={key}>
217
112
  <NavigationMenuLink asChild>
218
113
  <a
219
114
  ref={ref}
@@ -27,14 +27,6 @@ const CommerceUIComponent: React.FC = observer(() => {
27
27
  router.push('/checkout')
28
28
  }
29
29
 
30
- // see handleCloseGesture()
31
- const setOpen = (b: boolean): void => {
32
- if (!b) {
33
- if (!drawer.closedByUser) {
34
- drawer.setClosedByUser(true)
35
- }
36
- }
37
- }
38
30
 
39
31
  const handleHandleClicked = (): void => {
40
32
 
@@ -64,19 +56,10 @@ const CommerceUIComponent: React.FC = observer(() => {
64
56
  return false
65
57
  }
66
58
 
67
-
68
59
  return (
69
60
  <CommerceDrawer
70
- open={drawer.open}
71
- setOpen={setOpen}
72
- snapPoints={drawer.points}
73
- modal={drawer.modal}
74
- activeSnapPoint={drawer.activePoint}
75
- setActiveSnapPoint={drawer.onActivePointChanged.bind(drawer)}
76
61
  handleHandleClicked={handleHandleClicked}
77
62
  handleCloseGesture={handleCloseGesture}
78
- micro={drawer.state === 'micro'}
79
- mobile={drawer.isMobile}
80
63
  drawerClx='flex flex-col'
81
64
  >
82
65
  {drawer.state === 'full' && (
@@ -1,5 +1,6 @@
1
1
  'use client'
2
2
  import React, {type PropsWithChildren } from 'react'
3
+ import { observer } from 'mobx-react-lite'
3
4
 
4
5
  import {
5
6
  Drawer,
@@ -10,74 +11,75 @@ import {
10
11
  import { cn } from '@hanzo/ui/util'
11
12
 
12
13
  import '../../../style/drawer-handle-overrides.css'
14
+ import { useCommerceDrawer } from '../../../commerce/ui/context'
13
15
 
14
16
  const CommerceDrawer: React.FC<PropsWithChildren &
15
- Omit<DrawerProps, 'onOpenChange'> &
17
+ Omit<DrawerProps,
18
+ 'onOpenChange' |
19
+ 'open' |
20
+ 'snapPoints' |
21
+ 'modal' |
22
+ 'setActiveSnapPoint' |
23
+ 'activeSnapPoint'
24
+ > &
16
25
  {
17
- setOpen: (b: boolean) => void
18
26
  handleHandleClicked: () => void
19
27
  drawerClx?: string
20
- mobile?: boolean
21
- micro?: boolean
22
28
  }
23
- > = ({
29
+ > = observer(({
24
30
  children,
25
- open,
26
- setOpen,
27
- modal,
28
- snapPoints,
29
- setActiveSnapPoint,
30
- activeSnapPoint,
31
31
  handleHandleClicked,
32
32
  drawerClx='',
33
- mobile=false,
34
- micro=false,
35
33
  ...rest
36
- }) => (
37
- // @ts-ignore
38
- <Drawer
39
- open={open}
40
- onOpenChange={setOpen}
41
- modal={modal}
42
- snapPoints={snapPoints}
43
- setActiveSnapPoint={setActiveSnapPoint}
44
- activeSnapPoint={activeSnapPoint}
45
- fastDragSkipsToEnd={false}
46
- dragHandleOnly={true}
47
- handleHandleClicked={handleHandleClicked}
48
- extendHandleDragRegion={false}
49
- // debugOutput
50
- {...rest}
51
- >
52
- <DrawerContent
53
- defaultHandle={false}
54
- className={cn(
55
- 'border-0',
56
- //(micro ? (mobile ? 'mt-4 pt-1.5' : 'mt-5 pt-4') : 'mt-5 pt-5'),
57
- mobile ? 'pt-5' : 'pt-6',
58
- 'w-full h-full',
59
- )}
60
- // https://github.com/radix-ui/primitives/discussions/935
61
- onOpenAutoFocus={(e) => {e.preventDefault()}}
34
+ }) => {
35
+
36
+ const drawer = useCommerceDrawer()
37
+
38
+ return (
39
+ <Drawer
40
+ open={drawer.open}
41
+ onOpenChange={() => {}}
42
+ modal={drawer.modal}
43
+ snapPoints={drawer.points}
44
+ activeSnapPoint={drawer.activePoint}
45
+ setActiveSnapPoint={drawer.onActivePointChanged.bind(drawer)}
46
+ fastDragSkipsToEnd={false}
47
+ dragHandleOnly={true}
48
+ handleHandleClicked={handleHandleClicked}
49
+ extendHandleDragRegion={false}
50
+ // debugOutput
51
+ {...rest}
62
52
  >
63
- <DrawerHandle
53
+ <DrawerContent
54
+ defaultHandle={false}
64
55
  className={cn(
65
- 'absolute top-0 left-0 right-0 mx-auto z-10',
66
- 'flex justify-center items-start',
67
- 'border-t rounded-t-lg border-muted-2',
68
- mobile ? 'h-5 touch-pan-y' : 'h-6',
69
- )}
56
+ 'border-0',
57
+ drawer.isMobile ? 'pt-5' : 'pt-6',
58
+ 'w-full h-full',
59
+ )}
60
+ // https://github.com/radix-ui/primitives/discussions/935
61
+ onOpenAutoFocus={(e) => {e.preventDefault()}}
70
62
  >
71
- <div className={cn(
72
- // pseudo-handle
73
- 'rounded-[3px] bg-level-3',
74
- mobile ? 'w-[155px] mt-[5px] h-1.5' : 'w-[180px] mt-[3px] h-2.5 hover:bg-level-4',
75
- !mobile ? 'cursor-grab active:cursor-grabbing' : '',
76
- )} />
77
- </DrawerHandle>
78
- {children}
79
- </DrawerContent>
80
- </Drawer>
81
- )
63
+ <DrawerHandle
64
+ className={cn(
65
+ 'absolute top-0 left-0 right-0 mx-auto z-10',
66
+ 'flex justify-center items-start',
67
+ 'border-t rounded-t-lg border-muted-3',
68
+ drawer.isMobile ? 'h-5 touch-pan-y' : 'h-6',
69
+ )}
70
+ >
71
+ <div className={cn(
72
+ // pseudo-handle
73
+ 'rounded-[3px] bg-level-3',
74
+ drawer.isMobile ? 'w-[155px] mt-[5px] h-1.5' : 'w-[180px] mt-[3px] h-2.5 hover:bg-level-4',
75
+ !drawer.isMobile ? 'cursor-grab active:cursor-grabbing' : '',
76
+ )} />
77
+ </DrawerHandle>
78
+ {children}
79
+ </DrawerContent>
80
+ </Drawer>
81
+ )
82
+ })
83
+
82
84
 
83
85
  export default CommerceDrawer
@@ -2,9 +2,7 @@
2
2
  import React, { useState } from 'react'
3
3
  import { Plus } from 'lucide-react'
4
4
  import { Search } from '../icons'
5
- import { ChatWidget } from '../../components'
6
5
  import { Button, Card } from '@hanzo/ui/primitives'
7
- import LuxLogo from '../icons/lux-logo'
8
6
 
9
7
  interface MobileNavMenuAIProps {
10
8
  setMenuOpen: (open: boolean) => void
@@ -33,7 +33,7 @@ const Footer: React.FC<{
33
33
  'md:flex md:flex-row md:justify-between '
34
34
  }>
35
35
  <div className='hidden lg:flex flex-col' key={0}>
36
- <Logo size='md' layout='text-only' />
36
+ <Logo size='md' variant='text-only' />
37
37
  </div>
38
38
  {footer.map((defs: LinkDef[], index: number) => {
39
39
 
@@ -32,18 +32,10 @@ const DesktopHeader: React.FC<{
32
32
  'flex flex-row h-[80px] items-center justify-between ' +
33
33
  'px-[8px] w-full mx-auto max-w-screen'
34
34
  }>
35
- <Logo size='md' href='/' className='hidden lg:flex' key='two' layout='text-only'/>
36
- <Logo size='sm' href='/' className='hidden md:flex lg:hidden' key='one' layout='text-only'/>
35
+ <Logo size='md' href='/' outerClx='hidden lg:flex' key='two' variant='text-only'/>
36
+ <Logo size='sm' href='/' outerClx='hidden md:flex lg:hidden' key='one' variant='text-only'/>
37
37
  {/* md or larger */}
38
38
  <div className='flex gap-4 items-center'>
39
- {/* <NavItems
40
- currentAs={currentAs}
41
- items={links}
42
- className='flex md:gap-4 lg:justify-between lg:gap-7'
43
- itemClx='font-nav h-8'
44
- key='three'
45
- /> */}
46
-
47
39
  <DesktopNav links = {links}/>
48
40
  <DesktopBagPopup popupClx='w-[340px]' trigger={<BagButton className='text-primary -mr-[3px] lg:min-w-0' />} />
49
41
  <AuthWidget/>
@@ -86,28 +86,25 @@ const MobileHeader: React.FC<{
86
86
  // header element MUST be fixed, and NOT sticky. Or else drawer breaks on mobile browsers
87
87
  return (<>
88
88
  <header className={cn(
89
- `bg-background fixed z-header top-0 left-0 w-full h-19 ${menuOpen() ? 'hidden' : 'block'}`,
89
+ `bg-background fixed z-header top-0 left-0 w-full ${menuOpen() ? 'hidden' : 'block'}`,
90
90
  className
91
91
  )}>
92
92
  {/* smaller than md: mobile style drawer menu; h-11 is 44px, the standard mobile header height */}
93
- <div className="flex h-11 items-center justify-between pl-6 pr-4">
94
- <div className='h-[74px] w-pr-100 flex flex-row justify-between items-center font-bold'>
95
- <Logo href='/' size='sm' className={'top-[3px] h-full'} layout='text-only' />
96
- {/* Not that key to the cross-fade effect
97
- is that this is **on top of** the logo. */}
98
- {menuOpen() && (
99
- <div className={'absolute left-0 top-0 bottom-0 right-0 pl-8 ' +
100
- 'flex flex-row ' +
101
- 'bg-background animate-mobile-menu-open'
102
- }>
103
- <Icons.Avatar className='self-center ' />
104
- </div>
105
- )}
106
- <div className='flex gap-0 flex-row'>
107
- <BagButton className='text-primary -mr-[3px]' onClick={openBag} />
108
- <MenuToggleButton className='text-foreground' open={menuOpen()} setOpen={setMenuOpen} />
93
+ <div className='w-full h-11 flex flex-row justify-between items-center font-bold pl-6 pr-4'>
94
+ <Logo href='/' size='sm' outerClx={'top-[3px] h-full'} variant='text-only' />
95
+ {/* Not that key to the cross-fade effect
96
+ is that this is **on top of** the logo. */}
97
+ {menuOpen() && (
98
+ <div className={'absolute left-0 top-0 bottom-0 right-0 pl-8 ' +
99
+ 'flex flex-row ' +
100
+ 'bg-background animate-mobile-menu-open'
101
+ }>
102
+ <Icons.Avatar className='self-center ' />
109
103
  </div>
110
-
104
+ )}
105
+ <div className='flex gap-0 flex-row'>
106
+ <BagButton className='text-primary -mr-[3px]' onClick={openBag} />
107
+ <MenuToggleButton className='text-foreground' open={menuOpen()} setOpen={setMenuOpen} />
111
108
  </div>
112
109
 
113
110
  </div>
@@ -12,6 +12,7 @@ export { default as NotFound } from './not-found'
12
12
 
13
13
  export { default as AuthListener } from './auth/auth-listener'
14
14
  export { default as AddWidget } from './commerce/add-widget'
15
+ export { default as BackButton } from './back-button'
15
16
  export { default as BuyDrawer } from './commerce/drawer'
16
17
  export { default as DrawerMargin } from './drawer-margin'
17
18
  export { default as BuyButton } from './commerce/buy-button'
@@ -20,6 +21,7 @@ export { default as CheckoutPanel } from './commerce/checkout-panel'
20
21
  export { default as CheckoutWidget } from './commerce/checkout-widget'
21
22
  export { default as LoginPanel } from './auth/login-panel'
22
23
  export { default as Scripts } from './scripts'
24
+ export { default as Tooltip } from './tooltip'
23
25
 
24
26
  export { default as EmblaAutoplay } from 'embla-carousel-autoplay'
25
27
 
@@ -2,77 +2,85 @@ import React from 'react'
2
2
  import Link from 'next/link'
3
3
 
4
4
  import { type TShirtSize } from '@hanzo/ui/types'
5
+
5
6
  import { cn } from '@hanzo/ui/util'
6
7
 
7
8
  import * as Icons from './icons'
8
9
 
10
+ const TEXT = 'LUX'
11
+
9
12
  const Logo: React.FC<{
10
13
  size?: TShirtSize
11
- layout?: 'text-only' | 'logo-only' | 'full'
14
+ variant?: 'text-only' | 'logo-only' | 'full'
15
+ onClick?: () => void
12
16
  href?: string
13
- className?: string
14
- spanClassName?: string
17
+ outerClx?: string
18
+ textClx?: string
15
19
  }> = ({
16
20
  size,
17
21
  href, // no default please!
18
- className='',
19
- spanClassName,
20
- layout='full'
22
+ outerClx='',
23
+ textClx='',
24
+ variant='full',
25
+ onClick,
21
26
  }) => {
22
27
  let classes: any = {}
23
- const toAdd = (layout === 'logo-only') ? {
24
- span: ' hidden',
25
- icon: ''
26
- } :
27
- (layout === 'text-only') ? {
28
- span: '',
29
- icon: ' hidden'
30
- } :
31
- {
32
- span: '',
33
- icon: ''
34
- }
28
+ const toAdd = (variant === 'logo-only') ?
29
+ {
30
+ span: 'hidden',
31
+ icon: ''
32
+ }
33
+ :
34
+ (variant === 'text-only') ?
35
+ {
36
+ span: '',
37
+ icon: 'hidden'
38
+ }
39
+ :
40
+ {
41
+ span: '',
42
+ icon: ''
43
+ }
35
44
 
36
45
  if (size === 'lg' || size === 'xl' ) { // for safety
37
- classes.icon = 'h-10 w-10 mr-4 color-inherit' + toAdd.icon
38
- classes.span = 'text-3xl' + toAdd.span
46
+ classes.icon = 'h-10 w-10 mr-4 color-inherit '
47
+ classes.span = 'text-3xl '
39
48
  }
40
49
  // match lux.network
41
50
  else if (size === 'md') {
42
- classes.icon = 'h-[32px] w-[32px] mr-[12px] color-inherit' + toAdd.icon
43
- classes.span = 'text-[1.8rem]/[1.8rem] tracking-tighter' + toAdd.span
51
+ classes.icon = 'h-[32px] w-[32px] mr-[12px] color-inherit '
52
+ classes.span = 'text-[1.8rem]/[1.8rem] tracking-tighter '
44
53
  }
45
54
  else if (size === 'sm' ) {
46
- classes.icon = 'h-6 w-6 mr-2 color-inherit' + toAdd.icon
47
- classes.span = 'text-lg' + toAdd.span
55
+ classes.icon = 'h-6 w-6 mr-2 color-inherit '
56
+ classes.span = 'text-lg '
48
57
  }
49
58
  // xs
50
59
  else {
51
- classes.icon = 'h-4 w-4 mr-1 color-inherit' + toAdd.icon
52
- classes.span = 'text-base' + toAdd.span
60
+ classes.icon = 'h-4 w-4 mr-1 color-inherit '
61
+ classes.span = 'text-base '
53
62
  }
54
63
 
55
- const outerClasses = 'flex flex-row items-center ' + className
56
- const spanClasses = 'inline-block font-bold font-heading '
57
- + spanClassName
58
- + (href ? ' hover:text-accent ' : ' cursor-default ')
59
- + classes.span
64
+ classes.icon += toAdd.icon
65
+ classes.span += toAdd.span
60
66
 
61
- const Inner: React.FC = () => (<>
62
- <Icons.logo className={classes.icon} />
63
- <span className={cn(spanClasses, ' text-inherit')}>LUX</span>
64
- </>)
65
67
 
68
+ const outerClasses = 'flex flex-row items-center ' + outerClx
69
+ const spanClasses = 'inline-block font-bold font-heading '
70
+ + textClx
71
+ + (href ? ' hover:text-accent cursor-pointer ' : ' cursor-default ')
72
+ + classes.span
66
73
 
67
74
  return (
68
75
  href ? (
69
- <Link href={href} className={outerClasses} >
70
- <Inner />
76
+ <Link href={href} className={outerClasses} onClick={onClick} >
77
+ <Icons.logo className={classes.icon} />
78
+ <span className={spanClasses}>{TEXT}</span>
71
79
  </Link>
72
-
73
80
  ) : (
74
- <span className={outerClasses} >
75
- <Inner />
81
+ <span className={outerClasses} onClick={onClick}>
82
+ <Icons.logo className={classes.icon} />
83
+ <span className={spanClasses}>{TEXT}</span>
76
84
  </span>
77
85
  )
78
86
  )
@@ -0,0 +1,31 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import { Tooltip as RTTooltip, type PlacesType } from 'react-tooltip'
4
+
5
+ const Tooltip: React.FC<{
6
+ select: string
7
+ text: string
8
+ position?: PlacesType // https://react-tooltip.com/docs/options
9
+ clx?: string
10
+ offset?: number
11
+ }> = ({
12
+ select,
13
+ text,
14
+ clx='',
15
+ position='bottom',
16
+ offset=2
17
+ }) => (
18
+ <RTTooltip
19
+ anchorSelect={select}
20
+ noArrow
21
+ opacity={1}
22
+ content={text}
23
+ place={position}
24
+ offset={offset}
25
+ delayShow={100}
26
+ delayHide={100}
27
+ className={'!opacity-100 !bg-level-2 border rounded-[3px] !px-1.5 !py-1 z-floating' + clx}
28
+ />
29
+ )
30
+
31
+ export default Tooltip
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luxfi/core",
3
- "version": "5.2.6",
3
+ "version": "5.2.8",
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/",
@@ -44,6 +44,7 @@
44
44
  "firebase": "10.12.0",
45
45
  "react-device-detect": "^2.2.3",
46
46
  "react-social-icons": "^6.4.0",
47
+ "react-tooltip": "^5.26.4",
47
48
  "request": "^2.88.2",
48
49
  "usehooks-ts": "^3.1.0"
49
50
  },
@@ -1,26 +0,0 @@
1
- 'use client'
2
- import React from 'react'
3
-
4
- import { cn } from '@hanzo/ui/util'
5
-
6
- import Logo from '../../logo'
7
- import type { TShirtSize } from '@hanzo/ui/types'
8
-
9
- const CloseButton: React.FC<{
10
- close: () => void
11
- size?: TShirtSize
12
- className?: string
13
- }> = ({
14
- close,
15
- size,
16
- className=''
17
- }) => (
18
- <div
19
- onClick={close}
20
- className={cn('md:self-start', className)}
21
- >
22
- <Logo layout='text-only' href='/' size={size}/>
23
- </div>
24
- )
25
-
26
- export default CloseButton