@infonomic/uikit 5.2.1 → 5.3.0
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/dist/components/scroll-to-top/scroll-to-top.d.ts +12 -7
- package/dist/components/scroll-to-top/scroll-to-top.d.ts.map +1 -1
- package/dist/components/scroll-to-top/scroll-to-top.js +24 -14
- package/package.json +1 -1
- package/src/astro.d.ts +2 -0
- package/src/astro.js +3 -0
- package/src/components/scroll-to-top/scroll-to-top.astro +75 -0
- package/src/components/scroll-to-top/scroll-to-top.tsx +52 -33
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type ComponentProps } from 'react';
|
|
2
|
+
export interface ScrollToTopProps extends ComponentProps<'button'> {
|
|
3
|
+
/**
|
|
4
|
+
* The scroll position (Y-axis) in pixels that triggers the button to appear.
|
|
5
|
+
* @default 200
|
|
6
|
+
*/
|
|
7
|
+
showAt?: number;
|
|
8
|
+
/**
|
|
9
|
+
* The target scroll position (Y-axis) to scroll to when clicked.
|
|
10
|
+
* @default -65
|
|
11
|
+
*/
|
|
4
12
|
offset?: number;
|
|
5
13
|
}
|
|
6
|
-
export
|
|
7
|
-
export declare const ScrollToTop: ({ ref, offset, ...rest }: ScrollToTopProps & {
|
|
8
|
-
ref?: React.RefObject<HTMLButtonElement>;
|
|
9
|
-
}) => React.JSX.Element;
|
|
14
|
+
export declare function ScrollToTop({ className, showAt, offset, type, 'aria-label': ariaLabel, onClick, ...props }: ScrollToTopProps): import("react").JSX.Element;
|
|
10
15
|
//# sourceMappingURL=scroll-to-top.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-to-top.d.ts","sourceRoot":"","sources":["../../../src/components/scroll-to-top/scroll-to-top.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scroll-to-top.d.ts","sourceRoot":"","sources":["../../../src/components/scroll-to-top/scroll-to-top.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,cAAc,EAAuB,MAAM,OAAO,CAAA;AAIhE,MAAM,WAAW,gBAAiB,SAAQ,cAAc,CAAC,QAAQ,CAAC;IAChE;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,MAAY,EACZ,MAAY,EACZ,IAAe,EACf,YAAY,EAAE,SAA2B,EACzC,OAAO,EACP,GAAG,KAAK,EACT,EAAE,gBAAgB,+BAuDlB"}
|
|
@@ -3,43 +3,53 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import classnames from "classnames";
|
|
4
4
|
import { useEffect, useState } from "react";
|
|
5
5
|
import scroll_to_top_module from "./scroll-to-top.module.js";
|
|
6
|
-
|
|
6
|
+
function ScrollToTop({ className, showAt = 200, offset = -65, type = 'button', 'aria-label': ariaLabel = 'Scroll to top', onClick, ...props }) {
|
|
7
7
|
const [show, setShow] = useState(false);
|
|
8
|
-
const handleOnClick = ()=>{
|
|
8
|
+
const handleOnClick = (e)=>{
|
|
9
9
|
window.scrollTo({
|
|
10
10
|
top: offset,
|
|
11
11
|
left: 0,
|
|
12
12
|
behavior: 'smooth'
|
|
13
13
|
});
|
|
14
|
+
onClick?.(e);
|
|
14
15
|
};
|
|
15
16
|
useEffect(()=>{
|
|
17
|
+
let ticking = false;
|
|
16
18
|
const handleOnScroll = ()=>{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
if (!ticking) {
|
|
20
|
+
window.requestAnimationFrame(()=>{
|
|
21
|
+
setShow(window.scrollY > showAt);
|
|
22
|
+
ticking = false;
|
|
23
|
+
});
|
|
24
|
+
ticking = true;
|
|
25
|
+
}
|
|
19
26
|
};
|
|
20
|
-
|
|
27
|
+
window.addEventListener('scroll', handleOnScroll, {
|
|
28
|
+
passive: true
|
|
29
|
+
});
|
|
21
30
|
return ()=>{
|
|
22
31
|
window.removeEventListener('scroll', handleOnScroll);
|
|
23
32
|
};
|
|
24
|
-
}, [
|
|
33
|
+
}, [
|
|
34
|
+
showAt
|
|
35
|
+
]);
|
|
25
36
|
return /*#__PURE__*/ jsx("button", {
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
type: type,
|
|
38
|
+
"aria-label": ariaLabel,
|
|
28
39
|
onClick: handleOnClick,
|
|
29
|
-
type: "button",
|
|
30
|
-
id: "scroll-to-top",
|
|
31
40
|
className: classnames('scroll-to-top', scroll_to_top_module["scroll-to-top"], {
|
|
32
41
|
'scroll-to-top-shown': show,
|
|
33
42
|
[scroll_to_top_module["scroll-to-top-shown"]]: show
|
|
34
|
-
}),
|
|
43
|
+
}, className),
|
|
44
|
+
...props,
|
|
35
45
|
children: /*#__PURE__*/ jsx("span", {
|
|
46
|
+
"aria-hidden": "true",
|
|
36
47
|
children: /*#__PURE__*/ jsx("svg", {
|
|
37
48
|
className: "icon",
|
|
38
49
|
style: {
|
|
39
50
|
fill: 'currentColor'
|
|
40
51
|
},
|
|
41
52
|
focusable: "false",
|
|
42
|
-
"aria-hidden": "true",
|
|
43
53
|
viewBox: "0 0 51 32",
|
|
44
54
|
children: /*#__PURE__*/ jsx("path", {
|
|
45
55
|
d: "M25.4,9.8L45.6,30l4.5-4.5L25.4,0.8L0.8,25.4L5.3,30L25.4,9.8z"
|
|
@@ -47,5 +57,5 @@ const scroll_to_top_ScrollToTop = function({ ref, offset = -65, ...rest }) {
|
|
|
47
57
|
})
|
|
48
58
|
})
|
|
49
59
|
});
|
|
50
|
-
}
|
|
51
|
-
export {
|
|
60
|
+
}
|
|
61
|
+
export { ScrollToTop };
|
package/package.json
CHANGED
package/src/astro.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type InputComponent from './components/forms/input.astro'
|
|
|
14
14
|
import type InputAdornmentComponent from './components/forms/input-adornment.astro'
|
|
15
15
|
import type LabelComponent from './components/forms/label.astro'
|
|
16
16
|
import type SectionComponent from './components/section/section.astro'
|
|
17
|
+
import type ScrollToTopComponent from './components/scroll-to-top/scroll-to-top.astro'
|
|
17
18
|
import type CloseIconComponent from './icons/close-icon.astro'
|
|
18
19
|
import type IconElementComponent from './icons/icon-element.astro'
|
|
19
20
|
import type LightIconComponent from './icons/light-icon.astro'
|
|
@@ -41,3 +42,4 @@ export declare const LightIcon: typeof LightIconComponent
|
|
|
41
42
|
export declare const MoonIcon: typeof MoonIconComponent
|
|
42
43
|
export declare const SearchIcon: typeof SearchIconComponent
|
|
43
44
|
export declare const Section: typeof SectionComponent
|
|
45
|
+
export declare const ScrollToTop: typeof ScrollToTopComponent
|
package/src/astro.js
CHANGED
|
@@ -14,12 +14,14 @@ import InputComponent from './components/forms/input.astro'
|
|
|
14
14
|
import InputAdornmentComponent from './components/forms/input-adornment.astro'
|
|
15
15
|
import LabelComponent from './components/forms/label.astro'
|
|
16
16
|
import SectionComponent from './components/section/section.astro'
|
|
17
|
+
import ScrollToTopComponent from './components/scroll-to-top/scroll-to-top.astro'
|
|
17
18
|
import CloseIconComponent from './icons/close-icon.astro'
|
|
18
19
|
import IconElementComponent from './icons/icon-element.astro'
|
|
19
20
|
import LightIconComponent from './icons/light-icon.astro'
|
|
20
21
|
import MoonIconComponent from './icons/moon-icon.astro'
|
|
21
22
|
import SearchIconComponent from './icons/search-icon.astro'
|
|
22
23
|
|
|
24
|
+
|
|
23
25
|
export const Button = ButtonComponent
|
|
24
26
|
export const Hamburger = HamburgerComponent
|
|
25
27
|
export const IconButton = IconButtonComponent
|
|
@@ -36,6 +38,7 @@ export const InputAdornment = InputAdornmentComponent
|
|
|
36
38
|
export const Input = InputComponent
|
|
37
39
|
export const Label = LabelComponent
|
|
38
40
|
export const Section = SectionComponent
|
|
41
|
+
export const ScrollToTop = ScrollToTopComponent
|
|
39
42
|
export const IconElement = IconElementComponent
|
|
40
43
|
export const LightIcon = LightIconComponent
|
|
41
44
|
export const MoonIcon = MoonIconComponent
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
import styles from './scroll-to-top.module.css'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
class?: string
|
|
6
|
+
showAt?: number
|
|
7
|
+
offset?: number
|
|
8
|
+
'aria-label'?: string
|
|
9
|
+
[key: string]: any
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
class: className,
|
|
14
|
+
showAt = 200,
|
|
15
|
+
offset = -65,
|
|
16
|
+
'aria-label': ariaLabel = 'Scroll to top',
|
|
17
|
+
...rest
|
|
18
|
+
} = Astro.props
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<button
|
|
22
|
+
type="button"
|
|
23
|
+
aria-label={ariaLabel}
|
|
24
|
+
class:list={['scroll-to-top', styles['scroll-to-top'], className]}
|
|
25
|
+
data-show-at={showAt}
|
|
26
|
+
data-offset={offset}
|
|
27
|
+
data-class-shown={styles['scroll-to-top-shown']}
|
|
28
|
+
{...rest}
|
|
29
|
+
>
|
|
30
|
+
<span aria-hidden="true">
|
|
31
|
+
<svg class="icon" style="fill: currentColor" focusable="false" viewBox="0 0 51 32">
|
|
32
|
+
<path d="M25.4,9.8L45.6,30l4.5-4.5L25.4,0.8L0.8,25.4L5.3,30L25.4,9.8z"></path>
|
|
33
|
+
</svg>
|
|
34
|
+
</span>
|
|
35
|
+
</button>
|
|
36
|
+
|
|
37
|
+
<script>
|
|
38
|
+
const buttons = document.querySelectorAll('button.scroll-to-top')
|
|
39
|
+
|
|
40
|
+
buttons.forEach((button) => {
|
|
41
|
+
if (!(button instanceof HTMLElement)) return
|
|
42
|
+
|
|
43
|
+
const showAt = Number(button.dataset.showAt) || 200
|
|
44
|
+
const offset = Number(button.dataset.offset) || -65
|
|
45
|
+
const classShown = button.dataset.classShown
|
|
46
|
+
|
|
47
|
+
if (classShown == null) return
|
|
48
|
+
|
|
49
|
+
// Click Handler
|
|
50
|
+
button.addEventListener('click', () => {
|
|
51
|
+
window.scrollTo({ top: offset, left: 0, behavior: 'smooth' })
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// Scroll Handler
|
|
55
|
+
let ticking = false
|
|
56
|
+
const handleOnScroll = () => {
|
|
57
|
+
if (!ticking) {
|
|
58
|
+
window.requestAnimationFrame(() => {
|
|
59
|
+
const shouldShow = window.scrollY > showAt
|
|
60
|
+
if (shouldShow) {
|
|
61
|
+
button.classList.add(classShown)
|
|
62
|
+
button.classList.add('scroll-to-top-shown')
|
|
63
|
+
} else {
|
|
64
|
+
button.classList.remove(classShown)
|
|
65
|
+
button.classList.remove('scroll-to-top-shown')
|
|
66
|
+
}
|
|
67
|
+
ticking = false
|
|
68
|
+
})
|
|
69
|
+
ticking = true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
window.addEventListener('scroll', handleOnScroll, { passive: true })
|
|
74
|
+
})
|
|
75
|
+
</script>
|
|
@@ -1,62 +1,81 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import type React from 'react'
|
|
4
3
|
import cx from 'classnames'
|
|
5
|
-
import { useEffect, useState } from 'react'
|
|
4
|
+
import { type ComponentProps, useEffect, useState } from 'react'
|
|
6
5
|
|
|
7
|
-
import
|
|
6
|
+
import styles from './scroll-to-top.module.css'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export interface ScrollToTopProps extends ComponentProps<'button'> {
|
|
9
|
+
/**
|
|
10
|
+
* The scroll position (Y-axis) in pixels that triggers the button to appear.
|
|
11
|
+
* @default 200
|
|
12
|
+
*/
|
|
13
|
+
showAt?: number
|
|
14
|
+
/**
|
|
15
|
+
* The target scroll position (Y-axis) to scroll to when clicked.
|
|
16
|
+
* @default -65
|
|
17
|
+
*/
|
|
11
18
|
offset?: number
|
|
12
19
|
}
|
|
13
20
|
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
ref,
|
|
21
|
+
export function ScrollToTop({
|
|
22
|
+
className,
|
|
23
|
+
showAt = 200,
|
|
18
24
|
offset = -65,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
type = 'button',
|
|
26
|
+
'aria-label': ariaLabel = 'Scroll to top',
|
|
27
|
+
onClick,
|
|
28
|
+
...props
|
|
29
|
+
}: ScrollToTopProps) {
|
|
23
30
|
const [show, setShow] = useState(false)
|
|
24
31
|
|
|
25
|
-
const handleOnClick = (): void => {
|
|
32
|
+
const handleOnClick = (e: React.MouseEvent<HTMLButtonElement>): void => {
|
|
26
33
|
window.scrollTo({ top: offset, left: 0, behavior: 'smooth' })
|
|
34
|
+
onClick?.(e)
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
useEffect(() => {
|
|
38
|
+
let ticking = false
|
|
39
|
+
|
|
30
40
|
const handleOnScroll = (): void => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
if (!ticking) {
|
|
42
|
+
window.requestAnimationFrame(() => {
|
|
43
|
+
setShow(window.scrollY > showAt)
|
|
44
|
+
ticking = false
|
|
45
|
+
})
|
|
46
|
+
ticking = true
|
|
36
47
|
}
|
|
37
48
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
49
|
+
|
|
50
|
+
window.addEventListener('scroll', handleOnScroll, { passive: true })
|
|
41
51
|
return () => {
|
|
42
52
|
window.removeEventListener('scroll', handleOnScroll)
|
|
43
53
|
}
|
|
44
|
-
}, [])
|
|
54
|
+
}, [showAt])
|
|
45
55
|
|
|
46
56
|
return (
|
|
47
57
|
<button
|
|
48
|
-
|
|
49
|
-
{
|
|
58
|
+
type={type}
|
|
59
|
+
aria-label={ariaLabel}
|
|
50
60
|
onClick={handleOnClick}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
className={cx(
|
|
62
|
+
'scroll-to-top',
|
|
63
|
+
styles['scroll-to-top'],
|
|
64
|
+
{
|
|
65
|
+
'scroll-to-top-shown': show,
|
|
66
|
+
[styles['scroll-to-top-shown']]: show,
|
|
67
|
+
},
|
|
68
|
+
className
|
|
69
|
+
)}
|
|
70
|
+
{...props}
|
|
57
71
|
>
|
|
58
|
-
<span>
|
|
59
|
-
<svg
|
|
72
|
+
<span aria-hidden="true">
|
|
73
|
+
<svg
|
|
74
|
+
className="icon"
|
|
75
|
+
style={{ fill: 'currentColor' }}
|
|
76
|
+
focusable="false"
|
|
77
|
+
viewBox="0 0 51 32"
|
|
78
|
+
>
|
|
60
79
|
<path d="M25.4,9.8L45.6,30l4.5-4.5L25.4,0.8L0.8,25.4L5.3,30L25.4,9.8z" />
|
|
61
80
|
</svg>
|
|
62
81
|
</span>
|