@luxfi/core 5.3.0 → 5.3.2

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.
Files changed (179) hide show
  1. package/commerce/ui/conf.ts +13 -13
  2. package/commerce/ui/context.tsx +123 -123
  3. package/commerce/ui/store.ts +289 -289
  4. package/components/access-code-input.tsx +71 -71
  5. package/components/auth/auth-listener.tsx +29 -29
  6. package/components/auth/auth-token/clear-auth-token.tsx +12 -12
  7. package/components/auth/auth-token/set-auth-token.tsx +16 -16
  8. package/components/auth/common-auth-domains.ts +16 -16
  9. package/components/auth/login-panel.tsx +107 -107
  10. package/components/back-button.tsx +49 -49
  11. package/components/chat-widget.tsx +85 -85
  12. package/components/commerce/_to_deprecate_checkout-widget/const.ts +13 -13
  13. package/components/commerce/_to_deprecate_checkout-widget/index.tsx_ +188 -188
  14. package/components/commerce/_to_deprecate_checkout-widget/obs-string-set.ts +48 -48
  15. package/components/commerce/_to_deprecate_checkout-widget/use-anim-clx-set.ts +58 -58
  16. package/components/commerce/bag-button.tsx +98 -98
  17. package/components/commerce/buy-button.tsx +34 -34
  18. package/components/commerce/checkout-button.tsx +129 -129
  19. package/components/commerce/checkout-panel/cart-accordian.tsx +66 -66
  20. package/components/commerce/checkout-panel/checkout-panel-props.ts +9 -9
  21. package/components/commerce/checkout-panel/desktop-bag-carousel.tsx +36 -36
  22. package/components/commerce/checkout-panel/desktop-cp.tsx +82 -82
  23. package/components/commerce/checkout-panel/index.tsx +126 -126
  24. package/components/commerce/checkout-panel/mobile-cp.tsx +66 -66
  25. package/components/commerce/checkout-panel/policy-links.tsx +29 -29
  26. package/components/commerce/checkout-panel/steps-indicator.tsx +39 -39
  27. package/components/commerce/checkout-panel/thank-you.tsx +18 -18
  28. package/components/commerce/desktop-bag-popup.tsx +78 -78
  29. package/components/commerce/desktop-nav-menu.tsx +130 -130
  30. package/components/commerce/drawer/index.tsx +88 -88
  31. package/components/commerce/drawer/micro.tsx +144 -144
  32. package/components/commerce/drawer/shell.tsx +85 -85
  33. package/components/commerce/mobile-bag-drawer.tsx +51 -51
  34. package/components/commerce/mobile-login-button.tsx +107 -101
  35. package/components/commerce/mobile-menu-toggle-button.tsx +35 -35
  36. package/components/commerce/mobile-nav-menu-ai.tsx +50 -47
  37. package/components/commerce/mobile-nav-menu-item.tsx +49 -49
  38. package/components/commerce/mobile-nav-menu.tsx +101 -101
  39. package/components/contact-dialog/contact-form.tsx +113 -113
  40. package/components/contact-dialog/disclaimer.tsx +13 -13
  41. package/components/contact-dialog/index.tsx +64 -64
  42. package/components/copyright.tsx +21 -21
  43. package/components/drawer-margin.tsx +25 -25
  44. package/components/footer.tsx +77 -77
  45. package/components/header/desktop.tsx +51 -50
  46. package/components/header/index.tsx +50 -52
  47. package/components/header/mobile.tsx +163 -163
  48. package/components/header/theme-toggle.tsx +26 -26
  49. package/components/icons/24k-gold-card.tsx +43 -43
  50. package/components/icons/ai-chat-act.tsx +47 -47
  51. package/components/icons/ai-chat.tsx +29 -29
  52. package/components/icons/anodized-titanium.tsx +45 -45
  53. package/components/icons/avatar.tsx +11 -11
  54. package/components/icons/bag-icon.tsx +10 -10
  55. package/components/icons/blog-act.tsx +14 -14
  56. package/components/icons/blog.tsx +20 -20
  57. package/components/icons/bridge-act.tsx +18 -18
  58. package/components/icons/bridge.tsx +68 -68
  59. package/components/icons/changelog-act.tsx +15 -15
  60. package/components/icons/changelog.tsx +21 -21
  61. package/components/icons/chrome.tsx +45 -45
  62. package/components/icons/coins-act.tsx +29 -29
  63. package/components/icons/coins.tsx +20 -20
  64. package/components/icons/compare-cards-act.tsx +30 -30
  65. package/components/icons/compare-cards.tsx +21 -21
  66. package/components/icons/credit-act.tsx +29 -29
  67. package/components/icons/credit.tsx +20 -20
  68. package/components/icons/customer-support-act.tsx +27 -27
  69. package/components/icons/customer-support.tsx +21 -21
  70. package/components/icons/customers-act.tsx +65 -65
  71. package/components/icons/customers.tsx +33 -33
  72. package/components/icons/developer-docs-act.tsx +26 -26
  73. package/components/icons/developer-docs.tsx +20 -20
  74. package/components/icons/exchange-act.tsx +27 -27
  75. package/components/icons/exchange.tsx +21 -21
  76. package/components/icons/explorer-act.tsx +27 -27
  77. package/components/icons/explorer.tsx +22 -22
  78. package/components/icons/faqs-act.tsx +27 -27
  79. package/components/icons/faqs.tsx +21 -21
  80. package/components/icons/github.tsx +14 -14
  81. package/components/icons/guides-act.tsx +26 -26
  82. package/components/icons/guides.tsx +21 -21
  83. package/components/icons/gun-metal.tsx +44 -44
  84. package/components/icons/index.tsx +43 -43
  85. package/components/icons/integrations-act.tsx +41 -41
  86. package/components/icons/integrations.tsx +25 -25
  87. package/components/icons/irradescent.tsx +41 -41
  88. package/components/icons/launch-subnet.tsx +21 -21
  89. package/components/icons/launchsubnet-act.tsx +29 -29
  90. package/components/icons/left-arrow.tsx +11 -11
  91. package/components/icons/lux-finance-act.tsx +34 -34
  92. package/components/icons/lux-finance.tsx +23 -23
  93. package/components/icons/lux-logo.tsx +10 -10
  94. package/components/icons/lux-pass-act.tsx +41 -41
  95. package/components/icons/lux-pass.tsx +25 -25
  96. package/components/icons/lux-quests-act.tsx +15 -15
  97. package/components/icons/lux-quests.tsx +21 -21
  98. package/components/icons/market-act.tsx +39 -39
  99. package/components/icons/market.tsx +24 -24
  100. package/components/icons/mirrored-titanium.tsx +46 -46
  101. package/components/icons/more-benefits-act.tsx +29 -29
  102. package/components/icons/more-benefits.tsx +21 -21
  103. package/components/icons/open-source-act.tsx +41 -41
  104. package/components/icons/open-source.tsx +26 -26
  105. package/components/icons/right-arrow.tsx +10 -10
  106. package/components/icons/safe-act.tsx +77 -77
  107. package/components/icons/safe.tsx +37 -37
  108. package/components/icons/search.tsx +12 -12
  109. package/components/icons/secure-delivery.tsx +13 -13
  110. package/components/icons/shop-act.tsx +29 -29
  111. package/components/icons/shop.tsx +20 -20
  112. package/components/icons/social-icon.tsx +35 -35
  113. package/components/icons/social-svg.css +3 -3
  114. package/components/icons/sterling-silver-card.tsx +44 -44
  115. package/components/icons/templates-act.tsx +29 -29
  116. package/components/icons/templates.tsx +21 -21
  117. package/components/icons/validators-act.tsx +42 -42
  118. package/components/icons/validators.tsx +41 -41
  119. package/components/icons/view-all-card-act.tsx +28 -28
  120. package/components/icons/view-all-card.tsx +20 -20
  121. package/components/icons/wallet-act.tsx +29 -29
  122. package/components/icons/wallet.tsx +20 -20
  123. package/components/icons/warpcast.tsx +58 -58
  124. package/components/icons/youtube-logo.tsx +59 -59
  125. package/components/index.ts +25 -25
  126. package/components/logo.tsx +89 -89
  127. package/components/main.tsx +27 -27
  128. package/components/mini-chart/index.tsx +7 -7
  129. package/components/mini-chart/mini-chart-props.ts +43 -43
  130. package/components/mini-chart/mini-chart.tsx +85 -85
  131. package/components/mini-chart/wrapper.tsx +23 -23
  132. package/components/not-found/index.tsx +28 -28
  133. package/components/not-found/not-found-content.mdx +5 -5
  134. package/components/scripts.tsx +24 -24
  135. package/components/tooltip.tsx +31 -31
  136. package/environment.d.ts +5 -5
  137. package/next/analytics/fpixel.ts +15 -15
  138. package/next/analytics/google-analytics.ts +13 -13
  139. package/next/analytics/index.ts +3 -3
  140. package/next/analytics/pixel-analytics.tsx +54 -54
  141. package/next/font/get-app-router-font-classes.ts +12 -12
  142. package/next/font/load-and-return-lux-next-fonts-on-import.ts +68 -68
  143. package/next/font/next-font-desc.ts +27 -27
  144. package/next/font/pages-router-font-vars.tsx +18 -18
  145. package/next/head-metadata/from-next/metadata-types.ts +158 -158
  146. package/next/head-metadata/from-next/opengraph-types.ts +267 -267
  147. package/next/head-metadata/from-next/twitter-types.ts +92 -92
  148. package/next/head-metadata/index.tsx +208 -208
  149. package/next/middleware/determine-device-mw.ts +16 -16
  150. package/package.json +79 -79
  151. package/root-layout/WHY_THIS_IS_SEPARATE.txt +1 -1
  152. package/root-layout/index.tsx +112 -112
  153. package/server-actions/firebase-app.ts +14 -14
  154. package/server-actions/index.ts +5 -5
  155. package/server-actions/store-contact.ts +51 -51
  156. package/site-def/footer/community.tsx +67 -67
  157. package/site-def/footer/company.ts +37 -37
  158. package/site-def/footer/ecosystem.ts +37 -37
  159. package/site-def/footer/index.tsx +26 -26
  160. package/site-def/footer/legal.ts +28 -28
  161. package/site-def/footer/network.ts +45 -45
  162. package/site-def/footer/svg/warpcast-logo.svg +11 -11
  163. package/site-def/index.ts +2 -2
  164. package/site-def/main-nav.tsx +458 -458
  165. package/style/cart-animation.css +29 -29
  166. package/style/checkout-animation.css +23 -23
  167. package/style/drawer-handle-overrides.css +160 -160
  168. package/style/lux-colors.css +85 -85
  169. package/style/lux-global.css +50 -47
  170. package/tailwind/fontFamily.tailwind.lux.ts +18 -18
  171. package/tailwind/index.ts +2 -2
  172. package/tailwind/lux-tw-fonts.ts +39 -39
  173. package/tailwind/tailwind.config.lux-preset.ts +10 -10
  174. package/tsconfig.json +15 -15
  175. package/types/chatbot-config.ts +6 -6
  176. package/types/chatbot-suggested-question.ts +7 -7
  177. package/types/contact-info.ts +10 -10
  178. package/types/index.ts +4 -4
  179. package/types/site-def.ts +43 -43
