svelte-lazy-image
Advanced tools
Comparing version 0.2.2 to 0.3.0
506
index.js
@@ -1,504 +0,2 @@ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.LazyImage = {})); | ||
})(this, (function (exports) { 'use strict'; | ||
function noop() { } | ||
function assign(tar, src) { | ||
// @ts-ignore | ||
for (const k in src) | ||
tar[k] = src[k]; | ||
return tar; | ||
} | ||
function run(fn) { | ||
return fn(); | ||
} | ||
function blank_object() { | ||
return Object.create(null); | ||
} | ||
function run_all(fns) { | ||
fns.forEach(run); | ||
} | ||
function is_function(thing) { | ||
return typeof thing === 'function'; | ||
} | ||
function safe_not_equal(a, b) { | ||
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function'); | ||
} | ||
let src_url_equal_anchor; | ||
function src_url_equal(element_src, url) { | ||
if (!src_url_equal_anchor) { | ||
src_url_equal_anchor = document.createElement('a'); | ||
} | ||
src_url_equal_anchor.href = url; | ||
return element_src === src_url_equal_anchor.href; | ||
} | ||
function is_empty(obj) { | ||
return Object.keys(obj).length === 0; | ||
} | ||
function exclude_internal_props(props) { | ||
const result = {}; | ||
for (const k in props) | ||
if (k[0] !== '$') | ||
result[k] = props[k]; | ||
return result; | ||
} | ||
function compute_rest_props(props, keys) { | ||
const rest = {}; | ||
keys = new Set(keys); | ||
for (const k in props) | ||
if (!keys.has(k) && k[0] !== '$') | ||
rest[k] = props[k]; | ||
return rest; | ||
} | ||
function insert(target, node, anchor) { | ||
target.insertBefore(node, anchor || null); | ||
} | ||
function detach(node) { | ||
node.parentNode.removeChild(node); | ||
} | ||
function element(name) { | ||
return document.createElement(name); | ||
} | ||
function listen(node, event, handler, options) { | ||
node.addEventListener(event, handler, options); | ||
return () => node.removeEventListener(event, handler, options); | ||
} | ||
function attr(node, attribute, value) { | ||
if (value == null) | ||
node.removeAttribute(attribute); | ||
else if (node.getAttribute(attribute) !== value) | ||
node.setAttribute(attribute, value); | ||
} | ||
function set_attributes(node, attributes) { | ||
// @ts-ignore | ||
const descriptors = Object.getOwnPropertyDescriptors(node.__proto__); | ||
for (const key in attributes) { | ||
if (attributes[key] == null) { | ||
node.removeAttribute(key); | ||
} | ||
else if (key === 'style') { | ||
node.style.cssText = attributes[key]; | ||
} | ||
else if (key === '__value') { | ||
node.value = node[key] = attributes[key]; | ||
} | ||
else if (descriptors[key] && descriptors[key].set) { | ||
node[key] = attributes[key]; | ||
} | ||
else { | ||
attr(node, key, attributes[key]); | ||
} | ||
} | ||
} | ||
function children(element) { | ||
return Array.from(element.childNodes); | ||
} | ||
function toggle_class(element, name, toggle) { | ||
element.classList[toggle ? 'add' : 'remove'](name); | ||
} | ||
let current_component; | ||
function set_current_component(component) { | ||
current_component = component; | ||
} | ||
function get_current_component() { | ||
if (!current_component) | ||
throw new Error('Function called outside component initialization'); | ||
return current_component; | ||
} | ||
function onMount(fn) { | ||
get_current_component().$$.on_mount.push(fn); | ||
} | ||
const dirty_components = []; | ||
const binding_callbacks = []; | ||
const render_callbacks = []; | ||
const flush_callbacks = []; | ||
const resolved_promise = Promise.resolve(); | ||
let update_scheduled = false; | ||
function schedule_update() { | ||
if (!update_scheduled) { | ||
update_scheduled = true; | ||
resolved_promise.then(flush); | ||
} | ||
} | ||
function add_render_callback(fn) { | ||
render_callbacks.push(fn); | ||
} | ||
// flush() calls callbacks in this order: | ||
// 1. All beforeUpdate callbacks, in order: parents before children | ||
// 2. All bind:this callbacks, in reverse order: children before parents. | ||
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT | ||
// for afterUpdates called during the initial onMount, which are called in | ||
// reverse order: children before parents. | ||
// Since callbacks might update component values, which could trigger another | ||
// call to flush(), the following steps guard against this: | ||
// 1. During beforeUpdate, any updated components will be added to the | ||
// dirty_components array and will cause a reentrant call to flush(). Because | ||
// the flush index is kept outside the function, the reentrant call will pick | ||
// up where the earlier call left off and go through all dirty components. The | ||
// current_component value is saved and restored so that the reentrant call will | ||
// not interfere with the "parent" flush() call. | ||
// 2. bind:this callbacks cannot trigger new flush() calls. | ||
// 3. During afterUpdate, any updated components will NOT have their afterUpdate | ||
// callback called a second time; the seen_callbacks set, outside the flush() | ||
// function, guarantees this behavior. | ||
const seen_callbacks = new Set(); | ||
let flushidx = 0; // Do *not* move this inside the flush() function | ||
function flush() { | ||
const saved_component = current_component; | ||
do { | ||
// first, call beforeUpdate functions | ||
// and update components | ||
while (flushidx < dirty_components.length) { | ||
const component = dirty_components[flushidx]; | ||
flushidx++; | ||
set_current_component(component); | ||
update(component.$$); | ||
} | ||
set_current_component(null); | ||
dirty_components.length = 0; | ||
flushidx = 0; | ||
while (binding_callbacks.length) | ||
binding_callbacks.pop()(); | ||
// then, once components are updated, call | ||
// afterUpdate functions. This may cause | ||
// subsequent updates... | ||
for (let i = 0; i < render_callbacks.length; i += 1) { | ||
const callback = render_callbacks[i]; | ||
if (!seen_callbacks.has(callback)) { | ||
// ...so guard against infinite loops | ||
seen_callbacks.add(callback); | ||
callback(); | ||
} | ||
} | ||
render_callbacks.length = 0; | ||
} while (dirty_components.length); | ||
while (flush_callbacks.length) { | ||
flush_callbacks.pop()(); | ||
} | ||
update_scheduled = false; | ||
seen_callbacks.clear(); | ||
set_current_component(saved_component); | ||
} | ||
function update($$) { | ||
if ($$.fragment !== null) { | ||
$$.update(); | ||
run_all($$.before_update); | ||
const dirty = $$.dirty; | ||
$$.dirty = [-1]; | ||
$$.fragment && $$.fragment.p($$.ctx, dirty); | ||
$$.after_update.forEach(add_render_callback); | ||
} | ||
} | ||
const outroing = new Set(); | ||
function transition_in(block, local) { | ||
if (block && block.i) { | ||
outroing.delete(block); | ||
block.i(local); | ||
} | ||
} | ||
function get_spread_update(levels, updates) { | ||
const update = {}; | ||
const to_null_out = {}; | ||
const accounted_for = { $$scope: 1 }; | ||
let i = levels.length; | ||
while (i--) { | ||
const o = levels[i]; | ||
const n = updates[i]; | ||
if (n) { | ||
for (const key in o) { | ||
if (!(key in n)) | ||
to_null_out[key] = 1; | ||
} | ||
for (const key in n) { | ||
if (!accounted_for[key]) { | ||
update[key] = n[key]; | ||
accounted_for[key] = 1; | ||
} | ||
} | ||
levels[i] = n; | ||
} | ||
else { | ||
for (const key in o) { | ||
accounted_for[key] = 1; | ||
} | ||
} | ||
} | ||
for (const key in to_null_out) { | ||
if (!(key in update)) | ||
update[key] = undefined; | ||
} | ||
return update; | ||
} | ||
function mount_component(component, target, anchor, customElement) { | ||
const { fragment, on_mount, on_destroy, after_update } = component.$$; | ||
fragment && fragment.m(target, anchor); | ||
if (!customElement) { | ||
// onMount happens before the initial afterUpdate | ||
add_render_callback(() => { | ||
const new_on_destroy = on_mount.map(run).filter(is_function); | ||
if (on_destroy) { | ||
on_destroy.push(...new_on_destroy); | ||
} | ||
else { | ||
// Edge case - component was destroyed immediately, | ||
// most likely as a result of a binding initialising | ||
run_all(new_on_destroy); | ||
} | ||
component.$$.on_mount = []; | ||
}); | ||
} | ||
after_update.forEach(add_render_callback); | ||
} | ||
function destroy_component(component, detaching) { | ||
const $$ = component.$$; | ||
if ($$.fragment !== null) { | ||
run_all($$.on_destroy); | ||
$$.fragment && $$.fragment.d(detaching); | ||
// TODO null out other refs, including component.$$ (but need to | ||
// preserve final state?) | ||
$$.on_destroy = $$.fragment = null; | ||
$$.ctx = []; | ||
} | ||
} | ||
function make_dirty(component, i) { | ||
if (component.$$.dirty[0] === -1) { | ||
dirty_components.push(component); | ||
schedule_update(); | ||
component.$$.dirty.fill(0); | ||
} | ||
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31)); | ||
} | ||
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) { | ||
const parent_component = current_component; | ||
set_current_component(component); | ||
const $$ = component.$$ = { | ||
fragment: null, | ||
ctx: null, | ||
// state | ||
props, | ||
update: noop, | ||
not_equal, | ||
bound: blank_object(), | ||
// lifecycle | ||
on_mount: [], | ||
on_destroy: [], | ||
on_disconnect: [], | ||
before_update: [], | ||
after_update: [], | ||
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])), | ||
// everything else | ||
callbacks: blank_object(), | ||
dirty, | ||
skip_bound: false, | ||
root: options.target || parent_component.$$.root | ||
}; | ||
append_styles && append_styles($$.root); | ||
let ready = false; | ||
$$.ctx = instance | ||
? instance(component, options.props || {}, (i, ret, ...rest) => { | ||
const value = rest.length ? rest[0] : ret; | ||
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) { | ||
if (!$$.skip_bound && $$.bound[i]) | ||
$$.bound[i](value); | ||
if (ready) | ||
make_dirty(component, i); | ||
} | ||
return ret; | ||
}) | ||
: []; | ||
$$.update(); | ||
ready = true; | ||
run_all($$.before_update); | ||
// `false` as a special case of no DOM component | ||
$$.fragment = create_fragment ? create_fragment($$.ctx) : false; | ||
if (options.target) { | ||
if (options.hydrate) { | ||
const nodes = children(options.target); | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
$$.fragment && $$.fragment.l(nodes); | ||
nodes.forEach(detach); | ||
} | ||
else { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
$$.fragment && $$.fragment.c(); | ||
} | ||
if (options.intro) | ||
transition_in(component.$$.fragment); | ||
mount_component(component, options.target, options.anchor, options.customElement); | ||
flush(); | ||
} | ||
set_current_component(parent_component); | ||
} | ||
/** | ||
* Base class for Svelte components. Used when dev=false. | ||
*/ | ||
class SvelteComponent { | ||
$destroy() { | ||
destroy_component(this, 1); | ||
this.$destroy = noop; | ||
} | ||
$on(type, callback) { | ||
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = [])); | ||
callbacks.push(callback); | ||
return () => { | ||
const index = callbacks.indexOf(callback); | ||
if (index !== -1) | ||
callbacks.splice(index, 1); | ||
}; | ||
} | ||
$set($$props) { | ||
if (this.$$set && !is_empty($$props)) { | ||
this.$$.skip_bound = true; | ||
this.$$set($$props); | ||
this.$$.skip_bound = false; | ||
} | ||
} | ||
} | ||
/* src/LazyImage.svelte generated by Svelte v3.46.0 */ | ||
function create_fragment(ctx) { | ||
let img; | ||
let img_src_value; | ||
let mounted; | ||
let dispose; | ||
let img_levels = [ | ||
{ src: img_src_value = /*path*/ ctx[2] }, | ||
{ alt: /*alt*/ ctx[0] }, | ||
/*$$restProps*/ ctx[5], | ||
{ class: "svelte-lazy-image" } | ||
]; | ||
let img_data = {}; | ||
for (let i = 0; i < img_levels.length; i += 1) { | ||
img_data = assign(img_data, img_levels[i]); | ||
} | ||
return { | ||
c() { | ||
img = element("img"); | ||
set_attributes(img, img_data); | ||
toggle_class(img, "svelte-lazy-image--loaded", /*loaded*/ ctx[3]); | ||
}, | ||
m(target, anchor) { | ||
insert(target, img, anchor); | ||
/*img_binding*/ ctx[9](img); | ||
if (!mounted) { | ||
dispose = listen(img, "load", /*handleLoad*/ ctx[4]); | ||
mounted = true; | ||
} | ||
}, | ||
p(ctx, [dirty]) { | ||
set_attributes(img, img_data = get_spread_update(img_levels, [ | ||
dirty & /*path*/ 4 && !src_url_equal(img.src, img_src_value = /*path*/ ctx[2]) && { src: img_src_value }, | ||
dirty & /*alt*/ 1 && { alt: /*alt*/ ctx[0] }, | ||
dirty & /*$$restProps*/ 32 && /*$$restProps*/ ctx[5], | ||
{ class: "svelte-lazy-image" } | ||
])); | ||
toggle_class(img, "svelte-lazy-image--loaded", /*loaded*/ ctx[3]); | ||
}, | ||
i: noop, | ||
o: noop, | ||
d(detaching) { | ||
if (detaching) detach(img); | ||
/*img_binding*/ ctx[9](null); | ||
mounted = false; | ||
dispose(); | ||
} | ||
}; | ||
} | ||
function instance($$self, $$props, $$invalidate) { | ||
const omit_props_names = ["placeholder","src","alt"]; | ||
let $$restProps = compute_rest_props($$props, omit_props_names); | ||
let observerCallback = function (entries, observer) { | ||
entries.forEach(entry => { | ||
if (entry.isIntersecting) { | ||
$$invalidate(8, intersected = true); | ||
observer.unobserve(imgElement); | ||
} | ||
}); | ||
}; | ||
let { placeholder } = $$props; | ||
let { src } = $$props; | ||
let { alt } = $$props; | ||
let imgElement; | ||
let path; | ||
let observer; | ||
let intersected = false; | ||
let loaded = false; | ||
onMount(() => { | ||
observer = new IntersectionObserver(observerCallback); | ||
observer.observe(imgElement); | ||
return () => { | ||
observer.unobserve(imgElement); | ||
}; | ||
}); | ||
function handleLoad() { | ||
if (!loaded && path === src) { | ||
$$invalidate(3, loaded = true); | ||
} | ||
} | ||
function img_binding($$value) { | ||
binding_callbacks[$$value ? 'unshift' : 'push'](() => { | ||
imgElement = $$value; | ||
$$invalidate(1, imgElement); | ||
}); | ||
} | ||
$$self.$$set = $$new_props => { | ||
$$props = assign(assign({}, $$props), exclude_internal_props($$new_props)); | ||
$$invalidate(5, $$restProps = compute_rest_props($$props, omit_props_names)); | ||
if ('placeholder' in $$new_props) $$invalidate(6, placeholder = $$new_props.placeholder); | ||
if ('src' in $$new_props) $$invalidate(7, src = $$new_props.src); | ||
if ('alt' in $$new_props) $$invalidate(0, alt = $$new_props.alt); | ||
}; | ||
$$self.$$.update = () => { | ||
if ($$self.$$.dirty & /*intersected, src, placeholder*/ 448) { | ||
$$invalidate(2, path = intersected ? src : placeholder); | ||
} | ||
}; | ||
return [ | ||
alt, | ||
imgElement, | ||
path, | ||
loaded, | ||
handleLoad, | ||
$$restProps, | ||
placeholder, | ||
src, | ||
intersected, | ||
img_binding | ||
]; | ||
} | ||
class LazyImage extends SvelteComponent { | ||
constructor(options) { | ||
super(); | ||
init(this, options, instance, create_fragment, safe_not_equal, { placeholder: 6, src: 7, alt: 0 }); | ||
} | ||
} | ||
exports.LazyImage = LazyImage; | ||
exports["default"] = LazyImage; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
})); | ||
export { default as useLazyImage } from './use-lazy-image'; | ||
export { default as LazyImage } from './LazyImage.svelte'; |
{ | ||
"name": "svelte-lazy-image", | ||
"description": "Svelte component to lazy load images using Intersection Observer", | ||
"version": "0.3.0", | ||
"description": "Svelte action and component to lazy load images using Intersection Observer", | ||
"author": { | ||
@@ -13,29 +14,29 @@ "name": "Alexander Staroselsky", | ||
"license": "MIT", | ||
"svelte": "./src/index.js", | ||
"module": "./index.mjs", | ||
"types": "./types/index.d.ts", | ||
"main": "./index.js", | ||
"scripts": { | ||
"build": "rollup -c", | ||
"commit": "git cz", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"devDependencies": { | ||
"@rollup/plugin-node-resolve": "^13.1.3", | ||
"git-cz": "^3.3.0", | ||
"rollup": "^2.45.2", | ||
"rollup-plugin-svelte": "^7.1.0", | ||
"sveld": "^0.7.1", | ||
"svelte": "^3.6.5" | ||
"@sveltejs/adapter-auto": "next", | ||
"@sveltejs/kit": "next", | ||
"eslint": "^7.32.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-svelte3": "^3.2.1", | ||
"prettier": "^2.4.1", | ||
"prettier-plugin-svelte": "^2.4.0", | ||
"svelte": "^3.44.0", | ||
"svelte2tsx": "^0.4.14", | ||
"typescript": "^4.5.4" | ||
}, | ||
"keywords": [ | ||
"svelte" | ||
"svelte", | ||
"sveltekit", | ||
"intersection-observer", | ||
"lazy-load", | ||
"lazy-image" | ||
], | ||
"files": [ | ||
"src", | ||
"index.mjs", | ||
"index.js", | ||
"types" | ||
], | ||
"version": "0.2.2" | ||
} | ||
"type": "module", | ||
"exports": { | ||
"./package.json": "./package.json", | ||
"./LazyImage.svelte": "./LazyImage.svelte", | ||
".": "./index.js", | ||
"./use-lazy-image": "./use-lazy-image.js" | ||
}, | ||
"svelte": "./index.js" | ||
} |
@@ -13,7 +13,40 @@ # svelte-lazy-image | ||
#### use:action | ||
Set `data-src` and/or `data-srcset` on an `img` element: | ||
```html | ||
<script> | ||
import LazyImage from 'svelte-lazy-image'; | ||
import { useLazyImage as lazyImage } from 'svelte-lazy-image'; | ||
</script> | ||
<img | ||
data-src="https://via.placeholder.com/250?text=src1" | ||
alt="foobar" | ||
use:lazyImage | ||
/> | ||
``` | ||
Specify IntersectionObserver [options](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver) via object passed to `use`: | ||
```html | ||
<script> | ||
import { LazyImage, useLazyImage as lazyImage } from 'svelte-lazy-image'; | ||
</script> | ||
<img | ||
src="https://via.placeholder.com/250?text=placeholder1" | ||
data-src="https://via.placeholder.com/250?text=src1" | ||
alt="foobar" | ||
use:lazyImage={{ threshold: 0.5 }} | ||
/> | ||
``` | ||
#### Component | ||
```html | ||
<script> | ||
import { LazyImage } from 'svelte-lazy-image'; | ||
</script> | ||
<LazyImage | ||
@@ -30,3 +63,3 @@ src="https://via.placeholder.com/250?text=src" | ||
<script> | ||
import LazyImage from 'svelte-lazy-image'; | ||
import { LazyImage } from 'svelte-lazy-image'; | ||
</script> | ||
@@ -41,2 +74,17 @@ | ||
/> | ||
``` | ||
Specify IntersectionObserver [options](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver): | ||
``` | ||
<script> | ||
import { LazyImage } from 'svelte-lazy-image'; | ||
</script> | ||
<LazyImage | ||
src="https://via.placeholder.com/250?text=src" | ||
placeholder="https://via.placeholder.com/250?text=placeholder" | ||
alt="Lorem Ipsum" | ||
options={{ threshold: 0.5 }} | ||
/> | ||
``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
87
Yes
7817
10
86