Skip to content

Commit

Permalink
feat(core): added createObjectUrl utility
Browse files Browse the repository at this point in the history
  • Loading branch information
novaotp committed Feb 11, 2025
1 parent 91e14d0 commit 54e95cc
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sv-use/core",
"version": "1.14.0",
"version": "1.15.0",
"license": "MIT",
"description": "A collection of Svelte 5 utilities.",
"main": "./dist/index.js",
Expand Down
42 changes: 42 additions & 0 deletions packages/core/src/create-object-url/index.svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { normalizeValue } from '../__internal__/utils.svelte.js';
import type { CleanupFunction, MaybeGetter } from '../__internal__/types.js';

type CreateObjectUrlReturn = {
readonly current: string | null;
cleanup: CleanupFunction;
};

/**
* Creates a reactive URL representing the given object.
* @param object The object to generate the url for.
* @see https://svelte-librarian.github.io/sv-use/docs/create-object-url
*/
export function createObjectUrl(
object: MaybeGetter<Blob | MediaSource | null | undefined>
): CreateObjectUrlReturn {
let current = $state<string | null>(null);
const _object = $derived(normalizeValue(object));

$effect(() => {
if (_object) {
current = URL.createObjectURL(_object);
}

return cleanup;
});

function cleanup() {
if (current) {
URL.revokeObjectURL(current);
}

current = null;
}

return {
get current() {
return current;
},
cleanup
};
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './auto-reset-state/index.svelte.js';
export * from './create-drop-zone/index.svelte.js';
export * from './create-eye-dropper/index.svelte.js';
export * from './create-file-dialog/index.svelte.js';
export * from './create-object-url/index.svelte.js';
export * from './create-share/index.svelte.js';
export * from './create-speech-recognition/index.svelte.js';
export * from './create-vibration/index.svelte.js';
Expand Down
25 changes: 25 additions & 0 deletions packages/website/src/lib/docs/core/create-object-url/Demo.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script lang="ts">
import { createObjectUrl } from '$sv-use/core';
let file = $state<File | null>(null);
const url = createObjectUrl(() => file);
function onFileChange(event: Event & { currentTarget: EventTarget & HTMLInputElement }) {
file = event.currentTarget.files?.[0] ?? null;
}
</script>

<div class="relative flex w-full flex-col gap-2">
<p class="text-sm text-zinc-500 dark:text-zinc-400">Select file :</p>
<input type="file" onchange={onFileChange} class="dark:text-zinc-200" />
<p class="text-sm text-zinc-500 dark:text-zinc-400">Object URL :</p>
<code>
{#if url.current}
<a href={url.current} target="_blank" class="text-svelte dark:text-darksvelte underline">
{url.current}
</a>
{:else}
<p class="dark:text-zinc-200">none</p>
{/if}
</code>
</div>
30 changes: 30 additions & 0 deletions packages/website/src/lib/docs/core/create-object-url/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
category: browser
---

# createObjectUrl

Creates a reactive URL representing the given object.

Automatically releases the URL when the object changes or the component is
unmounted.

## Usage

> [!NOTE]
> It uses `$effect`.
```svelte
<script lang="ts">
import { createObjectUrl } from '@sv-use/core';
// Get a file in some way
// e.g. a dropzone, a cdn, etc.
const file = $state<File | null>(null);
const url = createObjectUrl(() => file);
</script>
<a href={url.current} download>
Upload file
</a>
```

0 comments on commit 54e95cc

Please sign in to comment.