@publikit/utils 0.1.1
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 +42 -0
- package/dist/index.cjs +87 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +81 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Pirimera
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @publikit/utils
|
|
2
|
+
|
|
3
|
+
Framework-agnostic utility functions for Publikit packages and applications.
|
|
4
|
+
|
|
5
|
+
- **No React peer dependency** — safe for scripts, edge workers, and non-UI code
|
|
6
|
+
- **Tree-shakeable** — `sideEffects: false`
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @publikit/utils
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Exports
|
|
15
|
+
|
|
16
|
+
| Export | Description |
|
|
17
|
+
|--------|-------------|
|
|
18
|
+
| `cn` | Merge Tailwind classes (`clsx` + `tailwind-merge`) |
|
|
19
|
+
| `debounce` | Debounce function calls |
|
|
20
|
+
| `getErrorMessage` | Extract message from unknown errors |
|
|
21
|
+
| `formatBytes` | Human-readable byte sizes |
|
|
22
|
+
| `calculateUsagePercentage` | Percentage capped at 100 |
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { cn, debounce, getErrorMessage, formatBytes } from '@publikit/utils';
|
|
28
|
+
|
|
29
|
+
const className = cn('px-4', isActive && 'bg-primary');
|
|
30
|
+
const onResize = debounce(() => measure(), 150);
|
|
31
|
+
const message = getErrorMessage(error, 'Something went wrong');
|
|
32
|
+
const size = formatBytes(1_048_576); // "1 MB"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Related packages
|
|
36
|
+
|
|
37
|
+
- [`@publikit/hooks`](../hooks) — generic React hooks
|
|
38
|
+
- [`@publikit/base`](../base) — re-exports `cn` for convenience
|
|
39
|
+
|
|
40
|
+
## License
|
|
41
|
+
|
|
42
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clsx = require('clsx');
|
|
4
|
+
var tailwindMerge = require('tailwind-merge');
|
|
5
|
+
|
|
6
|
+
// cn.ts
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// async.ts
|
|
12
|
+
function debounce(fn, ms) {
|
|
13
|
+
let timeoutId = null;
|
|
14
|
+
let lastArgs = null;
|
|
15
|
+
const debounced = (...args) => {
|
|
16
|
+
lastArgs = args;
|
|
17
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
18
|
+
timeoutId = setTimeout(() => {
|
|
19
|
+
timeoutId = null;
|
|
20
|
+
if (lastArgs) {
|
|
21
|
+
fn(...lastArgs);
|
|
22
|
+
lastArgs = null;
|
|
23
|
+
}
|
|
24
|
+
}, ms);
|
|
25
|
+
};
|
|
26
|
+
debounced.cancel = () => {
|
|
27
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
28
|
+
timeoutId = null;
|
|
29
|
+
lastArgs = null;
|
|
30
|
+
};
|
|
31
|
+
debounced.flush = () => {
|
|
32
|
+
if (!timeoutId || !lastArgs) return;
|
|
33
|
+
clearTimeout(timeoutId);
|
|
34
|
+
timeoutId = null;
|
|
35
|
+
fn(...lastArgs);
|
|
36
|
+
lastArgs = null;
|
|
37
|
+
};
|
|
38
|
+
return debounced;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// error.ts
|
|
42
|
+
function getErrorMessage(error, defaultMessage) {
|
|
43
|
+
if (error instanceof Error && error.message) {
|
|
44
|
+
return error.message;
|
|
45
|
+
}
|
|
46
|
+
if (typeof error === "string" && error.trim()) {
|
|
47
|
+
return error;
|
|
48
|
+
}
|
|
49
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
50
|
+
const message = error.message;
|
|
51
|
+
if (typeof message === "string" && message.trim()) {
|
|
52
|
+
return message;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return defaultMessage;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// format.ts
|
|
59
|
+
function formatBytes(bytes) {
|
|
60
|
+
if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
61
|
+
return "0 B";
|
|
62
|
+
}
|
|
63
|
+
const k = 1024;
|
|
64
|
+
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
65
|
+
const i = Math.min(
|
|
66
|
+
Math.floor(Math.log(bytes) / Math.log(k)),
|
|
67
|
+
sizes.length - 1
|
|
68
|
+
);
|
|
69
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
70
|
+
}
|
|
71
|
+
function calculateUsagePercentage(current, limit) {
|
|
72
|
+
if (!Number.isFinite(current) || !Number.isFinite(limit) || limit <= 0) {
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
if (current <= 0) {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
return Math.min(100, Math.round(current / limit * 100));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
exports.calculateUsagePercentage = calculateUsagePercentage;
|
|
82
|
+
exports.cn = cn;
|
|
83
|
+
exports.debounce = debounce;
|
|
84
|
+
exports.formatBytes = formatBytes;
|
|
85
|
+
exports.getErrorMessage = getErrorMessage;
|
|
86
|
+
//# sourceMappingURL=index.cjs.map
|
|
87
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../cn.ts","../async.ts","../error.ts","../format.ts"],"names":["twMerge","clsx"],"mappings":"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","file":"index.cjs","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\n/**\r\n * Merge Tailwind CSS class names with conflict resolution.\r\n */\r\nexport function cn(...inputs: ClassValue[]): string {\r\n return twMerge(clsx(inputs));\r\n}\r\n","/**\r\n * Debounced function with cancel and flush helpers.\r\n */\r\nexport interface DebouncedFunction<A extends unknown[], R> {\r\n (...args: A): void;\r\n cancel(): void;\r\n flush(): void;\r\n}\r\n\r\n/**\r\n * Debounce a function — only invoke after `ms` milliseconds of inactivity.\r\n */\r\nexport function debounce<A extends unknown[], R>(\r\n fn: (...args: A) => R,\r\n ms: number\r\n): DebouncedFunction<A, R> {\r\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\r\n let lastArgs: A | null = null;\r\n\r\n const debounced = (...args: A) => {\r\n lastArgs = args;\r\n if (timeoutId) clearTimeout(timeoutId);\r\n timeoutId = setTimeout(() => {\r\n timeoutId = null;\r\n if (lastArgs) {\r\n fn(...lastArgs);\r\n lastArgs = null;\r\n }\r\n }, ms);\r\n };\r\n\r\n debounced.cancel = () => {\r\n if (timeoutId) clearTimeout(timeoutId);\r\n timeoutId = null;\r\n lastArgs = null;\r\n };\r\n\r\n debounced.flush = () => {\r\n if (!timeoutId || !lastArgs) return;\r\n clearTimeout(timeoutId);\r\n timeoutId = null;\r\n fn(...lastArgs);\r\n lastArgs = null;\r\n };\r\n\r\n return debounced;\r\n}\r\n","/**\r\n * Extract a human-readable message from an unknown error value.\r\n */\r\nexport function getErrorMessage(error: unknown, defaultMessage: string): string {\r\n if (error instanceof Error && error.message) {\r\n return error.message;\r\n }\r\n\r\n if (typeof error === 'string' && error.trim()) {\r\n return error;\r\n }\r\n\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n const message = (error as { message: unknown }).message;\r\n if (typeof message === 'string' && message.trim()) {\r\n return message;\r\n }\r\n }\r\n\r\n return defaultMessage;\r\n}\r\n","/**\r\n * Format a byte count as a human-readable string.\r\n */\r\nexport function formatBytes(bytes: number): string {\r\n if (!Number.isFinite(bytes) || bytes <= 0) {\r\n return '0 B';\r\n }\r\n\r\n const k = 1024;\r\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\r\n const i = Math.min(\r\n Math.floor(Math.log(bytes) / Math.log(k)),\r\n sizes.length - 1\r\n );\r\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;\r\n}\r\n\r\n/**\r\n * Calculate usage percentage capped at 100.\r\n */\r\nexport function calculateUsagePercentage(current: number, limit: number): number {\r\n if (!Number.isFinite(current) || !Number.isFinite(limit) || limit <= 0) {\r\n return 0;\r\n }\r\n\r\n if (current <= 0) {\r\n return 0;\r\n }\r\n\r\n return Math.min(100, Math.round((current / limit) * 100));\r\n}\r\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Merge Tailwind CSS class names with conflict resolution.
|
|
5
|
+
*/
|
|
6
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Debounced function with cancel and flush helpers.
|
|
10
|
+
*/
|
|
11
|
+
interface DebouncedFunction<A extends unknown[], R> {
|
|
12
|
+
(...args: A): void;
|
|
13
|
+
cancel(): void;
|
|
14
|
+
flush(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Debounce a function — only invoke after `ms` milliseconds of inactivity.
|
|
18
|
+
*/
|
|
19
|
+
declare function debounce<A extends unknown[], R>(fn: (...args: A) => R, ms: number): DebouncedFunction<A, R>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Extract a human-readable message from an unknown error value.
|
|
23
|
+
*/
|
|
24
|
+
declare function getErrorMessage(error: unknown, defaultMessage: string): string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Format a byte count as a human-readable string.
|
|
28
|
+
*/
|
|
29
|
+
declare function formatBytes(bytes: number): string;
|
|
30
|
+
/**
|
|
31
|
+
* Calculate usage percentage capped at 100.
|
|
32
|
+
*/
|
|
33
|
+
declare function calculateUsagePercentage(current: number, limit: number): number;
|
|
34
|
+
|
|
35
|
+
export { type DebouncedFunction, calculateUsagePercentage, cn, debounce, formatBytes, getErrorMessage };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Merge Tailwind CSS class names with conflict resolution.
|
|
5
|
+
*/
|
|
6
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Debounced function with cancel and flush helpers.
|
|
10
|
+
*/
|
|
11
|
+
interface DebouncedFunction<A extends unknown[], R> {
|
|
12
|
+
(...args: A): void;
|
|
13
|
+
cancel(): void;
|
|
14
|
+
flush(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Debounce a function — only invoke after `ms` milliseconds of inactivity.
|
|
18
|
+
*/
|
|
19
|
+
declare function debounce<A extends unknown[], R>(fn: (...args: A) => R, ms: number): DebouncedFunction<A, R>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Extract a human-readable message from an unknown error value.
|
|
23
|
+
*/
|
|
24
|
+
declare function getErrorMessage(error: unknown, defaultMessage: string): string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Format a byte count as a human-readable string.
|
|
28
|
+
*/
|
|
29
|
+
declare function formatBytes(bytes: number): string;
|
|
30
|
+
/**
|
|
31
|
+
* Calculate usage percentage capped at 100.
|
|
32
|
+
*/
|
|
33
|
+
declare function calculateUsagePercentage(current: number, limit: number): number;
|
|
34
|
+
|
|
35
|
+
export { type DebouncedFunction, calculateUsagePercentage, cn, debounce, formatBytes, getErrorMessage };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
|
|
4
|
+
// cn.ts
|
|
5
|
+
function cn(...inputs) {
|
|
6
|
+
return twMerge(clsx(inputs));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// async.ts
|
|
10
|
+
function debounce(fn, ms) {
|
|
11
|
+
let timeoutId = null;
|
|
12
|
+
let lastArgs = null;
|
|
13
|
+
const debounced = (...args) => {
|
|
14
|
+
lastArgs = args;
|
|
15
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
16
|
+
timeoutId = setTimeout(() => {
|
|
17
|
+
timeoutId = null;
|
|
18
|
+
if (lastArgs) {
|
|
19
|
+
fn(...lastArgs);
|
|
20
|
+
lastArgs = null;
|
|
21
|
+
}
|
|
22
|
+
}, ms);
|
|
23
|
+
};
|
|
24
|
+
debounced.cancel = () => {
|
|
25
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
26
|
+
timeoutId = null;
|
|
27
|
+
lastArgs = null;
|
|
28
|
+
};
|
|
29
|
+
debounced.flush = () => {
|
|
30
|
+
if (!timeoutId || !lastArgs) return;
|
|
31
|
+
clearTimeout(timeoutId);
|
|
32
|
+
timeoutId = null;
|
|
33
|
+
fn(...lastArgs);
|
|
34
|
+
lastArgs = null;
|
|
35
|
+
};
|
|
36
|
+
return debounced;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// error.ts
|
|
40
|
+
function getErrorMessage(error, defaultMessage) {
|
|
41
|
+
if (error instanceof Error && error.message) {
|
|
42
|
+
return error.message;
|
|
43
|
+
}
|
|
44
|
+
if (typeof error === "string" && error.trim()) {
|
|
45
|
+
return error;
|
|
46
|
+
}
|
|
47
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
48
|
+
const message = error.message;
|
|
49
|
+
if (typeof message === "string" && message.trim()) {
|
|
50
|
+
return message;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return defaultMessage;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// format.ts
|
|
57
|
+
function formatBytes(bytes) {
|
|
58
|
+
if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
59
|
+
return "0 B";
|
|
60
|
+
}
|
|
61
|
+
const k = 1024;
|
|
62
|
+
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
63
|
+
const i = Math.min(
|
|
64
|
+
Math.floor(Math.log(bytes) / Math.log(k)),
|
|
65
|
+
sizes.length - 1
|
|
66
|
+
);
|
|
67
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
68
|
+
}
|
|
69
|
+
function calculateUsagePercentage(current, limit) {
|
|
70
|
+
if (!Number.isFinite(current) || !Number.isFinite(limit) || limit <= 0) {
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
if (current <= 0) {
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
return Math.min(100, Math.round(current / limit * 100));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { calculateUsagePercentage, cn, debounce, formatBytes, getErrorMessage };
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../cn.ts","../async.ts","../error.ts","../format.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\n/**\r\n * Merge Tailwind CSS class names with conflict resolution.\r\n */\r\nexport function cn(...inputs: ClassValue[]): string {\r\n return twMerge(clsx(inputs));\r\n}\r\n","/**\r\n * Debounced function with cancel and flush helpers.\r\n */\r\nexport interface DebouncedFunction<A extends unknown[], R> {\r\n (...args: A): void;\r\n cancel(): void;\r\n flush(): void;\r\n}\r\n\r\n/**\r\n * Debounce a function — only invoke after `ms` milliseconds of inactivity.\r\n */\r\nexport function debounce<A extends unknown[], R>(\r\n fn: (...args: A) => R,\r\n ms: number\r\n): DebouncedFunction<A, R> {\r\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\r\n let lastArgs: A | null = null;\r\n\r\n const debounced = (...args: A) => {\r\n lastArgs = args;\r\n if (timeoutId) clearTimeout(timeoutId);\r\n timeoutId = setTimeout(() => {\r\n timeoutId = null;\r\n if (lastArgs) {\r\n fn(...lastArgs);\r\n lastArgs = null;\r\n }\r\n }, ms);\r\n };\r\n\r\n debounced.cancel = () => {\r\n if (timeoutId) clearTimeout(timeoutId);\r\n timeoutId = null;\r\n lastArgs = null;\r\n };\r\n\r\n debounced.flush = () => {\r\n if (!timeoutId || !lastArgs) return;\r\n clearTimeout(timeoutId);\r\n timeoutId = null;\r\n fn(...lastArgs);\r\n lastArgs = null;\r\n };\r\n\r\n return debounced;\r\n}\r\n","/**\r\n * Extract a human-readable message from an unknown error value.\r\n */\r\nexport function getErrorMessage(error: unknown, defaultMessage: string): string {\r\n if (error instanceof Error && error.message) {\r\n return error.message;\r\n }\r\n\r\n if (typeof error === 'string' && error.trim()) {\r\n return error;\r\n }\r\n\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n const message = (error as { message: unknown }).message;\r\n if (typeof message === 'string' && message.trim()) {\r\n return message;\r\n }\r\n }\r\n\r\n return defaultMessage;\r\n}\r\n","/**\r\n * Format a byte count as a human-readable string.\r\n */\r\nexport function formatBytes(bytes: number): string {\r\n if (!Number.isFinite(bytes) || bytes <= 0) {\r\n return '0 B';\r\n }\r\n\r\n const k = 1024;\r\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\r\n const i = Math.min(\r\n Math.floor(Math.log(bytes) / Math.log(k)),\r\n sizes.length - 1\r\n );\r\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;\r\n}\r\n\r\n/**\r\n * Calculate usage percentage capped at 100.\r\n */\r\nexport function calculateUsagePercentage(current: number, limit: number): number {\r\n if (!Number.isFinite(current) || !Number.isFinite(limit) || limit <= 0) {\r\n return 0;\r\n }\r\n\r\n if (current <= 0) {\r\n return 0;\r\n }\r\n\r\n return Math.min(100, Math.round((current / limit) * 100));\r\n}\r\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@publikit/utils",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Framework-agnostic utility functions for Publikit packages and applications",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch",
|
|
25
|
+
"clean": "rimraf dist",
|
|
26
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"test": "vitest run"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"utilities",
|
|
32
|
+
"cn",
|
|
33
|
+
"tailwind",
|
|
34
|
+
"clsx",
|
|
35
|
+
"publikit"
|
|
36
|
+
],
|
|
37
|
+
"author": "Pirimera",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/pirimera/publikit.git",
|
|
42
|
+
"directory": "utils"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/pirimera/publikit/tree/main/utils#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/pirimera/publikit/issues"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=18"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"clsx": "^2.1.1",
|
|
56
|
+
"tailwind-merge": "^3.4.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"rimraf": "^5.0.0",
|
|
60
|
+
"tsup": "^8.0.0",
|
|
61
|
+
"typescript": "^5.8.3",
|
|
62
|
+
"vitest": "^4.0.18"
|
|
63
|
+
}
|
|
64
|
+
}
|