@mdxui/do 2.1.1 → 4.0.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.md +115 -323
- package/dist/{agents-xcIn2dUB.d.ts → agents-2_r9e9i7.d.ts} +213 -2
- package/dist/app/index.d.ts +347 -0
- package/dist/app/index.js +14 -0
- package/dist/app/index.js.map +1 -0
- package/dist/breadcrumbs-C9Qn3S7d.d.ts +81 -0
- package/dist/capnweb-client-Bq78FtEA.d.ts +229 -0
- package/dist/chunk-3XKYQRXY.js +192 -0
- package/dist/chunk-3XKYQRXY.js.map +1 -0
- package/dist/chunk-4KXVN3EQ.js +56 -0
- package/dist/chunk-4KXVN3EQ.js.map +1 -0
- package/dist/chunk-5SHZZC7L.js +234 -0
- package/dist/chunk-5SHZZC7L.js.map +1 -0
- package/dist/chunk-7UFINK3Q.js +1994 -0
- package/dist/chunk-7UFINK3Q.js.map +1 -0
- package/dist/chunk-JJLAES6W.js +76 -0
- package/dist/chunk-JJLAES6W.js.map +1 -0
- package/dist/chunk-KT52UU3U.js +985 -0
- package/dist/chunk-KT52UU3U.js.map +1 -0
- package/dist/chunk-LJIWB7KE.js +95 -0
- package/dist/chunk-LJIWB7KE.js.map +1 -0
- package/dist/chunk-NA652ART.js +596 -0
- package/dist/chunk-NA652ART.js.map +1 -0
- package/dist/chunk-OVLO7UOH.js +1071 -0
- package/dist/chunk-OVLO7UOH.js.map +1 -0
- package/dist/chunk-VRLUXCLD.js +31 -0
- package/dist/chunk-VRLUXCLD.js.map +1 -0
- package/dist/chunk-WMNT4OIE.js +249 -0
- package/dist/chunk-WMNT4OIE.js.map +1 -0
- package/dist/chunk-Y52IEYVM.js +131 -0
- package/dist/chunk-Y52IEYVM.js.map +1 -0
- package/dist/components/index.d.ts +14 -732
- package/dist/components/index.js +3 -6
- package/dist/config-CxvpD8Y6.d.ts +111 -0
- package/dist/{do-CaQVueZw.d.ts → do-D27i5bU0.d.ts} +32 -33
- package/dist/errors-DratdVIz.d.ts +346 -0
- package/dist/hooks/index.d.ts +450 -691
- package/dist/hooks/index.js +6 -4
- package/dist/hooks/things/index.d.ts +298 -0
- package/dist/hooks/things/index.js +8 -0
- package/dist/hooks/things/index.js.map +1 -0
- package/dist/index.d.ts +62 -989
- package/dist/index.js +12 -839
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +798 -0
- package/dist/lib/index.js +6 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/providers/index.d.ts +130 -34
- package/dist/providers/index.js +3 -2
- package/dist/query-keys-CZNFikIi.d.ts +153 -0
- package/dist/schemas/index.d.ts +5 -5
- package/dist/schemas/index.js +2 -2
- package/dist/schemas/index.js.map +1 -1
- package/dist/{thing-DtI25yZh.d.ts → thing-BF25aUtJ.d.ts} +72 -72
- package/dist/types/index.d.ts +693 -658
- package/dist/types/index.js +1 -2
- package/dist/views/index.d.ts +131 -0
- package/dist/views/index.js +11 -0
- package/dist/views/index.js.map +1 -0
- package/package.json +39 -17
- package/dist/__test-utils__/index.d.ts +0 -399
- package/dist/__test-utils__/index.js +0 -34641
- package/dist/__test-utils__/index.js.map +0 -1
- package/dist/chunk-EEDMN7UF.js +0 -1351
- package/dist/chunk-EEDMN7UF.js.map +0 -1
- package/dist/chunk-G3PMV62Z.js +0 -33
- package/dist/chunk-G3PMV62Z.js.map +0 -1
- package/dist/chunk-NXPXL5NA.js +0 -3789
- package/dist/chunk-NXPXL5NA.js.map +0 -1
- package/dist/chunk-PC5FJY6M.js +0 -20
- package/dist/chunk-PC5FJY6M.js.map +0 -1
- package/dist/chunk-XF6LKY2M.js +0 -445
- package/dist/chunk-XF6LKY2M.js.map +0 -1
- package/dist/magic-string.es-J7BYFTTJ.js +0 -1307
- package/dist/magic-string.es-J7BYFTTJ.js.map +0 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
|
|
4
|
+
// src/lib/utils.ts
|
|
5
|
+
function cn(...inputs) {
|
|
6
|
+
return twMerge(clsx(inputs));
|
|
7
|
+
}
|
|
8
|
+
function formatSemanticId(ns, type, id) {
|
|
9
|
+
return `${ns}/${type}/${id}`;
|
|
10
|
+
}
|
|
11
|
+
function parseSemanticId(semanticId) {
|
|
12
|
+
const parts = semanticId.split("/");
|
|
13
|
+
if (parts.length < 3) {
|
|
14
|
+
throw new Error(`Invalid semantic ID format: ${semanticId}`);
|
|
15
|
+
}
|
|
16
|
+
const type = parts[0];
|
|
17
|
+
const id = parts[parts.length - 1];
|
|
18
|
+
const namespace = parts.slice(1, -1).join("/");
|
|
19
|
+
return { type, namespace, id };
|
|
20
|
+
}
|
|
21
|
+
function formatDate(date, options) {
|
|
22
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
23
|
+
return d.toLocaleDateString(void 0, options ?? {
|
|
24
|
+
year: "numeric",
|
|
25
|
+
month: "short",
|
|
26
|
+
day: "numeric"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function formatDateTime(date, options) {
|
|
30
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
31
|
+
return d.toLocaleString(void 0, options ?? {
|
|
32
|
+
year: "numeric",
|
|
33
|
+
month: "short",
|
|
34
|
+
day: "numeric",
|
|
35
|
+
hour: "2-digit",
|
|
36
|
+
minute: "2-digit"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function formatRelativeTime(date) {
|
|
40
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
41
|
+
const now = /* @__PURE__ */ new Date();
|
|
42
|
+
const diffMs = now.getTime() - d.getTime();
|
|
43
|
+
const diffSec = Math.floor(diffMs / 1e3);
|
|
44
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
45
|
+
const diffHour = Math.floor(diffMin / 60);
|
|
46
|
+
const diffDay = Math.floor(diffHour / 24);
|
|
47
|
+
if (diffSec < 60) return `${diffSec} ${diffSec === 1 ? "second" : "seconds"} ago`;
|
|
48
|
+
if (diffMin < 60) return `${diffMin} ${diffMin === 1 ? "minute" : "minutes"} ago`;
|
|
49
|
+
if (diffHour < 24) return `${diffHour} ${diffHour === 1 ? "hour" : "hours"} ago`;
|
|
50
|
+
if (diffDay < 7) return `${diffDay} ${diffDay === 1 ? "day" : "days"} ago`;
|
|
51
|
+
return formatDate(d);
|
|
52
|
+
}
|
|
53
|
+
function formatDecimal(value, decimals = 1) {
|
|
54
|
+
const fixed = value.toFixed(decimals);
|
|
55
|
+
return fixed.endsWith(".0") ? fixed.slice(0, -2) : fixed;
|
|
56
|
+
}
|
|
57
|
+
function formatNumber(num) {
|
|
58
|
+
if (num < 0) return `-${formatNumber(-num)}`;
|
|
59
|
+
if (num >= 1e6) return `${formatDecimal(num / 1e6)}M`;
|
|
60
|
+
if (num >= 1e3) return `${formatDecimal(num / 1e3)}K`;
|
|
61
|
+
return num.toString();
|
|
62
|
+
}
|
|
63
|
+
function formatBytes(bytes) {
|
|
64
|
+
if (bytes === 0) return "0 B";
|
|
65
|
+
const k = 1024;
|
|
66
|
+
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
67
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
68
|
+
return `${formatDecimal(bytes / Math.pow(k, i))} ${sizes[i]}`;
|
|
69
|
+
}
|
|
70
|
+
function formatDuration(ms) {
|
|
71
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
72
|
+
if (ms < 6e4) return `${formatDecimal(ms / 1e3)}s`;
|
|
73
|
+
if (ms < 36e5) return `${Math.floor(ms / 6e4)}m ${Math.floor(ms % 6e4 / 1e3)}s`;
|
|
74
|
+
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
75
|
+
}
|
|
76
|
+
function truncate(text, maxLength, suffix = "...") {
|
|
77
|
+
if (text.length <= maxLength) return text;
|
|
78
|
+
return text.slice(0, maxLength) + suffix;
|
|
79
|
+
}
|
|
80
|
+
function capitalize(text) {
|
|
81
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
82
|
+
}
|
|
83
|
+
function camelToTitle(text) {
|
|
84
|
+
return text.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
|
|
85
|
+
}
|
|
86
|
+
function generateId(prefix) {
|
|
87
|
+
const id = Math.random().toString(36).substring(2, 15);
|
|
88
|
+
return prefix ? `${prefix}_${id}` : id;
|
|
89
|
+
}
|
|
90
|
+
function debounce(fn, delay) {
|
|
91
|
+
let timeoutId;
|
|
92
|
+
return (...args) => {
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
timeoutId = setTimeout(() => fn(...args), delay);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function groupBy(array, keyFn) {
|
|
98
|
+
return array.reduce((acc, item) => {
|
|
99
|
+
const key = keyFn(item);
|
|
100
|
+
if (!acc[key]) acc[key] = [];
|
|
101
|
+
acc[key].push(item);
|
|
102
|
+
return acc;
|
|
103
|
+
}, {});
|
|
104
|
+
}
|
|
105
|
+
async function retryWithBackoff(fn, config = {}) {
|
|
106
|
+
const { maxRetries = 3, backoffMultiplier = 1e3, signal, onRetry } = config;
|
|
107
|
+
let lastError;
|
|
108
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
109
|
+
if (signal?.aborted) {
|
|
110
|
+
throw lastError ?? new Error("Retry cancelled");
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
return await fn();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
lastError = error instanceof Error ? error : new Error("Retry failed");
|
|
116
|
+
if (attempt < maxRetries - 1) {
|
|
117
|
+
onRetry?.(lastError, attempt + 1);
|
|
118
|
+
const delay = Math.pow(2, attempt) * backoffMultiplier;
|
|
119
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
120
|
+
if (signal?.aborted) {
|
|
121
|
+
throw lastError ?? new Error("Retry cancelled");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
throw lastError;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { camelToTitle, capitalize, cn, debounce, formatBytes, formatDate, formatDateTime, formatDuration, formatNumber, formatRelativeTime, formatSemanticId, generateId, groupBy, parseSemanticId, retryWithBackoff, truncate };
|
|
130
|
+
//# sourceMappingURL=chunk-Y52IEYVM.js.map
|
|
131
|
+
//# sourceMappingURL=chunk-Y52IEYVM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts"],"names":[],"mappings":"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","file":"chunk-Y52IEYVM.js","sourcesContent":["import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\n/**\n * Merge class names with Tailwind CSS support\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n/**\n * Format a semantic ID (ns/type/id)\n */\nexport function formatSemanticId(ns: string, type: string, id: string): string {\n return `${ns}/${type}/${id}`\n}\n\n/**\n * Parse a semantic ID into components\n * Format: type/namespace/id where namespace can contain slashes\n * @throws Error if the semantic ID format is invalid\n */\nexport function parseSemanticId(semanticId: string): { type: string; namespace: string; id: string } {\n const parts = semanticId.split('/')\n if (parts.length < 3) {\n throw new Error(`Invalid semantic ID format: ${semanticId}`)\n }\n\n // Format is type/namespace.../id\n // Type is first, id is last, namespace is everything in between\n const type = parts[0]\n const id = parts[parts.length - 1]\n const namespace = parts.slice(1, -1).join('/')\n\n return { type, namespace, id }\n}\n\n/**\n * Format a date for display\n */\nexport function formatDate(date: Date | string, options?: Intl.DateTimeFormatOptions): string {\n const d = typeof date === 'string' ? new Date(date) : date\n return d.toLocaleDateString(undefined, options ?? {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n })\n}\n\n/**\n * Format a date and time for display\n */\nexport function formatDateTime(date: Date | string, options?: Intl.DateTimeFormatOptions): string {\n const d = typeof date === 'string' ? new Date(date) : date\n return d.toLocaleString(undefined, options ?? {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n}\n\n/**\n * Format a relative time (e.g., \"2 hours ago\")\n */\nexport function formatRelativeTime(date: Date | string): string {\n const d = typeof date === 'string' ? new Date(date) : date\n const now = new Date()\n const diffMs = now.getTime() - d.getTime()\n const diffSec = Math.floor(diffMs / 1000)\n const diffMin = Math.floor(diffSec / 60)\n const diffHour = Math.floor(diffMin / 60)\n const diffDay = Math.floor(diffHour / 24)\n\n if (diffSec < 60) return `${diffSec} ${diffSec === 1 ? 'second' : 'seconds'} ago`\n if (diffMin < 60) return `${diffMin} ${diffMin === 1 ? 'minute' : 'minutes'} ago`\n if (diffHour < 24) return `${diffHour} ${diffHour === 1 ? 'hour' : 'hours'} ago`\n if (diffDay < 7) return `${diffDay} ${diffDay === 1 ? 'day' : 'days'} ago`\n return formatDate(d)\n}\n\n/**\n * Format a decimal, removing trailing .0 for whole numbers\n */\nfunction formatDecimal(value: number, decimals: number = 1): string {\n const fixed = value.toFixed(decimals)\n // Remove trailing .0 for whole numbers\n return fixed.endsWith('.0') ? fixed.slice(0, -2) : fixed\n}\n\n/**\n * Format a number with abbreviation (1K, 1M, etc.)\n */\nexport function formatNumber(num: number): string {\n if (num < 0) return `-${formatNumber(-num)}`\n if (num >= 1_000_000) return `${formatDecimal(num / 1_000_000)}M`\n if (num >= 1_000) return `${formatDecimal(num / 1_000)}K`\n return num.toString()\n}\n\n/**\n * Format bytes to human-readable string\n */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${formatDecimal(bytes / Math.pow(k, i))} ${sizes[i]}`\n}\n\n/**\n * Format duration in milliseconds to human-readable string\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`\n if (ms < 60_000) return `${formatDecimal(ms / 1000)}s`\n if (ms < 3_600_000) return `${Math.floor(ms / 60_000)}m ${Math.floor((ms % 60_000) / 1000)}s`\n return `${Math.floor(ms / 3_600_000)}h ${Math.floor((ms % 3_600_000) / 60_000)}m`\n}\n\n/**\n * Truncate text with ellipsis\n */\nexport function truncate(text: string, maxLength: number, suffix: string = '...'): string {\n if (text.length <= maxLength) return text\n return text.slice(0, maxLength) + suffix\n}\n\n/**\n * Capitalize first letter\n */\nexport function capitalize(text: string): string {\n return text.charAt(0).toUpperCase() + text.slice(1)\n}\n\n/**\n * Convert camelCase to Title Case\n */\nexport function camelToTitle(text: string): string {\n return text\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .trim()\n}\n\n/**\n * Generate a random ID\n */\nexport function generateId(prefix?: string): string {\n const id = Math.random().toString(36).substring(2, 15)\n return prefix ? `${prefix}_${id}` : id\n}\n\n/**\n * Debounce function\n *\n * Creates a debounced version of the function that delays execution\n * until after the specified delay has passed since the last call.\n *\n * @example\n * ```ts\n * const debouncedSearch = debounce((query: string) => {\n * fetch(`/search?q=${query}`)\n * }, 300)\n *\n * // Only the last call within 300ms will execute\n * debouncedSearch('h')\n * debouncedSearch('he')\n * debouncedSearch('hello') // Only this one runs\n * ```\n */\nexport function debounce<Args extends unknown[]>(\n fn: (...args: Args) => unknown,\n delay: number\n): (...args: Args) => void {\n let timeoutId: ReturnType<typeof setTimeout>\n return (...args: Args) => {\n clearTimeout(timeoutId)\n timeoutId = setTimeout(() => fn(...args), delay)\n }\n}\n\n/**\n * Group array by key\n */\nexport function groupBy<T, K extends string | number>(\n array: T[],\n keyFn: (item: T) => K\n): Record<K, T[]> {\n return array.reduce((acc, item) => {\n const key = keyFn(item)\n if (!acc[key]) acc[key] = []\n acc[key].push(item)\n return acc\n }, {} as Record<K, T[]>)\n}\n\n/**\n * Configuration for retry with exponential backoff\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts (default: 3) */\n maxRetries?: number\n /** Base multiplier for backoff in ms (default: 1000). Backoff = 2^attempt * multiplier */\n backoffMultiplier?: number\n /** Optional AbortSignal for cancellation */\n signal?: AbortSignal\n /** Callback invoked before each retry with the error and attempt number */\n onRetry?: (error: Error, attempt: number) => void\n}\n\n/**\n * Execute an async function with retry and exponential backoff\n *\n * Retries the provided function on failure with exponential backoff delays.\n * Backoff formula: 2^attempt * backoffMultiplier (default: 1s, 2s, 4s, etc.)\n *\n * @param fn - Async function to execute\n * @param config - Retry configuration\n * @returns Promise resolving to the function result\n * @throws Last error if all retries exhausted\n *\n * @example\n * ```ts\n * // Basic usage\n * const result = await retryWithBackoff(\n * () => fetch('/api/health'),\n * { maxRetries: 3 }\n * )\n *\n * // With cancellation\n * const controller = new AbortController()\n * const result = await retryWithBackoff(\n * () => fetch('/api/health'),\n * { maxRetries: 3, signal: controller.signal }\n * )\n * // Later: controller.abort()\n *\n * // With retry callback\n * const result = await retryWithBackoff(\n * () => fetch('/api/health'),\n * {\n * maxRetries: 3,\n * onRetry: (error, attempt) => console.log(`Retry ${attempt}: ${error.message}`)\n * }\n * )\n * ```\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n config: RetryConfig = {}\n): Promise<T> {\n const { maxRetries = 3, backoffMultiplier = 1000, signal, onRetry } = config\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n // Check for cancellation before each attempt\n if (signal?.aborted) {\n throw lastError ?? new Error('Retry cancelled')\n }\n\n try {\n return await fn()\n } catch (error) {\n lastError = error instanceof Error ? error : new Error('Retry failed')\n\n // Don't wait after last attempt\n if (attempt < maxRetries - 1) {\n // Notify before retry\n onRetry?.(lastError, attempt + 1)\n\n // Exponential backoff: 2^0 * mult, 2^1 * mult, 2^2 * mult, etc.\n const delay = Math.pow(2, attempt) * backoffMultiplier\n\n // Wait with timeout\n await new Promise<void>((resolve) => setTimeout(resolve, delay))\n\n // Check for cancellation after waiting\n if (signal?.aborted) {\n throw lastError ?? new Error('Retry cancelled')\n }\n }\n }\n }\n\n throw lastError\n}\n"]}
|