@haventmet/carousel 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/.mcp.json +8 -0
- package/CLAUDE.md +177 -0
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/biome.json +174 -0
- package/package.json +33 -0
- package/packages/alpine/index.html +50 -0
- package/packages/alpine/package.json +70 -0
- package/packages/alpine/src/index.ts +46 -0
- package/packages/alpine/style.css +76 -0
- package/packages/alpine/tsconfig.json +28 -0
- package/packages/alpine/vite.config.ts +28 -0
- package/packages/core/README.md +69 -0
- package/packages/core/package.json +45 -0
- package/packages/core/src/carousel.ts +842 -0
- package/packages/core/src/index.ts +2 -0
- package/packages/core/src/style.css +46 -0
- package/packages/core/vite.config.js +14 -0
- package/packages/react/.vite/deps/_metadata.json +25 -0
- package/packages/react/.vite/deps/chunk-7CQ73C3Q.js +1908 -0
- package/packages/react/.vite/deps/chunk-7CQ73C3Q.js.map +7 -0
- package/packages/react/.vite/deps/package.json +3 -0
- package/packages/react/.vite/deps/react-dom_client.js +21712 -0
- package/packages/react/.vite/deps/react-dom_client.js.map +7 -0
- package/packages/react/.vite/deps/react.js +4 -0
- package/packages/react/.vite/deps/react.js.map +7 -0
- package/packages/react/README.md +75 -0
- package/packages/react/index.html +12 -0
- package/packages/react/package.json +74 -0
- package/packages/react/src/App.tsx +38 -0
- package/packages/react/src/BlossomCarousel.tsx +77 -0
- package/packages/react/src/index.ts +2 -0
- package/packages/react/src/main.jsx +6 -0
- package/packages/react/src/style.css +50 -0
- package/packages/react/tsconfig.json +17 -0
- package/packages/react/vite.config.js +27 -0
- package/packages/svelte/README.md +58 -0
- package/packages/svelte/index.html +12 -0
- package/packages/svelte/package.json +71 -0
- package/packages/svelte/src/App.svelte +12 -0
- package/packages/svelte/src/BlossomCarousel.svelte +39 -0
- package/packages/svelte/src/BlossomCarousel.svelte.d.ts +8 -0
- package/packages/svelte/src/index.ts +2 -0
- package/packages/svelte/src/main.js +10 -0
- package/packages/svelte/src/style.css +52 -0
- package/packages/svelte/tsconfig.json +16 -0
- package/packages/svelte/vite.config.js +45 -0
- package/packages/vue/README.md +70 -0
- package/packages/vue/index.html +12 -0
- package/packages/vue/package.json +69 -0
- package/packages/vue/src/App.vue +82 -0
- package/packages/vue/src/BlossomCarousel.vue +52 -0
- package/packages/vue/src/index.ts +2 -0
- package/packages/vue/src/main.js +5 -0
- package/packages/vue/src/style.css +18 -0
- package/packages/vue/vite.config.js +25 -0
- package/packages/web/README.md +44 -0
- package/packages/web/index.html +29 -0
- package/packages/web/package.json +65 -0
- package/packages/web/src/index.ts +27 -0
- package/packages/web/src/style.css +53 -0
- package/packages/web/style.css +54 -0
- package/packages/web/tsconfig.json +18 -0
- package/packages/web/vite.config.ts +23 -0
- package/pnpm-workspace.yaml +8 -0
- package/public/cover.jpg +0 -0
- package/turbo.json +12 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Blossom Carousel
|
|
2
|
+
|
|
3
|
+
A native-scroll-first carousel enhanced with drag support for React.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
`npm install @numbered/carousel/react`
|
|
8
|
+
|
|
9
|
+
#### React
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
import { BlossomCarousel } from "@numbered/carousel/react";
|
|
13
|
+
import "@numbered/carousel/core/style.css";
|
|
14
|
+
|
|
15
|
+
function App() {
|
|
16
|
+
return <BlossomCarousel>{/* slides */}</BlossomCarousel>;
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
#### Next.js
|
|
21
|
+
|
|
22
|
+
Add the import to your page or component:
|
|
23
|
+
|
|
24
|
+
```jsx
|
|
25
|
+
import { BlossomCarousel } from "@numbered/carousel/react";
|
|
26
|
+
import "@numbered/carousel/core/style.css";
|
|
27
|
+
|
|
28
|
+
export default function Page() {
|
|
29
|
+
return <BlossomCarousel>{/* slides */}</BlossomCarousel>;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```jsx
|
|
36
|
+
<BlossomCarousel>
|
|
37
|
+
{Array.from({ length: 12 }, (_, i) => (
|
|
38
|
+
<div>{i}</div>
|
|
39
|
+
))}
|
|
40
|
+
</BlossomCarousel>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### as
|
|
44
|
+
|
|
45
|
+
Define the HTMLElement of the carousel root.
|
|
46
|
+
|
|
47
|
+
```jsx
|
|
48
|
+
<BlossomCarousel as="ul">
|
|
49
|
+
{Array.from({ length: 12 }, (_, i) => (
|
|
50
|
+
<div>{i}</div>
|
|
51
|
+
))}
|
|
52
|
+
</BlossomCarousel>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Renders as
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<ul>
|
|
59
|
+
<li>Slide 1</li>
|
|
60
|
+
<li>Slide 2</li>
|
|
61
|
+
<li>Slide 3</li>
|
|
62
|
+
...
|
|
63
|
+
</ul>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Examples
|
|
67
|
+
|
|
68
|
+
- [Simple](https://www.blossom-carousel.com/docs/examples#simple)
|
|
69
|
+
- [Variable widths](https://www.blossom-carousel.com/docs/examples#variable-widths)
|
|
70
|
+
- [CSS Grid](https://www.blossom-carousel.com/docs/examples#css-grid)
|
|
71
|
+
- [Multiple rows](https://www.blossom-carousel.com/docs/examples#multiple-rows)
|
|
72
|
+
- [Snapping](https://www.blossom-carousel.com/docs/examples#snapping)
|
|
73
|
+
- [Grouping](https://www.blossom-carousel.com/docs/examples#grouping)
|
|
74
|
+
- [Sticky](https://www.blossom-carousel.com/docs/examples#sticky)
|
|
75
|
+
- [Coverflow](https://www.blossom-carousel.com/docs/examples#cover-flow)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Blossom React</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@haventmet/carousel-react",
|
|
3
|
+
"version": "0.1.14",
|
|
4
|
+
"author": "Loris",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "A native-scroll-first carousel component for React.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/loris-numbered/carousel"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/loris-numbered/carousel/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://www.blossom-carousel.com",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"blossom",
|
|
17
|
+
"carousel",
|
|
18
|
+
"slider",
|
|
19
|
+
"slideshow",
|
|
20
|
+
"scroll",
|
|
21
|
+
"scroller",
|
|
22
|
+
"drag",
|
|
23
|
+
"dragging",
|
|
24
|
+
"js",
|
|
25
|
+
"vanilla",
|
|
26
|
+
"javascript",
|
|
27
|
+
"typescript",
|
|
28
|
+
"web",
|
|
29
|
+
"html",
|
|
30
|
+
"css",
|
|
31
|
+
"svelte",
|
|
32
|
+
"react",
|
|
33
|
+
"vue"
|
|
34
|
+
],
|
|
35
|
+
"type": "module",
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"main": "dist/blossom-carousel-react.umd.cjs",
|
|
40
|
+
"module": "dist/blossom-carousel-react.js",
|
|
41
|
+
"types": "dist/index.d.ts",
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"import": "./dist/blossom-carousel-react.js",
|
|
46
|
+
"require": "./dist/blossom-carousel-react.umd.cjs"
|
|
47
|
+
},
|
|
48
|
+
"./style.css": "./dist/blossom-carousel-react.css"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"dev": "vite",
|
|
55
|
+
"build": "vite build",
|
|
56
|
+
"preview": "vite preview"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"react": "^18.0.0 || >=19.0.0-0",
|
|
60
|
+
"react-dom": "^18.0.0 || >=19.0.0-0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/react": "19.2.2",
|
|
64
|
+
"@types/react-dom": "19.2.2",
|
|
65
|
+
"@vitejs/plugin-react": "^5.0.4",
|
|
66
|
+
"react": "19.2.0",
|
|
67
|
+
"react-dom": "19.2.0",
|
|
68
|
+
"vite": "^7.1.10",
|
|
69
|
+
"vite-plugin-dts": "^4.5.4"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@haventmet/carousel": "workspace:*"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useRef, useState } from 'react'
|
|
2
|
+
import BlossomCarousel, { type BlossomCarouselRef } from './BlossomCarousel'
|
|
3
|
+
import '@numbered/carousel/style.css'
|
|
4
|
+
|
|
5
|
+
export default function App() {
|
|
6
|
+
const carouselRef = useRef<BlossomCarouselRef>(null)
|
|
7
|
+
const [currentIndex, setCurrentIndex] = useState(0)
|
|
8
|
+
|
|
9
|
+
const handlePrev = () => {
|
|
10
|
+
carouselRef.current?.prev()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const handleNext = () => {
|
|
14
|
+
carouselRef.current?.next()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const handleChange = (e: CustomEvent<{ index: number }>) => {
|
|
18
|
+
setCurrentIndex(e.detail.index)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className='page'>
|
|
23
|
+
<h1>Blossom in React</h1>
|
|
24
|
+
<p>Current slide: {currentIndex + 1}</p>
|
|
25
|
+
<BlossomCarousel ref={carouselRef} as='ul' className='carousel' onChange={handleChange}>
|
|
26
|
+
{Array.from({ length: 12 }, (_, i) => (
|
|
27
|
+
<li key={`slide${i + 1}`} className='slide'>
|
|
28
|
+
{i + 1}
|
|
29
|
+
</li>
|
|
30
|
+
))}
|
|
31
|
+
</BlossomCarousel>
|
|
32
|
+
<div>
|
|
33
|
+
<button onClick={handlePrev}>Previous</button>
|
|
34
|
+
<button onClick={handleNext}>Next</button>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Blossom } from '@numbered/carousel'
|
|
2
|
+
import { type ElementType, type ReactNode, type Ref, useEffect, useImperativeHandle, useRef } from 'react'
|
|
3
|
+
|
|
4
|
+
export interface BlossomCarouselRef {
|
|
5
|
+
next: () => void
|
|
6
|
+
prev: () => void
|
|
7
|
+
currentIndex: () => number
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function BlossomCarousel({
|
|
11
|
+
children,
|
|
12
|
+
as: Component = 'div',
|
|
13
|
+
repeat,
|
|
14
|
+
load,
|
|
15
|
+
onChange,
|
|
16
|
+
ref,
|
|
17
|
+
elementRef,
|
|
18
|
+
...props
|
|
19
|
+
}: {
|
|
20
|
+
children?: ReactNode | Array<ReactNode>
|
|
21
|
+
as?: ElementType
|
|
22
|
+
repeat?: boolean
|
|
23
|
+
load?: 'always'
|
|
24
|
+
onChange?: (event: CustomEvent<{ index: number }>) => void
|
|
25
|
+
ref?: Ref<BlossomCarouselRef | null>
|
|
26
|
+
elementRef?: Ref<HTMLElement | null>
|
|
27
|
+
[key: string]: unknown
|
|
28
|
+
}) {
|
|
29
|
+
const localRef = useRef<HTMLElement>(null)
|
|
30
|
+
const blossomRef = useRef<ReturnType<typeof Blossom> | null>(null)
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!localRef.current) return
|
|
34
|
+
|
|
35
|
+
const hasMouse = window.matchMedia('(hover: hover) and (pointer: fine)').matches
|
|
36
|
+
if (!hasMouse && load !== 'always') return
|
|
37
|
+
|
|
38
|
+
const blossom = Blossom(localRef.current, { repeat })
|
|
39
|
+
blossomRef.current = blossom
|
|
40
|
+
blossom.init()
|
|
41
|
+
|
|
42
|
+
return () => {
|
|
43
|
+
blossom.destroy()
|
|
44
|
+
blossomRef.current = null
|
|
45
|
+
}
|
|
46
|
+
}, [repeat])
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!localRef.current || !onChange) return
|
|
50
|
+
|
|
51
|
+
const handleChange = (e: Event) => {
|
|
52
|
+
onChange(e as CustomEvent<{ index: number }>)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
localRef.current.addEventListener('change', handleChange)
|
|
56
|
+
|
|
57
|
+
return () => {
|
|
58
|
+
localRef.current?.removeEventListener('change', handleChange)
|
|
59
|
+
}
|
|
60
|
+
}, [onChange])
|
|
61
|
+
|
|
62
|
+
useImperativeHandle(
|
|
63
|
+
ref,
|
|
64
|
+
() => ({
|
|
65
|
+
next: () => blossomRef.current?.next(),
|
|
66
|
+
prev: () => blossomRef.current?.prev(),
|
|
67
|
+
currentIndex: () => blossomRef.current?.currentIndex() ?? 0,
|
|
68
|
+
}),
|
|
69
|
+
[],
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Component ref={localRef} blossom-carousel='true' {...props}>
|
|
74
|
+
{children}
|
|
75
|
+
</Component>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.page {
|
|
21
|
+
height: 100vh;
|
|
22
|
+
width: 100%;
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
overflow: clip;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.carousel {
|
|
31
|
+
display: grid;
|
|
32
|
+
grid-auto-flow: column;
|
|
33
|
+
grid-auto-columns: 300px;
|
|
34
|
+
gap: 1rem;
|
|
35
|
+
padding-inline: 1rem;
|
|
36
|
+
scroll-padding-inline: 1rem;
|
|
37
|
+
scroll-snap-type: x mandatory;
|
|
38
|
+
scroll-snap-stop: always;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.slide {
|
|
42
|
+
width: 100%;
|
|
43
|
+
aspect-ratio: 3/4;
|
|
44
|
+
border-radius: 1rem;
|
|
45
|
+
background-color: #404040;
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
justify-content: center;
|
|
49
|
+
scroll-snap-align: center;
|
|
50
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react-jsx",
|
|
4
|
+
"allowJs": true,
|
|
5
|
+
"checkJs": false,
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"module": "esnext",
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"target": "esnext",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"paths": {
|
|
13
|
+
"@numbered/carousel": ["../core/src/index.ts"]
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"include": ["src"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
import { defineConfig } from 'vite'
|
|
4
|
+
import dts from 'vite-plugin-dts'
|
|
5
|
+
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
plugins: [react(), dts()],
|
|
8
|
+
build: {
|
|
9
|
+
lib: {
|
|
10
|
+
entry: path.resolve(__dirname, 'src/index.ts'),
|
|
11
|
+
name: 'BlossomCarousel',
|
|
12
|
+
fileName: 'blossom-carousel-react',
|
|
13
|
+
},
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
external: ['react', 'react-dom', 'react/jsx-runtime', 'react/jsx-dev-runtime', '@numbered/carousel'],
|
|
16
|
+
output: {
|
|
17
|
+
globals: {
|
|
18
|
+
react: 'React',
|
|
19
|
+
'react-dom': 'ReactDOM',
|
|
20
|
+
'react/jsx-runtime': 'React',
|
|
21
|
+
'react/jsx-dev-runtime': 'React',
|
|
22
|
+
'@numbered/carousel': 'BlossomCarouselCore',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Blossom Svelte
|
|
2
|
+
|
|
3
|
+
A native-scroll-first carousel for Svelte.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
`npm install @numbered/carousel/svelte`
|
|
8
|
+
|
|
9
|
+
#### Svelte
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
import BlossomCarousel from "@numbered/carousel/svelte";
|
|
13
|
+
import "@numbered/carousel/core/style.css";
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<BlossomCarousel>
|
|
20
|
+
{#each Array(12).fill(0).map((_, i) => i + 1) as num}
|
|
21
|
+
<div key="{num}">{num}</div>
|
|
22
|
+
{/each}
|
|
23
|
+
</BlossomCarousel>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### as
|
|
27
|
+
|
|
28
|
+
Define the HTMLElement of the carousel root.
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<BlossomCarousel as="ul">
|
|
32
|
+
{#each Array(12).fill(0).map((_, i) => i + 1) as num}
|
|
33
|
+
<li key="{num}">{num}</li>
|
|
34
|
+
{/each}
|
|
35
|
+
</BlossomCarousel>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Renders as
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<ul>
|
|
42
|
+
<li>Slide 1</li>
|
|
43
|
+
<li>Slide 2</li>
|
|
44
|
+
<li>Slide 3</li>
|
|
45
|
+
...
|
|
46
|
+
</ul>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
- [Simple](https://www.blossom-carousel.com/docs/examples#simple)
|
|
52
|
+
- [Variable widths](https://www.blossom-carousel.com/docs/examples#variable-widths)
|
|
53
|
+
- [CSS Grid](https://www.blossom-carousel.com/docs/examples#css-grid)
|
|
54
|
+
- [Multiple rows](https://www.blossom-carousel.com/docs/examples#multiple-rows)
|
|
55
|
+
- [Snapping](https://www.blossom-carousel.com/docs/examples#snapping)
|
|
56
|
+
- [Grouping](https://www.blossom-carousel.com/docs/examples#grouping)
|
|
57
|
+
- [Sticky](https://www.blossom-carousel.com/docs/examples#sticky)
|
|
58
|
+
- [Coverflow](https://www.blossom-carousel.com/docs/examples#cover-flow)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Blossom Svelte</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.js"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@haventmet/carousel-svelte",
|
|
3
|
+
"version": "0.1.16",
|
|
4
|
+
"author": "Loris",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "A native-scroll-first carousel component for Svelte.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/loris-numbered/carousel"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/loris-numbered/carousel/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://www.blossom-carousel.com",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"blossom",
|
|
17
|
+
"carousel",
|
|
18
|
+
"slider",
|
|
19
|
+
"slideshow",
|
|
20
|
+
"scroll",
|
|
21
|
+
"scroller",
|
|
22
|
+
"drag",
|
|
23
|
+
"dragging",
|
|
24
|
+
"js",
|
|
25
|
+
"vanilla",
|
|
26
|
+
"javascript",
|
|
27
|
+
"typescript",
|
|
28
|
+
"web",
|
|
29
|
+
"html",
|
|
30
|
+
"css",
|
|
31
|
+
"svelte",
|
|
32
|
+
"react",
|
|
33
|
+
"vue"
|
|
34
|
+
],
|
|
35
|
+
"type": "module",
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"main": "dist/blossom-carousel-svelte.umd.cjs",
|
|
40
|
+
"module": "dist/blossom-carousel-svelte.js",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"svelte": "./dist/blossom-carousel-svelte.js",
|
|
46
|
+
"import": "./dist/blossom-carousel-svelte.js",
|
|
47
|
+
"require": "./dist/blossom-carousel-svelte.umd.cjs"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"svelte": "^4.0.0 || ^5.0.0"
|
|
55
|
+
},
|
|
56
|
+
"optionalDependencies": {
|
|
57
|
+
"@haventmet/carousel": "workspace:*"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"dev": "vite",
|
|
61
|
+
"build": "vite build",
|
|
62
|
+
"preview": "vite preview"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@sveltejs/vite-plugin-svelte": "^2.0.0",
|
|
66
|
+
"svelte": "^5.34.3",
|
|
67
|
+
"typescript": "^5.0.0",
|
|
68
|
+
"vite": "^4.4.0",
|
|
69
|
+
"vite-plugin-dts": "^4.5.3"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import BlossomCarousel from './BlossomCarousel.svelte';
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<div class="page">
|
|
6
|
+
<h1>Blossom in Svelte</h1>
|
|
7
|
+
<BlossomCarousel as="ul" class="carousel">
|
|
8
|
+
{#each Array(12).fill(0).map((_, i) => i + 1) as num (num)}
|
|
9
|
+
<li class="slide">{num}</li>
|
|
10
|
+
{/each}
|
|
11
|
+
</BlossomCarousel>
|
|
12
|
+
</div>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { onMount, onDestroy } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export let as = 'div';
|
|
5
|
+
export let load = 'conditional'; // 'always' or 'conditional'
|
|
6
|
+
export let repeat = false;
|
|
7
|
+
|
|
8
|
+
let root;
|
|
9
|
+
let blossom;
|
|
10
|
+
|
|
11
|
+
onMount(async () => {
|
|
12
|
+
if (root) {
|
|
13
|
+
const hasMouse = window.matchMedia("(hover: hover) and (pointer: fine)").matches;
|
|
14
|
+
|
|
15
|
+
// don't load if the user has no mouse.
|
|
16
|
+
// overwritten by props.load: 'always'
|
|
17
|
+
if (!hasMouse && load !== "always") return;
|
|
18
|
+
|
|
19
|
+
const { Blossom } = await import("@numbered/carousel");
|
|
20
|
+
|
|
21
|
+
blossom = Blossom(root, { repeat });
|
|
22
|
+
blossom.init();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
onDestroy(() => {
|
|
28
|
+
blossom?.destroy();
|
|
29
|
+
});
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<svelte:element
|
|
33
|
+
this={as}
|
|
34
|
+
bind:this={root}
|
|
35
|
+
blossom-carousel="true"
|
|
36
|
+
{...$$restProps}
|
|
37
|
+
>
|
|
38
|
+
<slot />
|
|
39
|
+
</svelte:element>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.page {
|
|
21
|
+
height: 100vh;
|
|
22
|
+
width: 100%;
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.carousel {
|
|
30
|
+
display: grid;
|
|
31
|
+
grid-auto-flow: column;
|
|
32
|
+
grid-auto-columns: 300px;
|
|
33
|
+
gap: 1rem;
|
|
34
|
+
padding-inline: 1rem;
|
|
35
|
+
scroll-padding-inline: 1rem;
|
|
36
|
+
scroll-snap-type: x mandatory;
|
|
37
|
+
scroll-snap-stop: always;
|
|
38
|
+
|
|
39
|
+
padding-block: 4rem;
|
|
40
|
+
margin-block: -4rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.slide {
|
|
44
|
+
width: 100%;
|
|
45
|
+
aspect-ratio: 3/4;
|
|
46
|
+
border-radius: 1rem;
|
|
47
|
+
background-color: #404040;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
scroll-snap-align: center;
|
|
52
|
+
}
|