@ngockhoi96/ctc 0.1.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/LICENSE +21 -0
- package/README.md +302 -0
- package/dist/clipboard/index.cjs +7 -0
- package/dist/clipboard/index.d.cts +2 -0
- package/dist/clipboard/index.d.mts +2 -0
- package/dist/clipboard/index.mjs +2 -0
- package/dist/clipboard-Bs9DV14p.cjs +338 -0
- package/dist/clipboard-Bs9DV14p.cjs.map +1 -0
- package/dist/clipboard-OTP55cvN.mjs +309 -0
- package/dist/clipboard-OTP55cvN.mjs.map +1 -0
- package/dist/index-B7FFRy7e.d.mts +193 -0
- package/dist/index-CHCHjqWe.d.cts +193 -0
- package/dist/index.cjs +7 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +2 -0
- package/package.json +77 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
//#region src/lib/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Error codes for browser utility operations.
|
|
4
|
+
*/
|
|
5
|
+
type ErrorCode = "CLIPBOARD_NOT_SUPPORTED" | "CLIPBOARD_PERMISSION_DENIED" | "CLIPBOARD_WRITE_FAILED" | "CLIPBOARD_READ_FAILED" | "INSECURE_CONTEXT";
|
|
6
|
+
/**
|
|
7
|
+
* Structured error for browser utility operations.
|
|
8
|
+
*
|
|
9
|
+
* All clipboard functions accept an optional `onError` callback
|
|
10
|
+
* that receives this type with a specific error code.
|
|
11
|
+
*/
|
|
12
|
+
interface BrowserUtilsError {
|
|
13
|
+
code: ErrorCode;
|
|
14
|
+
message: string;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Callback invoked when a browser utility operation fails.
|
|
19
|
+
*
|
|
20
|
+
* @param error - Structured error with code and message
|
|
21
|
+
*/
|
|
22
|
+
type OnErrorCallback = (error: BrowserUtilsError) => void;
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/clipboard/types.d.ts
|
|
25
|
+
/**
|
|
26
|
+
* Options for clipboard operations.
|
|
27
|
+
*/
|
|
28
|
+
interface ClipboardOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Callback invoked when the clipboard operation fails.
|
|
31
|
+
* Receives a structured error with a specific error code.
|
|
32
|
+
*/
|
|
33
|
+
onError?: OnErrorCallback | undefined;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/clipboard/copy.d.ts
|
|
37
|
+
/**
|
|
38
|
+
* Copy text to the clipboard using the modern Clipboard API.
|
|
39
|
+
*
|
|
40
|
+
* Requires a secure context (HTTPS or localhost) and must be called from
|
|
41
|
+
* within a user gesture handler (click, keydown, etc.).
|
|
42
|
+
*
|
|
43
|
+
* @param text - The text to copy to the clipboard
|
|
44
|
+
* @param options - Optional configuration including `onError` callback
|
|
45
|
+
* @returns `true` on success, `false` on any failure (never throws)
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* **User gesture requirement:** Must be called synchronously within a user
|
|
49
|
+
* gesture handler. Programmatic calls from timers or microtasks will be
|
|
50
|
+
* rejected by the browser with `CLIPBOARD_PERMISSION_DENIED`.
|
|
51
|
+
*
|
|
52
|
+
* **Secure context:** Returns `false` on HTTP pages with `INSECURE_CONTEXT`
|
|
53
|
+
* error code. Use `copyToClipboardLegacy()` for HTTP environments.
|
|
54
|
+
*
|
|
55
|
+
* **Safari:** Calling any async operation before `writeText()` in the same
|
|
56
|
+
* microtask may break Safari's user activation window. Keep the call
|
|
57
|
+
* synchronous within the click handler.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* button.addEventListener('click', async () => {
|
|
62
|
+
* const success = await copyToClipboard('Hello, world!')
|
|
63
|
+
* if (!success) {
|
|
64
|
+
* showError('Copy failed — check HTTPS and permissions')
|
|
65
|
+
* }
|
|
66
|
+
* })
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function copyToClipboard(text: string, options?: ClipboardOptions): Promise<boolean>;
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/clipboard/detect.d.ts
|
|
72
|
+
/**
|
|
73
|
+
* Check if the Clipboard API is available and usable in the current context.
|
|
74
|
+
*
|
|
75
|
+
* Returns `true` only when `navigator.clipboard.writeText` exists AND the
|
|
76
|
+
* page is running in a secure context (HTTPS or localhost). Returns `false`
|
|
77
|
+
* in SSR environments, on HTTP pages, or when the Clipboard API is absent.
|
|
78
|
+
*
|
|
79
|
+
* @returns `true` if clipboard write operations are supported
|
|
80
|
+
*
|
|
81
|
+
* @remarks
|
|
82
|
+
* Permission state is not checked — a `true` result does not guarantee the
|
|
83
|
+
* user has granted clipboard access. Permission denial is surfaced at call
|
|
84
|
+
* time via the `CLIPBOARD_PERMISSION_DENIED` error code on `copyToClipboard`.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* if (isClipboardSupported()) {
|
|
89
|
+
* await copyToClipboard(text)
|
|
90
|
+
* } else {
|
|
91
|
+
* copyToClipboardLegacy(text)
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
declare function isClipboardSupported(): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Check if clipboard read operations are available and usable in the current context.
|
|
98
|
+
*
|
|
99
|
+
* Returns `true` only when `navigator.clipboard.readText` exists AND the
|
|
100
|
+
* page is running in a secure context (HTTPS or localhost). Returns `false`
|
|
101
|
+
* in SSR environments, on HTTP pages, or when the read API is absent.
|
|
102
|
+
*
|
|
103
|
+
* @returns `true` if clipboard read operations are supported
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* Permission state is not checked — a `true` result does not guarantee the
|
|
107
|
+
* user has granted clipboard read access. Permission denial is surfaced at
|
|
108
|
+
* call time via the `CLIPBOARD_PERMISSION_DENIED` error code on `readFromClipboard`.
|
|
109
|
+
*
|
|
110
|
+
* Firefox does not support the Permissions API `clipboard-read` query. This
|
|
111
|
+
* function uses synchronous feature detection only — no async permission
|
|
112
|
+
* queries are performed.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* if (isClipboardReadSupported()) {
|
|
117
|
+
* const text = await readFromClipboard()
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function isClipboardReadSupported(): boolean;
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/clipboard/fallback.d.ts
|
|
124
|
+
/**
|
|
125
|
+
* Copy text to the clipboard using the legacy `document.execCommand` API.
|
|
126
|
+
*
|
|
127
|
+
* Use this function when the modern Clipboard API is unavailable — for
|
|
128
|
+
* example, on HTTP pages (non-HTTPS) or in browsers that do not support
|
|
129
|
+
* `navigator.clipboard`. For HTTPS pages, prefer `copyToClipboard()`.
|
|
130
|
+
*
|
|
131
|
+
* @param text - The text to copy to the clipboard
|
|
132
|
+
* @param options - Optional configuration including `onError` callback
|
|
133
|
+
* @returns `true` on success, `false` on any failure (never throws)
|
|
134
|
+
*
|
|
135
|
+
* @remarks
|
|
136
|
+
* This function uses the deprecated `document.execCommand('copy')` API,
|
|
137
|
+
* which is synchronous and text-only. It temporarily creates and removes a
|
|
138
|
+
* textarea element in the DOM to perform the copy operation.
|
|
139
|
+
*
|
|
140
|
+
* **No secure context requirement:** This function works on HTTP pages.
|
|
141
|
+
* This is by design — it exists for environments where `copyToClipboard()`
|
|
142
|
+
* is unavailable due to missing secure context.
|
|
143
|
+
*
|
|
144
|
+
* **iOS Safari:** `execCommand` copy is not reliably supported on iOS.
|
|
145
|
+
* This function may return `false` on iOS Safari without a usable fallback.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* if (isClipboardSupported()) {
|
|
150
|
+
* await copyToClipboard(text)
|
|
151
|
+
* } else {
|
|
152
|
+
* const success = copyToClipboardLegacy(text)
|
|
153
|
+
* if (!success) {
|
|
154
|
+
* showManualCopyInstructions()
|
|
155
|
+
* }
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
declare function copyToClipboardLegacy(text: string, options?: ClipboardOptions): boolean;
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/clipboard/read.d.ts
|
|
162
|
+
/**
|
|
163
|
+
* Read text from the clipboard using the modern Clipboard API.
|
|
164
|
+
*
|
|
165
|
+
* Requires a secure context (HTTPS or localhost). The browser may prompt
|
|
166
|
+
* the user for permission on the first call.
|
|
167
|
+
*
|
|
168
|
+
* @param options - Optional configuration including `onError` callback
|
|
169
|
+
* @returns The clipboard text on success, `null` on any failure (never throws)
|
|
170
|
+
*
|
|
171
|
+
* @remarks
|
|
172
|
+
* **Permission prompt:** Chrome prompts for `clipboard-read` permission on
|
|
173
|
+
* the first call. Firefox and Safari show a system-level paste prompt.
|
|
174
|
+
* Permission denial is reported via `CLIPBOARD_PERMISSION_DENIED`.
|
|
175
|
+
*
|
|
176
|
+
* **Non-text content:** If the clipboard contains only non-text content
|
|
177
|
+
* (e.g., an image), the browser throws `NotFoundError` which is reported
|
|
178
|
+
* as `CLIPBOARD_READ_FAILED`.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* button.addEventListener('click', async () => {
|
|
183
|
+
* const text = await readFromClipboard()
|
|
184
|
+
* if (text !== null) {
|
|
185
|
+
* input.value = text
|
|
186
|
+
* }
|
|
187
|
+
* })
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
declare function readFromClipboard(options?: ClipboardOptions): Promise<string | null>;
|
|
191
|
+
//#endregion
|
|
192
|
+
export { copyToClipboard as a, ErrorCode as c, isClipboardSupported as i, OnErrorCallback as l, copyToClipboardLegacy as n, ClipboardOptions as o, isClipboardReadSupported as r, BrowserUtilsError as s, readFromClipboard as t };
|
|
193
|
+
//# sourceMappingURL=index-CHCHjqWe.d.cts.map
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_clipboard = require("./clipboard-Bs9DV14p.cjs");
|
|
3
|
+
exports.copyToClipboard = require_clipboard.copyToClipboard;
|
|
4
|
+
exports.copyToClipboardLegacy = require_clipboard.copyToClipboardLegacy;
|
|
5
|
+
exports.isClipboardReadSupported = require_clipboard.isClipboardReadSupported;
|
|
6
|
+
exports.isClipboardSupported = require_clipboard.isClipboardSupported;
|
|
7
|
+
exports.readFromClipboard = require_clipboard.readFromClipboard;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as copyToClipboard, c as ErrorCode, i as isClipboardSupported, l as OnErrorCallback, n as copyToClipboardLegacy, o as ClipboardOptions, r as isClipboardReadSupported, s as BrowserUtilsError, t as readFromClipboard } from "./index-CHCHjqWe.cjs";
|
|
2
|
+
export { type BrowserUtilsError, type ClipboardOptions, type ErrorCode, type OnErrorCallback, copyToClipboard, copyToClipboardLegacy, isClipboardReadSupported, isClipboardSupported, readFromClipboard };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as copyToClipboard, c as ErrorCode, i as isClipboardSupported, l as OnErrorCallback, n as copyToClipboardLegacy, o as ClipboardOptions, r as isClipboardReadSupported, s as BrowserUtilsError, t as readFromClipboard } from "./index-B7FFRy7e.mjs";
|
|
2
|
+
export { type BrowserUtilsError, type ClipboardOptions, type ErrorCode, type OnErrorCallback, copyToClipboard, copyToClipboardLegacy, isClipboardReadSupported, isClipboardSupported, readFromClipboard };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as copyToClipboard, i as isClipboardSupported, n as copyToClipboardLegacy, r as isClipboardReadSupported, t as readFromClipboard } from "./clipboard-OTP55cvN.mjs";
|
|
2
|
+
export { copyToClipboard, copyToClipboardLegacy, isClipboardReadSupported, isClipboardSupported, readFromClipboard };
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ngockhoi96/ctc",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Modular, tree-shakeable browser utilities library",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=20"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsdown",
|
|
13
|
+
"lint": "biome check",
|
|
14
|
+
"lint:fix": "biome check --fix",
|
|
15
|
+
"format": "biome format --write",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"test:e2e": "playwright test",
|
|
19
|
+
"size": "size-limit",
|
|
20
|
+
"validate": "publint && attw --pack",
|
|
21
|
+
"setup": "lefthook install",
|
|
22
|
+
"changeset": "changeset"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"size-limit": [
|
|
28
|
+
{
|
|
29
|
+
"path": "dist/index.mjs",
|
|
30
|
+
"limit": "1 KB"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"path": "dist/clipboard/index.mjs",
|
|
34
|
+
"limit": "1 KB"
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@arethetypeswrong/cli": "0.18.2",
|
|
39
|
+
"@biomejs/biome": "2.4.10",
|
|
40
|
+
"@changesets/changelog-github": "0.6.0",
|
|
41
|
+
"@changesets/cli": "2.30.0",
|
|
42
|
+
"@commitlint/cli": "20.5.0",
|
|
43
|
+
"@commitlint/config-conventional": "20.5.0",
|
|
44
|
+
"@playwright/test": "^1.59.1",
|
|
45
|
+
"@size-limit/file": "12.0.1",
|
|
46
|
+
"@types/node": "^25.6.0",
|
|
47
|
+
"@vitest/coverage-v8": "4.1.3",
|
|
48
|
+
"http-server": "^14.1.1",
|
|
49
|
+
"lefthook": "2.1.5",
|
|
50
|
+
"publint": "0.3.18",
|
|
51
|
+
"size-limit": "12.0.1",
|
|
52
|
+
"tsdown": "0.21.7",
|
|
53
|
+
"typescript": "6.0.2",
|
|
54
|
+
"vitest": "4.1.3"
|
|
55
|
+
},
|
|
56
|
+
"main": "./dist/index.cjs",
|
|
57
|
+
"module": "./dist/index.mjs",
|
|
58
|
+
"types": "./dist/index.d.cts",
|
|
59
|
+
"typesVersions": {
|
|
60
|
+
"*": {
|
|
61
|
+
"clipboard": [
|
|
62
|
+
"./dist/clipboard/index.d.cts"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"exports": {
|
|
67
|
+
".": {
|
|
68
|
+
"import": "./dist/index.mjs",
|
|
69
|
+
"require": "./dist/index.cjs"
|
|
70
|
+
},
|
|
71
|
+
"./clipboard": {
|
|
72
|
+
"import": "./dist/clipboard/index.mjs",
|
|
73
|
+
"require": "./dist/clipboard/index.cjs"
|
|
74
|
+
},
|
|
75
|
+
"./package.json": "./package.json"
|
|
76
|
+
}
|
|
77
|
+
}
|