marqy 1.0.2 → 1.1.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.
Files changed (117) hide show
  1. package/README.md +1 -1
  2. package/dist/core-COOoOGpB.js +21 -0
  3. package/dist/core-COOoOGpB.js.map +1 -0
  4. package/dist/core-CuZGUfsl.cjs +2 -0
  5. package/dist/core-CuZGUfsl.cjs.map +1 -0
  6. package/dist/index.cjs.js +2 -0
  7. package/dist/index.cjs.js.map +1 -0
  8. package/dist/index.d.ts +15 -0
  9. package/dist/index.esm.js +5 -0
  10. package/dist/index.esm.js.map +1 -0
  11. package/dist/marqy.css +4 -0
  12. package/dist/react.cjs.js +2 -0
  13. package/dist/react.cjs.js.map +1 -0
  14. package/dist/react.d.ts +15 -0
  15. package/dist/react.esm.js +60 -0
  16. package/dist/react.esm.js.map +1 -0
  17. package/dist/svelte.cjs.js +2 -0
  18. package/dist/svelte.cjs.js.map +1 -0
  19. package/dist/svelte.d.ts +7 -0
  20. package/dist/svelte.esm.js +54 -0
  21. package/dist/svelte.esm.js.map +1 -0
  22. package/dist/vanilla.cjs.js +2 -0
  23. package/dist/vanilla.cjs.js.map +1 -0
  24. package/dist/vanilla.d.ts +32 -0
  25. package/dist/vanilla.esm.js +96 -0
  26. package/dist/vanilla.esm.js.map +1 -0
  27. package/dist/vue.cjs.js +2 -0
  28. package/dist/vue.cjs.js.map +1 -0
  29. package/dist/vue.d.ts +45 -0
  30. package/dist/vue.esm.js +70 -0
  31. package/dist/vue.esm.js.map +1 -0
  32. package/package.json +81 -19
  33. package/.claude/settings.local.json +0 -13
  34. package/.prettierrc +0 -6
  35. package/.vscode/settings.json +0 -3
  36. package/dist/marqy.d.ts +0 -9
  37. package/dist/marqy.esm.js +0 -2
  38. package/dist/marqy.esm.js.map +0 -1
  39. package/dist/marqy.js +0 -2
  40. package/dist/marqy.js.map +0 -1
  41. package/dist/marqy.umd.js +0 -2
  42. package/dist/marqy.umd.js.map +0 -1
  43. package/examples/.astro/content-assets.mjs +0 -1
  44. package/examples/.astro/content-modules.mjs +0 -1
  45. package/examples/.astro/content.d.ts +0 -154
  46. package/examples/.astro/data-store.json +0 -1
  47. package/examples/.astro/fonts/font-akkurat-mono-500-normal-40f4e0ea0b54adc5.woff2 +0 -0
  48. package/examples/.astro/fonts/font-akkurat-mono-700-normal-b9f40f1447b587bd.woff +0 -0
  49. package/examples/.astro/fonts/font-grtsk-300-normal-8ef14ca23be6893c.woff2 +0 -0
  50. package/examples/.astro/fonts/font-grtsk-400-normal-13ba8954073ee64a.woff2 +0 -0
  51. package/examples/.astro/fonts/font-grtsk-500-normal-d214468daf16245f.woff2 +0 -0
  52. package/examples/.astro/fonts/font-grtsk-wide-500-normal-6f8c2658b9c2ba8e.woff2 +0 -0
  53. package/examples/.astro/fonts/font-grtsk-wide-700-normal-17406f09c7b68ca3.woff2 +0 -0
  54. package/examples/.astro/fonts.d.ts +0 -4
  55. package/examples/.astro/settings.json +0 -5
  56. package/examples/.astro/types.d.ts +0 -3
  57. package/examples/.yarnrc +0 -1
  58. package/examples/astro.config.mjs +0 -101
  59. package/examples/package.json +0 -30
  60. package/examples/public/apple-touch-icon.png +0 -0
  61. package/examples/public/favicon.ico +0 -0
  62. package/examples/public/favicon.svg +0 -4
  63. package/examples/public/marqy-logo.svg +0 -35
  64. package/examples/src/assets/baggu.jpg +0 -0
  65. package/examples/src/assets/bluesky.jpg +0 -0
  66. package/examples/src/assets/clams-lol.jpg +0 -0
  67. package/examples/src/assets/coconut-club-2.jpg +0 -0
  68. package/examples/src/assets/coconut-club.jpg +0 -0
  69. package/examples/src/assets/lucci.jpg +0 -0
  70. package/examples/src/assets/phila-museum.jpg +0 -0
  71. package/examples/src/assets/red-rooster.jpg +0 -0
  72. package/examples/src/assets/sanity.jpg +0 -0
  73. package/examples/src/assets/usal.jpg +0 -0
  74. package/examples/src/assets/vacation.jpg +0 -0
  75. package/examples/src/components/CopyButton.tsx +0 -26
  76. package/examples/src/components/Divider.tsx +0 -3
  77. package/examples/src/components/Footer.astro +0 -7
  78. package/examples/src/components/InUse.astro +0 -89
  79. package/examples/src/components/InUseExamples.tsx +0 -60
  80. package/examples/src/components/MarqyCredits.tsx +0 -33
  81. package/examples/src/components/MarqyHero.tsx +0 -77
  82. package/examples/src/components/MarqyInteractiveDemo.tsx +0 -46
  83. package/examples/src/components/MarqyPlayground.tsx +0 -496
  84. package/examples/src/components/MarqySpeedDemo.tsx +0 -34
  85. package/examples/src/components/MarqyVerticalDemo.tsx +0 -44
  86. package/examples/src/components/Playground.astro +0 -11
  87. package/examples/src/components/QuickStart.astro +0 -59
  88. package/examples/src/components/SectionHeadline.tsx +0 -41
  89. package/examples/src/components/Tile.tsx +0 -32
  90. package/examples/src/content.config.ts +0 -3
  91. package/examples/src/fonts/Akkurat-Mono-Bold.woff +0 -0
  92. package/examples/src/fonts/Akkurat-Mono.woff +0 -0
  93. package/examples/src/fonts/Akkurat-Mono.woff2 +0 -0
  94. package/examples/src/fonts/Grtsk-Peta-Light.woff +0 -0
  95. package/examples/src/fonts/Grtsk-Peta-Light.woff2 +0 -0
  96. package/examples/src/fonts/Grtsk-Peta-Medium.woff +0 -0
  97. package/examples/src/fonts/Grtsk-Peta-Medium.woff2 +0 -0
  98. package/examples/src/fonts/Grtsk-Peta-Regular.woff +0 -0
  99. package/examples/src/fonts/Grtsk-Peta-Regular.woff2 +0 -0
  100. package/examples/src/fonts/Grtsk-Tera-Bold.woff +0 -0
  101. package/examples/src/fonts/Grtsk-Tera-Bold.woff2 +0 -0
  102. package/examples/src/fonts/Grtsk-Tera-Medium.woff +0 -0
  103. package/examples/src/fonts/Grtsk-Tera-Medium.woff2 +0 -0
  104. package/examples/src/layouts/layout.astro +0 -107
  105. package/examples/src/lib/cn.ts +0 -16
  106. package/examples/src/lib/helpers.ts +0 -13
  107. package/examples/src/lib/hooks/useCopyText.ts +0 -47
  108. package/examples/src/pages/index.astro +0 -56
  109. package/examples/src/styles/_base.css +0 -155
  110. package/examples/src/styles/_components.css +0 -123
  111. package/examples/src/styles/_utilities.css +0 -23
  112. package/examples/src/styles/app.css +0 -397
  113. package/examples/tsconfig.json +0 -3
  114. package/examples/yarn.lock +0 -3316
  115. package/marqy.css +0 -131
  116. package/src/marqy.tsx +0 -97
  117. package/tsconfig.json +0 -9