@@ -1,85 +1,85 @@
1
- 'use client'
2
- import React from 'react'
3
-
4
- import { Button, Card } from '@hanzo/ui/primitives'
5
- import { cn } from '@hanzo/ui/util'
6
-
7
- import LuxLogo from './icons/lux-logo'
8
- import type { ChatbotSuggestedQuestion } from '../types'
9
-
10
- const ChatWidget: React.FC<{
11
- title: string
12
- chatbotUrl: string
13
- subtitle?: string
14
- question?: string
15
- buttonClx?: string
16
- /*
17
- ChatBotSuggestQuestion.icon
18
- Currently supports these icons from remix icons (https://remixicon.com/):
19
- GlobalLineIcon,
20
- ShieldFlashLineIcon,
21
- BankCardLineIcon,
22
- GroupLineIcon,
23
- QuestionnaireLineIcon
24
- */
25
- suggestedQuestions?: ChatbotSuggestedQuestion[]
26
- }> = ({
27
- title,
28
- chatbotUrl,
29
- subtitle,
30
- question,
31
- suggestedQuestions,
32
- buttonClx=''
33
- }) => {
34
-
35
- const [showChatbot, setShowChatbot] = React.useState<boolean>(false)
36
-
37
- const onClick = () => { setShowChatbot(!showChatbot) }
38
-
39
- const searchParams = new URLSearchParams()
40
- if (question) {
41
- searchParams.append('question', question)
42
- }
43
- if (suggestedQuestions) {
44
- searchParams.append('sQuestions', suggestedQuestions.map(({ message }) => message).join(','))
45
- searchParams.append('sHeadings', suggestedQuestions.map(({ heading }) => heading).join(','))
46
- searchParams.append('sIcons', suggestedQuestions.map(({ icon }) => icon).join(','))
47
- }
48
-
49
- const iframeSrc = `${chatbotUrl}?${searchParams.toString()}`
50
-
51
- return (<>
52
- <div className={
53
- 'fixed bottom-0 sm:bottom-16 right-0 w-full h-full ' +
54
- 'sm:max-w-[400px] sm:max-h-[550px] sm:px-4 z-floating ' +
55
- (showChatbot ? 'flex' : 'hidden')
56
- }>
57
- <Card className='flex flex-col h-full w-full'>
58
- <div className='flex px-4 py-2 h-12 bg-level-0 items-center justify-between'>
59
- <h3 className='font-semibold font-heading'>{title} <span className='opacity-60'>{subtitle}</span></h3>
60
- <Button onClick={onClick} variant='link' size='icon' className='w-fit sm:hidden'>
61
- <LuxLogo width={24} height={24}/>
62
- </Button>
63
- </div>
64
- <iframe src={iframeSrc} className='h-full' />
65
- </Card>
66
- </div>
67
-
68
- <LuxLogo
69
- width={28}
70
- height={28}
71
- onClick={onClick}
72
- className={cn(
73
- // z-index should be below anything in commerce-iu (buy drawer and checkout widget)
74
- 'fixed bottom-5 right-5 z-floating cursor-pointer',
75
- 'hover:drop-shadow-[0_2px_6px_rgba(255,255,255,1)]',
76
- 'transition-transform',
77
- showChatbot ? 'rotate-180' : '',
78
- buttonClx
79
- )}
80
- strokeWidth={1}
81
- />
82
- </>)
83
- }
84
-
85
- export default ChatWidget
1
+ 'use client'
2
+ import React from 'react'
3
+
4
+ import { Button, Card } from '@hanzo/ui/primitives'
5
+ import { cn } from '@hanzo/ui/util'
6
+
7
+ import LuxLogo from './icons/lux-logo'
8
+ import type { ChatbotSuggestedQuestion } from '../types'
9
+
10
+ const ChatWidget: React.FC<{
11
+ title: string
12
+ chatbotUrl: string
13
+ subtitle?: string
14
+ question?: string
15
+ buttonClx?: string
16
+ /*
17
+ ChatBotSuggestQuestion.icon
18
+ Currently supports these icons from remix icons (https://remixicon.com/):
19
+ GlobalLineIcon,
20
+ ShieldFlashLineIcon,
21
+ BankCardLineIcon,
22
+ GroupLineIcon,
23
+ QuestionnaireLineIcon
24
+ */
25
+ suggestedQuestions?: ChatbotSuggestedQuestion[]
26
+ }> = ({
27
+ title,
28
+ chatbotUrl,
29
+ subtitle,
30
+ question,
31
+ suggestedQuestions,
32
+ buttonClx=''
33
+ }) => {
34
+
35
+ const [showChatbot, setShowChatbot] = React.useState<boolean>(false)
36
+
37
+ const onClick = () => { setShowChatbot(!showChatbot) }
38
+
39
+ const searchParams = new URLSearchParams()
40
+ if (question) {
41
+ searchParams.append('question', question)
42
+ }
43
+ if (suggestedQuestions) {
44
+ searchParams.append('sQuestions', suggestedQuestions.map(({ message }) => message).join(','))
45
+ searchParams.append('sHeadings', suggestedQuestions.map(({ heading }) => heading).join(','))
46
+ searchParams.append('sIcons', suggestedQuestions.map(({ icon }) => icon).join(','))
47
+ }
48
+
49
+ const iframeSrc = `${chatbotUrl}?${searchParams.toString()}`
50
+
51
+ return (<>
52
+ <div className={
53
+ 'fixed bottom-0 sm:bottom-16 right-0 w-full h-full ' +
54
+ 'sm:max-w-[400px] sm:max-h-[550px] sm:px-4 z-floating ' +
55
+ (showChatbot ? 'flex' : 'hidden')
56
+ }>
57
+ <Card className='flex flex-col h-full w-full'>
58
+ <div className='flex px-4 py-2 h-12 bg-level-0 items-center justify-between'>
59
+ <h1 className='font-semibold font-heading'>{title} <span className='opacity-60'>{subtitle}</span></h1>
60
+ <Button onClick={onClick} variant='link' size='icon' className='w-fit sm:hidden'>
61
+ <LuxLogo width={24} height={24}/>
62
+ </Button>
63
+ </div>
64
+ <iframe src={iframeSrc} className='h-full' />
65
+ </Card>
66
+ </div>
67
+
68
+ <LuxLogo
69
+ width={28}
70
+ height={28}
71
+ onClick={onClick}
72
+ className={cn(
73
+ // z-index should be below anything in commerce-iu (buy drawer and checkout widget)
74
+ 'fixed bottom-5 right-[24px] md:z-floating z-16 cursor-pointer',
75
+ 'hover:drop-shadow-[0_2px_6px_rgba(255,255,255,1)]',
76
+ 'transition-transform',
77
+ showChatbot ? 'rotate-180' : '',
78
+ buttonClx
79
+ )}
80
+ strokeWidth={1}
81
+ />
82
+ </>)
83
+ }
84
+
85
+ export default ChatWidget
@@ -1,13 +1,13 @@
1
- export default {
2
- itemImgConstraint: { w: 40, h: 24 },
3
- animDurationMs: 400,
4
- animTimingFn: 'cubic-bezier(0.4, 0, 0.2, 1)',
5
- compWidthClx: {
6
- checkout: 'w-pr-40',
7
- itemInfo: 'w-pr-60'
8
- },
9
- shadowStyle: {
10
- border: '1px solid rgb(100 100 100)',
11
- boxShadow: '2px 4px 4px -3px rgb(125 125 125 / 0.7), 4px -4px 8px -4px rgb(125 125 125 / 0.7)'
12
- }
13
- }
1
+ export default {
2
+ itemImgConstraint: { w: 40, h: 24 },
3
+ animDurationMs: 400,
4
+ animTimingFn: 'cubic-bezier(0.4, 0, 0.2, 1)',
5
+ compWidthClx: {
6
+ checkout: 'w-pr-40',
7
+ itemInfo: 'w-pr-60'
8
+ },
9
+ shadowStyle: {
10
+ border: '1px solid rgb(100 100 100)',
11
+ boxShadow: '2px 4px 4px -3px rgb(125 125 125 / 0.7), 4px -4px 8px -4px rgb(125 125 125 / 0.7)'
12
+ }
13
+ }
@@ -1,188 +1,188 @@
1
- 'use client'
2
- import React, { useRef } from 'react'
3
- import { createPortal } from 'react-dom'
4
- import { usePathname, useRouter } from 'next/navigation'
5
- import { observer } from 'mobx-react-lite'
6
-
7
- import { cn } from '@hanzo/ui/util'
8
- import { useStepAnimation } from '@hanzo/ui/util-client'
9
-
10
- import { Image } from '@hanzo/ui/primitives'
11
-
12
- import CheckoutButton from '../checkout-button'
13
- import useAnimationClxSet from './use-anim-clx-set'
14
- import CONST from './const'
15
- import type { LineItem } from '@hanzo/commerce/types'
16
-
17
- const transStyle = (t: { transition: string, from : string, to: string } | undefined) : any => (
18
- t ? {
19
- transitionProperty: t.transition,
20
- transitionTimingFunction: CONST.animTimingFn,
21
- transitionDuration: `${CONST.animDurationMs}ms`
22
- } : {}
23
- )
24
-
25
- const transClx = (on: boolean, t: { transition: string, from : string, to: string } | undefined) : string => (
26
- on ? (t?.from ?? '') : (t?.to ?? '')
27
- )
28
-
29
- const VARS: any = {
30
- BR: {
31
- pos: 'bottom-[24px] right-[66px]',
32
- width: 'w-initial',
33
- centerText: false,
34
- coClx: 'w-auto',
35
- infoClx: 'w-auto',
36
- activeItemAnim: {
37
- co: {
38
- transition: 'none',
39
- from : 'px-3 gap-2.5',
40
- to: ''
41
- },
42
- coText: {
43
- transition: 'max-width',
44
- from : 'max-w-[100px]',
45
- to: 'max-w-[0px]'
46
- },
47
- info: {
48
- transition: 'transform, opacity',
49
- from : 'scale-x-100 opacity-100 origin-right',
50
- to: 'scale-x-0 opacity-0 origin-right'
51
- }
52
- },
53
- showArrow: true
54
- },
55
- TR: {
56
- pos: 'top-[48px] md:top-[80px] right-[28px]',
57
- width: 'w-initial',
58
- centerText: false,
59
- showQuantity: false,
60
- showArrow: true,
61
- coClx: 'w-auto px-3 gap-1',
62
- infoClx: 'w-auto',
63
- activeItemAnim: {
64
- co: {
65
- transition: 'none',
66
- from : 'px-3 gap-2.5',
67
- to: ''
68
- },
69
- coText: {
70
- transition: 'max-width',
71
- from : 'max-w-[100px]',
72
- to: 'max-w-[0px]'
73
- },
74
- info: {
75
- transition: 'transform',
76
- from : 'scale-x-100 origin-right',
77
- to: 'scale-x-0 origin-right'
78
- }
79
- },
80
- },
81
- TRIO: {
82
- pos: 'top-[48px] md:top-[70px] right-[28px]',
83
- centerText: false,
84
- showQuantity: true,
85
- showArrow: true,
86
- width: 'w-initial',
87
- coClx: 'hidden',
88
- infoClx: 'w-auto',
89
- activeItemAnim: {
90
- info: {
91
- transition: 'transform, opacity',
92
- from : 'scale-x-100 opacity-100',
93
- to: 'scale-x-50 opacity-0'
94
- }
95
- },
96
- }
97
- }
98
-
99
- const v = 'TR'
100
-
101
- const CheckoutWidget: React.FC<{
102
- clx?: string
103
- }> = observer(({
104
- clx=''
105
- }) => {
106
-
107
- const router = useRouter()
108
-
109
- const isCheckout = usePathname() === '/checkout'
110
- const clxSet = useAnimationClxSet(isCheckout)
111
-
112
- // for rendering content after recentActivity.item() would return false
113
- const persistentRef = useRef<LineItem | undefined>(undefined)
114
-
115
- // Doing double duty of being initial step fn for StepAnimation,
116
- // and also capturing the item for persistentRef :)
117
- const initialStepFn = (): boolean => {
118
- if (!!recentActivity.item && !persistentRef.current) {
119
- persistentRef.current = recentActivity.item
120
- }
121
- return !!recentActivity.item
122
- }
123
- const steps = useStepAnimation(initialStepFn, [CONST.animDurationMs, CONST.animDurationMs, CONST.animDurationMs])
124
-
125
- const handleCheckout = () => { router.push('/checkout')}
126
-
127
- return globalThis?.document?.body && createPortal(
128
- (<div
129
- className={cn(
130
- VARS[v].width,
131
- 'z-below-modal-2 fixed ',
132
- VARS[v].pos,
133
- 'rounded-lg',
134
- 'flex',
135
- steps.notPast(0) ? 'bg-background' : '',
136
- steps.notPast(1) ? 'gap-2' : '',
137
- clxSet.asArray.join(' ')
138
- )}
139
- style={steps.notPast(1) ? {} : VARS[v].coClx?.includes('hidden') ? {} : CONST.shadowStyle}
140
- >
141
- <div
142
- className={cn(
143
- 'flex flex-row justify-between items-center',
144
- transClx(steps.notPast(0), VARS[v].activeItemAnim.info),
145
- VARS[v].itemClx,
146
- steps.notPast(1) ? 'px-3 border rounded-lg bg-level-1 border-muted-3' : ''
147
- )}
148
- style={transStyle(VARS[v].activeItemAnim.info)}
149
- >
150
- {steps.notPast(1) && persistentRef.current?.img && (
151
- <Image def={persistentRef.current.img} constrainTo={CONST.itemImgConstraint} preload className='grow-0 shrink-0'/>
152
- )}
153
- {steps.notPast(1) && persistentRef.current && (<div className='text-foreground grow ml-1'>
154
- <p className='whitespace-nowrap text-ellipsis text-sm'>{persistentRef.current.title}</p>
155
- <p className='whitespace-nowrap text-clip text-xxs' >recently added...</p>
156
- </div>)}
157
- </div>
158
- <CheckoutButton
159
- handleCheckout={handleCheckout}
160
- centerText={VARS[v].centerText ?? !steps.notPast(0)}
161
- variant='primary'
162
- rounded='lg'
163
- showQuantity={VARS[v].showQuantity ?? true}
164
- showArrow={VARS[v].showArrow ?? true}
165
- className={cn(
166
- // for setting and unsetting 'gap'
167
- transClx((VARS[v].activeItemAnim.coText ? steps.notPast(3) : true), VARS[v].activeItemAnim.co),
168
- VARS[v].coClx
169
- )}
170
- style={transStyle(VARS[v].activeItemAnim.co)}
171
- >
172
- <div
173
- className={cn(
174
- 'overflow-hidden',
175
- 'flex justify-center items-center',
176
- transClx(steps.notPast(2), VARS[v].activeItemAnim.coText),
177
- )}
178
- style={transStyle(VARS[v].activeItemAnim.coText)}
179
- >
180
- Checkout
181
- </div>
182
- </CheckoutButton>
183
- </div>),
184
- globalThis?.document?.body
185
- )
186
- })
187
-
188
- export default CheckoutWidget
1
+ 'use client'
2
+ import React, { useRef } from 'react'
3
+ import { createPortal } from 'react-dom'
4
+ import { usePathname, useRouter } from 'next/navigation'
5
+ import { observer } from 'mobx-react-lite'
6
+
7
+ import { cn } from '@hanzo/ui/util'
8
+ import { useStepAnimation } from '@hanzo/ui/util-client'
9
+
10
+ import { Image } from '@hanzo/ui/primitives'
11
+
12
+ import CheckoutButton from '../checkout-button'
13
+ import useAnimationClxSet from './use-anim-clx-set'
14
+ import CONST from './const'
15
+ import type { LineItem } from '@hanzo/commerce/types'
16
+
17
+ const transStyle = (t: { transition: string, from : string, to: string } | undefined) : any => (
18
+ t ? {
19
+ transitionProperty: t.transition,
20
+ transitionTimingFunction: CONST.animTimingFn,
21
+ transitionDuration: `${CONST.animDurationMs}ms`
22
+ } : {}
23
+ )
24
+
25
+ const transClx = (on: boolean, t: { transition: string, from : string, to: string } | undefined) : string => (
26
+ on ? (t?.from ?? '') : (t?.to ?? '')
27
+ )
28
+
29
+ const VARS: any = {
30
+ BR: {
31
+ pos: 'bottom-[24px] right-[66px]',
32
+ width: 'w-initial',
33
+ centerText: false,
34
+ coClx: 'w-auto',
35
+ infoClx: 'w-auto',
36
+ activeItemAnim: {
37
+ co: {
38
+ transition: 'none',
39
+ from : 'px-3 gap-2.5',
40
+ to: ''
41
+ },
42
+ coText: {
43
+ transition: 'max-width',
44
+ from : 'max-w-[100px]',
45
+ to: 'max-w-[0px]'
46
+ },
47
+ info: {
48
+ transition: 'transform, opacity',
49
+ from : 'scale-x-100 opacity-100 origin-right',
50
+ to: 'scale-x-0 opacity-0 origin-right'
51
+ }
52
+ },
53
+ showArrow: true
54
+ },
55
+ TR: {
56
+ pos: 'top-[48px] md:top-[80px] right-[28px]',
57
+ width: 'w-initial',
58
+ centerText: false,
59
+ showQuantity: false,
60
+ showArrow: true,
61
+ coClx: 'w-auto px-3 gap-1',
62
+ infoClx: 'w-auto',
63
+ activeItemAnim: {
64
+ co: {
65
+ transition: 'none',
66
+ from : 'px-3 gap-2.5',
67
+ to: ''
68
+ },
69
+ coText: {
70
+ transition: 'max-width',
71
+ from : 'max-w-[100px]',
72
+ to: 'max-w-[0px]'
73
+ },
74
+ info: {
75
+ transition: 'transform',
76
+ from : 'scale-x-100 origin-right',
77
+ to: 'scale-x-0 origin-right'
78
+ }
79
+ },
80
+ },
81
+ TRIO: {
82
+ pos: 'top-[48px] md:top-[70px] right-[28px]',
83
+ centerText: false,
84
+ showQuantity: true,
85
+ showArrow: true,
86
+ width: 'w-initial',
87
+ coClx: 'hidden',
88
+ infoClx: 'w-auto',
89
+ activeItemAnim: {
90
+ info: {
91
+ transition: 'transform, opacity',
92
+ from : 'scale-x-100 opacity-100',
93
+ to: 'scale-x-50 opacity-0'
94
+ }
95
+ },
96
+ }
97
+ }
98
+
99
+ const v = 'TR'
100
+
101
+ const CheckoutWidget: React.FC<{
102
+ clx?: string
103
+ }> = observer(({
104
+ clx=''
105
+ }) => {
106
+
107
+ const router = useRouter()
108
+
109
+ const isCheckout = usePathname() === '/checkout'
110
+ const clxSet = useAnimationClxSet(isCheckout)
111
+
112
+ // for rendering content after recentActivity.item() would return false
113
+ const persistentRef = useRef<LineItem | undefined>(undefined)
114
+
115
+ // Doing double duty of being initial step fn for StepAnimation,
116
+ // and also capturing the item for persistentRef :)
117
+ const initialStepFn = (): boolean => {
118
+ if (!!recentActivity.item && !persistentRef.current) {
119
+ persistentRef.current = recentActivity.item
120
+ }
121
+ return !!recentActivity.item
122
+ }
123
+ const steps = useStepAnimation(initialStepFn, [CONST.animDurationMs, CONST.animDurationMs, CONST.animDurationMs])
124
+
125
+ const handleCheckout = () => { router.push('/checkout')}
126
+
127
+ return globalThis?.document?.body && createPortal(
128
+ (<div
129
+ className={cn(
130
+ VARS[v].width,
131
+ 'z-below-modal-2 fixed ',
132
+ VARS[v].pos,
133
+ 'rounded-lg',
134
+ 'flex',
135
+ steps.notPast(0) ? 'bg-background' : '',
136
+ steps.notPast(1) ? 'gap-2' : '',
137
+ clxSet.asArray.join(' ')
138
+ )}
139
+ style={steps.notPast(1) ? {} : VARS[v].coClx?.includes('hidden') ? {} : CONST.shadowStyle}
140
+ >
141
+ <div
142
+ className={cn(
143
+ 'flex flex-row justify-between items-center',
144
+ transClx(steps.notPast(0), VARS[v].activeItemAnim.info),
145
+ VARS[v].itemClx,
146
+ steps.notPast(1) ? 'px-3 border rounded-lg bg-level-1 border-muted-3' : ''
147
+ )}
148
+ style={transStyle(VARS[v].activeItemAnim.info)}
149
+ >
150
+ {steps.notPast(1) && persistentRef.current?.img && (
151
+ <Image def={persistentRef.current.img} constrainTo={CONST.itemImgConstraint} preload className='grow-0 shrink-0'/>
152
+ )}
153
+ {steps.notPast(1) && persistentRef.current && (<div className='text-foreground grow ml-1'>
154
+ <p className='whitespace-nowrap text-ellipsis text-sm'>{persistentRef.current.title}</p>
155
+ <p className='whitespace-nowrap text-clip text-xxs' >recently added...</p>
156
+ </div>)}
157
+ </div>
158
+ <CheckoutButton
159
+ handleCheckout={handleCheckout}
160
+ centerText={VARS[v].centerText ?? !steps.notPast(0)}
161
+ variant='primary'
162
+ rounded='lg'
163
+ showQuantity={VARS[v].showQuantity ?? true}
164
+ showArrow={VARS[v].showArrow ?? true}
165
+ className={cn(
166
+ // for setting and unsetting 'gap'
167
+ transClx((VARS[v].activeItemAnim.coText ? steps.notPast(3) : true), VARS[v].activeItemAnim.co),
168
+ VARS[v].coClx
169
+ )}
170
+ style={transStyle(VARS[v].activeItemAnim.co)}
171
+ >
172
+ <div
173
+ className={cn(
174
+ 'overflow-hidden',
175
+ 'flex justify-center items-center',
176
+ transClx(steps.notPast(2), VARS[v].activeItemAnim.coText),
177
+ )}
178
+ style={transStyle(VARS[v].activeItemAnim.coText)}
179
+ >
180
+ Checkout
181
+ </div>
182
+ </CheckoutButton>
183
+ </div>),
184
+ globalThis?.document?.body
185
+ )
186
+ })
187
+
188
+ export default CheckoutWidget
@@ -1,48 +1,48 @@
1
- import {
2
- action,
3
- computed,
4
- makeObservable,
5
- observable
6
- } from 'mobx'
7
-
8
- class ObsStringSet {
9
-
10
- private _set = observable.set(new Set<string>())
11
-
12
- constructor(initial: string[] = []) {
13
- initial.forEach((el) => {this._set.add(el)})
14
- makeObservable(this, {
15
- add: action,
16
- remove: action,
17
- asArray: computed
18
- })
19
- }
20
-
21
- add = (v: string | string[]): void => {
22
- if (Array.isArray(v)) {
23
- v.forEach((el) => {this._set.add(el)})
24
- }
25
- else {
26
- this._set.add(v)
27
- }
28
- }
29
-
30
- remove = (v: string | string[]): void => {
31
- if (Array.isArray(v)) {
32
- v.forEach((el) => {this._set.delete(el)})
33
- }
34
- else {
35
- this._set.delete(v)
36
- }
37
- }
38
-
39
- has = (v: string): boolean => (
40
- this._set.has(v)
41
- )
42
-
43
- get asArray() {
44
- return Array.from(this._set)
45
- }
46
- }
47
-
48
- export default ObsStringSet
1
+ import {
2
+ action,
3
+ computed,
4
+ makeObservable,
5
+ observable
6
+ } from 'mobx'
7
+
8
+ class ObsStringSet {
9
+
10
+ private _set = observable.set(new Set<string>())
11
+
12
+ constructor(initial: string[] = []) {
13
+ initial.forEach((el) => {this._set.add(el)})
14
+ makeObservable(this, {
15
+ add: action,
16
+ remove: action,
17
+ asArray: computed
18
+ })
19
+ }
20
+
21
+ add = (v: string | string[]): void => {
22
+ if (Array.isArray(v)) {
23
+ v.forEach((el) => {this._set.add(el)})
24
+ }
25
+ else {
26
+ this._set.add(v)
27
+ }
28
+ }
29
+
30
+ remove = (v: string | string[]): void => {
31
+ if (Array.isArray(v)) {
32
+ v.forEach((el) => {this._set.delete(el)})
33
+ }
34
+ else {
35
+ this._set.delete(v)
36
+ }
37
+ }
38
+
39
+ has = (v: string): boolean => (
40
+ this._set.has(v)
41
+ )
42
+
43
+ get asArray() {
44
+ return Array.from(this._set)
45
+ }
46
+ }
47
+
48
+ export default ObsStringSet