UNPKG

svelte-headroom

Version:
460 lines (419 loc) 13.4 kB
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'); } function create_slot(definition, ctx, fn) { if (definition) { const slot_ctx = get_slot_context(definition, ctx, fn); return definition[0](slot_ctx); } } function get_slot_context(definition, ctx, fn) { return definition[1] ? assign({}, assign(ctx.$$scope.ctx, definition[1](fn ? fn(ctx) : {}))) : ctx.$$scope.ctx; } function get_slot_changes(definition, ctx, changed, fn) { return definition[1] ? assign({}, assign(ctx.$$scope.changed || {}, definition[1](fn ? fn(changed) : {}))) : ctx.$$scope.changed || {}; } function null_to_empty(value) { return value == null ? '' : value; } function append(target, node) { target.appendChild(node); } 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 node.setAttribute(attribute, value); } function children(element) { return Array.from(element.childNodes); } function custom_event(type, detail) { const e = document.createEvent('CustomEvent'); e.initCustomEvent(type, false, false, detail); return e; } let current_component; function set_current_component(component) { current_component = component; } function createEventDispatcher() { const component = current_component; return (type, detail) => { const callbacks = component.$$.callbacks[type]; if (callbacks) { // TODO are there situations where events could be dispatched // in a server (non-DOM) environment? const event = custom_event(type, detail); callbacks.slice().forEach(fn => { fn.call(component, event); }); } }; } 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); } function flush() { const seen_callbacks = new Set(); do { // first, call beforeUpdate functions // and update components while (dirty_components.length) { const component = dirty_components.shift(); set_current_component(component); update(component.$$); } 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)) { callback(); // ...so guard against infinite loops seen_callbacks.add(callback); } } render_callbacks.length = 0; } while (dirty_components.length); while (flush_callbacks.length) { flush_callbacks.pop()(); } update_scheduled = false; } function update($$) { if ($$.fragment) { $$.update($$.dirty); run_all($$.before_update); $$.fragment.p($$.dirty, $$.ctx); $$.dirty = null; $$.after_update.forEach(add_render_callback); } } const outroing = new Set(); let outros; function transition_in(block, local) { if (block && block.i) { outroing.delete(block); block.i(local); } } function transition_out(block, local, detach, callback) { if (block && block.o) { if (outroing.has(block)) return; outroing.add(block); outros.c.push(() => { outroing.delete(block); if (callback) { if (detach) block.d(1); callback(); } }); block.o(local); } } function mount_component(component, target, anchor) { const { fragment, on_mount, on_destroy, after_update } = component.$$; fragment.m(target, anchor); // 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) { if (component.$$.fragment) { run_all(component.$$.on_destroy); component.$$.fragment.d(detaching); // TODO null out other refs, including component.$$ (but need to // preserve final state?) component.$$.on_destroy = component.$$.fragment = null; component.$$.ctx = {}; } } function make_dirty(component, key) { if (!component.$$.dirty) { dirty_components.push(component); schedule_update(); component.$$.dirty = blank_object(); } component.$$.dirty[key] = true; } function init(component, options, instance, create_fragment, not_equal, prop_names) { const parent_component = current_component; set_current_component(component); const props = options.props || {}; const $$ = component.$$ = { fragment: null, ctx: null, // state props: prop_names, update: noop, not_equal, bound: blank_object(), // lifecycle on_mount: [], on_destroy: [], before_update: [], after_update: [], context: new Map(parent_component ? parent_component.$$.context : []), // everything else callbacks: blank_object(), dirty: null }; let ready = false; $$.ctx = instance ? instance(component, props, (key, ret, value = ret) => { if ($$.ctx && not_equal($$.ctx[key], $$.ctx[key] = value)) { if ($$.bound[key]) $$.bound[key](value); if (ready) make_dirty(component, key); } return ret; }) : props; $$.update(); ready = true; run_all($$.before_update); $$.fragment = create_fragment($$.ctx); if (options.target) { if (options.hydrate) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion $$.fragment.l(children(options.target)); } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion $$.fragment.c(); } if (options.intro) transition_in(component.$$.fragment); mount_component(component, options.target, options.anchor); flush(); } set_current_component(parent_component); } 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() { // overridden by instance, if it has props } } const warn = (msg, val) => console.warn(`[svelte-headroom]:`, msg, val); function validate({ duration, offset, tolerance }) { if (typeof offset !== "number") warn("The `offset` prop is not a number: ", offset); if (typeof tolerance !== "number") warn("The `tolerance` prop is not a number: ", tolerance); if (typeof duration !== "string") warn("The `duration` prop is not a string such as '200ms': ", duration); } /* src/index.svelte generated by Svelte v3.12.1 */ function add_css() { var style = element("style"); style.id = 'svelte-1ql6gaa-style'; style.textContent = "div.svelte-1ql6gaa{position:fixed;width:100%;top:0;transition:transform 300ms linear;transform:translateY(0%)}.svelte-headroom--unpin.svelte-1ql6gaa{transform:translateY(-100%)}"; append(document.head, style); } function create_fragment(ctx) { var scrolling = false, clear_scrolling = () => { scrolling = false; }, scrolling_timeout, div, div_class_value, action_action, current, dispose; add_render_callback(ctx.onwindowscroll); const default_slot_template = ctx.$$slots.default; const default_slot = create_slot(default_slot_template, ctx, null); return { c() { div = element("div"); if (default_slot) default_slot.c(); attr(div, "class", div_class_value = "" + null_to_empty(ctx.headerClass) + " svelte-1ql6gaa"); dispose = listen(window, "scroll", () => { scrolling = true; clearTimeout(scrolling_timeout); scrolling_timeout = setTimeout(clear_scrolling, 100); ctx.onwindowscroll(); }); }, l(nodes) { if (default_slot) default_slot.l(div_nodes); }, m(target, anchor) { insert(target, div, anchor); if (default_slot) { default_slot.m(div, null); } action_action = ctx.action.call(null, div) || {}; current = true; }, p(changed, ctx) { if (changed.y && !scrolling) { scrolling = true; clearTimeout(scrolling_timeout); scrollTo(window.pageXOffset, ctx.y); scrolling_timeout = setTimeout(clear_scrolling, 100); } if (default_slot && default_slot.p && changed.$$scope) { default_slot.p( get_slot_changes(default_slot_template, ctx, changed, null), get_slot_context(default_slot_template, ctx, null) ); } if ((!current || changed.headerClass) && div_class_value !== (div_class_value = "" + null_to_empty(ctx.headerClass) + " svelte-1ql6gaa")) { attr(div, "class", div_class_value); } }, i(local) { if (current) return; transition_in(default_slot, local); current = true; }, o(local) { transition_out(default_slot, local); current = false; }, d(detaching) { if (detaching) { detach(div); } if (default_slot) default_slot.d(detaching); if (action_action && typeof action_action.destroy === 'function') action_action.destroy(); dispose(); } }; } let prefix = "svelte-headroom--"; function instance($$self, $$props, $$invalidate) { let { duration = "300ms", offset = 0, tolerance = 0 } = $$props; let headerClass = ""; let lastHeaderClass = ""; let y = 0; let lastY = 0; const dispatch = createEventDispatcher(); function deriveClass(y = 0, scrolled = 0) { if (y < offset) return ""; if (Math.abs(scrolled) < tolerance) return headerClass; if (scrolled > 0) return ""; if (scrolled < 0) return `${prefix}unpin`; return headerClass; } function updateClass(y = 0) { const scrolledPxs = lastY - y; const result = deriveClass(y, scrolledPxs); lastY = y; return result; } function action(node) { node.style.transitionDuration = duration; } let { $$slots = {}, $$scope } = $$props; function onwindowscroll() { y = window.pageYOffset; $$invalidate('y', y); } $$self.$set = $$props => { if ('duration' in $$props) $$invalidate('duration', duration = $$props.duration); if ('offset' in $$props) $$invalidate('offset', offset = $$props.offset); if ('tolerance' in $$props) $$invalidate('tolerance', tolerance = $$props.tolerance); if ('$$scope' in $$props) $$invalidate('$$scope', $$scope = $$props.$$scope); }; $$self.$$.update = ($$dirty = { duration: 1, offset: 1, tolerance: 1, y: 1, headerClass: 1, lastHeaderClass: 1 }) => { if ($$dirty.duration || $$dirty.offset || $$dirty.tolerance || $$dirty.y || $$dirty.headerClass || $$dirty.lastHeaderClass) { { validate({ duration, offset, tolerance }); $$invalidate('headerClass', headerClass = updateClass(y)); if (headerClass !== lastHeaderClass) { dispatch(headerClass ? "unpin" : "pin"); } $$invalidate('lastHeaderClass', lastHeaderClass = headerClass); } } }; return { duration, offset, tolerance, headerClass, y, action, onwindowscroll, $$slots, $$scope }; } class Index extends SvelteComponent { constructor(options) { super(); if (!document.getElementById("svelte-1ql6gaa-style")) add_css(); init(this, options, instance, create_fragment, safe_not_equal, ["duration", "offset", "tolerance"]); } } export default Index;