@@ -1,496 +0,0 @@
1
- import React, { forwardRef, useState, useEffect, useRef } from 'react'
2
- import { gsap } from 'gsap'
3
- import { Marqy } from 'marqy'
4
- import { RadioGroup } from '@base-ui-components/react/radio-group'
5
- import { Radio } from '@base-ui-components/react/radio'
6
- import { Slider } from '@base-ui-components/react/slider'
7
- import { Switch } from '@base-ui-components/react/switch'
8
- import { ResizableBox } from 'react-resizable'
9
- import useDimensions from 'react-cool-dimensions'
10
-
11
- import { cn } from '../lib/cn'
12
- import Divider from './Divider'
13
-
14
- const DIRECTIONS = ['left', 'right', 'up', 'down'] as const
15
- type Direction = (typeof DIRECTIONS)[number]
16
-
17
- type DragHandleProps = React.HTMLAttributes<HTMLDivElement> & {
18
- handleAxis?: string
19
- }
20
-
21
- const DragHandle = forwardRef<HTMLDivElement, DragHandleProps>((props, ref) => {
22
- const { handleAxis, ...restProps } = props
23
- return (
24
- <div
25
- ref={ref}
26
- className={cn(
27
- 'flex justify-center items-center absolute bg-purple rounded-2 z-4 cursor-grab active:cursor-grabbing text-center',
28
- {
29
- // Y-axis
30
- 'w-55 h-8 -translate-y-1/2 -translate-x-1/2 after:absolute after:h-px after:w-20 after:bg-black/30':
31
- handleAxis === 'n' || handleAxis === 's',
32
- 'top-0 left-1/2': handleAxis === 'n',
33
- 'top-full left-1/2': handleAxis === 's',
34
-
35
- // X-axis
36
- 'h-55 w-8 -translate-y-1/2 -translate-x-1/2 after:absolute after:w-px after:h-20 after:bg-black/30':
37
- handleAxis === 'w' || handleAxis === 'e',
38
- 'left-0 top-1/2': handleAxis === 'w',
39
- 'left-full top-1/2': handleAxis === 'e',
40
- },
41
- )}
42
- {...restProps}
43
- />
44
- )
45
- })
46
-
47
- export default function MarqyPlayground() {
48
- const $marqyContainer = useRef<HTMLDivElement>(null)
49
- const { observe, height, width } = useDimensions<HTMLDivElement>({
50
- useBorderBoxSize: true,
51
- })
52
- const [itemCount, setItemCount] = useState<number>(0)
53
- const [duration, setDuration] = useState('')
54
-
55
- const DEFAULT_TEXT = 'marqy'
56
- const [size, setSize] = useState({ width: width - 40, height: -40 })
57
- const [isResizing, setIsResizing] = useState(false)
58
- const [text, setText] = useState(DEFAULT_TEXT)
59
- const [direction, setDirection] = useState<Direction>('left')
60
- const [speed, setSpeed] = useState(1)
61
- const [pauseOnHover, setPauseOnHover] = useState(false)
62
- const [manual, setManual] = useState(false)
63
- const [showXRay, setShowXRay] = useState(false)
64
-
65
- const [gsapEnabled, setGsapEnabled] = useState(false)
66
-
67
- const isVertical = direction === 'up' || direction === 'down'
68
- const overlayClass = 'after:absolute after:inset-y-0 after:bg-black/80'
69
-
70
- useEffect(() => {
71
- const container = $marqyContainer.current
72
- const $content = gsap.utils.toArray<HTMLElement>(
73
- '[data-marqy-content]',
74
- container,
75
- )
76
- if (!container || !$content.length) return
77
-
78
- if (!gsapEnabled) {
79
- // Only kill stale tweens — don't touch inline styles, CSS owns the transform
80
- gsap.killTweensOf($content)
81
- return
82
- }
83
-
84
- let tween: gsap.core.Tween | null = null
85
-
86
- const buildTween = () => {
87
- const dur = parseFloat($content[0].dataset.marqyStatic ?? '')
88
- if (!dur) return
89
-
90
- gsap.killTweensOf(tween)
91
- tween?.kill()
92
- gsap.killTweensOf($content)
93
- gsap.set($content, { xPercent: 0, yPercent: 0 })
94
-
95
- if (direction === 'down') {
96
- // CSS marqyD: translate from -100% → 0
97
- gsap.set($content, { yPercent: -100 })
98
- tween = gsap.to($content, {
99
- yPercent: 0,
100
- ease: 'none',
101
- duration: dur,
102
- repeat: -1,
103
- })
104
- } else if (direction === 'up') {
105
- // CSS marqyU: translate from 0 → -100%
106
- tween = gsap.to($content, {
107
- yPercent: -100,
108
- ease: 'none',
109
- duration: dur,
110
- repeat: -1,
111
- })
112
- } else {
113
- tween = gsap.to($content, {
114
- xPercent: direction === 'left' ? -100 : 100,
115
- ease: 'none',
116
- duration: dur,
117
- repeat: -1,
118
- })
119
- }
120
-
121
- // If cursor is already inside the container (e.g. enabled via button click),
122
- // immediately apply the paused state so hover works without needing a re-enter
123
- if (pauseOnHover && container.matches(':hover')) {
124
- gsap.set(tween, { timeScale: 0 })
125
- }
126
- }
127
-
128
- // attrObserver handles speed/dimension changes without a full effect re-run
129
- const attrObserver = new MutationObserver(buildTween)
130
- attrObserver.observe($content[0], {
131
- attributes: true,
132
- attributeFilter: ['data-marqy-static'],
133
- })
134
- buildTween()
135
-
136
- const slowDown = () => {
137
- if (!tween) return
138
- gsap.to(tween, {
139
- timeScale: 0,
140
- duration: 1.5,
141
- ease: 'power3.out',
142
- overwrite: 'auto',
143
- })
144
- }
145
- const speedUp = () => {
146
- if (!tween) return
147
- gsap.to(tween, {
148
- timeScale: 1,
149
- duration: 0.75,
150
- ease: 'power3.out',
151
- overwrite: 'auto',
152
- })
153
- }
154
-
155
- if (pauseOnHover) {
156
- container.addEventListener('mouseenter', slowDown)
157
- container.addEventListener('mouseleave', speedUp)
158
- }
159
-
160
- return () => {
161
- attrObserver.disconnect()
162
- gsap.killTweensOf(tween)
163
- tween?.kill()
164
- gsap.killTweensOf($content)
165
- // clearProps lets CSS animation take over cleanly when GSAP is disabled
166
- gsap.set($content, { clearProps: 'transform,xPercent,yPercent' })
167
- container.removeEventListener('mouseenter', slowDown)
168
- container.removeEventListener('mouseleave', speedUp)
169
- }
170
- }, [gsapEnabled, direction, isVertical, pauseOnHover])
171
-
172
- function onResize(
173
- _: any,
174
- { size }: { size: { width: number; height: number } },
175
- ) {
176
- setSize({ width: size.width, height: size.height })
177
- }
178
-
179
- useEffect(() => {
180
- const el = $marqyContainer.current
181
- if (!el) return
182
-
183
- const read = () => {
184
- const firstContent = el.querySelector<HTMLElement>('[data-marqy-content]')
185
- setDuration(firstContent?.style.animationDuration ?? '')
186
- setItemCount(
187
- firstContent?.querySelectorAll('[data-marqy-item]').length ?? 0,
188
- )
189
- }
190
-
191
- const observer = new MutationObserver(read)
192
- observer.observe(el, {
193
- subtree: true,
194
- attributes: true,
195
- attributeFilter: ['style'],
196
- childList: true,
197
- })
198
-
199
- return () => observer.disconnect()
200
- }, [])
201
-
202
- useEffect(() => {
203
- setSize({ width: width - 40, height: height - 40 })
204
- }, [isVertical, width, height])
205
-
206
- return (
207
- <div className={cn('relative grid grid-cols-8 gap-20 sm:gap-40')}>
208
- {/* Controls */}
209
- <div
210
- className={cn(
211
- 'relative col-span-8 md:col-span-4 backdrop-blur-md z-1 rounded-5',
212
- 'after:-left-40 after:-right-40 after:-z-1',
213
- overlayClass,
214
- )}
215
- >
216
- <div
217
- ref={observe}
218
- className="flex flex-col gap-20 bg-white/10 p-20 rounded-5"
219
- >
220
- {/* Text */}
221
- <div className="relative flex justify-between items-center gap-10">
222
- <h3 className="text-p1 sr-only">Text</h3>
223
- <input
224
- value={text}
225
- onChange={(e) => setText(e.target.value)}
226
- className="rounded-4 h-40 pr-75 bg-white/10 font-headline font-bold text-15 uppercase text-white px-10 py-0 focus:outline-none"
227
- />
228
-
229
- <button
230
- disabled={text === DEFAULT_TEXT}
231
- onClick={() => setText(DEFAULT_TEXT)}
232
- className="disabled:cursor-not-allowed clean-btn cursor-pointer rounded-3 flex items-center justify-center absolute right-10 h-20 w-55 bg-white/20 text-white disabled:text-white/40 disabled:bg-white/10"
233
- >
234
- <span className="text-p0 uppercase tracking-10">Reset</span>
235
- </button>
236
- </div>
237
-
238
- {/* Direction */}
239
- <div className="flex justify-between items-center gap-x-20 border-t border-white/10 pt-20">
240
- <h3 className="text-p1">direction</h3>
241
- <RadioGroup
242
- value={direction}
243
- onValueChange={(val) => setDirection(val as Direction)}
244
- className="flex gap-5"
245
- >
246
- {DIRECTIONS.map((dir) => (
247
- <label key={dir} className="flex items-center cursor-pointer">
248
- <Radio.Root
249
- value={dir}
250
- nativeButton
251
- render={<button />}
252
- className="clean-btn cursor-pointer rounded-3 data-checked:animate-flicker-opacity hover:bg-white/20 bg-white/10 min-w-55 h-20 flex items-center justify-center data-checked:bg-neon data-checked:text-black transition-colors"
253
- >
254
- <span className="text-p0 uppercase tracking-10">{dir}</span>
255
- </Radio.Root>
256
- </label>
257
- ))}
258
- </RadioGroup>
259
- </div>
260
-
261
- {/* Speed */}
262
- <div className="flex flex-col gap-10 border-t border-white/10 pt-20">
263
- <div className="flex items-center justify-between gap-x-20">
264
- <h3 className="text-p1">speed</h3>
265
-
266
- <div className="flex-1 flex items-center justify-end gap-x-10">
267
- <Slider.Root
268
- value={speed}
269
- onValueChange={(val) => setSpeed(val as number)}
270
- min={0.1}
271
- max={3}
272
- step={0.1}
273
- thumbAlignment="edge-client-only"
274
- className="flex flex-col w-full max-w-215"
275
- >
276
- <Slider.Control className="flex items-center h-20 w-full data-dragging:cursor-grabbing">
277
- <Slider.Track className="h-20 bg-white/10 rounded-3 w-full relative">
278
- <Slider.Indicator>
279
- <span className="absolute inset-3 rounded-2 bg-white/50" />
280
- </Slider.Indicator>
281
- <Slider.Thumb className="flex focus:outline-none cursor-grab px-3">
282
- <span className="w-25 h-14 rounded-2 bg-white" />
283
- </Slider.Thumb>
284
- </Slider.Track>
285
- </Slider.Control>
286
- </Slider.Root>
287
- <span className="text-p0 shrink-0 tabular-nums text-neon">
288
- {speed.toFixed(1)}
289
- </span>
290
- </div>
291
- </div>
292
- </div>
293
-
294
- {/* Boolean props */}
295
- <div className="flex flex-col gap-10 pb-10">
296
- {[
297
- {
298
- name: 'pauseOnHover',
299
- label: 'pauseOnHover',
300
- value: pauseOnHover,
301
- onChange: setPauseOnHover,
302
- },
303
- {
304
- name: 'manual',
305
- label: 'manual',
306
- subLabel: 'GSAP',
307
- value: manual,
308
- onChange: (checked: boolean) => {
309
- setManual(checked)
310
- setGsapEnabled(checked)
311
- },
312
- },
313
- {
314
- name: 'xray',
315
- label: 'x-ray mode',
316
- value: showXRay,
317
- onChange: setShowXRay,
318
- },
319
- ].map(({ name, label, subLabel, value, onChange }) => (
320
- <label
321
- key={name}
322
- className="flex items-center justify-between cursor-pointer border-t border-white/10 pt-20"
323
- >
324
- <span className="text-p1 flex items-center gap-x-10">
325
- {label}
326
- {subLabel && (
327
- <span className="text-neon text-p0 uppercase bg-neon/20 rounded-2 p-5 tracking-10">
328
- {subLabel}
329
- </span>
330
- )}
331
- </span>
332
- <Switch.Root
333
- checked={value}
334
- onCheckedChange={onChange}
335
- className={cn(
336
- 'w-55 h-20 rounded-3 bg-white/10 relative transition-colors',
337
- {
338
- 'data-checked:bg-neon': name !== 'xray',
339
- 'data-checked:bg-purple': name === 'xray',
340
- },
341
- )}
342
- >
343
- <Switch.Thumb className="w-25 h-14 rounded-2 bg-white absolute top-3 left-3 data-checked:translate-x-24 transition-all data-checked:bg-black" />
344
- </Switch.Root>
345
- </label>
346
- ))}
347
- </div>
348
- </div>
349
- </div>
350
-
351
- {/* Preview */}
352
- <div className="overflow-hidden col-span-8 md:col-span-4 isolate rounded-5 flex justify-center items-center p-20">
353
- <ResizableBox
354
- width={size.width}
355
- height={size.height}
356
- draggableOpts={{ grid: [20, 20] }}
357
- axis={isVertical ? 'y' : 'x'}
358
- resizeHandles={isVertical ? ['n', 's'] : ['w', 'e']}
359
- minConstraints={isVertical ? [width, 80] : [220, height]}
360
- maxConstraints={[width - 40, height - 40]}
361
- handle={<DragHandle />}
362
- onResize={onResize}
363
- onResizeStart={() => setIsResizing(true)}
364
- onResizeStop={() => setIsResizing(false)}
365
- className={cn(
366
- 'absolute border border-purple rounded-5 flex flex-col',
367
- {
368
- 'cursor-grabbing': isResizing,
369
- },
370
- )}
371
- >
372
- <span
373
- className={cn(
374
- 'absolute bottom-full mb-px h-200 z-1 before:absolute before:inset-0 before:bg-white/10 before:z-1 after:absolute after:inset-0 after:bg-black/85',
375
- {
376
- '-inset-x-px': !isVertical,
377
- '-inset-x-21': isVertical,
378
- },
379
- )}
380
- />
381
- <span
382
- className={cn(
383
- 'absolute top-full mt-px h-200 z-1 before:absolute before:inset-0 before:bg-white/10 before:z-1 after:absolute after:inset-0 after:bg-black/85',
384
- {
385
- '-inset-x-px': !isVertical,
386
- '-inset-x-21': isVertical,
387
- },
388
- )}
389
- />
390
-
391
- <span
392
- className={cn(
393
- 'absolute right-full mr-px w-[50vw] z-1 before:absolute before:inset-0 before:bg-white/10 before:z-1 after:absolute after:inset-0 after:bg-black/85',
394
- {
395
- '-inset-y-21': !isVertical,
396
- '-inset-y-px': isVertical,
397
- },
398
- )}
399
- />
400
- <span
401
- className={cn(
402
- 'absolute left-full ml-px w-[50vw] z-1 before:absolute before:inset-0 before:bg-white/10 before:z-1 after:absolute after:inset-0 after:bg-black/85',
403
- {
404
- '-inset-y-21': !isVertical,
405
- '-inset-y-px': isVertical,
406
- },
407
- )}
408
- />
409
-
410
- <div
411
- ref={$marqyContainer}
412
- style={
413
- { '--height': `${size.height - 2}px` } as React.CSSProperties
414
- }
415
- className={cn(
416
- 'relative flex flex-col items-center justify-center grow',
417
- )}
418
- >
419
- <Marqy
420
- direction={direction}
421
- speed={speed}
422
- pauseOnHover={pauseOnHover}
423
- manual={manual || gsapEnabled}
424
- className={cn('select-none', {
425
- 'h-(--height) grow': isVertical,
426
- 'overflow-visible! [&_[data-marqy-content]:last-child]:text-purple/20 [&_[data-marqy-content]:last-child]:[-webkit-text-stroke:1px_var(--color-purple)]':
427
- showXRay,
428
- })}
429
- >
430
- <p className="flex justify-center text-h1 text-60 py-20 uppercase whitespace-pre text-center">
431
- {text?.trim() && (
432
- <>
433
- {!isVertical && (
434
- <Divider value={direction === 'left' ? ' ← ' : ' → '} />
435
- )}
436
- {isVertical && (
437
- <span className="opacity-40 shrink-0">
438
- {direction === 'up' ? '↑' : '↓'}
439
- </span>
440
- )}
441
- <span className="text-ellipsis overflow-hidden">
442
- {text}
443
- </span>
444
- {isVertical && (
445
- <span className="opacity-40 shrink-0">
446
- {direction === 'up' ? '↑' : '↓'}
447
- </span>
448
- )}
449
- </>
450
- )}
451
- </p>
452
- </Marqy>
453
-
454
- {!text?.trim() && (
455
- <div className="absolute inset-0 flex justify-center items-center select-none">
456
- <p className="text-h1 text-h1 uppercase text-white/20">
457
- not_defined
458
- </p>
459
- </div>
460
- )}
461
-
462
- <span className="select-none backdrop-blur-sm flex gap-x-5 absolute top-0 left-0 text-p0 m-10 text-purple bg-purple/20 p-5 rounded-3">
463
- <span className="text-purple/50 uppercase">duration</span>
464
- {duration?.trim() ? duration : 'NA'}
465
- </span>
466
- <span className="select-none backdrop-blur-sm flex gap-x-5 absolute top-0 right-0 text-p0 m-10 text-purple bg-purple/20 p-5 rounded-3">
467
- <span className="text-purple/50 uppercase">reps</span>
468
- {itemCount}
469
- </span>
470
-
471
- {manual && (
472
- <button
473
- onClick={() => setGsapEnabled((v) => !v)}
474
- className={cn(
475
- 'clean-btn cursor-pointer select-none backdrop-blur-sm absolute bottom-0 left-0 m-10 p-5 rounded-3',
476
- gsapEnabled
477
- ? 'text-neon/50 bg-neon/20'
478
- : 'text-black/50 bg-neon',
479
- )}
480
- >
481
- <span className="flex gap-x-5 text-p0 uppercase">
482
- {gsapEnabled ? 'Disable' : 'Enable'}
483
- <span
484
- className={cn(gsapEnabled ? 'text-neon' : 'text-black')}
485
- >
486
- GSAP
487
- </span>
488
- </span>
489
- </button>
490
- )}
491
- </div>
492
- </ResizableBox>
493
- </div>
494
- </div>
495
- )
496
- }
@@ -1,34 +0,0 @@
1
- import { Marqy } from 'marqy'
2
-
3
- import Divider from './Divider'
4
-
5
- export default function MarqySpeedDemo() {
6
- return (
7
- <section>
8
- <Marqy speed={0.2} direction="right" className="border-t">
9
- <p className="uppercase py-20 text-p1 whitespace-pre">
10
- <Divider />
11
- BPM_0.5: Chillwave
12
- </p>
13
- </Marqy>
14
- <Marqy speed={0.5} direction="right" className="border-t">
15
- <p className="uppercase py-20 text-p1 whitespace-pre">
16
- <Divider />
17
- BPM_1: House
18
- </p>
19
- </Marqy>
20
- <Marqy speed={1.5} direction="right" className="border-t">
21
- <p className="uppercase py-20 text-p1 whitespace-pre">
22
- <Divider />
23
- BPM_1.5: Techno
24
- </p>
25
- </Marqy>
26
- <Marqy speed={3} direction="right" className="border-t">
27
- <p className="uppercase py-20 text-p1 whitespace-pre">
28
- <Divider />
29
- BPM_3: Dubstep
30
- </p>
31
- </Marqy>
32
- </section>
33
- )
34
- }
@@ -1,44 +0,0 @@
1
- import { Marqy } from 'marqy'
2
-
3
- function Char({ value }: { value: string }) {
4
- return (
5
- <span className="w-1/5 aspect-square text-jumbo text-[8vw] bg-white flex items-center justify-center">
6
- {value}
7
- </span>
8
- )
9
- }
10
-
11
- export default function MarqyInteractiveDemo() {
12
- return (
13
- <section className="flex flex-col sm:flex-row p-20 border-t gap-px">
14
- <Marqy
15
- speed={1}
16
- direction="up"
17
- className="bg-white text-black text-center min-h-[calc(10vw+2rem)] max-h-[calc((10vw+2rem)*2)] h-[calc(10vw+2rem)] overflow-hidden"
18
- >
19
- <p className="flex w-full gap-px bg-black text-center border-t select-none">
20
- <Char value="↑" />
21
- <Char value="↑" />
22
- <Char value="↑" />
23
- <Char value="↑" />
24
- <Char value="↑" />
25
- <Char value="↑" />
26
- </p>
27
- </Marqy>
28
- <Marqy
29
- speed={1}
30
- direction="down"
31
- className="bg-white text-black text-center min-h-[calc(10vw+2rem)] max-h-[calc((10vw+2rem)*2)] h-[calc(10vw+2rem)] overflow-hidden"
32
- >
33
- <p className="flex w-full gap-px bg-black text-center border-t select-none">
34
- <Char value="↓" />
35
- <Char value="↓" />
36
- <Char value="↓" />
37
- <Char value="↓" />
38
- <Char value="↓" />
39
- <Char value="↓" />
40
- </p>
41
- </Marqy>
42
- </section>
43
- )
44
- }
@@ -1,11 +0,0 @@
1
- ---
2
- import SectionHeadline from '../components/SectionHeadline'
3
- import MarqyPlayground from './MarqyPlayground'
4
- ---
5
-
6
- <section class="md:p-40 relative overflow-hidden">
7
- <SectionHeadline text="Playground" client:load />
8
- <div class="p-20 md:px-80 md:py-0">
9
- <MarqyPlayground client:only="react" />
10
- </div>
11
- </section>
@@ -1,59 +0,0 @@
1
- ---
2
- import { Code } from 'astro:components'
3
- import SectionHeadline from '../components/SectionHeadline'
4
- import CopyButton from '../components/CopyButton'
5
-
6
- const installCode = `yarn add marqy`
7
-
8
- const usageCode = `import { Marqy } from 'marqy'
9
- import 'marqy/dist/marqy.css'
10
-
11
- <Marqy speed={1} direction="left" pauseOnHover>
12
- <span>Your content here</span>
13
- </Marqy>`
14
-
15
- const props = [
16
- { name: 'speed', type: 'number', default: '0.5', description: 'Scroll speed multiplier' },
17
- { name: 'direction', type: "'left' | 'right' | 'up' | 'down'", default: "'left'", description: 'Direction of scroll' },
18
- { name: 'pauseOnHover', type: 'boolean', default: 'false', description: 'Pauses the animation on hover' },
19
- { name: 'manual', type: 'boolean', default: 'false', description: 'Renders without applying CSS animations' },
20
- { name: 'children', type: 'React.ReactNode', default: '—', description: 'Content to repeat inside the marqy' },
21
- ]
22
- ---
23
-
24
- <section class="md:p-40 relative overflow-hidden transform-[translateZ(0)] border-t">
25
- <SectionHeadline text="Quick Start" client:load />
26
- <div class="grid grid-cols-2 gap-20 sm:gap-40 p-20 md:px-80 md:py-0 items-center">
27
- <div class="flex flex-col gap-20 sm:gap-40 col-span-2 lg:col-span-1">
28
- <div>
29
- <div class="flex justify-between mb-10 items-center bg-white text-black pl-10 rounded-5">
30
- <p class="text-h3 uppercase">Install</p>
31
- <CopyButton text={installCode} client:load />
32
- </div>
33
- <Code code={installCode} lang="sh" theme="css-variables" />
34
- </div>
35
- <div>
36
- <div class="flex justify-between mb-10 items-center bg-white text-black pl-10 rounded-5">
37
- <p class="text-h3 uppercase">Usage</p>
38
- <CopyButton text={usageCode} client:load />
39
- </div>
40
- <Code code={usageCode} lang="jsx" theme="css-variables" />
41
- </div>
42
- </div>
43
- <div class="col-span-2 lg:col-span-1">
44
- <!-- <p class="text-p1 border-b pb-10">Props</p> -->
45
- <div class="@container flex flex-col divide-y divide-white/20">
46
- {props.map((prop) => (
47
- <div class="grid grid-cols-[15ch_1fr] @min-[50rem]:grid-cols-[12ch_1fr_auto] gap-10 pt-10 first:pt-0 pb-20 items-start">
48
- <code class="font-mono font-bold text-neon">{prop.name}</code>
49
- <div class="flex flex-col gap-y-8 items-start">
50
- <code class="font-mono text-white/60 text-end @min-[50rem]:text-start">{prop.type}</code>
51
- {prop.default !== '—' && <span class="shrink-0 uppercase text-p0 bg-white/15 p-5 rounded-5"> Default: <code class="normal-case text-white/60">{prop.default}</code></span>}
52
- </div>
53
- <span class="col-span-2 @min-[50rem]:col-span-1 inline-flex items-center justify-between gap-x-10 font-sans">{prop.description}</span>
54
- </div>
55
- ))}
56
- </div>
57
- </div>
58
- </div>
59
- </section>
@@ -1,41 +0,0 @@
1
- import { Marqy } from 'marqy'
2
-
3
- import { cn } from '../lib/cn'
4
-
5
- export default function SectionHeadline({ text }: { text: string }) {
6
- return (
7
- <>
8
- <h2
9
- className={cn(
10
- 'md:absolute md:top-1/2 md:left-0 md:w-lvh md:transform-[rotate(-90deg)_translateX(-50%)] origin-top-left border-b py-20 z-2 bg-black',
11
- )}
12
- >
13
- <Marqy speed={1} direction="left">
14
- <span className="text-jumbo text-15 sm:text-40 px-20">{text}</span>
15
- </Marqy>
16
- </h2>
17
-
18
- <h2
19
- aria-hidden="true"
20
- className={cn(
21
- 'hidden md:block',
22
- 'absolute top-1/2 right-0 w-lvh transform-[rotate(90deg)_translateX(50%)] origin-top-right border-b py-20 z-2 bg-black',
23
- )}
24
- >
25
- <Marqy speed={1} direction="left">
26
- <span className="text-jumbo text-15 sm:text-40 px-20">{text}</span>
27
- </Marqy>
28
- </h2>
29
-
30
- {/* <h2
31
- className={cn(
32
- 'w-lvh fixed right-0 top-0 origin-top-left transform-[translateY(-100%)_rotate(90deg)] border-b py-20 z-2 bg-black',
33
- )}
34
- >
35
- <Marqy speed={1} direction="left">
36
- <span className="text-jumbo text-40 px-20">{text}</span>
37
- </Marqy>
38
- </h2> */}
39
- </>
40
- )
41
- }