sinuous-bind v0.0.6
sinuous-bind
About
sinuous-bind brings the bind element directives of Svelte to Sinuous.
Don't do
`
<input value=${state} oninput=${e => state(e.target.value)} />
`Do
`
<input bind=${state} />
`| size | esm | cdn |
|---|---|---|
sinuous-bind | https://unpkg.com/sinuous-bind@latest/dist/all.min.js | |
sinuous-bind/bind | https://unpkg.com/sinuous-bind@latest/dist/bind.min.js | |
sinuous-bind/bindArea | https://unpkg.com/sinuous-bind@latest/dist/bindArea.min.js | |
sinuous-bind/bindGroup | https://unpkg.com/sinuous-bind@latest/dist/bindGroup.min.js | |
sinuous-bind/bindMedia | https://unpkg.com/sinuous-bind@latest/dist/bindMedia.min.js |
Installation
There are two ways to consume sinuous-bind:
ESM
Run the following inside your project directory to get all the bind packages:
npm install sinuous-bind
Setup
Import all the packages into the root of your project like so:
import "sinuous-bind";Alternatively, bring in any or all of the packages, depending on what you need:
import "sinuous-bind/bind";
import "sinuous-bind/bindGroup";
import "sinuous-bind/bindArea";
import "sinuous-bind/bindMedia";Gotchas
These packages are not tree-shakeable. If you import the submodule, you will be stuck with it in your bundle.
CDN
Put this in your html to get all the packages:
<script src="https://unpkg.com/sinuous-bind@latest/dist/all.min.js"></script>Alternatively, you can bring in just what you need (though you must include the top one):
<script src="https://unpkg.com/sinuous-bind@latest/dist/bind.min.js"></script>
<script src="https://unpkg.com/sinuous-bind@latest/dist/bindArea.min.js"></script>
<script src="https://unpkg.com/sinuous-bind@latest/dist/bindGroup.min.js"></script>
<script src="https://unpkg.com/sinuous-bind@latest/dist/bindMedia.min.js"></script>You must also bring in Sinuous:
<script src="https://unpkg.com/sinuous/dist/all.js"></script>Setup
If you have brought in sinuous-bind/dist/all.min.js, setup is something like what follows:
window.bindAll.enableBind(window.S);Alternatively, if you brought in only sinuous-bind/dist/bind.min.js, setup is as follows:
window.bind.enableBind(window.S);If you have brought in more than one package, setup is something like this:
let w = window;
let { register, enableBind } = w.bind;
register(w.bindArea.getBindArea);
register(w.bindGroup.getBindGroup);
register(w.bindMedia.getBindMedia);
enableBind(w.S);Gotchas
Unlike the esm format, the cdn format requires the basic bind package (sinuous-bind/dist/bind.min.js) for any of the others to be enabled.
sinuous-bind/bind
bind can take two kinds of arguments
bind=${<observable>}bind=${[<observable> [, <attribute> [, <event> [, <boolean>]]]]}<attribute>defaults to"value"<event>defaults to"oninput"<boolean>- Pass in
trueto set the attribute with a Sinuoussubscribe. This is necessary for things like acontentEditablebinding totextContentorinnerHTML.
- Pass in
Generally, bind=${state} is sufficient.
bind will attempt to coerce values to numerical values, but will not attempt to coerce booleans or the empty string.
<input> (implicit)
function component() {
const state = o("");
return html`
<input bind=${state} />
`;
}<input> (explicit)
function component() {
const state = o("");
return html`
<input bind=${[state, "value", "oninput"]} />
`;
}<input type="range">
function component() {
const state = o(5);
return html`
<input type="range" bind=${state} min="0" max="10" />
`;
}contentEditable
function component() {
const state = o("");
return html`
<div contentEditable bind=${[state, "textContent", , true]} />
`;
}Takes "textContent" or "innerHTML" as the second element of the array. Requires true as the fourth element.
<input type="checkbox">
function component() {
const state = o("");
return html`
<input type="checkbox" bind=${[state, "checked", "onchange"]} />
`;
}<input type="radio">
function component() {
const state = o("");
return html`
<input type="radio" bind=${[state, "checked", "onchange"]} />
`;
}<select>
function component() {
const state = o(1);
return html`
<select bind=${state}>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
`;
}Gotchas: It won't work with the multiple attribute. Also, it won't sync until user action. If you need either of these things, use sinuous-bind/bindGroup
ref
function component() {
const ref = o();
return html`
<div ref=${ref}></div>
`;
}Gotchas: The value will not be passed into the ref observable until the call to html is made. The DOM node has to be created before it can be passed to ref.
sinuous-bind/bindArea
Both bind:area and bindArea work.
All bind:area bindings are read-only.
bind:area accepts an object of observables, with any of the following keys:
clientWidth, clientHeight, offsetWidth, offsetHeight, scrollLeft, scrollTop
All these keys can be updated whenever the element is resized. Additionally, scrollLeft and scrollTop are updated whenever the element is scrolled.
Effects: Set a function on the object passed to bind:area with the key effect. The effect will be called on resize and scroll. Set a function with any other key, and it will be called on resize, only.
Gotchas: bind:area sets position: relative on the bound element. Do not set the style on the element unless you set position.
single property
function component() {
const clientWidth = o();
return html`
<div bind:area=${{ clientWidth }}></div>
`;
}multiple properties
function component() {
const clientWidth = o();
const clientHeight = o();
const offsetHeight = o();
return html`
<div bind:area=${{ clientWidth, clientHeight, offsetHeight }}></div>
`;
}multiple properties with scrolling
function component() {
const clientWidth = o();
const clientHeight = o();
const scrollLeft = o();
const scrollTop = o();
return html`
<div
bind:area=${{ clientWidth, clientHeight, scrollLeft, scrollTop }}
></div>
`;
}multiple properties with effects
function component() {
const clientWidth = o();
const arbitraryEffect = () => console.log("resizing only");
const scrollLeft = o();
const effect = () => console.log("resizing and/or scrolling");
return html`
<div
bind:area=${{ clientWidth, arbitraryEffect, scrollLeft, effect }}
></div>
`;
}sinuous-bind/bindGroup
Both bind:group and bindGroup work.
Like bind, bind:group will attempt to coerce values to numerical values, but will not attempt to coerce booleans or the empty string.
select
function component() {
const state = o(1);
return html`
<select bind:group=${state}>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
`;
}select multiple
function component() {
const state = o([1, 2]);
return html`
<select bind:group=${state} multiple>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
`;
}radio group
function component() {
const state = o(1);
return html`
<input type="radio" bind:group=${state} value="1" />
<input type="radio" bind:group=${state} value="2" />
<input type="radio" bind:group=${state} value="3" />
`;
}checkbox group
function component() {
const state = o([1, 2]);
return html`
<input type="checkbox" bind:group=${state} value="1" />
<input type="checkbox" bind:group=${state} value="2" />
<input type="checkbox" bind:group=${state} value="3" />
`;
}sinuous-bind/bindMedia
Both bind:media and bindMedia work.
Read-only Properties: duration, buffered, seekable, seeking, played, ended
Read/Write Properties: currentTime, playbackRate, paused, volume
Video-only Properties videoWidth, videoHeight
video
function component() {
const currentTime = o();
const playbackRate = o();
const paused = o();
const volume = o();
const duration = o();
const buffered = o();
const seekable = o();
const seeking = o();
const played = o();
const ended = o();
const videoWidth = o();
const videoHeight = o();
const state = {
currentTime,
playbackRate,
paused,
volume,
duration,
buffered,
seekable,
seeking,
played,
ended,
videoWidth,
videoHeight
};
return html`
<video controls bind:media=${state}>
<source src=http://video.com type=video/webm />
</video>
`;
}audio
function component() {
const currentTime = o();
const playbackRate = o();
const paused = o();
const volume = o();
const duration = o();
const buffered = o();
const seekable = o();
const seeking = o();
const played = o();
const ended = o();
const state = {
currentTime,
playbackRate,
paused,
volume,
duration,
buffered,
seekable,
seeking,
played,
ended
};
return html`
<audio controls bind:media=${state}>
<source src=http://audio.com type=audio/webm />
</audio>
`;
}Acknowledgments and Thanks
- Author of Sinuous
Rich Harris and the rest of the Svelte team
- These packages are a port of much of the bind directive functionality present in the Svelte framework