Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/clipboard-solid-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@solid-primitives/clipboard": major
---

Upgrade to Solid 2.0 (`solid-js@^2.0.0-beta.7`).

**`createClipboard`** — replaced `createResource` with a Solid 2.0 async `createMemo`. The accessor starts as `[]` synchronously (no initial suspension) and resolves asynchronously after `refetch()`. Use `isPending(() => clipboard())` for a loading indicator instead of `<Suspense>`.

**`copyToClipboard`** — converted from a `use:` directive to a `ref` directive factory. Replace `use:copyToClipboard={opts}` with `ref={copyToClipboard(opts)}`.

**`isServer`** — moved from `solid-js/web` to `@solidjs/web` in Solid 2.0; the package now imports from `@solidjs/web`.

**`createEffect` + `on`** — `on` helper removed; replaced with the Solid 2.0 split `createEffect(compute, effect)` form with explicit defer-by-default behavior.
14 changes: 14 additions & 0 deletions packages/clipboard/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# @solid-primitives/clipboard

## 2.0.0-beta.0

### Major Changes

- Upgrade to Solid 2.0 (`solid-js@^2.0.0-beta.7`).

**`createClipboard`** — replaced `createResource` with a Solid 2.0 async `createMemo`. The accessor returns `[]` synchronously on first access (no suspension) and resolves asynchronously after `refetch()`. Use `isPending(() => clipboard())` for a loading indicator instead of `<Suspense>`.

**`copyToClipboard`** — converted from a `use:` directive to a `ref` directive factory. Replace `use:copyToClipboard={opts}` with `ref={copyToClipboard(opts)}`.

**`isServer`** — moved from `solid-js/web` to `@solidjs/web` in Solid 2.0; the source now imports from `@solidjs/web`.

**`createEffect` with `on`** — `on` helper removed; replaced with the Solid 2.0 split `createEffect(compute, effect)` form plus an explicit `skip` flag to preserve the `defer: true` default.

## 1.6.4

