npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@teamleaf-js/medialibrary-ui

v0.1.3

Published

<p align="center"> <a href="https://senses.co.uk" target="_blank"> <img src="https://github.com/Senses-Web-Solutions/meta/blob/main/art/senses-logo.png?raw=true"> </a> </p>

Downloads

3

Readme

senses-medialibrary-ui

A cross-project frontend for media library UI.

Usage

MediaLibrary.vue is the main component. An example is viewable in App.vue.

The Media Library requires a few props to function:

Url

Required

Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.

The url function generates the URL that the media library will use to retrieve files from your API.

The URL should be returned as a string. The function is passed the previousResponse (can be null), sort as a string and filters as an object.

You can use this information to manipulate the URL. If sort or filters are updated, the media library will perform a fresh load.

Note: Your API response should return your files in an object with a data key. The Laravel paginator already does this.

Example url function

const url = (previousResponse = null, sort = null, filters = null) => {
    // If the previous response is not set, we're on the first page. Supply a base URL.
    // Otherwise, use the next_page_url from the past response.
    const baseUrl = previousResponse ? previousResponse.next_page_url : 'http://teamleaf.harry/api/v2/files-test';
    const urlOb = new URL(baseUrl);

    // Set the sort param in the URL
    urlOb.searchParams.set('sort', sort);

    if (filters) {
        // Loop through the filter groups
        Object.keys(filters).forEach((filterGroupKey) => {
            const selectedValues = [];
            const filterGroupValues = filters[filterGroupKey];
            // Loop through the values in the filter groups
            Object.keys(filterGroupValues).forEach((filterKey) => {
                if (filterGroupValues[filterKey]) {
                    selectedValues.push(filterKey);
                }
            });
            // Set the URL
            if (selectedValues.length) {
                urlOb.searchParams.set(`filter[${filterGroupKey}]`, selectedValues.join(','));
            } else {
                urlOb.searchParams.delete(`filter[${filterGroupKey}]`);
            }
        });
    }

    // Return the URL as a string.
    return urlOb.toString();
};

Filters

Required

This prop provides the data to generate the filter options in the sidebar.

The below code will create filters that look like this:

Type

[] PDF

[] DOC

[] IMG

const filters = [
    {
        title: 'Type',
        key: 'service_type_id',
        options: {
            pdf: 'PDF',
            doc: 'DOC',
            img: 'IMG',
        },
    },
]

Upload

Required

Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.

This prop is a function that allows you to handle file uploads. The file will be supplied as the first (and only) param.

The function must return a promise.

const upload = (file) => {
    const formData = new FormData();
    formData.set('file', file);
    return axios.post('/api/v2/files', formData); // returns a Promise
};

Map

Optional

Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.

The map function handles mapping each individual file to a format the media library is able to use.

The required format is:

interface File {
    name: string;
    size: number; // in Megabytes
    created_at: string; // Format doesn't matter. Provide it in a nice display format.
    preview_url: string; // A thumbnail size image.
    download_url: string; // The full size file
    extension: string; // the file extension (png/jpg/pdf etc)
    creator: {
        full_name: string;
    }
}

Example:

const map = (file) => {
    file.size /= 1000000; // mb
    file.created_at = format(
        parse(file.created_at, 'yyyy-MM-dd HH:mm:ss', new Date()),
        'dd/MM/yyyy'
    );
    return file;
};

Axios

Optional

Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.

You can optionally pass in an instance of axios which can be preconfigured to work with your API's authentication. The media library will use that instance rather than the default axios instance.

Slots

Info

The info slot allows you to display more information about a file below its attributes. This is good for custom data.

The file will be passed as a slot prop. As well as close, which is a function you can call to close the modal.

Form

The form slot allows you to add an edit form to the media library. You need to register a callback to tell the media library that you're done updating, as well as register a hook to fire your save event when the media library's save button is clicked.

<!-- Inside <MediaLibrary> -->
<template #form="{ file, close, onSave, afterSave }">
    <file-form :file="file" :close="close" :on-save="onSave" :after-save="afterSave" />
</template>

<!-- Inside <FileForm> -->
<script>
props: {
    onSave: {
        type: Function,
        required: true
    },
    afterSave: {
        type: Function,
        required: true
    }
}
mounted() {
    // ...
    // The media library will call your submit function
    // when the user hits the save button.
    this.onSave(this.submit)
},
methods: {
    submit() {
        axios.post(/*..*/, { /*...*/ }).then(() => {
            // Return the modified version of the file back
            // to the media library.
            this.afterSave(file);
        })
    }
},

</script>

unplugin

This package is using unplugin auto import for both Vue components and certain js libraries, just means you don't have to import Vue components, Vue functions or @vueuse/core functions directly, it'll be done for you. Configurable in vite.config.js. Installed purely for speed of development.

It won't affect usage.