Skip to content

Commit

Permalink
with element size
Browse files Browse the repository at this point in the history
  • Loading branch information
tglide committed Mar 11, 2024
1 parent 6a1389d commit 30cb9b4
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/withrunes/src/lib/functions/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./withDebounce.svelte.js";
export * from "./withElementSize.svelte.js";
43 changes: 43 additions & 0 deletions packages/withrunes/src/lib/functions/withElementSize.svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { ValueOrGetter } from "$lib/internal/types.js";
import { boxed } from "$lib/internal/utils/boxed.svelte.js";

type Options = {
initialSize?: {
width: number;
height: number;
};
box?: "content-box" | "border-box";
};

export function withElementSize(
_node: ValueOrGetter<HTMLElement | undefined>,
options: Options = {
box: "border-box",
}
) {
const node = boxed(_node);
const size = $state({
width: options.initialSize?.width ?? 0,
height: options.initialSize?.height ?? 0,
});

$effect(() => {
if (!node.value) return;

const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const boxSize = options.box === "content-box" ? entry.contentBoxSize : entry.borderBoxSize;
const boxSizeArr = Array.isArray(boxSize) ? boxSize : [boxSize];
size.width = boxSizeArr.reduce((acc, size) => Math.max(acc, size.inlineSize), 0);
size.height = boxSizeArr.reduce((acc, size) => Math.max(acc, size.blockSize), 0);
}
});
observer.observe(node.value);

return () => {
observer.disconnect();
};
});

return size;
}
1 change: 1 addition & 0 deletions packages/withrunes/src/lib/internal/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type FunctionArgs<Args extends any[] = any[], Return = void> = (...args: Args) => Return;

export type Getter<T> = () => T;
export type ValueOrGetter<T> = T | (() => T);
10 changes: 10 additions & 0 deletions packages/withrunes/src/lib/internal/utils/boxed.svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { ValueOrGetter } from "../types.js";
import { isFunction } from "./is.js";

export function boxed<T>(value: ValueOrGetter<T>) {
return {
get value() {
return isFunction(value) ? value() : value;
},
};
}
3 changes: 3 additions & 0 deletions packages/withrunes/src/lib/internal/utils/is.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isFunction(value: unknown): value is (...args: unknown[]) => unknown {
return typeof value === "function";
}
44 changes: 44 additions & 0 deletions sites/docs/content/functions/with-element-size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: WithElementSize
description: A higher-order function that debounces the execution of a function.
---

<script>
import { WithElementSizeDemo } from '$lib/components/demos';
</script>

## Demo

<WithElementSizeDemo />

## Usage

```svelte
<script lang="ts">
import { withElementSize } from "withrunes";
let count = $state(0);
let logged = $state("");
let isFirstTime = $state(true);
const logCount = withElementSize(() => {
if (isFirstTime) {
isFirstTime = false;
logged = `You pressed the button ${count} times!`;
} else {
logged = `You pressed the button ${count} times since last time!`;
}
count = 0;
}, 1000);
function ding() {
count++;
logCount();
}
</script>
<div>
<button onclick={ding}>DING DING DING</button>
<p>{logged || "Press the button!"}</p>
</div>
```
1 change: 1 addition & 0 deletions sites/docs/src/lib/components/demos/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as WithDebounceDemo } from "./with-debounce.svelte";
export { default as WithElementSizeDemo } from "./with-element-size.svelte";
15 changes: 15 additions & 0 deletions sites/docs/src/lib/components/demos/with-element-size.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts">
import { withElementSize } from "withrunes";
let el: HTMLElement | undefined = $state(undefined);
const size = withElementSize(() => el);
const text = $derived(`Width: ${size.width}\nHeight: ${size.height}`);
</script>

<div class="bg-card rounded-md p-8">
<textarea
bind:this={el}
class="h-[200px] min-h-[100px] w-[300px] min-w-[200px] resize rounded-md bg-neutral-800 p-4"
value={text}
/>
</div>
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 @@ -66,6 +66,11 @@ export const navigation: Navigation = {
href: "/docs/functions/with-debounce",
items: [],
},
{
title: "withElementSize",
href: "/docs/functions/with-element-size",
items: [],
},
],
},
],
Expand Down

0 comments on commit 30cb9b4

Please sign in to comment.