@becklyn/components 0.4.2 → 0.4.4
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/components/atoms/IntersectionObserverBox/IntersectionObserverBox.module.scss +19 -0
- package/components/atoms/IntersectionObserverBox/IntersectionObserverBox.stories.module.scss +13 -0
- package/components/atoms/IntersectionObserverBox/IntersectionObserverBox.stories.tsx +51 -0
- package/components/atoms/IntersectionObserverBox/IntersectionObserverBox.tsx +35 -0
- package/components/atoms/Slider/Slider.module.scss +49 -0
- package/components/atoms/Slider/Slider.stories.module.scss +16 -0
- package/components/atoms/Slider/Slider.stories.tsx +80 -0
- package/components/atoms/Slider/Slider.tsx +53 -0
- package/dist/components/atoms/IntersectionObserverBox/IntersectionObserverBox.d.ts +6 -0
- package/dist/components/atoms/IntersectionObserverBox/IntersectionObserverBox.d.ts.map +1 -0
- package/dist/components/atoms/IntersectionObserverBox/IntersectionObserverBox.js +25 -0
- package/dist/components/atoms/IntersectionObserverBox/IntersectionObserverBox.stories.d.ts +11 -0
- package/dist/components/atoms/IntersectionObserverBox/IntersectionObserverBox.stories.d.ts.map +1 -0
- package/dist/components/atoms/IntersectionObserverBox/IntersectionObserverBox.stories.js +37 -0
- package/dist/components/atoms/Slider/Slider.d.ts +10 -0
- package/dist/components/atoms/Slider/Slider.d.ts.map +1 -0
- package/dist/components/atoms/Slider/Slider.js +33 -0
- package/dist/components/atoms/Slider/Slider.stories.d.ts +11 -0
- package/dist/components/atoms/Slider/Slider.stories.d.ts.map +1 -0
- package/dist/components/atoms/Slider/Slider.stories.js +40 -0
- package/package.json +11 -11
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.box {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
padding: 24px;
|
|
6
|
+
border-radius: 8px;
|
|
7
|
+
background-color: #f0f0f0;
|
|
8
|
+
border: 2px solid #ccc;
|
|
9
|
+
font-weight: bold;
|
|
10
|
+
font-size: 16px;
|
|
11
|
+
color: #999;
|
|
12
|
+
transition: background-color 0.3s, border-color 0.3s, color 0.3s;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.visible {
|
|
16
|
+
background-color: #d4edda;
|
|
17
|
+
border-color: #6abf69;
|
|
18
|
+
color: #2e7d32;
|
|
19
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
|
+
import { IntersectionObserverBox } from "./IntersectionObserverBox";
|
|
3
|
+
import styles from "./IntersectionObserverBox.stories.module.scss";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof IntersectionObserverBox> = {
|
|
6
|
+
title: "Atoms/IntersectionObserverBox",
|
|
7
|
+
component: IntersectionObserverBox,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: "padded",
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof IntersectionObserverBox>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {};
|
|
17
|
+
|
|
18
|
+
export const WithThreshold: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
options: { threshold: 0.5 },
|
|
21
|
+
children: "Visible when 50% in viewport",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Scrollable: Story = {
|
|
26
|
+
render: args => (
|
|
27
|
+
<div className={styles.scrollContainer}>
|
|
28
|
+
<div className={styles.scrollHint}>↓ Scroll down ↓</div>
|
|
29
|
+
<IntersectionObserverBox {...args} />
|
|
30
|
+
<div className={styles.scrollHint}>↑ Scroll up ↑</div>
|
|
31
|
+
</div>
|
|
32
|
+
),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const WithCallback: Story = {
|
|
36
|
+
render: args => (
|
|
37
|
+
<IntersectionObserverBox
|
|
38
|
+
{...args}
|
|
39
|
+
callback={(_, isVisible) => console.log("Visibility changed:", isVisible)}>
|
|
40
|
+
Watch the console when visibility changes
|
|
41
|
+
</IntersectionObserverBox>
|
|
42
|
+
),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const CustomFilter: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
filter: entry => entry.intersectionRatio >= 0.75,
|
|
48
|
+
options: { threshold: [0, 0.25, 0.5, 0.75, 1] },
|
|
49
|
+
children: "Visible when ≥75% intersecting",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { FC, PropsWithChildren, useRef } from "react";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import { UseIntersectionProps, useIntersection } from "@becklyn/next/lib/intersection";
|
|
6
|
+
import { PropsWithClassName } from "@becklyn/next/types/style";
|
|
7
|
+
import styles from "./IntersectionObserverBox.module.scss";
|
|
8
|
+
|
|
9
|
+
export type IntersectionObserverBoxProps = Omit<UseIntersectionProps, "ref"> & PropsWithClassName;
|
|
10
|
+
|
|
11
|
+
export const IntersectionObserverBox: FC<PropsWithChildren<IntersectionObserverBoxProps>> = ({
|
|
12
|
+
children,
|
|
13
|
+
className,
|
|
14
|
+
defaultValue,
|
|
15
|
+
callback,
|
|
16
|
+
filter,
|
|
17
|
+
dependencies,
|
|
18
|
+
options,
|
|
19
|
+
}) => {
|
|
20
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
21
|
+
const isVisible = useIntersection({
|
|
22
|
+
ref,
|
|
23
|
+
defaultValue,
|
|
24
|
+
callback,
|
|
25
|
+
filter,
|
|
26
|
+
dependencies,
|
|
27
|
+
options,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div ref={ref} className={clsx(styles.box, isVisible && styles.visible, className)}>
|
|
32
|
+
{children ?? (isVisible ? "In viewport" : "Out of viewport")}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 12px;
|
|
5
|
+
width: 100%;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.slide {
|
|
9
|
+
display: flex;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.nav {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
gap: 16px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.navButton {
|
|
20
|
+
background: none;
|
|
21
|
+
border: 1px solid #ccc;
|
|
22
|
+
border-radius: 4px;
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
padding: 6px 12px;
|
|
25
|
+
font-size: 16px;
|
|
26
|
+
line-height: 1;
|
|
27
|
+
|
|
28
|
+
&:hover {
|
|
29
|
+
background-color: #f0f0f0;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.dots {
|
|
34
|
+
display: flex;
|
|
35
|
+
gap: 6px;
|
|
36
|
+
align-items: center;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.dot {
|
|
40
|
+
width: 8px;
|
|
41
|
+
height: 8px;
|
|
42
|
+
border-radius: 50%;
|
|
43
|
+
background-color: #ccc;
|
|
44
|
+
transition: background-color 0.2s;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.dotActive {
|
|
48
|
+
background-color: #333;
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.exampleSlide {
|
|
2
|
+
display: flex;
|
|
3
|
+
justify-content: center;
|
|
4
|
+
align-items: center;
|
|
5
|
+
border-radius: 8px;
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: 200px;
|
|
8
|
+
color: #fff;
|
|
9
|
+
font-weight: bold;
|
|
10
|
+
font-size: 24px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.storyContainer {
|
|
14
|
+
margin: 0 auto;
|
|
15
|
+
max-width: 480px;
|
|
16
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
|
+
import { Slide, Slider } from "./Slider";
|
|
3
|
+
import styles from "./Slider.stories.module.scss";
|
|
4
|
+
|
|
5
|
+
const SLIDE_COLORS = ["#4f86c6", "#6abf69", "#f0a500", "#e05c5c", "#a97cc7"];
|
|
6
|
+
|
|
7
|
+
const SampleSlides = ({ count = 3 }: { count?: number }) => (
|
|
8
|
+
<>
|
|
9
|
+
{Array.from({ length: count }).map((_, i) => (
|
|
10
|
+
<Slide key={i}>
|
|
11
|
+
<div
|
|
12
|
+
style={{
|
|
13
|
+
background: SLIDE_COLORS[i % SLIDE_COLORS.length],
|
|
14
|
+
}}
|
|
15
|
+
className={styles.exampleSlide}>
|
|
16
|
+
Slide {i + 1}
|
|
17
|
+
</div>
|
|
18
|
+
</Slide>
|
|
19
|
+
))}
|
|
20
|
+
</>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const meta: Meta<typeof Slider> = {
|
|
24
|
+
title: "Atoms/Slider",
|
|
25
|
+
component: Slider,
|
|
26
|
+
parameters: {
|
|
27
|
+
layout: "padded",
|
|
28
|
+
},
|
|
29
|
+
decorators: [
|
|
30
|
+
Story => (
|
|
31
|
+
<div className={styles.storyContainer}>
|
|
32
|
+
<Story />
|
|
33
|
+
</div>
|
|
34
|
+
),
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default meta;
|
|
39
|
+
type Story = StoryObj<typeof Slider>;
|
|
40
|
+
|
|
41
|
+
export const Default: Story = {
|
|
42
|
+
render: args => (
|
|
43
|
+
<Slider {...args}>
|
|
44
|
+
<SampleSlides count={3} />
|
|
45
|
+
</Slider>
|
|
46
|
+
),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const ManySlides: Story = {
|
|
50
|
+
render: args => (
|
|
51
|
+
<Slider {...args}>
|
|
52
|
+
<SampleSlides count={5} />
|
|
53
|
+
</Slider>
|
|
54
|
+
),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const WithoutNav: Story = {
|
|
58
|
+
render: args => (
|
|
59
|
+
<Slider {...args} showNav={false}>
|
|
60
|
+
<SampleSlides count={3} />
|
|
61
|
+
</Slider>
|
|
62
|
+
),
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const Loop: Story = {
|
|
66
|
+
render: args => (
|
|
67
|
+
<Slider {...args} loop>
|
|
68
|
+
<SampleSlides count={3} />
|
|
69
|
+
</Slider>
|
|
70
|
+
),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const AutoDisable: Story = {
|
|
74
|
+
name: "Auto Disable (single slide)",
|
|
75
|
+
render: args => (
|
|
76
|
+
<Slider {...args} shouldAutoDisable>
|
|
77
|
+
<SampleSlides count={1} />
|
|
78
|
+
</Slider>
|
|
79
|
+
),
|
|
80
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { FC, PropsWithChildren } from "react";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import "keen-slider/keen-slider.min.css";
|
|
6
|
+
import { SliderOptions, useSlider } from "@becklyn/next/lib/slider";
|
|
7
|
+
import { PropsWithClassName } from "@becklyn/next/types/style";
|
|
8
|
+
import styles from "./Slider.module.scss";
|
|
9
|
+
|
|
10
|
+
export interface SliderProps extends SliderOptions {
|
|
11
|
+
showNav?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const Slider: FC<PropsWithChildren<PropsWithClassName<SliderProps>>> = ({
|
|
15
|
+
children,
|
|
16
|
+
className,
|
|
17
|
+
showNav = true,
|
|
18
|
+
...options
|
|
19
|
+
}) => {
|
|
20
|
+
const [setRef, { next, prev, isActiveIndex, details, isDisabled }] = useSlider(options);
|
|
21
|
+
|
|
22
|
+
const slideCount = details?.slides.length ?? 0;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className={clsx(styles.wrapper, isDisabled && styles.disabled, className)}>
|
|
26
|
+
<div ref={node => setRef(node)} className={clsx("keen-slider", styles.slider)}>
|
|
27
|
+
{children}
|
|
28
|
+
</div>
|
|
29
|
+
{showNav && !isDisabled && slideCount > 1 && (
|
|
30
|
+
<div className={styles.nav}>
|
|
31
|
+
<button onClick={prev} className={styles.navButton} type="button">
|
|
32
|
+
←
|
|
33
|
+
</button>
|
|
34
|
+
<div className={styles.dots}>
|
|
35
|
+
{Array.from({ length: slideCount }).map((_, i) => (
|
|
36
|
+
<span
|
|
37
|
+
key={i}
|
|
38
|
+
className={clsx(styles.dot, isActiveIndex(i) && styles.dotActive)}
|
|
39
|
+
/>
|
|
40
|
+
))}
|
|
41
|
+
</div>
|
|
42
|
+
<button onClick={next} className={styles.navButton} type="button">
|
|
43
|
+
→
|
|
44
|
+
</button>
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const Slide: FC<PropsWithChildren<PropsWithClassName>> = ({ children, className }) => (
|
|
52
|
+
<div className={clsx("keen-slider__slide", styles.slide, className)}>{children}</div>
|
|
53
|
+
);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from "react";
|
|
2
|
+
import { UseIntersectionProps } from "@becklyn/next/lib/intersection";
|
|
3
|
+
import { PropsWithClassName } from "@becklyn/next/types/style";
|
|
4
|
+
export type IntersectionObserverBoxProps = Omit<UseIntersectionProps, "ref"> & PropsWithClassName;
|
|
5
|
+
export declare const IntersectionObserverBox: FC<PropsWithChildren<IntersectionObserverBoxProps>>;
|
|
6
|
+
//# sourceMappingURL=IntersectionObserverBox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntersectionObserverBox.d.ts","sourceRoot":"","sources":["../../../../components/atoms/IntersectionObserverBox/IntersectionObserverBox.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAU,MAAM,OAAO,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAmB,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,GAAG,kBAAkB,CAAC;AAElG,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,iBAAiB,CAAC,4BAA4B,CAAC,CAwBvF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.IntersectionObserverBox = void 0;
|
|
8
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
9
|
+
const react_1 = require("react");
|
|
10
|
+
const clsx_1 = __importDefault(require("clsx"));
|
|
11
|
+
const intersection_1 = require("@becklyn/next/lib/intersection");
|
|
12
|
+
const IntersectionObserverBox_module_scss_1 = __importDefault(require("./IntersectionObserverBox.module.scss"));
|
|
13
|
+
const IntersectionObserverBox = ({ children, className, defaultValue, callback, filter, dependencies, options, }) => {
|
|
14
|
+
const ref = (0, react_1.useRef)(null);
|
|
15
|
+
const isVisible = (0, intersection_1.useIntersection)({
|
|
16
|
+
ref,
|
|
17
|
+
defaultValue,
|
|
18
|
+
callback,
|
|
19
|
+
filter,
|
|
20
|
+
dependencies,
|
|
21
|
+
options,
|
|
22
|
+
});
|
|
23
|
+
return ((0, jsx_runtime_1.jsx)("div", { ref: ref, className: (0, clsx_1.default)(IntersectionObserverBox_module_scss_1.default.box, isVisible && IntersectionObserverBox_module_scss_1.default.visible, className), children: children !== null && children !== void 0 ? children : (isVisible ? "In viewport" : "Out of viewport") }));
|
|
24
|
+
};
|
|
25
|
+
exports.IntersectionObserverBox = IntersectionObserverBox;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
|
+
import { IntersectionObserverBox } from "./IntersectionObserverBox";
|
|
3
|
+
declare const meta: Meta<typeof IntersectionObserverBox>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof IntersectionObserverBox>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const WithThreshold: Story;
|
|
8
|
+
export declare const Scrollable: Story;
|
|
9
|
+
export declare const WithCallback: Story;
|
|
10
|
+
export declare const CustomFilter: Story;
|
|
11
|
+
//# sourceMappingURL=IntersectionObserverBox.stories.d.ts.map
|
package/dist/components/atoms/IntersectionObserverBox/IntersectionObserverBox.stories.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntersectionObserverBox.stories.d.ts","sourceRoot":"","sources":["../../../../components/atoms/IntersectionObserverBox/IntersectionObserverBox.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,uBAAuB,CAM9C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAEtD,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,aAAa,EAAE,KAK3B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAQxB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CustomFilter = exports.WithCallback = exports.Scrollable = exports.WithThreshold = exports.Default = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const IntersectionObserverBox_1 = require("./IntersectionObserverBox");
|
|
9
|
+
const IntersectionObserverBox_stories_module_scss_1 = __importDefault(require("./IntersectionObserverBox.stories.module.scss"));
|
|
10
|
+
const meta = {
|
|
11
|
+
title: "Atoms/IntersectionObserverBox",
|
|
12
|
+
component: IntersectionObserverBox_1.IntersectionObserverBox,
|
|
13
|
+
parameters: {
|
|
14
|
+
layout: "padded",
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
exports.default = meta;
|
|
18
|
+
exports.Default = {};
|
|
19
|
+
exports.WithThreshold = {
|
|
20
|
+
args: {
|
|
21
|
+
options: { threshold: 0.5 },
|
|
22
|
+
children: "Visible when 50% in viewport",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
exports.Scrollable = {
|
|
26
|
+
render: args => ((0, jsx_runtime_1.jsxs)("div", { className: IntersectionObserverBox_stories_module_scss_1.default.scrollContainer, children: [(0, jsx_runtime_1.jsx)("div", { className: IntersectionObserverBox_stories_module_scss_1.default.scrollHint, children: "\u2193 Scroll down \u2193" }), (0, jsx_runtime_1.jsx)(IntersectionObserverBox_1.IntersectionObserverBox, Object.assign({}, args)), (0, jsx_runtime_1.jsx)("div", { className: IntersectionObserverBox_stories_module_scss_1.default.scrollHint, children: "\u2191 Scroll up \u2191" })] })),
|
|
27
|
+
};
|
|
28
|
+
exports.WithCallback = {
|
|
29
|
+
render: args => ((0, jsx_runtime_1.jsx)(IntersectionObserverBox_1.IntersectionObserverBox, Object.assign({}, args, { callback: (_, isVisible) => console.log("Visibility changed:", isVisible), children: "Watch the console when visibility changes" }))),
|
|
30
|
+
};
|
|
31
|
+
exports.CustomFilter = {
|
|
32
|
+
args: {
|
|
33
|
+
filter: entry => entry.intersectionRatio >= 0.75,
|
|
34
|
+
options: { threshold: [0, 0.25, 0.5, 0.75, 1] },
|
|
35
|
+
children: "Visible when ≥75% intersecting",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from "react";
|
|
2
|
+
import "keen-slider/keen-slider.min.css";
|
|
3
|
+
import { SliderOptions } from "@becklyn/next/lib/slider";
|
|
4
|
+
import { PropsWithClassName } from "@becklyn/next/types/style";
|
|
5
|
+
export interface SliderProps extends SliderOptions {
|
|
6
|
+
showNav?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const Slider: FC<PropsWithChildren<PropsWithClassName<SliderProps>>>;
|
|
9
|
+
export declare const Slide: FC<PropsWithChildren<PropsWithClassName>>;
|
|
10
|
+
//# sourceMappingURL=Slider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../../components/atoms/Slider/Slider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,iCAAiC,CAAC;AACzC,OAAO,EAAE,aAAa,EAAa,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,MAAM,WAAW,WAAY,SAAQ,aAAa;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,MAAM,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAmCzE,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAE3D,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
4
|
+
var t = {};
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
8
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
9
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
10
|
+
t[p[i]] = s[p[i]];
|
|
11
|
+
}
|
|
12
|
+
return t;
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.Slide = exports.Slider = void 0;
|
|
19
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
20
|
+
const clsx_1 = __importDefault(require("clsx"));
|
|
21
|
+
require("keen-slider/keen-slider.min.css");
|
|
22
|
+
const slider_1 = require("@becklyn/next/lib/slider");
|
|
23
|
+
const Slider_module_scss_1 = __importDefault(require("./Slider.module.scss"));
|
|
24
|
+
const Slider = (_a) => {
|
|
25
|
+
var _b;
|
|
26
|
+
var { children, className, showNav = true } = _a, options = __rest(_a, ["children", "className", "showNav"]);
|
|
27
|
+
const [setRef, { next, prev, isActiveIndex, details, isDisabled }] = (0, slider_1.useSlider)(options);
|
|
28
|
+
const slideCount = (_b = details === null || details === void 0 ? void 0 : details.slides.length) !== null && _b !== void 0 ? _b : 0;
|
|
29
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, clsx_1.default)(Slider_module_scss_1.default.wrapper, isDisabled && Slider_module_scss_1.default.disabled, className), children: [(0, jsx_runtime_1.jsx)("div", { ref: node => setRef(node), className: (0, clsx_1.default)("keen-slider", Slider_module_scss_1.default.slider), children: children }), showNav && !isDisabled && slideCount > 1 && ((0, jsx_runtime_1.jsxs)("div", { className: Slider_module_scss_1.default.nav, children: [(0, jsx_runtime_1.jsx)("button", { onClick: prev, className: Slider_module_scss_1.default.navButton, type: "button", children: "\u2190" }), (0, jsx_runtime_1.jsx)("div", { className: Slider_module_scss_1.default.dots, children: Array.from({ length: slideCount }).map((_, i) => ((0, jsx_runtime_1.jsx)("span", { className: (0, clsx_1.default)(Slider_module_scss_1.default.dot, isActiveIndex(i) && Slider_module_scss_1.default.dotActive) }, i))) }), (0, jsx_runtime_1.jsx)("button", { onClick: next, className: Slider_module_scss_1.default.navButton, type: "button", children: "\u2192" })] }))] }));
|
|
30
|
+
};
|
|
31
|
+
exports.Slider = Slider;
|
|
32
|
+
const Slide = ({ children, className }) => ((0, jsx_runtime_1.jsx)("div", { className: (0, clsx_1.default)("keen-slider__slide", Slider_module_scss_1.default.slide, className), children: children }));
|
|
33
|
+
exports.Slide = Slide;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
|
+
import { Slider } from "./Slider";
|
|
3
|
+
declare const meta: Meta<typeof Slider>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof Slider>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const ManySlides: Story;
|
|
8
|
+
export declare const WithoutNav: Story;
|
|
9
|
+
export declare const Loop: Story;
|
|
10
|
+
export declare const AutoDisable: Story;
|
|
11
|
+
//# sourceMappingURL=Slider.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Slider.stories.d.ts","sourceRoot":"","sources":["../../../../components/atoms/Slider/Slider.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAS,MAAM,EAAE,MAAM,UAAU,CAAC;AAqBzC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,MAAM,CAa7B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,MAAM,CAAC,CAAC;AAErC,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAMlB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AutoDisable = exports.Loop = exports.WithoutNav = exports.ManySlides = exports.Default = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const Slider_1 = require("./Slider");
|
|
9
|
+
const Slider_stories_module_scss_1 = __importDefault(require("./Slider.stories.module.scss"));
|
|
10
|
+
const SLIDE_COLORS = ["#4f86c6", "#6abf69", "#f0a500", "#e05c5c", "#a97cc7"];
|
|
11
|
+
const SampleSlides = ({ count = 3 }) => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: Array.from({ length: count }).map((_, i) => ((0, jsx_runtime_1.jsx)(Slider_1.Slide, { children: (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
12
|
+
background: SLIDE_COLORS[i % SLIDE_COLORS.length],
|
|
13
|
+
}, className: Slider_stories_module_scss_1.default.exampleSlide, children: ["Slide ", i + 1] }) }, i))) }));
|
|
14
|
+
const meta = {
|
|
15
|
+
title: "Atoms/Slider",
|
|
16
|
+
component: Slider_1.Slider,
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: "padded",
|
|
19
|
+
},
|
|
20
|
+
decorators: [
|
|
21
|
+
Story => ((0, jsx_runtime_1.jsx)("div", { className: Slider_stories_module_scss_1.default.storyContainer, children: (0, jsx_runtime_1.jsx)(Story, {}) })),
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
exports.default = meta;
|
|
25
|
+
exports.Default = {
|
|
26
|
+
render: args => ((0, jsx_runtime_1.jsx)(Slider_1.Slider, Object.assign({}, args, { children: (0, jsx_runtime_1.jsx)(SampleSlides, { count: 3 }) }))),
|
|
27
|
+
};
|
|
28
|
+
exports.ManySlides = {
|
|
29
|
+
render: args => ((0, jsx_runtime_1.jsx)(Slider_1.Slider, Object.assign({}, args, { children: (0, jsx_runtime_1.jsx)(SampleSlides, { count: 5 }) }))),
|
|
30
|
+
};
|
|
31
|
+
exports.WithoutNav = {
|
|
32
|
+
render: args => ((0, jsx_runtime_1.jsx)(Slider_1.Slider, Object.assign({}, args, { showNav: false, children: (0, jsx_runtime_1.jsx)(SampleSlides, { count: 3 }) }))),
|
|
33
|
+
};
|
|
34
|
+
exports.Loop = {
|
|
35
|
+
render: args => ((0, jsx_runtime_1.jsx)(Slider_1.Slider, Object.assign({}, args, { loop: true, children: (0, jsx_runtime_1.jsx)(SampleSlides, { count: 3 }) }))),
|
|
36
|
+
};
|
|
37
|
+
exports.AutoDisable = {
|
|
38
|
+
name: "Auto Disable (single slide)",
|
|
39
|
+
render: args => ((0, jsx_runtime_1.jsx)(Slider_1.Slider, Object.assign({}, args, { shouldAutoDisable: true, children: (0, jsx_runtime_1.jsx)(SampleSlides, { count: 1 }) }))),
|
|
40
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@becklyn/components",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://github.com/Becklyn-Studios/ts-libs/tree/main/packages/components",
|
|
6
6
|
"repository": {
|
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
"@becklyn/eslint": "*",
|
|
23
23
|
"@becklyn/next": "*",
|
|
24
24
|
"@becklyn/tsconfig": "*",
|
|
25
|
-
"@storybook/addon-docs": "^10.3.
|
|
26
|
-
"@storybook/nextjs-vite": "10.3.
|
|
27
|
-
"@types/node": "^25.
|
|
25
|
+
"@storybook/addon-docs": "^10.3.6",
|
|
26
|
+
"@storybook/nextjs-vite": "10.3.6",
|
|
27
|
+
"@types/node": "^25.6.0",
|
|
28
28
|
"@types/react": "^19.2.14",
|
|
29
29
|
"clsx": "^2.1.1",
|
|
30
|
-
"eslint-plugin-storybook": "^10.3.
|
|
31
|
-
"next": "^16.2.
|
|
32
|
-
"react": "^19.2.
|
|
33
|
-
"react-dom": "^19.2.
|
|
34
|
-
"sass": "^1.
|
|
35
|
-
"storybook": "^10.3.
|
|
36
|
-
"vite": "^7.3.
|
|
30
|
+
"eslint-plugin-storybook": "^10.3.6",
|
|
31
|
+
"next": "^16.2.4",
|
|
32
|
+
"react": "^19.2.5",
|
|
33
|
+
"react-dom": "^19.2.5",
|
|
34
|
+
"sass": "^1.99.0",
|
|
35
|
+
"storybook": "^10.3.6",
|
|
36
|
+
"vite": "^7.3.2"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"react": "^18.3.1 || ^19.0.0",
|