marqy 0.0.9 → 1.0.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/.claude/settings.local.json +13 -0
- package/.vscode/settings.json +3 -0
- package/README.md +43 -12
- package/dist/marqy.css +131 -0
- package/dist/marqy.d.ts +4 -3
- package/dist/marqy.esm.js +1 -1
- package/dist/marqy.esm.js.map +1 -1
- package/dist/marqy.js +1 -1
- package/dist/marqy.js.map +1 -1
- package/dist/marqy.umd.js +1 -1
- package/dist/marqy.umd.js.map +1 -1
- package/examples/.astro/content-assets.mjs +1 -0
- package/examples/.astro/content-modules.mjs +1 -0
- package/examples/.astro/content.d.ts +154 -0
- package/examples/.astro/data-store.json +1 -0
- package/examples/.astro/fonts/font-akkurat-mono-500-normal-40f4e0ea0b54adc5.woff2 +0 -0
- package/examples/.astro/fonts/font-akkurat-mono-700-normal-b9f40f1447b587bd.woff +0 -0
- package/examples/.astro/fonts/font-grtsk-300-normal-8ef14ca23be6893c.woff2 +0 -0
- package/examples/.astro/fonts/font-grtsk-400-normal-13ba8954073ee64a.woff2 +0 -0
- package/examples/.astro/fonts/font-grtsk-500-normal-d214468daf16245f.woff2 +0 -0
- package/examples/.astro/fonts/font-grtsk-wide-500-normal-6f8c2658b9c2ba8e.woff2 +0 -0
- package/examples/.astro/fonts/font-grtsk-wide-700-normal-17406f09c7b68ca3.woff2 +0 -0
- package/examples/.astro/fonts.d.ts +4 -0
- package/examples/.astro/settings.json +5 -0
- package/examples/.astro/types.d.ts +3 -0
- package/examples/.yarnrc +1 -0
- package/examples/astro.config.mjs +101 -0
- package/examples/package.json +30 -0
- package/examples/public/apple-touch-icon.png +0 -0
- package/examples/public/favicon.ico +0 -0
- package/examples/public/favicon.svg +4 -0
- package/examples/public/marqy-logo.svg +35 -0
- package/examples/src/assets/baggu.jpg +0 -0
- package/examples/src/assets/bluesky.jpg +0 -0
- package/examples/src/assets/clams-lol.jpg +0 -0
- package/examples/src/assets/coconut-club-2.jpg +0 -0
- package/examples/src/assets/coconut-club.jpg +0 -0
- package/examples/src/assets/lucci.jpg +0 -0
- package/examples/src/assets/phila-museum.jpg +0 -0
- package/examples/src/assets/red-rooster.jpg +0 -0
- package/examples/src/assets/sanity.jpg +0 -0
- package/examples/src/assets/usal.jpg +0 -0
- package/examples/src/assets/vacation.jpg +0 -0
- package/examples/src/components/CopyButton.tsx +26 -0
- package/examples/src/components/Divider.tsx +3 -0
- package/examples/src/components/Footer.astro +7 -0
- package/examples/src/components/InUse.astro +89 -0
- package/examples/src/components/InUseExamples.tsx +60 -0
- package/examples/src/components/MarqyCredits.tsx +33 -0
- package/examples/src/components/MarqyHero.tsx +77 -0
- package/examples/src/components/MarqyInteractiveDemo.tsx +46 -0
- package/examples/src/components/MarqyPlayground.tsx +496 -0
- package/examples/src/components/MarqySpeedDemo.tsx +34 -0
- package/examples/src/components/MarqyVerticalDemo.tsx +44 -0
- package/examples/src/components/Playground.astro +11 -0
- package/examples/src/components/QuickStart.astro +59 -0
- package/examples/src/components/SectionHeadline.tsx +41 -0
- package/examples/src/components/Tile.tsx +32 -0
- package/examples/src/content.config.ts +3 -0
- package/examples/src/fonts/Akkurat-Mono-Bold.woff +0 -0
- package/examples/src/fonts/Akkurat-Mono.woff +0 -0
- package/examples/src/fonts/Akkurat-Mono.woff2 +0 -0
- package/examples/src/fonts/Grtsk-Peta-Light.woff +0 -0
- package/examples/src/fonts/Grtsk-Peta-Light.woff2 +0 -0
- package/examples/src/fonts/Grtsk-Peta-Medium.woff +0 -0
- package/examples/src/fonts/Grtsk-Peta-Medium.woff2 +0 -0
- package/examples/src/fonts/Grtsk-Peta-Regular.woff +0 -0
- package/examples/src/fonts/Grtsk-Peta-Regular.woff2 +0 -0
- package/examples/src/fonts/Grtsk-Tera-Bold.woff +0 -0
- package/examples/src/fonts/Grtsk-Tera-Bold.woff2 +0 -0
- package/examples/src/fonts/Grtsk-Tera-Medium.woff +0 -0
- package/examples/src/fonts/Grtsk-Tera-Medium.woff2 +0 -0
- package/examples/src/layouts/layout.astro +107 -0
- package/examples/src/lib/cn.ts +16 -0
- package/examples/src/lib/helpers.ts +13 -0
- package/examples/src/lib/hooks/useCopyText.ts +47 -0
- package/examples/src/pages/index.astro +56 -0
- package/examples/src/styles/_base.css +155 -0
- package/examples/src/styles/_components.css +123 -0
- package/examples/src/styles/_utilities.css +23 -0
- package/examples/src/styles/app.css +397 -0
- package/examples/tsconfig.json +3 -0
- package/examples/yarn.lock +3316 -0
- package/marqy.css +131 -0
- package/package.json +25 -11
- package/src/marqy.tsx +63 -53
- package/tsconfig.json +5 -2
- package/dist/marqy.modern.js +0 -2
- package/dist/marqy.modern.js.map +0 -1
- package/examples/index.css +0 -96
- package/examples/index.html +0 -15
- package/examples/index.js +0 -62
- package/styles.css +0 -65
package/marqy.css
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
[data-marqy] {
|
|
2
|
+
position: relative;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
[data-marqy][data-direction='left'],
|
|
7
|
+
[data-marqy][data-direction='right'] {
|
|
8
|
+
overflow-x: clip;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
[data-marqy][data-direction='up'],
|
|
12
|
+
[data-marqy][data-direction='down'] {
|
|
13
|
+
overflow-y: clip;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
[data-marqy-inner] {
|
|
17
|
+
display: flex;
|
|
18
|
+
-ms-overflow-style: none;
|
|
19
|
+
scrollbar-width: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
[data-marqy][data-direction='up'] [data-marqy-inner],
|
|
23
|
+
[data-marqy][data-direction='down'] [data-marqy-inner],
|
|
24
|
+
[data-marqy][data-direction='up'] [data-marqy-content],
|
|
25
|
+
[data-marqy][data-direction='down'] [data-marqy-content] {
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
[data-marqy-inner]::-webkit-scrollbar {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
[data-marqy][data-direction='right'] [data-marqy-inner] {
|
|
34
|
+
justify-content: flex-end;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[data-marqy][data-direction='down'] [data-marqy-inner],
|
|
38
|
+
[data-marqy][data-direction='down'] [data-marqy-content] {
|
|
39
|
+
justify-content: flex-end;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[data-marqy-content] {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex: 1 0 auto;
|
|
45
|
+
animation-timing-function: linear;
|
|
46
|
+
animation-iteration-count: infinite;
|
|
47
|
+
animation-play-state: running;
|
|
48
|
+
will-change: transform;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[data-marqy-static] [data-marqy-content] {
|
|
52
|
+
animation: none !important;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
[data-marqy][data-direction='left'] [data-marqy-content] {
|
|
56
|
+
animation-name: marqyL;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
[data-marqy][data-direction='right'] [data-marqy-content] {
|
|
60
|
+
animation-name: marqyR;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
[data-marqy][data-direction='up'] [data-marqy-content] {
|
|
64
|
+
animation-name: marqyU;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
[data-marqy][data-direction='down'] [data-marqy-content] {
|
|
68
|
+
animation-name: marqyD;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[data-marqy][data-pause-on-hover]:hover
|
|
72
|
+
> [data-marqy-inner]
|
|
73
|
+
> [data-marqy-content] {
|
|
74
|
+
animation-play-state: paused;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
[data-marqy-item] {
|
|
78
|
+
flex-grow: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@keyframes marqyL {
|
|
82
|
+
0% {
|
|
83
|
+
transform: translate3d(0, 0, 0);
|
|
84
|
+
}
|
|
85
|
+
100% {
|
|
86
|
+
transform: translate3d(-100%, 0, 0);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@keyframes marqyR {
|
|
91
|
+
0% {
|
|
92
|
+
transform: translate3d(0, 0, 0);
|
|
93
|
+
}
|
|
94
|
+
100% {
|
|
95
|
+
transform: translate3d(100%, 0, 0);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@keyframes marqyU {
|
|
100
|
+
0% {
|
|
101
|
+
transform: translate3d(0, 0, 0);
|
|
102
|
+
}
|
|
103
|
+
100% {
|
|
104
|
+
transform: translate3d(0, -100%, 0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@keyframes marqyD {
|
|
109
|
+
0% {
|
|
110
|
+
transform: translate3d(0, -100%, 0);
|
|
111
|
+
}
|
|
112
|
+
100% {
|
|
113
|
+
transform: translate3d(0, 0, 0);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@media (prefers-reduced-motion) {
|
|
118
|
+
[data-marqy][data-direction='left'] [data-marqy-inner],
|
|
119
|
+
[data-marqy][data-direction='right'] [data-marqy-inner] {
|
|
120
|
+
overflow-x: scroll;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
[data-marqy][data-direction='up'],
|
|
124
|
+
[data-marqy][data-direction='down'] {
|
|
125
|
+
overflow-y: scroll;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
[data-marqy-content] {
|
|
129
|
+
animation: none !important;
|
|
130
|
+
}
|
|
131
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "marqy",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Accessible, performant React marquees.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
"module": "dist/marqy.esm.js",
|
|
22
22
|
"unpkg": "dist/marqy.umd.js",
|
|
23
23
|
"exports": {
|
|
24
|
+
"./dist/marqy.css": "./dist/marqy.css",
|
|
24
25
|
".": {
|
|
25
|
-
"
|
|
26
|
+
"types": "./dist/marqy.d.ts",
|
|
26
27
|
"umd": "./dist/marqy.umd.js",
|
|
27
28
|
"import": "./dist/marqy.esm.js",
|
|
28
29
|
"require": "./dist/marqy.js"
|
|
@@ -30,22 +31,35 @@
|
|
|
30
31
|
},
|
|
31
32
|
"types": "dist/marqy.d.ts",
|
|
32
33
|
"scripts": {
|
|
33
|
-
"build": "microbundle build src/marqy.tsx --jsx React.createElement",
|
|
34
|
+
"build": "microbundle build src/marqy.tsx --jsx React.createElement && cp marqy.css dist/marqy.css",
|
|
34
35
|
"watch": "microbundle watch src/marqy.tsx --jsx React.createElement",
|
|
35
|
-
"examples": "
|
|
36
|
+
"install:examples": "yarn --cwd examples install",
|
|
37
|
+
"examples": "yarn --cwd examples dev",
|
|
38
|
+
"predev": "yarn build",
|
|
36
39
|
"dev": "concurrently \"yarn watch\" \"yarn examples\"",
|
|
40
|
+
"size": "size-limit",
|
|
37
41
|
"prepublishOnly": "yarn build"
|
|
38
42
|
},
|
|
43
|
+
"size-limit": [
|
|
44
|
+
{
|
|
45
|
+
"path": "dist/marqy.esm.js",
|
|
46
|
+
"limit": "2 KB"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
39
49
|
"devDependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"
|
|
50
|
+
"@size-limit/preset-small-lib": "^12.1.0",
|
|
51
|
+
"@types/react": "^19.0.8",
|
|
52
|
+
"@types/react-dom": "^19.0.3",
|
|
53
|
+
"concurrently": "^9.1.2",
|
|
42
54
|
"microbundle": "^0.15.1",
|
|
43
55
|
"parcel-bundler": "^1.12.5",
|
|
44
|
-
"react": "^
|
|
45
|
-
"react-dom": "^
|
|
56
|
+
"react": "^19.0.0",
|
|
57
|
+
"react-dom": "^19.0.0",
|
|
58
|
+
"size-limit": "^12.1.0"
|
|
46
59
|
},
|
|
47
60
|
"peerDependencies": {
|
|
48
|
-
"react": "
|
|
49
|
-
"react-dom": "
|
|
50
|
-
}
|
|
61
|
+
"react": "17.x || 18.x || 19.x",
|
|
62
|
+
"react-dom": "17.x || 18.x || 19.x"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {}
|
|
51
65
|
}
|
package/src/marqy.tsx
CHANGED
|
@@ -1,29 +1,43 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
speed?: number
|
|
5
|
-
direction?: 'left' | 'right'
|
|
6
|
-
pauseOnHover?: boolean
|
|
7
|
-
|
|
3
|
+
export interface MarqyProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
4
|
+
speed?: number
|
|
5
|
+
direction?: 'left' | 'right' | 'up' | 'down'
|
|
6
|
+
pauseOnHover?: boolean
|
|
7
|
+
manual?: boolean
|
|
8
|
+
children: React.ReactNode
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export function Marqy({
|
|
11
12
|
speed = 0.5,
|
|
12
13
|
direction = 'left',
|
|
13
14
|
pauseOnHover,
|
|
15
|
+
manual = false,
|
|
14
16
|
children,
|
|
15
17
|
...rest
|
|
16
|
-
}: MarqyProps):
|
|
18
|
+
}: MarqyProps): React.ReactElement {
|
|
17
19
|
const [reps, setReps] = React.useState(1)
|
|
18
20
|
|
|
19
|
-
const [container,
|
|
20
|
-
const [item,
|
|
21
|
+
const [container, containerDimensions] = useDimensions()
|
|
22
|
+
const [item, itemDimensions] = useDimensions()
|
|
23
|
+
|
|
24
|
+
const isVertical = direction === 'up' || direction === 'down'
|
|
25
|
+
|
|
26
|
+
const getAnimationDuration = React.useCallback(
|
|
27
|
+
(itemDimension: number) => {
|
|
28
|
+
return `${((itemDimension ?? 0) * reps) / (100 * speed)}s`
|
|
29
|
+
},
|
|
30
|
+
[reps, speed]
|
|
31
|
+
)
|
|
21
32
|
|
|
22
33
|
React.useEffect(() => {
|
|
23
|
-
if (
|
|
24
|
-
setReps(Math.ceil(
|
|
34
|
+
if (!isVertical && containerDimensions.width && itemDimensions.width) {
|
|
35
|
+
setReps(Math.ceil(containerDimensions.width / itemDimensions.width))
|
|
36
|
+
}
|
|
37
|
+
if (isVertical && containerDimensions.height && itemDimensions.height) {
|
|
38
|
+
setReps(Math.ceil(containerDimensions.height / itemDimensions.height))
|
|
25
39
|
}
|
|
26
|
-
}, [
|
|
40
|
+
}, [isVertical, containerDimensions, itemDimensions])
|
|
27
41
|
|
|
28
42
|
return (
|
|
29
43
|
<div
|
|
@@ -34,54 +48,50 @@ export function Marqy({
|
|
|
34
48
|
{...rest}
|
|
35
49
|
>
|
|
36
50
|
<div data-marqy-inner="">
|
|
37
|
-
{new Array(2).fill(0).map((_, clone) =>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</div>
|
|
62
|
-
)
|
|
63
|
-
})}
|
|
51
|
+
{new Array(2).fill(0).map((_, clone) => (
|
|
52
|
+
<div
|
|
53
|
+
key={clone}
|
|
54
|
+
data-marqy-content=""
|
|
55
|
+
{...(manual
|
|
56
|
+
? { 'data-marqy-static': getAnimationDuration(isVertical ? itemDimensions.height : itemDimensions.width) }
|
|
57
|
+
: { style: { animationDuration: getAnimationDuration(isVertical ? itemDimensions.height : itemDimensions.width) } }
|
|
58
|
+
)}
|
|
59
|
+
>
|
|
60
|
+
{new Array(reps).fill(0).map((_, rep) => {
|
|
61
|
+
const isFirstItem = clone === 0 && rep === 0
|
|
62
|
+
return (
|
|
63
|
+
<div
|
|
64
|
+
key={rep}
|
|
65
|
+
ref={isFirstItem ? item : null}
|
|
66
|
+
aria-hidden={!isFirstItem || null}
|
|
67
|
+
data-marqy-item=""
|
|
68
|
+
>
|
|
69
|
+
{children}
|
|
70
|
+
</div>
|
|
71
|
+
)
|
|
72
|
+
})}
|
|
73
|
+
</div>
|
|
74
|
+
))}
|
|
64
75
|
</div>
|
|
65
76
|
</div>
|
|
66
77
|
)
|
|
67
78
|
}
|
|
68
79
|
|
|
69
|
-
function
|
|
70
|
-
const [
|
|
71
|
-
const [node, setNode] = React.useState<HTMLElement | null>(null)
|
|
80
|
+
function useDimensions() {
|
|
81
|
+
const [dimensions, setDimensions] = React.useState({ width: 0, height: 0 })
|
|
72
82
|
const observer = React.useRef<ResizeObserver | null>(null)
|
|
73
83
|
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
observer.current = new ResizeObserver(([entry]) =>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}, [
|
|
84
|
+
const ref = React.useCallback((node: HTMLElement | null) => {
|
|
85
|
+
observer.current?.disconnect()
|
|
86
|
+
if (!node) return
|
|
87
|
+
observer.current = new ResizeObserver(([entry]) =>
|
|
88
|
+
setDimensions({
|
|
89
|
+
width: entry.contentRect.width,
|
|
90
|
+
height: entry.contentRect.height,
|
|
91
|
+
})
|
|
92
|
+
)
|
|
93
|
+
observer.current.observe(node)
|
|
94
|
+
}, [])
|
|
85
95
|
|
|
86
|
-
return [
|
|
96
|
+
return [ref, dimensions] as const
|
|
87
97
|
}
|
package/tsconfig.json
CHANGED
package/dist/marqy.modern.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{useState as e,useEffect as n,createElement as r,useRef as t,useCallback as a}from"react";function i(t){let{speed:a=.5,direction:i="left",pauseOnHover:o,children:u}=t,c=function(e,n){if(null==e)return{};var r,t,a={},i=Object.keys(e);for(t=0;t<i.length;t++)n.indexOf(r=i[t])>=0||(a[r]=e[r]);return a}(t,["speed","direction","pauseOnHover","children"]);const[d,s]=e(1),[f,v]=l(),[m,y]=l();return n(()=>{v&&y&&s(Math.ceil(v/y))},[v,y]),r("div",Object.assign({ref:f,"data-marqy":"","data-direction":i,"data-pause-on-hover":o?"":null},c),r("div",{"data-marqy-inner":""},new Array(2).fill(0).map((e,n)=>r("div",{key:n,"data-marqy-content":"",style:{animationDuration:(null!=y?y:0)*d/(100*a)+"s"}},new Array(d).fill(0).map((e,t)=>{const a=0===n&&0===t;return r("div",{key:t,ref:a?m:null,"aria-hidden":!a||null,"data-marqy-item":""},u)})))))}function l(){const[r,i]=e(0),[l,o]=e(null),u=t(null),c=a(()=>{var e;return null==(e=u.current)?void 0:e.disconnect()},[]),d=a(()=>{u.current=new ResizeObserver(([e])=>i(e.contentRect.width)),l&&u.current.observe(l)},[l]);return n(()=>(d(),()=>c()),[c,d]),[o,r]}export{i as Marqy};
|
|
2
|
-
//# sourceMappingURL=marqy.modern.js.map
|
package/dist/marqy.modern.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"marqy.modern.js","sources":["../src/marqy.tsx"],"sourcesContent":["import * as React from 'react'\n\nexport declare interface MarqyProps {\n speed?: number;\n direction?: 'left' | 'right';\n pauseOnHover?: boolean;\n children: React.ReactNode;\n}\n\nexport function Marqy({\n speed = 0.5,\n direction = 'left',\n pauseOnHover,\n children,\n ...rest\n}: MarqyProps): JSX.Element {\n const [reps, setReps] = React.useState(1)\n\n const [container, containerWidth] = useWidth()\n const [item, itemWidth] = useWidth()\n\n React.useEffect(() => {\n if (containerWidth && itemWidth) {\n setReps(Math.ceil(containerWidth / itemWidth))\n }\n }, [containerWidth, itemWidth])\n\n return (\n <div\n ref={container}\n data-marqy=\"\"\n data-direction={direction}\n data-pause-on-hover={pauseOnHover ? '' : null}\n {...rest}\n >\n <div data-marqy-inner=\"\">\n {new Array(2).fill(0).map((_, clone) => {\n return (\n <div\n key={clone}\n data-marqy-content=\"\"\n style={{\n animationDuration: `${\n ((itemWidth ?? 0) * reps) / (100 * speed)\n }s`,\n }}\n >\n {new Array(reps).fill(0).map((_, rep) => {\n const isFirstItem = clone === 0 && rep === 0\n return (\n <div\n key={rep}\n ref={isFirstItem ? item : null}\n aria-hidden={!isFirstItem || null}\n data-marqy-item=\"\"\n >\n {children}\n </div>\n )\n })}\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n\nfunction useWidth() {\n const [width, setWidth] = React.useState(0)\n const [node, setNode] = React.useState<HTMLElement | null>(null)\n const observer = React.useRef<ResizeObserver | null>(null)\n\n const disconnect = React.useCallback(() => observer.current?.disconnect(), [])\n\n const observe = React.useCallback(() => {\n observer.current = new ResizeObserver(([entry]) => setWidth(entry.contentRect.width))\n if (node) observer.current.observe(node)\n }, [node])\n\n React.useEffect(() => {\n observe()\n return () => disconnect()\n }, [disconnect, observe])\n\n return [setNode, width] as const\n}\n"],"names":["Marqy","speed","direction","pauseOnHover","children","rest","reps","setReps","React","container","containerWidth","useWidth","item","itemWidth","Math","ceil","ref","Array","fill","map","_","clone","key","style","animationDuration","rep","isFirstItem","width","setWidth","node","setNode","observer","disconnect","current","_observer$current","observe","ResizeObserver","entry","contentRect"],"mappings":"yGASgBA,SAAMC,MACpBA,EAAQ,GADYC,UAEpBA,EAAY,OAFQC,aAGpBA,EAHoBC,SAIpBA,KACGC,wLAEH,MAAOC,EAAMC,GAAWC,EAAe,IAEhCC,EAAWC,GAAkBC,KAC7BC,EAAMC,GAAaF,IAQ1B,OANAH,EAAgB,KACVE,GAAkBG,GACpBN,EAAQO,KAAKC,KAAKL,EAAiBG,KAEpC,CAACH,EAAgBG,IAGlBL,uBACEQ,IAAKP,eACM,oBACKP,wBACKC,EAAe,GAAK,MACrCE,GAEJG,4BAAsB,IACnB,IAAIS,MAAM,GAAGC,KAAK,GAAGC,IAAI,CAACC,EAAGC,IAE1Bb,SACEc,IAAKD,uBACc,GACnBE,MAAO,CACLC,yBACIX,EAAAA,EAAa,GAAKP,GAAS,IAAML,SAItC,IAAIgB,MAAMX,GAAMY,KAAK,GAAGC,IAAI,CAACC,EAAGK,KAC/B,MAAMC,EAAwB,IAAVL,GAAuB,IAARI,EACnC,OACEjB,SACEc,IAAKG,EACLT,IAAKU,EAAcd,EAAO,oBACZc,GAAe,uBACb,IAEftB,SAYrB,SAASO,IACP,MAAOgB,EAAOC,GAAYpB,EAAe,IAClCqB,EAAMC,GAAWtB,EAAmC,MACrDuB,EAAWvB,EAAoC,MAE/CwB,EAAaxB,EAAkB,2BAAMuB,EAASE,gBAATC,EAAkBF,cAAc,IAErEG,EAAU3B,EAAkB,KAChCuB,EAASE,QAAU,IAAIG,eAAe,EAAEC,KAAWT,EAASS,EAAMC,YAAYX,QAC1EE,GAAME,EAASE,QAAQE,QAAQN,IAClC,CAACA,IAOJ,OALArB,EAAgB,KACd2B,IACO,IAAMH,KACZ,CAACA,EAAYG,IAET,CAACL,EAASH"}
|
package/examples/index.css
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
* {
|
|
2
|
-
box-sizing: border-box;
|
|
3
|
-
margin: 0;
|
|
4
|
-
-webkit-font-smoothing: antialiased;
|
|
5
|
-
-moz-osx-font-smoothing: grayscale;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
body {
|
|
9
|
-
font-family: 'Arial Narrow', sans-serif;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
h1,
|
|
13
|
-
h2,
|
|
14
|
-
h3,
|
|
15
|
-
h4,
|
|
16
|
-
h5,
|
|
17
|
-
h6 {
|
|
18
|
-
font-weight: 400;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
button {
|
|
22
|
-
border: unset;
|
|
23
|
-
border-radius: unset;
|
|
24
|
-
background: unset;
|
|
25
|
-
color: block;
|
|
26
|
-
font-size: 20px;
|
|
27
|
-
font-family: serif;
|
|
28
|
-
padding: 0.5em;
|
|
29
|
-
border: 1px solid black;
|
|
30
|
-
border-radius: 10px;
|
|
31
|
-
outline: unset;
|
|
32
|
-
cursor: pointer;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
button:hover {
|
|
36
|
-
background-color: rgba(0, 0, 0, 0.15);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.invert button,
|
|
40
|
-
button.invert {
|
|
41
|
-
color: white;
|
|
42
|
-
border: 1px solid white;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.invert button:hover,
|
|
46
|
-
button.invert:hover {
|
|
47
|
-
background-color: rgba(255, 255, 255, 0.15);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
img {
|
|
51
|
-
border-radius: 9999px;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.py-025 {
|
|
55
|
-
padding-top: 0.25em;
|
|
56
|
-
padding-bottom: 0.25em;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.p-05 {
|
|
60
|
-
padding: 0.5em;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.py-05 {
|
|
64
|
-
padding-top: 0.5em;
|
|
65
|
-
padding-bottom: 0.5em;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.mr-025 {
|
|
69
|
-
margin-right: 0.25em;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.mx-05 {
|
|
73
|
-
margin-right: 0.5em;
|
|
74
|
-
margin-left: 0.5em;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.flex {
|
|
78
|
-
display: flex;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.items-center {
|
|
82
|
-
align-items: center;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.invert {
|
|
86
|
-
background-color: black;
|
|
87
|
-
color: white;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.text-20 {
|
|
91
|
-
font-size: 20px;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
.text-32 {
|
|
95
|
-
font-size: 32px;
|
|
96
|
-
}
|
package/examples/index.html
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>marqy examples</title>
|
|
8
|
-
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🤠</text></svg>">
|
|
9
|
-
</head>
|
|
10
|
-
<link rel="stylesheet" href="./index.css">
|
|
11
|
-
<body>
|
|
12
|
-
<div id="root"></div>
|
|
13
|
-
<script src="./index.js"></script>
|
|
14
|
-
</body>
|
|
15
|
-
</html>
|
package/examples/index.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import React, { useReducer } from 'react'
|
|
2
|
-
import { render } from 'react-dom'
|
|
3
|
-
import { Marqy } from '../dist/marqy.js'
|
|
4
|
-
import '../styles.css'
|
|
5
|
-
|
|
6
|
-
function App() {
|
|
7
|
-
const [count, increment] = useReducer((x) => x + 1, 0)
|
|
8
|
-
const [shown, toggle] = useReducer((x) => !x, true)
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
<div>
|
|
12
|
-
<Marqy>
|
|
13
|
-
<p className="text-32 py-025 mr-025">Default configuration ●</p>
|
|
14
|
-
</Marqy>
|
|
15
|
-
<Marqy className="invert">
|
|
16
|
-
<p className="text-32 py-025 mr-025">
|
|
17
|
-
Synchronized speeds even if content length is different.
|
|
18
|
-
</p>
|
|
19
|
-
</Marqy>
|
|
20
|
-
<Marqy direction="right">
|
|
21
|
-
<p className="text-32 py-025 mr-025">You can change the direction…</p>
|
|
22
|
-
</Marqy>
|
|
23
|
-
<Marqy className="invert" direction="right" speed="0.25">
|
|
24
|
-
<p className="text-32 py-025 mr-025">And customize the speed!</p>
|
|
25
|
-
</Marqy>
|
|
26
|
-
<Marqy direction="right" speed="0.4">
|
|
27
|
-
<div className="flex items-center py-05">
|
|
28
|
-
<p className="text-32 mx-05">Render whatever you want:</p>
|
|
29
|
-
<img
|
|
30
|
-
width="100"
|
|
31
|
-
src="https://picsum.photos/seed/picsum/550/350"
|
|
32
|
-
alt="Lorem Picsum"
|
|
33
|
-
/>
|
|
34
|
-
</div>
|
|
35
|
-
</Marqy>
|
|
36
|
-
<Marqy className="invert" speed="0.7" pauseOnHover>
|
|
37
|
-
<div className="flex items-center py-025">
|
|
38
|
-
<p className="text-20">Pause on hover for interactivity:</p>
|
|
39
|
-
<button className="mx-05" onClick={increment}>
|
|
40
|
-
Count: {count}
|
|
41
|
-
</button>
|
|
42
|
-
</div>
|
|
43
|
-
</Marqy>
|
|
44
|
-
<div className="p-05">
|
|
45
|
-
<button onClick={toggle}>Toggle</button>
|
|
46
|
-
</div>
|
|
47
|
-
{shown ? (
|
|
48
|
-
<Marqy className="invert text-20 py-05">
|
|
49
|
-
<p className="mx-05">
|
|
50
|
-
Toggle me on or off to make sure I have no memory leaks!
|
|
51
|
-
</p>
|
|
52
|
-
</Marqy>
|
|
53
|
-
) : null}
|
|
54
|
-
{/* Child with no width */}
|
|
55
|
-
<Marqy>
|
|
56
|
-
<p className="text-32 py-025"></p>
|
|
57
|
-
</Marqy>
|
|
58
|
-
</div>
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
render(<App />, document.getElementById('root'))
|
package/styles.css
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
[data-marqy] {
|
|
2
|
-
position: relative;
|
|
3
|
-
overflow: hidden;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
[data-marqy-inner] {
|
|
7
|
-
display: flex;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
[data-marqy][data-direction='right'] [data-marqy-inner] {
|
|
11
|
-
justify-content: flex-end;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
[data-marqy-content] {
|
|
15
|
-
display: flex;
|
|
16
|
-
flex: 1 0 auto;
|
|
17
|
-
animation-timing-function: linear;
|
|
18
|
-
animation-iteration-count: infinite;
|
|
19
|
-
animation-play-state: running;
|
|
20
|
-
will-change: transform;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
[data-marqy][data-direction='left'] [data-marqy-content] {
|
|
24
|
-
animation-name: marqyL;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
[data-marqy][data-direction='right'] [data-marqy-content] {
|
|
28
|
-
animation-name: marqyR;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
[data-marqy][data-pause-on-hover]:hover [data-marqy-content] {
|
|
32
|
-
animation-play-state: paused;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
[data-marqy-item] {
|
|
36
|
-
flex-grow: 0;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@keyframes marqyL {
|
|
40
|
-
0% {
|
|
41
|
-
transform: translate3d(0, 0, 0);
|
|
42
|
-
}
|
|
43
|
-
100% {
|
|
44
|
-
transform: translate3d(-100%, 0, 0);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
@keyframes marqyR {
|
|
49
|
-
0% {
|
|
50
|
-
transform: translate3d(0, 0, 0);
|
|
51
|
-
}
|
|
52
|
-
100% {
|
|
53
|
-
transform: translate3d(100%, 0, 0);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
@media (prefers-reduced-motion) {
|
|
58
|
-
[data-marqy-inner] {
|
|
59
|
-
overflow-x: scroll;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
[data-marqy-content] {
|
|
63
|
-
animation: none !important;
|
|
64
|
-
}
|
|
65
|
-
}
|