@slidy/element
Simple, configurable & reusable carousel CustomElement based on @slidy/core.
DEMO
Try theGetting started
The package is available via NPM:
npm i -D @slidy/element
or from CDN:
<script src="https://unpkg.com/@slidy/element"></script>
Playground is available in svelte REPL.
Usage
CustomElement <slidy-element>
is available via import as MJS/CJS
module or via global Window.Slidy
object props as IIFE
.
MJS/CJS module import
<head>
<script type="module">
import 'https://unpkg.com/@slidy/core/dist/index.mjs'; // MJS module
// OR
import 'https://unpkg.com/@slidy/core/dist/index.cjs'; // CJS module
</script>
</head>
<slidy-element id="slidy" index="5">
<img src="..." width="..." height="..."/>
...
</slidy-element>
Window
Object
IIFE as window.Slidy object contain Slidy Class like element
props, @slidy/animation, @slidy/easing & @slidy/media functions.
window.Slidy = {
animation, // animation functions
easing, // easing functions
element, // Slidy Class
media // global media store
}
<head>
<script src="https://unpkg.com/@slidy/element/dist/index.js"></script>
</head>
<slidy-element id="slidy" index="5" snap="center">
<img src="..." width="..." height="..."/>
...
</slidy-element>
<script>
const animation = Slidy.animation.flip
const easing = Slidy.easing.cubic
const media = Slidy.media
const node = document.querySelector('#slidy')
node.setAttribute('easing', easing.toString())
// options set after attributes on init <slidy-element> & merged/rewrite
node.options = {animation: animation.toString()}
</script>
As third party module in any frameworks
<!-- Svelte -->
<script>
import '@slidy/element';
</script>
<slidy-element id="slidy" index="5" snap="center">
<img src="..." width="..." height="..."/>
...
</slidy-element>
Options
All options
are optional & can be passed through element attributes or like options keys. Options set after attributes on init <slidy-element>
& merged/rewrite.
animation
& easing
functions also can be passed through attributes with: key: function.tostring()
transformation.
If you need reversed flow use css rules on target node, like: flex-flow: row-reverse / column-reverse
, direction: rtl
or html attribute dir="rtl"
.
If you need keyboard navigation just set tabindex=0
on <slidy-element>
.
absolute
, because @slidy use coordinates from childNodes. For deck flow use options.snap: 'deck'
.
Key | Default | Type | Description |
---|---|---|---|
index |
0 |
number |
Start index |
clamp |
0 |
number |
Clamping sliding by index: clamp - index + clamp
|
indent |
1 |
number |
Sliding indent: part of gap padding both start/end edges of slide gap * indent
|
sensity |
5 |
number |
Sliding sensity: how many pixels to drag in the RAF ~16ms to start move, 0 when sliding |
gravity |
1.2 |
number |
Sliding gravity: 0(space) ~ 1(eath) ~ 2(underground)
|
duration |
375 |
number |
Sliding duration in ms |
animation |
undefuned |
function |
Animation function: AnimationFunc = (args: AnimationArgs) => Styles - predefined in @slidy/animation. |
easing |
undefined |
function |
Easing function: t value from 1 to 0 - predefined in @slidy/easing. |
snap |
undefined |
string |
Snapping side: 'start', 'center', 'end', 'deck', undefined . Default clamp sliding by edges. |
axis |
undefined |
string |
Control coordinate axis: 'x', 'y' . |
loop |
false |
boolean |
Infinite loop mode |
Internal calculated - readonly
Key | Type | Description |
---|---|---|
position |
number |
Current position |
direction |
number |
Children move direction |
vertical |
number |
Children axis flow: 0 or any Number as true
|
reverse |
number |
Children reverse flow: -1 or 1
|
scrollable |
number |
Children full size with gaps > target node size |
Usage
<head>
<script src="https://unpkg.com/@slidy/element/dist/index.js"></script>
</head>
<slidy-element id="slidy" index="5" snap="center">
<img src="..." width="..." height="..."/>
...
</slidy-element>
<script>
let animation = Slidy.animation.flip
easing = Slidy.easing.cubic
media = Slidy.media
node = document.querySelector('#slidy')
node.setAttribute('easing', easing.toString())
// options set after attributes on init <slidy-element> & merged/rewrite
node.options = {animation: animation.toString()}
</script>
Events
Slidy instance reinit on every change childNodes.length in on:mutate
event.
Name | Detail | Description |
---|---|---|
mount |
{options} |
Fires when node.children.length & node.children isConnected |
resize |
{ROE,options} |
Fires on resize target node ROE: ResizeObserverEntry[]
|
mutate |
{ML,options} |
Fires on mutation childNodes in target node ML: MutationRecord[]
|
move |
{index,position} |
Fires on any sliding |
index |
{index} |
Fires on each index change: index === changed.index
|
keys |
{e.key} |
Fires if target node focusing and any key pressed. Predefined keys: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'] is defaultPrevented & navigate to(index + options.clamp) . Focus not in core & can do programaticaly or with tabindex attribute on target node. |
update |
{updated.options} |
Fires on each options update |
destroy |
{node} |
Fires when async destroy() resolved or before target node unmounted from the DOM |
Usage
<head>
<script src="https://unpkg.com/@slidy/element/dist/index.js"></script>
</head>
<slidy-element id="slidy" index="5" snap="center" onmove="onMove">
<img src="..." width="..." height="..."/>
...
</slidy-element>
<script>
const node = document.querySelector('#slidy');
node.addEventListener('mount', (e) => console.log(e))
node.onupdate = (e) => console.log(e.detail) // ???
function onMove(e) {
const { index, position } = e.detail
console.log(index, position)
}
</script>
Methods
Name | Arguments | Description |
---|---|---|
to() |
(index) |
Scroll to index
|
init() |
(node) |
Init slidy() instance |
update() |
({option:value}) |
Update any property in options |
destroy() |
() |
Remove event listners, observers & defaulted props on slidy() instance |
Usage
<head>
<script src="https://unpkg.com/@slidy/core/dist/index.js"></script>
</head>
<slidy-element id="slidy" index="5" snap="center" onmove="onMove">
<img src="..." width="..." height="..."/>
...
</slidy-element>
<nav>
<button id="prev">←</button>
<button id="next">→</button>
</nav>
<script>;
const slidy = document.querySelector('#slidy');
const prev = document.querySelector('#prev');
const next = document.querySelector('#next');
slidy.update({ snap: 'center' })
prev.onclick = () => slidy.to(index - 1)
next.onclick = () => slidy.to(index + 1)
</script>
Styling
<slidy-element>
nested @slidy/core
styles outline: 0; overflow: hidden; user-select: none; -webkit-user-select:none;
& have base simple incapsulated styles. Also you can style it & his childs as native HTMLElements or you can pass CSSvariables props via style
attribute or in css scope. For <img>
children required pass width/height
attributes.
Incapsulated styles
:host {
display: flex;
flex-flow: var(--flow);
gap: var(--gap, 1rem);
width: 100%;
height: var(--height, 20rem);
}
::slotted(*) {
flex: 0 0 var(--width, auto);
width: var(--width, auto);
height: 100%;
}
CSS variables
Name | Default | Description |
---|---|---|
--flow |
row |
Flex flow |
--width |
auto |
Each children width |
--height |
20rem |
<slidy-element> height |
--gap |
1rem |
Gap between childs |
Usage
<head>
<script src="https://unpkg.com/@slidy/core/dist/index.js"></script>
<style>
#slidy {
--flow: row;
border: 1px solid red;
}
</style>
</head>
<slidy-element
id="slidy"
index="5"
snap="center"
style="--width: 100px; --height: 100px; --gap: 1rem;"
>
<img src="..." width="..." height="..."/>
...
</slidy-element>
MIT © Valexr