Skip to content

Commit

Permalink
feat: useSupported (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte authored Apr 26, 2024
1 parent 70e5289 commit c9c375a
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/tricky-suns-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"runed": minor
---

feat: `useSupported`
1 change: 1 addition & 0 deletions packages/runed/src/lib/functions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./useDebounce/index.js";
export * from "./useElementSize/index.js";
export * from "./useEventListener/index.js";
export * from "./useMounted/index.js";
export * from "./useSupported/index.js";
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { type ReadableBox, box } from "../box/box.svelte.js";
import { isBrowser } from "$lib/internal/utils/browser.js";

/**
* Returns a reactive value that is equal to `document.activeElement`.
* It automatically listens for changes, keeping the reference up to date.
*
* @returns an object with a reactive value `value` that is equal to `document.activeElement`, or `null`
* if there's no active element.
* @returns an object with a reactive value `value` that is equal to `document.activeElement`,
* or `null` if there's no active element.
*/
export function useActiveElement(): { value: Readonly<Element | null> } {
const activeElement = $state({ value: isBrowser() ? document.activeElement : null });
export function useActiveElement(): ReadableBox<Element | null> {
const activeElement = box(isBrowser() ? document.activeElement : null);

function onFocusChange() {
activeElement.value = document.activeElement;
Expand All @@ -24,5 +25,5 @@ export function useActiveElement(): { value: Readonly<Element | null> } {
};
});

return activeElement;
return box.readonly(activeElement);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { box } from "../box/box.svelte.js";
import type { MaybeBoxOrGetter } from "$lib/internal/types.js";

type Options = {
export type UseElementSizeOptions = {
initialSize?: {
width: number;
height: number;
Expand All @@ -20,7 +20,7 @@ type Options = {
*/
export function useElementSize(
_node: MaybeBoxOrGetter<HTMLElement | undefined>,
options: Options = {
options: UseElementSizeOptions = {
box: "border-box",
}
): { width: number; height: number } {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export function useMounted(): ReadableBox<boolean> {

$effect(() => {
untrack(() => (isMounted.value = true));

return () => {
isMounted.value = false;
};
});

return box.readonly(isMounted);
Expand Down
1 change: 1 addition & 0 deletions packages/runed/src/lib/functions/useSupported/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./useSupported.svelte.js";
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { type ReadableBox, box } from "../box/box.svelte.js";

/**
* A hook that takes a predicate determine if a browser API is supported.
*
* Useful for checking if a browser API is supported before attempting to use it.
*
* @example
* ```ts
* const isSupported = useSupported(() => navigator);
*
* if (isSupported) {
* // do something with navigator
* }
* ```
*/
export function useSupported(predicate: () => unknown): ReadableBox<boolean> {
const isSupported = box(false);

$effect(() => {
isSupported.value = Boolean(predicate());
});

return box.readonly(isSupported);
}
18 changes: 18 additions & 0 deletions sites/docs/content/functions/use-supported.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: useSupported
description: Determine if a feature is supported by the environment before using it.
---

## Usage

```svelte
<script lang="ts">
import { useSupported } from "runed";
const isSupported = useSupported(() => navigator && "geolocation" in navigator);
if (isSupported.value) {
// Do something with the geolocation API
}
</script>
```
18 changes: 17 additions & 1 deletion sites/docs/mdsx.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const prettyCodeOptions = {

export const mdsxConfig = defineConfig({
extensions: [".md"],
remarkPlugins: [remarkGfm, remarkRemovePrettierIgnore],
remarkPlugins: [remarkGfm, remarkRemovePrettierIgnore, remarkTabsToSpaces],
rehypePlugins: [[rehypePrettyCode, prettyCodeOptions], rehypeHandleMetadata, rehypeSlug],
blueprints: {
default: {
Expand Down Expand Up @@ -100,6 +100,22 @@ function remarkRemovePrettierIgnore() {
};
}

/**
* Converts tabs to spaces in code blocks to fit more into the viewport.
*
* @returns {MdastTransformer} - A unified transformer
*
*/
function remarkTabsToSpaces() {
return async (tree) => {
visit(tree, "code", (node) => {
node.value = node.value
// @ts-expect-error - not dealing with this rn
.replaceAll("\t", " ");
});
};
}

/**
* Adds `data-metadata` to `<figure>` elements that contain a `<figcaption>`.
* We use this to style elements within the `<figure>` differently if a `<figcaption>`
Expand Down
5 changes: 5 additions & 0 deletions sites/docs/src/lib/config/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ export const navigation: Navigation = {
href: "/docs/functions/use-mounted",
items: [],
},
{
title: "useSupported",
href: "/docs/functions/use-supported",
items: [],
},
],
},
],
Expand Down

0 comments on commit c9c375a

Please sign in to comment.