### Patch Changes
Expand Down
134 changes: 63 additions & 71 deletions packages/clipboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,41 @@
[![size](https://img.shields.io/npm/v/@solid-primitives/clipboard?style=for-the-badge)](https://www.npmjs.com/package/@solid-primitives/clipboard)
[![stage](https://img.shields.io/endpoint?style=for-the-badge&url=https%3A%2F%2Fraw.githubusercontent.com%2Fsolidjs-community%2Fsolid-primitives%2Fmain%2Fassets%2Fbadges%2Fstage-3.json)](https://github.com/solidjs-community/solid-primitives#contribution-process)

This primitive is designed to that make reading and writing to [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) easy. It also comes with a convenient directive to write to clipboard.
Primitives for reading and writing to the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API).

- [`readClipboard`](#readclipboard) - A basic non-reactive primitive that makes accessing the clipboard easy.
- [`writeClipboard`](#writeclipboard) - A basic non-reactive primitive that makes writing to the clipboard easy.
- [`createClipboard`](#createclipboard) - This primitive provides full facilities for reading and writing to the clipboard. It allows for writing to clipboard via exported function or input signal. It wraps the Clipboard Async API with a resource and supplies reactive helpers to make pulling from the clipboard easy.
- [`copyToClipboard`](#copytoclipboard) - convenient directive for setting the clipboard value.
- [`readClipboard`](#readclipboard) - One-shot async read of clipboard items.
- [`writeClipboard`](#writeclipboard) - One-shot async write to the clipboard.
- [`createClipboard`](#createclipboard) - Reactive clipboard backed by an async memo. Reads on demand, writes reactively from a signal.
- [`copyToClipboard`](#copytoclipboard) - `ref` directive factory that copies an element's value to clipboard on click.

## Installation

```bash
npm install @solid-primitives/clipboard
# or
yarn add @solid-primitives/clipboard
# or
pnpm add @solid-primitives/clipboard
```

## `readClipboard`

A basic non-reactive primitive that makes accessing the clipboard easy. Note that write supports both string and ClipboardItems object structure.

### How to use it
One-shot async read that returns a `Promise<ClipboardItem[]>`.

```ts
import { readClipboard } from "@solid-primitives/clipboard";

const clipboard = await readClipboard();

clipboard.forEach(item => {
if (item.type == "text/plain") {
console.log(item.text());
}
});
const items = await readClipboard();
```

## `writeClipboard`

A basic non-reactive primitive that makes writing to the clipboard easy. Note that write supports both string and ClipboardItems object structure.

### How to use it
One-shot async write. Accepts a string or `ClipboardItem[]`.

```ts
import { writeClipboard } from "@solid-primitives/clipboard";

writeClipboard("Hello World");
await writeClipboard("Hello World");

// or

writeClipboard([
await writeClipboard([
new ClipboardItem({
"text/plain": new Blob(["Hello World"], { type: "text/plain" }),
}),
Expand All @@ -65,86 +51,92 @@ writeClipboard([

## `createClipboard`

This primitive provides full facilities for reading and writing to the clipboard. It allows for writing to clipboard via exported function or input signal. It wraps the Clipboard Async API with a resource and supplies reactive helpers to make pulling from the clipboard easy.
Reactive primitive backed by a Solid 2.0 async memo.

### How to use it
```ts
const [clipboard, refetch, write] = createClipboard(optionalSignal?, deferInitial?);
```

- `clipboard()` — `Accessor<ClipboardResourceItem[]>`. Starts as `[]` synchronously (no initial suspension). After `refetch()`, resolves asynchronously; the previous value stays visible while pending.
- `refetch()` — trigger a fresh clipboard read.
- `write` — same as `writeClipboard`.

Automatically calls `refetch()` on the native `clipboardchange` event.

When an optional data signal is passed, its value is written to the clipboard on every change. The initial write is deferred by default (`deferInitial` defaults to `true`).

```tsx
import { createSignal } from "solid-js";
import { createClipboard } from "@solid-primitives/clipboard";

const [data, setData] = createSignal("Hello");
const [clipboard, refresh] = createClipboard(data); // will write "Hello" to clipboard
const [clipboard, refetch] = createClipboard(data);

setData("foobar"); // will write "foobar" to clipboard
setData("World"); // writes "World" to clipboard

refresh(); // will read from clipboard and update clipboard() signal
refetch(); // reads clipboard into clipboard()

return (
<Suspense fallback={"Loading..."}>
<For each={clipboard()}>
{item => (
<Switch>
<Match when={item.type == "text/plain"}>{item.text}</Match>
<Match when={item.type == "image/png"}>
<img class="w-full" src={URL.createObjectURL(item.blob)} />
</Match>
</Switch>
)}
</For>
</Suspense>
<For each={clipboard()}>
{item => (
<Switch>
<Match when={item.type === "text/plain"}>{item.text}</Match>
<Match when={item.type === "image/png"}>
<img src={URL.createObjectURL(item.blob)} />
</Match>
</Switch>
)}
</For>
);
```

Note: The primitive binds and listens for `clipboardchange` meaning that clipboard changes should automatically propagate. The implementation however is buggy on certain browsers.
No `<Suspense>` needed — `clipboard()` never suspends before the first `refetch()`. If you want a loading indicator during a read, use `isPending`:

```tsx
import { isPending } from "solid-js";

<p>{isPending(() => clipboard()) ? "Reading…" : `${clipboard().length} items`}</p>
```

## `copyToClipboard`

You can also use clipboard as a convenient directive for setting the clipboard value. You can override the default value and the setter with the options parameter.
A `ref` directive factory that writes an element's value to clipboard on click. On `<input>`/`<textarea>` elements it captures `.value`; on any other element it captures `.innerHTML`. Both can be overridden via `options.value`.

```ts
```tsx
import { copyToClipboard } from "@solid-primitives/clipboard";
<input type="text" use:copyToClipboard />;
```

### Definition
// Copies input value on click
<input type="text" ref={copyToClipboard()} />

```ts
function copyToClipboard(
el: Element,
options: MaybeAccessor<{
value?: any;
setter?: ClipboardSetter;
highlight?: HighlightModifier;
}>,
);
```
// With explicit value
<button ref={copyToClipboard({ value: "copy me" })}>Copy</button>

### Highlighters/Range Selection
// With reactive options
<button ref={copyToClipboard(() => ({ value: text() }))}>Copy</button>
```

In some scenarios you'll want to highlight or select a range of text. copyToClipboard has an option to specify the type of highlighting you'd like. Use either `input` or `element` based on the type you're making selectable.
### Highlighters / range selection

```tsx
import { copyToClipboard, input, element } from "@solid-primitives/clipboard";
<input type="text" use:copyToClipboard={{ highlight: input() }} />;
<div use:copyToClipboard={{ highlight: element(5, 10) }} />;

<input type="text" ref={copyToClipboard({ highlight: input() })} />
<div ref={copyToClipboard({ highlight: element(5, 10) })} />
```

## `newItem`
## `newClipboardItem`

This package ships with newItem which is a helper method for creating new ClipboardItem types.
Helper for creating `ClipboardItem` objects. `newItem` is a deprecated alias.

```ts
import { newItem } from "@solid-primitives/clipboard";
write([newItem("image/png", await image.blob())]);
```

### Definition
import { newClipboardItem } from "@solid-primitives/clipboard";

```ts
function newItem(type: string, data: ClipboardItemData): ClipboardItem;
writeClipboard([newClipboardItem("image/png", await image.blob())]);
```

## Demo

You may view a working example in [the /dev playground](./dev/index.tsx) deplayed on [primitives.solidjs.community/playground/clipboard](https://primitives.solidjs.community/playground/clipboard/)
You may view a working example in [the /dev playground](./dev/index.tsx) deployed on [primitives.solidjs.community/playground/clipboard](https://primitives.solidjs.community/playground/clipboard/).

## Changelog

Expand Down
8 changes: 5 additions & 3 deletions packages/clipboard/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@solid-primitives/clipboard",
"version": "1.6.4",
"version": "2.0.0-beta.0",
"description": "Primitives for reading and writing to clipboard.",
"author": "David Di Biase <dave@solidjs.com>",
"contributors": [
Expand Down Expand Up @@ -59,10 +59,12 @@
"@solid-primitives/utils": "workspace:^"
},
"peerDependencies": {
"solid-js": "^1.6.12"
"@solidjs/web": "^2.0.0-beta.7",
"solid-js": "^2.0.0-beta.7"
},
"typesVersions": {},
"devDependencies": {
"solid-js": "^1.9.7"
"@solidjs/web": "2.0.0-beta.7",
"solid-js": "2.0.0-beta.7"
}
}
Loading
Loading