oddsgate-ds 1.0.185 → 1.0.186

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.
@@ -5,9 +5,10 @@ export type ILegalLinksDropdown = {
5
5
  style?: CSSProperties;
6
6
  children: React.ReactNode;
7
7
  };
8
- export type ILegalLinksDropdownContainer = {
8
+ export interface ILegalLinksDropdownContainer {
9
9
  isVisible: boolean;
10
- };
10
+ openUpward?: boolean;
11
+ }
11
12
  export type ILegalLinksDropdownItem = {
12
13
  className?: string;
13
14
  style?: CSSProperties;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oddsgate-ds",
3
- "version": "1.0.185",
3
+ "version": "1.0.186",
4
4
  "description": "Miew theme component library",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -22,7 +22,6 @@ const LegalLinks = ({
22
22
  <LegalLinksDropdown title={link.label} className="font-epilogue">
23
23
  {link.children.map((childLink, childIndex) => {
24
24
  if (!childLink.label || !childLink.url) return null
25
-
26
25
  return (
27
26
  <LegalLinksDropdownItem key={`childLink-${childIndex}`}>
28
27
  <a
@@ -16,45 +16,117 @@ export const Example: StoryObj<ILegalLinks> = {
16
16
  args: {
17
17
  links: [
18
18
  {
19
- 'label': 'Terms of Service',
20
- 'url': 'https://www.miew.com/terms-of-service'
19
+ label: 'Terms of Service',
20
+ url: 'https://www.miew.com/terms-of-service'
21
21
  },
22
22
  {
23
- 'label': 'Privacy Policy',
24
- 'url': 'https://www.miew.com/privacy-policy'
23
+ label: 'Privacy Policy',
24
+ url: 'https://www.miew.com/privacy-policy'
25
25
  },
26
26
  {
27
- 'label': 'Cookie Policy',
28
- 'url': 'https://www.miew.com/cookie-policy'
27
+ label: 'Cookie Policy',
28
+ url: 'https://www.miew.com/cookie-policy'
29
29
  },
30
30
  {
31
- 'label': 'Accessibility Statement',
32
- 'url': 'https://www.miew.com/accessibility-statement',
33
- 'children': [
31
+ label: 'Accessibility Statement',
32
+ url: 'https://www.miew.com/accessibility-statement',
33
+ children: [
34
34
  {
35
- 'label': 'Sub Link 1',
36
- 'url': 'https://www.miew.com/accessibility-statement/sublink1'
35
+ label: 'Sub Link 1',
36
+ url: 'https://www.miew.com/accessibility-statement/sublink1'
37
37
  },
38
38
  {
39
- 'label': 'Sub Link 2',
40
- 'url': 'https://www.miew.com/accessibility-statement/sublink2'
39
+ label: 'Sub Link 2',
40
+ url: 'https://www.miew.com/accessibility-statement/sublink2'
41
41
  },
42
42
  {
43
- 'label': 'Sub Link 3',
44
- 'url': 'https://www.miew.com/accessibility-statement/sublink3'
43
+ label: 'Sub Link 3',
44
+ url: 'https://www.miew.com/accessibility-statement/sublink3'
45
45
  },
46
46
  {
47
- 'label': 'Sub Link 4',
48
- 'url': 'https://www.miew.com/accessibility-statement/sublink4'
47
+ label: 'Sub Link 4',
48
+ url: 'https://www.miew.com/accessibility-statement/sublink4'
49
49
  }
50
50
  ]
51
51
  }
52
52
  ]
53
53
  },
54
54
  decorators: [
55
- (Story) => (
56
- <div style={{ background: 'black', padding: '2rem' }}>
57
- {Story()}
55
+ Story => (
56
+ <div style={{ background: 'black', padding: '2rem' }}>{Story()}</div>
57
+ )
58
+ ]
59
+ }
60
+
61
+ export const TestUpwardOpening: StoryObj<ILegalLinks> = {
62
+ args: {
63
+ links: [
64
+ {
65
+ label: 'Regular Link',
66
+ url: 'https://www.miew.com/terms'
67
+ },
68
+ {
69
+ label: 'Dropdown Menu',
70
+ url: 'https://www.miew.com/dropdown',
71
+ children: [
72
+ {
73
+ label: 'First Child Link',
74
+ url: 'https://www.miew.com/child1'
75
+ },
76
+ {
77
+ label: 'Second Child Link',
78
+ url: 'https://www.miew.com/child2'
79
+ },
80
+ {
81
+ label: 'Third Child Link',
82
+ url: 'https://www.miew.com/child3'
83
+ },
84
+ {
85
+ label: 'Fourth Child Link',
86
+ url: 'https://www.miew.com/child4'
87
+ },
88
+ {
89
+ label: 'Fifth Child Link',
90
+ url: 'https://www.miew.com/child5'
91
+ }
92
+ ]
93
+ },
94
+ {
95
+ label: 'Another Link',
96
+ url: 'https://www.miew.com/another'
97
+ }
98
+ ]
99
+ },
100
+ decorators: [
101
+ Story => (
102
+ <div
103
+ style={{
104
+ background: 'black',
105
+ height: '100vh',
106
+ display: 'flex',
107
+ alignItems: 'flex-end',
108
+ justifyContent: 'center',
109
+ paddingBottom: '50px'
110
+ }}
111
+ >
112
+ <div
113
+ style={{
114
+ border: '1px dashed #666',
115
+ padding: '20px',
116
+ borderRadius: '8px'
117
+ }}
118
+ >
119
+ <p
120
+ style={{
121
+ color: 'white',
122
+ marginBottom: '20px',
123
+ textAlign: 'center'
124
+ }}
125
+ >
126
+ Test upward opening
127
+ </p>
128
+ {Story()}
129
+ </div>
58
130
  </div>
59
131
  )
60
132
  ]
@@ -1,5 +1,8 @@
1
- import { ILegalLinksDropdown, ILegalLinksDropdownItem } from './LegalLinksDropdown.interface'
2
- import React, { useState } from 'react'
1
+ import {
2
+ ILegalLinksDropdown,
3
+ ILegalLinksDropdownItem
4
+ } from './LegalLinksDropdown.interface'
5
+ import React, { useState, useRef, useEffect } from 'react'
3
6
  import {
4
7
  StyledLegalLinksDropdown,
5
8
  StyledLegalLinksDropdownContainer,
@@ -17,14 +20,43 @@ const LegalLinksDropdown = ({
17
20
  style,
18
21
  ...props
19
22
  }: ILegalLinksDropdown) => {
20
- const [isVisible, setIsVisible] = useState(false)
23
+ const [isOpen, setIsOpen] = useState(false)
24
+ const [openUpward, setOpenUpward] = useState(false)
25
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null)
26
+ const dropdownRef = useRef<HTMLDivElement>(null)
27
+ const containerRef = useRef<HTMLUListElement>(null)
28
+
29
+ const handleMouseEnter = () => {
30
+ if (timeoutRef.current) {
31
+ clearTimeout(timeoutRef.current)
32
+ timeoutRef.current = null
33
+ }
34
+ setIsOpen(true)
35
+ }
36
+
37
+ const handleMouseLeave = () => {
38
+ timeoutRef.current = setTimeout(() => {
39
+ setIsOpen(false)
40
+ }, 100)
41
+ }
42
+
43
+ useEffect(() => {
44
+ if (isOpen && dropdownRef.current && containerRef.current) {
45
+ const triggerRect = dropdownRef.current.getBoundingClientRect()
46
+ const containerHeight = containerRef.current.offsetHeight
47
+ const spaceBelow = window.innerHeight - triggerRect.bottom
48
+
49
+ setOpenUpward(spaceBelow < containerHeight)
50
+ }
51
+ }, [isOpen])
21
52
 
22
53
  return (
23
54
  <StyledLegalLinksDropdown
24
- className={className}
55
+ ref={dropdownRef}
56
+ className={className}
25
57
  style={style}
26
- onMouseEnter={() => setIsVisible(true)}
27
- onMouseLeave={() => setIsVisible(false)}
58
+ onMouseEnter={handleMouseEnter}
59
+ onMouseLeave={handleMouseLeave}
28
60
  >
29
61
  <StyledLegalLinksDropdownTrigger>
30
62
  <StyledLegalLinksDropdownTitle>{title}</StyledLegalLinksDropdownTitle>
@@ -32,7 +64,13 @@ const LegalLinksDropdown = ({
32
64
  <Icon icon="icon-chevron-down" />
33
65
  </StyledLegalLinksDropdownIcon>
34
66
  </StyledLegalLinksDropdownTrigger>
35
- <StyledLegalLinksDropdownContainer isVisible={isVisible}>
67
+ <StyledLegalLinksDropdownContainer
68
+ ref={containerRef}
69
+ isVisible={isOpen}
70
+ openUpward={openUpward}
71
+ onMouseEnter={handleMouseEnter}
72
+ onMouseLeave={handleMouseLeave}
73
+ >
36
74
  {children}
37
75
  </StyledLegalLinksDropdownContainer>
38
76
  </StyledLegalLinksDropdown>
@@ -57,4 +95,4 @@ export const LegalLinksDropdownItem = ({
57
95
  {children}
58
96
  </StyledLegalLinksDropdownItem>
59
97
  )
60
- }
98
+ }
@@ -1,19 +1,20 @@
1
- import { CSSProperties } from 'react';
1
+ import { CSSProperties } from 'react'
2
2
 
3
3
  export type ILegalLinksDropdown = {
4
4
  title?: string
5
- className?: string;
5
+ className?: string
6
6
  style?: CSSProperties
7
7
  children: React.ReactNode
8
8
  }
9
9
 
10
- export type ILegalLinksDropdownContainer = {
10
+ export interface ILegalLinksDropdownContainer {
11
11
  isVisible: boolean
12
+ openUpward?: boolean
12
13
  }
13
14
 
14
15
  export type ILegalLinksDropdownItem = {
15
- className?: string;
16
+ className?: string
16
17
  style?: CSSProperties
17
18
  children: React.ReactNode
18
19
  onClick?: () => void
19
- }
20
+ }
@@ -1,11 +1,15 @@
1
- import { ILegalLinksDropdown, ILegalLinksDropdownContainer, ILegalLinksDropdownItem } from './LegalLinksDropdown.interface';
2
- import { colors, radius, responsiveMedia, shadows } from '@/styles/variables';
3
- import styled from 'styled-components';
1
+ import {
2
+ ILegalLinksDropdown,
3
+ ILegalLinksDropdownContainer,
4
+ ILegalLinksDropdownItem
5
+ } from './LegalLinksDropdown.interface'
6
+ import { colors, radius, responsiveMedia, shadows } from '@/styles/variables'
7
+ import styled from 'styled-components'
4
8
 
5
9
  export const StyledLegalLinksDropdown = styled.div<ILegalLinksDropdown>`
6
10
  position: relative;
7
11
  display: inline-flex;
8
- `;
12
+ `
9
13
 
10
14
  export const StyledLegalLinksDropdownTrigger = styled.div`
11
15
  font-family: var(--alternative-fontFamily);
@@ -16,7 +20,7 @@ export const StyledLegalLinksDropdownTrigger = styled.div`
16
20
  display: inline-flex;
17
21
  gap: 4px;
18
22
  align-items: center;
19
-
23
+
20
24
  &:hover {
21
25
  opacity: 0.6;
22
26
  }
@@ -24,19 +28,19 @@ export const StyledLegalLinksDropdownTrigger = styled.div`
24
28
  @media only screen and (min-width: ${responsiveMedia}) {
25
29
  font-size: 15px;
26
30
  }
27
- `;
31
+ `
28
32
 
29
33
  export const StyledLegalLinksDropdownTitle = styled.span`
30
34
  text-decoration: underline;
31
- `;
35
+ `
32
36
 
33
37
  export const StyledLegalLinksDropdownContainer = styled.ul<ILegalLinksDropdownContainer>`
34
38
  position: absolute;
35
- top: 100%;
39
+ ${props => (props.openUpward ? 'bottom: 100%;' : 'top: 100%;')}
36
40
  left: 50%;
37
41
  transform: translateX(-50%);
38
42
 
39
- margin-top: 2px;
43
+ ${props => (props.openUpward ? 'margin-bottom: 2px;' : 'margin-top: 2px;')}
40
44
  background: ${colors.primary50};
41
45
  box-shadow: ${shadows.sm};
42
46
  border-radius: ${radius.md};
@@ -44,17 +48,23 @@ export const StyledLegalLinksDropdownContainer = styled.ul<ILegalLinksDropdownCo
44
48
  min-width: 200px;
45
49
  white-space: nowrap;
46
50
 
47
- opacity: ${props => props.isVisible ? 1 : 0};
48
- pointer-events: ${props => props.isVisible ? "auto" : "none"};
49
- visibility: ${props => props.isVisible ? "visible" : "hidden"};
51
+ opacity: ${props => (props.isVisible ? 1 : 0)};
52
+ pointer-events: ${props => (props.isVisible ? 'auto' : 'none')};
53
+ visibility: ${props => (props.isVisible ? 'visible' : 'hidden')};
50
54
 
51
- transform: ${props => props.isVisible
52
- ? "translateX(-50%) translateY(0)"
53
- : "translateX(-50%) translateY(-10px)"};
55
+ transform: ${props => {
56
+ const baseTransform = 'translateX(-50%)'
57
+ if (!props.isVisible) {
58
+ return props.openUpward
59
+ ? `${baseTransform} translateY(10px)`
60
+ : `${baseTransform} translateY(-10px)`
61
+ }
62
+ return `${baseTransform} translateY(0)`
63
+ }};
54
64
 
55
65
  z-index: 100;
56
66
  transition: all 0.2s ease-in-out;
57
- `;
67
+ `
58
68
 
59
69
  export const StyledLegalLinksDropdownItem = styled.li<ILegalLinksDropdownItem>`
60
70
  display: flex;
@@ -64,23 +74,23 @@ export const StyledLegalLinksDropdownItem = styled.li<ILegalLinksDropdownItem>`
64
74
  color: ${colors.gray50};
65
75
  background-color: ${colors.primary50};
66
76
  transition: background-color 0.3s linear;
67
-
77
+
68
78
  &:first-child {
69
79
  border-radius: ${radius.md} ${radius.md} 0 0;
70
80
  }
71
-
81
+
72
82
  &:last-child {
73
83
  border-radius: 0 0 ${radius.md} ${radius.md};
74
84
  }
75
-
85
+
76
86
  &:first-child:last-child {
77
87
  border-radius: ${radius.md};
78
88
  }
79
-
89
+
80
90
  &:hover {
81
91
  background-color: ${colors.third10};
82
92
  }
83
-
93
+
84
94
  a {
85
95
  font-family: var(--alternative-fontFamily);
86
96
  text-decoration: none;
@@ -89,7 +99,7 @@ export const StyledLegalLinksDropdownItem = styled.li<ILegalLinksDropdownItem>`
89
99
  color: inherit;
90
100
  width: 100%;
91
101
  display: block;
92
-
102
+
93
103
  &:hover {
94
104
  opacity: 1;
95
105
  }