@wcstack/clipboard 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md ADDED
@@ -0,0 +1,203 @@
1
+ # @wcstack/clipboard
2
+
3
+ `@wcstack/clipboard` は wcstack エコシステム向けのヘッドレスなクリップボードコンポーネントです。
4
+
5
+ これは視覚的な UI ウィジェットではありません。
6
+ `@wcstack/fetch` がネットワークリクエストをリアクティブな状態に変え、`@wcstack/geolocation` がデバイスの位置情報をリアクティブな状態に変えるのと同じように、**クリップボードへのアクセスをリアクティブな状態に変える非同期プリミティブノード**です。
7
+
8
+ 位置情報(読み取り専用センサ)と異なり、クリップボードは**双方向**です。そのため `<wcs-clipboard>` は wc-bindable トークンプロトコルの両方向のショーケースになっています。
9
+
10
+ - **write**(`state → element`)— command-token プロトコル経由(`command.writeText: $command.copy`)
11
+ - **read**(`element → state`)— コマンド結果経由。加えて、ユーザーの `copy` / `cut` / `paste` を event-token プロトコルで再発行する monitor モード(`eventToken.pasted: clipboardPasted`)
12
+
13
+ `@wcstack/state` と組み合わせると、`<wcs-clipboard>` はパス契約を通じて直接バインドできます。
14
+
15
+ - **入力面**: `monitor`
16
+ - **コマンド面**: `writeText`, `write`, `readText`, `read`, `startMonitor`, `stopMonitor`
17
+ - **出力状態面**: `text`, `items`, `loading`, `error`, `readPermission`, `writePermission`, `monitoring`, `copied`, `cut`, `pasted`
18
+
19
+ つまり、クリップボードを扱う処理を HTML 上で宣言的に表現でき、UI 層に `navigator.clipboard.writeText()` / `readText()` / `read()`、イベントリスナ、後始末のグルーコードを書く必要がありません。
20
+
21
+ `@wcstack/clipboard` は [CSBC](https://github.com/csbc-dev/arch/blob/main/README.md)(Core / Shell / Binding Contract)アーキテクチャに従います。
22
+
23
+ - **Core**(`ClipboardCore`)が read/write、リッチな `ClipboardItem` の正規化、エラー処理、monitor の購読、パーミッションのライブ追跡を担当
24
+ - **Shell**(`<wcs-clipboard>`)がその状態を DOM 属性・ライフサイクル・宣言的コマンドに接続
25
+ - **Binding Contract**(`static wcBindable`)が観測可能な `properties`・書き込み可能な `inputs`・呼び出し可能な `commands` を宣言
26
+
27
+ ## なぜ存在するのか
28
+
29
+ Clipboard API は `fetch` と同様、値を非同期に生み出すソースですが、加えて**双方向**(read *かつ* write)であり、**2 つの独立したパーミッション**(`clipboard-read` / `clipboard-write`)でゲートされています。命令的に書くと、ジェスチャに紐づく呼び出し・パーミッション照会・イベント配線・切断時の後始末が必要になります。
30
+
31
+ `@wcstack/clipboard` はそのロジックを再利用可能なコンポーネントに押し込み、結果をバインド可能な状態として公開します。コピーやペーストが命令的なコールバック配線ではなく、**状態遷移**になります。
32
+
33
+ > **セキュアコンテキスト + ユーザージェスチャが必須。** Clipboard API はセキュアコンテキスト(HTTPS、または `localhost`)でのみ動作します。書き込み(`writeText` / `write`)には一時的なアクティベーション(transient activation)が必要なので、クリックハンドラやユーザー操作に配線した command-token から呼び出してください。読み取り(`readText` / `read`)にはフォーカスと読み取りパーミッションが必要です。`navigator.clipboard` が存在しない場合(非セキュアコンテキストや非対応ブラウザ)、コマンドは throw せず `error` プロパティを通じて `NotSupportedError` を表面化します。Firefox はクリップボードのパーミッション名を公開しないため、そこでは `readPermission` / `writePermission` は `"unsupported"` にフォールバックします。
34
+
35
+ ## インストール
36
+
37
+ ```bash
38
+ npm install @wcstack/clipboard
39
+ ```
40
+
41
+ ## クイックスタート
42
+
43
+ ### 1. テキストをコピー(write)
44
+
45
+ 書き込みにはユーザージェスチャが必要なので、DOM クリック(autoTrigger)または command-token から起動します。
46
+
47
+ ```html
48
+ <script type="module" src="https://esm.run/@wcstack/state/auto"></script>
49
+ <script type="module" src="https://esm.run/@wcstack/clipboard/auto"></script>
50
+
51
+ <wcs-clipboard id="cb"></wcs-clipboard>
52
+
53
+ <!-- 任意の DOM トリガ: クリックでリテラルテキストをコピー -->
54
+ <input id="token" value="abc-123" readonly />
55
+ <button data-clipboardtarget="cb" data-clipboard-from="#token">Copy</button>
56
+ <button data-clipboardtarget="cb" data-clipboard-text="Hello!">Copy greeting</button>
57
+ ```
58
+
59
+ `data-clipboard-text` はリテラル文字列をコピーします。`data-clipboard-from` はセレクタにマッチした要素の `value`(なければ `textContent`)をコピーします。
60
+
61
+ ### 2. 状態からコピー(command-token)
62
+
63
+ ```html
64
+ <wcs-state>
65
+ <script type="module">
66
+ export default {
67
+ message: "Shareable link",
68
+ $commandTokens: ["copy"],
69
+ onShare() { this.$command.copy.emit(this.message); }
70
+ };
71
+ </script>
72
+ </wcs-state>
73
+
74
+ <wcs-clipboard data-wcs="command.writeText: $command.copy"></wcs-clipboard>
75
+ <button data-wcs="onclick: onShare">Share</button>
76
+ ```
77
+
78
+ ### 3. テキストを読み取り(command-token で readText を起動)
79
+
80
+ DOM の autoTrigger は書き込み(`writeText`)のみを起動します。読み取りを起動する DOM トリガ経路はありません。読み取りは command-token、または要素への命令的な `readText()` / `read()` 呼び出しで起動してください。
81
+
82
+ ```html
83
+ <wcs-state>
84
+ <script type="module">
85
+ export default {
86
+ pasted: "",
87
+ busy: false,
88
+ $commandTokens: ["paste"],
89
+ onPaste() { this.$command.paste.emit(); }
90
+ };
91
+ </script>
92
+ </wcs-state>
93
+
94
+ <wcs-clipboard
95
+ data-wcs="command.readText: $command.paste; text: pasted; loading: busy"></wcs-clipboard>
96
+ <button data-wcs="onclick: onPaste">Paste</button>
97
+ <p data-wcs="textContent: pasted"></p>
98
+ ```
99
+
100
+ > 読み取りにはフォーカスと読み取りパーミッションが必要で、ブラウザが許可を求めることがあります。拒否された読み取りを扱うには `error` をバインドしてください。
101
+
102
+ ### 4. ユーザーのクリップボード操作を監視(event-token)
103
+
104
+ `monitor` 属性を付けると、ドキュメントの `copy` / `cut` / `paste` をリアクティブな状態として再発行します。
105
+
106
+ ```html
107
+ <wcs-state>
108
+ <script type="module">
109
+ export default {
110
+ lastPaste: "",
111
+ $eventTokens: ["clipboardPasted"],
112
+ $on: {
113
+ clipboardPasted: (state, event) => { state.lastPaste = event.detail; }
114
+ }
115
+ };
116
+ </script>
117
+ </wcs-state>
118
+
119
+ <wcs-clipboard monitor
120
+ data-wcs="pasted: lastPaste; eventToken.pasted: clipboardPasted"></wcs-clipboard>
121
+ ```
122
+
123
+ ## 属性 / 入力(Attributes / Inputs)
124
+
125
+ | 属性 | 型 | 既定値 | 説明 |
126
+ | --------- | ------- | ------- | --------------------------------------------------------------------------- |
127
+ | `monitor` | boolean | `false` | 接続時にドキュメントの `copy` / `cut` / `paste` を購読し、`copied` / `cut` / `pasted` として再発行する。 |
128
+
129
+ ### DOM トリガ属性(autoTrigger、クリックでコピー)
130
+
131
+ | 属性 | 付与先 | 説明 |
132
+ | --------------------- | -------------- | ---------------------------------------------------------------------- |
133
+ | `data-clipboardtarget`| トリガボタン | 駆動する `<wcs-clipboard>` の id。 |
134
+ | `data-clipboard-text` | トリガボタン | コピーするリテラルテキスト(優先される。空文字列も有効)。 |
135
+ | `data-clipboard-from` | トリガボタン | CSS セレクタ。マッチした要素の `value`(なければ `textContent`)をコピー。 |
136
+
137
+ > DOM トリガは**書き込み専用**です。クリックは常に `writeText` を起動し、読み取り(`readText` / `read`)を起動する経路はありません。読み取りは command-token または命令的呼び出しで起動してください。
138
+
139
+ > DOM トリガによる `writeText` は fire-and-forget(`Promise` を await しません)ですが、決して reject しません。コピー失敗は他の書き込みと同様 `error` プロパティに現れます。autoTrigger の失敗を観測するには `error` をバインドしてください(例: `text: error.message@cb`)。
140
+
141
+ ## 観測可能なプロパティ(出力)
142
+
143
+ | プロパティ | イベント | 説明 |
144
+ | ----------------- | ----------------------------------------- | --------------------------------------------------------------------- |
145
+ | `text` | `wcs-clipboard:read` | 直近の `readText()` / `read()` のプレーンテキスト(なければ `null`)。 |
146
+ | `items` | `wcs-clipboard:read` | `read()` から正規化した `ClipboardItem` スナップショット(`{ types, data }[]`)、なければ `null`。 |
147
+ | `loading` | `wcs-clipboard:loading-changed` | 非同期の read/write 中は `true`。 |
148
+ | `error` | `wcs-clipboard:error` | 正規化された `{ name, message }`(例: `NotAllowedError`, `NotSupportedError`)。 |
149
+ | `readPermission` | `wcs-clipboard:read-permission-changed` | `clipboard-read` の `"prompt"` / `"granted"` / `"denied"` / `"unsupported"`。 |
150
+ | `writePermission` | `wcs-clipboard:write-permission-changed` | `clipboard-write` について同様の状態。 |
151
+ | `monitoring` | `wcs-clipboard:monitoring-changed` | ドキュメントのクリップボードイベントを監視中は `true`。 |
152
+ | `copied` | `wcs-clipboard:copied` | 直近に監視した `copy` のテキスト(選択範囲から取得)。 |
153
+ | `cut` | `wcs-clipboard:cut` | 直近に監視した `cut` のテキスト。 |
154
+ | `pasted` | `wcs-clipboard:pasted` | 直近に監視した `paste` の `text/plain`。 |
155
+
156
+ ## コマンド
157
+
158
+ | コマンド | 説明 |
159
+ | -------------- | ------------------------------------------------------------------------- |
160
+ | `writeText` | クリップボードに文字列を書き込む(非同期。reject しない — 失敗は `error` へ)。ユーザージェスチャが必要。 |
161
+ | `write` | `ClipboardItem[]`(画像・HTML・複数 MIME タイプ)を書き込む(非同期)。 |
162
+ | `readText` | プレーンテキストを読み取り、`text` と `wcs-clipboard:read` を発行(非同期)。 |
163
+ | `read` | リッチな `ClipboardItem` を読み取り、各表現を `Blob` に解決する(非同期)。 |
164
+ | `startMonitor` | ドキュメントの `copy` / `cut` / `paste` の監視を開始(既に監視中なら no-op)。 |
165
+ | `stopMonitor` | 監視を停止。`monitoring` が `false` になる。 |
166
+
167
+ 状態からの起動には command-token プロトコルを使います。
168
+
169
+ ```html
170
+ <wcs-clipboard data-wcs="command.writeText: $command.copy"></wcs-clipboard>
171
+ ```
172
+
173
+ ## 注意点と制約
174
+
175
+ - **属性は接続時に読み取られ、監視されない。** `<wcs-clipboard>` は `observedAttributes` / `attributeChangedCallback` を実装していません。`monitor` 属性は要素の接続時に読み取られます。接続*後*に命令的にトグルしても、それだけでは監視は開始/停止しません。`startMonitor()` / `stopMonitor()` を呼ぶか、要素を再接続してください。
176
+ - **接続時の読み取りは無い。** `<wcs-geo>` と異なり、クリップボードは接続時に自動読み取りできません(読み取りにはユーザージェスチャとパーミッションが必要)。そのため `connectedCallbackPromise` / SSR スナップショットはありません。接続時の唯一のアクションは任意の監視です。
177
+ - **再接続で再購読する。** 要素を削除して再挿入すると `connectedCallback` が再度実行されるため、パーミッション追跡が復活し、`monitor` 属性を持つ要素は監視を再開します(切断時に解体するのと対称です)。監視の永続性は**属性駆動のみ**です。`monitor` 属性*なし*の要素で `startMonitor()` を使って命令的に監視を開始した場合、再接続では復元されません(属性が真実の源)。リペアレント間で監視を永続させたい場合は `monitor` 属性を付けてください。
178
+ - **`copy` / `cut` のテキストは選択範囲から取得する。** `copy` / `cut` イベント中はクリップボードのペイロードがまだ読めない(セキュリティ上ブラウザは空文字列を返す)ため、`copied` / `cut` は `document.getSelection().toString()` — ユーザーの選択テキストを報告します。ページが `clipboardData.setData(...)` でペイロードを上書きするカスタム `copy` ハンドラを設置している場合、その上書きは `copied` / `cut` に**反映されません**。`pasted` は `event.clipboardData.getData("text/plain")` を読み取ります。
179
+ - **無言のエラー処理(ゼロログ)。** wcstack 全体のゼロ依存・最小主義に従い、`<wcs-clipboard>` は実行時の失敗に対して一切ログ出力も throw もしません。パーミッション照会の失敗(クリップボードのパーミッション名を持たない Firefox など)は無言で `"unsupported"` にフォールバックします。read/write の失敗(パーミッション拒否・フォーカス無し・Clipboard API 欠如)は `error` プロパティ / `wcs-clipboard:error` イベントを通じてのみ表面化します — コマンドは resolve し、決して reject しません。観測・対処するには `error`(および `*Permission` プロパティ)をバインドしてください。
180
+
181
+ ## ヘッドレス利用(`ClipboardCore`)
182
+
183
+ Core はグローバルな `document` / `navigator` 以外に DOM 依存を持たず、`@wc-bindable/core` の `bind()` と直接組み合わせて使えます。
184
+
185
+ ```typescript
186
+ import { ClipboardCore } from "@wcstack/clipboard";
187
+
188
+ const clip = new ClipboardCore();
189
+ clip.addEventListener("wcs-clipboard:read", (e) => {
190
+ console.log((e as CustomEvent).detail); // { text, items }
191
+ });
192
+
193
+ await clip.writeText("hello");
194
+ await clip.readText();
195
+ // または、ユーザーのクリップボード操作を監視する場合:
196
+ clip.startMonitor();
197
+ // ...後で
198
+ clip.stopMonitor();
199
+ ```
200
+
201
+ ## ライセンス
202
+
203
+ MIT
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ # @wcstack/clipboard
2
+
3
+ `@wcstack/clipboard` is a headless clipboard component for the wcstack ecosystem.
4
+
5
+ It is not a visual UI widget.
6
+ It is an **async primitive node** that turns clipboard access into reactive state — the same way `@wcstack/fetch` turns a network request into reactive state and `@wcstack/geolocation` turns the device's location into reactive state.
7
+
8
+ Unlike geolocation (a read-only sensor), the clipboard is **bidirectional**, which makes `<wcs-clipboard>` the showcase for both directions of the wc-bindable token protocol:
9
+
10
+ - **write** (`state → element`) via the command-token protocol — `command.writeText: $command.copy`
11
+ - **read** (`element → state`) via command results, plus a monitor mode that republishes the user's `copy` / `cut` / `paste` via the event-token protocol — `eventToken.pasted: clipboardPasted`
12
+
13
+ With `@wcstack/state`, `<wcs-clipboard>` can be bound directly through path contracts:
14
+
15
+ - **input surface**: `monitor`
16
+ - **command surface**: `writeText`, `write`, `readText`, `read`, `startMonitor`, `stopMonitor`
17
+ - **output state surface**: `text`, `items`, `loading`, `error`, `readPermission`, `writePermission`, `monitoring`, `copied`, `cut`, `pasted`
18
+
19
+ This means clipboard work can be expressed declaratively in HTML, without writing `navigator.clipboard.writeText()`, `readText()`, `read()`, event listeners, or teardown glue in your UI layer.
20
+
21
+ `@wcstack/clipboard` follows the [CSBC](https://github.com/csbc-dev/arch/blob/main/README.md) (Core / Shell / Binding Contract) architecture:
22
+
23
+ - **Core** (`ClipboardCore`) handles read/write, rich `ClipboardItem` normalization, error handling, monitor subscriptions, and live permission tracking
24
+ - **Shell** (`<wcs-clipboard>`) connects that state to DOM attributes, lifecycle, and declarative commands
25
+ - **Binding Contract** (`static wcBindable`) declares observable `properties`, writable `inputs`, and callable `commands`
26
+
27
+ ## Why this exists
28
+
29
+ The Clipboard API is, like `fetch`, an asynchronous source of values — but it is bidirectional (read *and* write) and gated by two separate permissions (`clipboard-read` / `clipboard-write`). Imperatively it requires gesture-bound calls, permission queries, event wiring, and cleanup on disconnect.
30
+
31
+ `@wcstack/clipboard` moves that logic into a reusable component and exposes the result as bindable state. A copy or a paste becomes a **state transition**, not imperative callback wiring.
32
+
33
+ > **Secure context + user gesture required.** The Clipboard API only works in a secure context (HTTPS, or `localhost`). Writes (`writeText` / `write`) require transient activation — call them from a click handler or a command-token wired to a user action. Reads (`readText` / `read`) require focus and read permission. When `navigator.clipboard` is absent (non-secure context or unsupported browser), commands surface a `NotSupportedError` through the `error` property rather than throwing. Firefox does not expose the clipboard permission names, so `readPermission` / `writePermission` fall back to `"unsupported"` there.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ npm install @wcstack/clipboard
39
+ ```
40
+
41
+ ## Quick Start
42
+
43
+ ### 1. Copy text (write)
44
+
45
+ Writes need a user gesture, so drive them from a DOM click (autoTrigger) or a command-token.
46
+
47
+ ```html
48
+ <script type="module" src="https://esm.run/@wcstack/state/auto"></script>
49
+ <script type="module" src="https://esm.run/@wcstack/clipboard/auto"></script>
50
+
51
+ <wcs-clipboard id="cb"></wcs-clipboard>
52
+
53
+ <!-- Optional DOM triggering: click copies the literal text -->
54
+ <input id="token" value="abc-123" readonly />
55
+ <button data-clipboardtarget="cb" data-clipboard-from="#token">Copy</button>
56
+ <button data-clipboardtarget="cb" data-clipboard-text="Hello!">Copy greeting</button>
57
+ ```
58
+
59
+ `data-clipboard-text` copies a literal string; `data-clipboard-from` copies the `value` (or `textContent`) of the element matched by the selector.
60
+
61
+ ### 2. Copy from state (command-token)
62
+
63
+ ```html
64
+ <wcs-state>
65
+ <script type="module">
66
+ export default {
67
+ message: "Shareable link",
68
+ $commandTokens: ["copy"],
69
+ onShare() { this.$command.copy.emit(this.message); }
70
+ };
71
+ </script>
72
+ </wcs-state>
73
+
74
+ <wcs-clipboard data-wcs="command.writeText: $command.copy"></wcs-clipboard>
75
+ <button data-wcs="onclick: onShare">Share</button>
76
+ ```
77
+
78
+ ### 3. Read text (paste on demand, command-token)
79
+
80
+ The DOM autoTrigger only drives **writes** (`writeText`); there is no DOM-trigger
81
+ path for reads. Drive a read from a command-token, or call `readText()` /
82
+ `read()` imperatively on the element.
83
+
84
+ ```html
85
+ <wcs-state>
86
+ <script type="module">
87
+ export default {
88
+ pasted: "",
89
+ busy: false,
90
+ $commandTokens: ["paste"],
91
+ onPaste() { this.$command.paste.emit(); }
92
+ };
93
+ </script>
94
+ </wcs-state>
95
+
96
+ <wcs-clipboard
97
+ data-wcs="command.readText: $command.paste; text: pasted; loading: busy"></wcs-clipboard>
98
+ <button data-wcs="onclick: onPaste">Paste</button>
99
+ <p data-wcs="textContent: pasted"></p>
100
+ ```
101
+
102
+ > Reading requires focus + read permission; the browser may prompt. Bind `error` to handle a denied read.
103
+
104
+ ### 4. Monitor the user's clipboard activity (event-token)
105
+
106
+ Add the `monitor` attribute to republish document `copy` / `cut` / `paste` as reactive state.
107
+
108
+ ```html
109
+ <wcs-state>
110
+ <script type="module">
111
+ export default {
112
+ lastPaste: "",
113
+ $eventTokens: ["clipboardPasted"],
114
+ $on: {
115
+ clipboardPasted: (state, event) => { state.lastPaste = event.detail; }
116
+ }
117
+ };
118
+ </script>
119
+ </wcs-state>
120
+
121
+ <wcs-clipboard monitor
122
+ data-wcs="pasted: lastPaste; eventToken.pasted: clipboardPasted"></wcs-clipboard>
123
+ ```
124
+
125
+ ## Attributes / Inputs
126
+
127
+ | Attribute | Type | Default | Description |
128
+ | --------- | ------- | ------- | --------------------------------------------------------------------------- |
129
+ | `monitor` | boolean | `false` | Subscribe to document `copy` / `cut` / `paste` on connect and republish them as `copied` / `cut` / `pasted`. |
130
+
131
+ ### DOM trigger attributes (autoTrigger, copy-on-click)
132
+
133
+ | Attribute | On | Description |
134
+ | --------------------- | -------------- | ---------------------------------------------------------------------- |
135
+ | `data-clipboardtarget`| trigger button | Id of the `<wcs-clipboard>` to drive. |
136
+ | `data-clipboard-text` | trigger button | Literal text to copy (takes precedence; empty string is valid). |
137
+ | `data-clipboard-from` | trigger button | CSS selector; copies the matched element's `value` (or `textContent`). |
138
+
139
+ > DOM triggers are **write-only**: a click always drives `writeText`. There is no DOM-trigger path for reads (`readText` / `read`) — drive reads from a command-token or imperatively.
140
+
141
+ > A DOM-triggered `writeText` is fire-and-forget (its `Promise` is not awaited), but it never rejects: a failed copy surfaces through the `error` property like any other write. Bind `error` (e.g. `text: error.message@cb`) to observe autoTrigger failures.
142
+
143
+ ## Observable Properties (outputs)
144
+
145
+ | Property | Event | Description |
146
+ | ---------------- | ---------------------------------------- | -------------------------------------------------------------------- |
147
+ | `text` | `wcs-clipboard:read` | Plain text from the last `readText()` / `read()` (or `null`). |
148
+ | `items` | `wcs-clipboard:read` | Normalized `ClipboardItem` snapshot from `read()` (`{ types, data }[]`), or `null`. |
149
+ | `loading` | `wcs-clipboard:loading-changed` | `true` during any async read/write. |
150
+ | `error` | `wcs-clipboard:error` | Normalized `{ name, message }` (e.g. `NotAllowedError`, `NotSupportedError`). |
151
+ | `readPermission` | `wcs-clipboard:read-permission-changed` | `"prompt"` / `"granted"` / `"denied"` / `"unsupported"` for `clipboard-read`. |
152
+ | `writePermission`| `wcs-clipboard:write-permission-changed` | Same states for `clipboard-write`. |
153
+ | `monitoring` | `wcs-clipboard:monitoring-changed` | `true` while monitoring document clipboard events. |
154
+ | `copied` | `wcs-clipboard:copied` | Text of the latest monitored `copy` (from the selection). |
155
+ | `cut` | `wcs-clipboard:cut` | Text of the latest monitored `cut`. |
156
+ | `pasted` | `wcs-clipboard:pasted` | `text/plain` of the latest monitored `paste`. |
157
+
158
+ ## Commands
159
+
160
+ | Command | Description |
161
+ | ------------- | ------------------------------------------------------------------------- |
162
+ | `writeText` | Write a string to the clipboard (async; never rejects — failures go to `error`). Needs a user gesture. |
163
+ | `write` | Write `ClipboardItem[]` (images, HTML, multiple MIME types) (async). |
164
+ | `readText` | Read plain text; publishes `text` and `wcs-clipboard:read` (async). |
165
+ | `read` | Read rich `ClipboardItem`s, resolving each representation to a `Blob` (async). |
166
+ | `startMonitor`| Begin monitoring document `copy` / `cut` / `paste` (no-op if already monitoring). |
167
+ | `stopMonitor` | Stop monitoring; `monitoring` becomes `false`. |
168
+
169
+ State-driven invocation uses the command-token protocol:
170
+
171
+ ```html
172
+ <wcs-clipboard data-wcs="command.writeText: $command.copy"></wcs-clipboard>
173
+ ```
174
+
175
+ ## Notes & limitations
176
+
177
+ - **Attributes are read at connect time, not observed.** `<wcs-clipboard>` does not implement `observedAttributes` / `attributeChangedCallback`. The `monitor` attribute is read when the element connects — toggling it imperatively after connect does not start/stop monitoring by itself; call `startMonitor()` / `stopMonitor()`, or re-connect the element.
178
+ - **No connect-time read.** Unlike `<wcs-geo>`, the clipboard cannot auto-read on connect (reads need a user gesture and permission), so there is no `connectedCallbackPromise` / SSR snapshot. The only connect-time action is optional monitoring.
179
+ - **Reconnect re-subscribes.** Removing and re-inserting the element runs `connectedCallback` again, so permission tracking is revived and a `monitor`-attribute element restarts monitoring (matching how it tears them down on disconnect). Monitoring persistence is **attribute-driven only**: if you started monitoring imperatively with `startMonitor()` on an element *without* the `monitor` attribute, a reconnect does not restore it (the attribute is the source of truth). Add the `monitor` attribute for persistent monitoring across reparents.
180
+ - **`copy` / `cut` text comes from the selection.** During a `copy` / `cut` event the clipboard payload is not yet readable (the browser returns an empty string for security reasons), so `copied` / `cut` report `document.getSelection().toString()` — the user's selected text. If the page installs a custom `copy` handler that overrides the payload via `clipboardData.setData(...)`, that override is **not** reflected in `copied` / `cut`. `pasted` reads `event.clipboardData.getData("text/plain")`.
181
+ - **Silent failure handling (zero-log).** Consistent with the rest of wcstack's zero-dependency, minimal philosophy, `<wcs-clipboard>` never logs or throws for runtime failures. A failed permission query (e.g. Firefox, which has no clipboard permission names) silently falls back to `"unsupported"`. Read/write failures (denied permission, no focus, missing Clipboard API) are surfaced only through the `error` property / `wcs-clipboard:error` event — the commands resolve and never reject. Bind `error` (and the `*Permission` properties) to observe and react.
182
+
183
+ ## Headless usage (`ClipboardCore`)
184
+
185
+ The Core has no DOM dependency beyond the global `document` / `navigator` and can be used directly with `bind()` from `@wc-bindable/core`:
186
+
187
+ ```typescript
188
+ import { ClipboardCore } from "@wcstack/clipboard";
189
+
190
+ const clip = new ClipboardCore();
191
+ clip.addEventListener("wcs-clipboard:read", (e) => {
192
+ console.log((e as CustomEvent).detail); // { text, items }
193
+ });
194
+
195
+ await clip.writeText("hello");
196
+ await clip.readText();
197
+ // or, to monitor the user's clipboard activity:
198
+ clip.startMonitor();
199
+ // ...later
200
+ clip.stopMonitor();
201
+ ```
202
+
203
+ ## License
204
+
205
+ MIT
package/dist/auto.js ADDED
@@ -0,0 +1,3 @@
1
+ import { bootstrapClipboard } from "./index.esm.js";
2
+
3
+ bootstrapClipboard();
@@ -0,0 +1,3 @@
1
+ import { bootstrapClipboard } from "./index.esm.min.js";
2
+
3
+ bootstrapClipboard();