@ai-matrx/kit 0.5.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/CHANGELOG.md +132 -0
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/dist/autosave.cjs +92 -0
- package/dist/autosave.cjs.map +1 -0
- package/dist/autosave.d.cts +17 -0
- package/dist/autosave.d.ts +17 -0
- package/dist/autosave.js +72 -0
- package/dist/autosave.js.map +1 -0
- package/dist/clipboard.cjs +152 -0
- package/dist/clipboard.cjs.map +1 -0
- package/dist/clipboard.d.cts +17 -0
- package/dist/clipboard.d.ts +17 -0
- package/dist/clipboard.js +132 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/color-util.cjs +790 -0
- package/dist/color-util.cjs.map +1 -0
- package/dist/color-util.d.cts +235 -0
- package/dist/color-util.d.ts +235 -0
- package/dist/color-util.js +767 -0
- package/dist/color-util.js.map +1 -0
- package/dist/concurrency.cjs +59 -0
- package/dist/concurrency.cjs.map +1 -0
- package/dist/concurrency.d.cts +19 -0
- package/dist/concurrency.d.ts +19 -0
- package/dist/concurrency.js +38 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/confirm.cjs +344 -0
- package/dist/confirm.cjs.map +1 -0
- package/dist/confirm.d.cts +132 -0
- package/dist/confirm.d.ts +132 -0
- package/dist/confirm.js +312 -0
- package/dist/confirm.js.map +1 -0
- package/dist/delimiter-guard.cjs +172 -0
- package/dist/delimiter-guard.cjs.map +1 -0
- package/dist/delimiter-guard.d.cts +119 -0
- package/dist/delimiter-guard.d.ts +119 -0
- package/dist/delimiter-guard.js +151 -0
- package/dist/delimiter-guard.js.map +1 -0
- package/dist/drafts.cjs +223 -0
- package/dist/drafts.cjs.map +1 -0
- package/dist/drafts.d.cts +62 -0
- package/dist/drafts.d.ts +62 -0
- package/dist/drafts.js +201 -0
- package/dist/drafts.js.map +1 -0
- package/dist/idb-store.cjs +178 -0
- package/dist/idb-store.cjs.map +1 -0
- package/dist/idb-store.d.cts +111 -0
- package/dist/idb-store.d.ts +111 -0
- package/dist/idb-store.js +155 -0
- package/dist/idb-store.js.map +1 -0
- package/dist/idle-scheduler.cjs +268 -0
- package/dist/idle-scheduler.cjs.map +1 -0
- package/dist/idle-scheduler.d.cts +185 -0
- package/dist/idle-scheduler.d.ts +185 -0
- package/dist/idle-scheduler.js +246 -0
- package/dist/idle-scheduler.js.map +1 -0
- package/dist/index.cjs +3113 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +897 -0
- package/dist/index.d.ts +897 -0
- package/dist/index.js +3088 -0
- package/dist/index.js.map +1 -0
- package/dist/invalidation.cjs +64 -0
- package/dist/invalidation.cjs.map +1 -0
- package/dist/invalidation.d.cts +52 -0
- package/dist/invalidation.d.ts +52 -0
- package/dist/invalidation.js +43 -0
- package/dist/invalidation.js.map +1 -0
- package/dist/json-format.cjs +319 -0
- package/dist/json-format.cjs.map +1 -0
- package/dist/json-format.d.cts +148 -0
- package/dist/json-format.d.ts +148 -0
- package/dist/json-format.js +286 -0
- package/dist/json-format.js.map +1 -0
- package/dist/latest-request.cjs +36 -0
- package/dist/latest-request.cjs.map +1 -0
- package/dist/latest-request.d.cts +29 -0
- package/dist/latest-request.d.ts +29 -0
- package/dist/latest-request.js +16 -0
- package/dist/latest-request.js.map +1 -0
- package/dist/qr.cjs +109 -0
- package/dist/qr.cjs.map +1 -0
- package/dist/qr.d.cts +47 -0
- package/dist/qr.d.ts +47 -0
- package/dist/qr.js +78 -0
- package/dist/qr.js.map +1 -0
- package/dist/react-tree.cjs +69 -0
- package/dist/react-tree.cjs.map +1 -0
- package/dist/react-tree.d.cts +38 -0
- package/dist/react-tree.d.ts +38 -0
- package/dist/react-tree.js +38 -0
- package/dist/react-tree.js.map +1 -0
- package/dist/search-scoring.cjs +116 -0
- package/dist/search-scoring.cjs.map +1 -0
- package/dist/search-scoring.d.cts +77 -0
- package/dist/search-scoring.d.ts +77 -0
- package/dist/search-scoring.js +95 -0
- package/dist/search-scoring.js.map +1 -0
- package/dist/text-case.cjs +313 -0
- package/dist/text-case.cjs.map +1 -0
- package/dist/text-case.d.cts +53 -0
- package/dist/text-case.d.ts +53 -0
- package/dist/text-case.js +292 -0
- package/dist/text-case.js.map +1 -0
- package/dist/toast.cjs +74 -0
- package/dist/toast.cjs.map +1 -0
- package/dist/toast.d.cts +92 -0
- package/dist/toast.d.ts +92 -0
- package/dist/toast.js +54 -0
- package/dist/toast.js.map +1 -0
- package/dist/url-state.cjs +212 -0
- package/dist/url-state.cjs.map +1 -0
- package/dist/url-state.d.cts +90 -0
- package/dist/url-state.d.ts +90 -0
- package/dist/url-state.js +199 -0
- package/dist/url-state.js.map +1 -0
- package/package.json +286 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
// src/text-case.ts
|
|
2
|
+
var DEFAULT_WORD_REPLACEMENTS = {
|
|
3
|
+
// Acronyms & initialisms
|
|
4
|
+
"api": "API",
|
|
5
|
+
"apis": "APIs",
|
|
6
|
+
"ui": "UI",
|
|
7
|
+
"ux": "UX",
|
|
8
|
+
"id": "ID",
|
|
9
|
+
"ids": "IDs",
|
|
10
|
+
"qr": "QR",
|
|
11
|
+
"ssr": "SSR",
|
|
12
|
+
"csr": "CSR",
|
|
13
|
+
"ssg": "SSG",
|
|
14
|
+
"isr": "ISR",
|
|
15
|
+
"spa": "SPA",
|
|
16
|
+
"pwa": "PWA",
|
|
17
|
+
"sdk": "SDK",
|
|
18
|
+
"sdks": "SDKs",
|
|
19
|
+
"cli": "CLI",
|
|
20
|
+
"tty": "TTY",
|
|
21
|
+
"repl": "REPL",
|
|
22
|
+
"ci": "CI",
|
|
23
|
+
"cd": "CD",
|
|
24
|
+
"cpu": "CPU",
|
|
25
|
+
"cpus": "CPUs",
|
|
26
|
+
"gpu": "GPU",
|
|
27
|
+
"gpus": "GPUs",
|
|
28
|
+
"ram": "RAM",
|
|
29
|
+
"rom": "ROM",
|
|
30
|
+
"ssd": "SSD",
|
|
31
|
+
"ssds": "SSDs",
|
|
32
|
+
"hdd": "HDD",
|
|
33
|
+
"hdds": "HDDs",
|
|
34
|
+
"kpi": "KPI",
|
|
35
|
+
"kpis": "KPIs",
|
|
36
|
+
"sla": "SLA",
|
|
37
|
+
"slas": "SLAs",
|
|
38
|
+
"slo": "SLO",
|
|
39
|
+
"slos": "SLOs",
|
|
40
|
+
"sli": "SLI",
|
|
41
|
+
"slis": "SLIs",
|
|
42
|
+
"dom": "DOM",
|
|
43
|
+
// Web, formats, protocols
|
|
44
|
+
"url": "URL",
|
|
45
|
+
"urls": "URLs",
|
|
46
|
+
"uri": "URI",
|
|
47
|
+
"uris": "URIs",
|
|
48
|
+
"http": "HTTP",
|
|
49
|
+
"https": "HTTPS",
|
|
50
|
+
"html": "HTML",
|
|
51
|
+
"css": "CSS",
|
|
52
|
+
"json": "JSON",
|
|
53
|
+
"yaml": "YAML",
|
|
54
|
+
"yml": "YML",
|
|
55
|
+
"toml": "TOML",
|
|
56
|
+
"csv": "CSV",
|
|
57
|
+
"pdf": "PDF",
|
|
58
|
+
"tsv": "TSV",
|
|
59
|
+
"jpg": "JPG",
|
|
60
|
+
"jpeg": "JPEG",
|
|
61
|
+
"png": "PNG",
|
|
62
|
+
"gif": "GIF",
|
|
63
|
+
"webp": "WebP",
|
|
64
|
+
"heic": "HEIC",
|
|
65
|
+
"heif": "HEIF",
|
|
66
|
+
"bmp": "BMP",
|
|
67
|
+
"tiff": "TIFF",
|
|
68
|
+
"ico": "ICO",
|
|
69
|
+
"xml": "XML",
|
|
70
|
+
"sql": "SQL",
|
|
71
|
+
"db": "DB",
|
|
72
|
+
"dbs": "DBs",
|
|
73
|
+
"nosql": "NoSQL",
|
|
74
|
+
"graphql": "GraphQL",
|
|
75
|
+
"grpc": "gRPC",
|
|
76
|
+
"rest": "REST",
|
|
77
|
+
"restful": "RESTful",
|
|
78
|
+
"websocket": "WebSocket",
|
|
79
|
+
"websockets": "WebSockets",
|
|
80
|
+
"webrtc": "WebRTC",
|
|
81
|
+
// Networking
|
|
82
|
+
"ip": "IP",
|
|
83
|
+
"ipv4": "IPv4",
|
|
84
|
+
"ipv6": "IPv6",
|
|
85
|
+
"dns": "DNS",
|
|
86
|
+
"dhcp": "DHCP",
|
|
87
|
+
"nat": "NAT",
|
|
88
|
+
"tcp": "TCP",
|
|
89
|
+
"udp": "UDP",
|
|
90
|
+
"icmp": "ICMP",
|
|
91
|
+
"ttl": "TTL",
|
|
92
|
+
"lan": "LAN",
|
|
93
|
+
"wan": "WAN",
|
|
94
|
+
"vlan": "VLAN",
|
|
95
|
+
"cdn": "CDN",
|
|
96
|
+
"ftp": "FTP",
|
|
97
|
+
"ssh": "SSH",
|
|
98
|
+
"tls": "TLS",
|
|
99
|
+
"ssl": "SSL",
|
|
100
|
+
// Security & crypto
|
|
101
|
+
"jwt": "JWT",
|
|
102
|
+
"jws": "JWS",
|
|
103
|
+
"jwe": "JWE",
|
|
104
|
+
"hmac": "HMAC",
|
|
105
|
+
"rsa": "RSA",
|
|
106
|
+
"ecdsa": "ECDSA",
|
|
107
|
+
"aes": "AES",
|
|
108
|
+
"pbkdf2": "PBKDF2",
|
|
109
|
+
"argon2": "Argon2",
|
|
110
|
+
"scrypt": "scrypt",
|
|
111
|
+
"totp": "TOTP",
|
|
112
|
+
"hotp": "HOTP",
|
|
113
|
+
"mfa": "MFA",
|
|
114
|
+
"2fa": "2FA",
|
|
115
|
+
"csrf": "CSRF",
|
|
116
|
+
"xss": "XSS",
|
|
117
|
+
"ssrf": "SSRF",
|
|
118
|
+
"rce": "RCE",
|
|
119
|
+
"dos": "DoS",
|
|
120
|
+
"ddos": "DDoS",
|
|
121
|
+
"mitm": "MITM",
|
|
122
|
+
"csp": "CSP",
|
|
123
|
+
"cors": "CORS",
|
|
124
|
+
"pii": "PII",
|
|
125
|
+
"phi": "PHI",
|
|
126
|
+
"gdpr": "GDPR",
|
|
127
|
+
"ccpa": "CCPA",
|
|
128
|
+
"hipaa": "HIPAA",
|
|
129
|
+
"rfc": "RFC",
|
|
130
|
+
// Platforms, langs, tools (single-token)
|
|
131
|
+
"javascript": "JavaScript",
|
|
132
|
+
"typescript": "TypeScript",
|
|
133
|
+
"jsx": "JSX",
|
|
134
|
+
"tsx": "TSX",
|
|
135
|
+
"node": "Node",
|
|
136
|
+
// (used when tokenized alone)
|
|
137
|
+
"deno": "Deno",
|
|
138
|
+
"bun": "Bun",
|
|
139
|
+
"react": "React",
|
|
140
|
+
"nextjs": "Next.js",
|
|
141
|
+
// if your tokenizer drops dots, keep this
|
|
142
|
+
"nodejs": "Node.js",
|
|
143
|
+
"postgresql": "PostgreSQL",
|
|
144
|
+
"postgres": "Postgres",
|
|
145
|
+
"mysql": "MySQL",
|
|
146
|
+
"sqlite": "SQLite",
|
|
147
|
+
"redis": "Redis",
|
|
148
|
+
"supabase": "Supabase",
|
|
149
|
+
"docker": "Docker",
|
|
150
|
+
"kubernetes": "Kubernetes",
|
|
151
|
+
"k8s": "Kubernetes",
|
|
152
|
+
"helm": "Helm",
|
|
153
|
+
"npm": "npm",
|
|
154
|
+
"pnpm": "pnpm",
|
|
155
|
+
"yarn": "Yarn",
|
|
156
|
+
"eslint": "ESLint",
|
|
157
|
+
"prettier": "Prettier",
|
|
158
|
+
"vite": "Vite",
|
|
159
|
+
"webpack": "Webpack",
|
|
160
|
+
"babel": "Babel",
|
|
161
|
+
// OS & vendors
|
|
162
|
+
"macos": "macOS",
|
|
163
|
+
"ios": "iOS",
|
|
164
|
+
"ipados": "iPadOS",
|
|
165
|
+
"watchos": "watchOS",
|
|
166
|
+
"tvos": "tvOS",
|
|
167
|
+
"windows": "Windows",
|
|
168
|
+
"linux": "Linux",
|
|
169
|
+
"ubuntu": "Ubuntu",
|
|
170
|
+
"github": "GitHub",
|
|
171
|
+
"gitlab": "GitLab",
|
|
172
|
+
"bitbucket": "Bitbucket",
|
|
173
|
+
// Data & analytics
|
|
174
|
+
"etl": "ETL",
|
|
175
|
+
"elt": "ELT",
|
|
176
|
+
"olap": "OLAP",
|
|
177
|
+
"oltp": "OLTP",
|
|
178
|
+
"bi": "BI",
|
|
179
|
+
// Time & locales
|
|
180
|
+
"utc": "UTC",
|
|
181
|
+
"gmt": "GMT",
|
|
182
|
+
"pst": "PST",
|
|
183
|
+
"pdt": "PDT",
|
|
184
|
+
"pt": "PT",
|
|
185
|
+
// Common “small words” to keep lowercase (unless first/last word)
|
|
186
|
+
"or": "or",
|
|
187
|
+
"and": "and",
|
|
188
|
+
"the": "the",
|
|
189
|
+
"of": "of",
|
|
190
|
+
"in": "in",
|
|
191
|
+
"to": "to",
|
|
192
|
+
"with": "with",
|
|
193
|
+
"as": "as",
|
|
194
|
+
"by": "by",
|
|
195
|
+
"for": "for",
|
|
196
|
+
"on": "on",
|
|
197
|
+
"at": "at",
|
|
198
|
+
"up": "up",
|
|
199
|
+
"a": "a",
|
|
200
|
+
"an": "an",
|
|
201
|
+
"is": "is",
|
|
202
|
+
"are": "are",
|
|
203
|
+
"was": "was",
|
|
204
|
+
"were": "were",
|
|
205
|
+
"be": "be",
|
|
206
|
+
"but": "but",
|
|
207
|
+
"nor": "nor",
|
|
208
|
+
"so": "so",
|
|
209
|
+
"yet": "yet",
|
|
210
|
+
"per": "per",
|
|
211
|
+
"via": "via",
|
|
212
|
+
// Latin abbreviations (tokenized as words in some pipelines)
|
|
213
|
+
"eg": "e.g.",
|
|
214
|
+
"ie": "i.e.",
|
|
215
|
+
"etc": "etc.",
|
|
216
|
+
"aka": "aka",
|
|
217
|
+
"vs": "vs.",
|
|
218
|
+
"v": "v.",
|
|
219
|
+
// Client abbreviations
|
|
220
|
+
"CIC": "CIC",
|
|
221
|
+
"AGR": "AGR",
|
|
222
|
+
"AGER": "AGER",
|
|
223
|
+
"DD": "DD",
|
|
224
|
+
"TS": "TS",
|
|
225
|
+
"TM": "TM",
|
|
226
|
+
"arman": "Arman"
|
|
227
|
+
};
|
|
228
|
+
var DEFAULT_OPTIONS = {
|
|
229
|
+
textCase: "title",
|
|
230
|
+
wordReplacements: DEFAULT_WORD_REPLACEMENTS,
|
|
231
|
+
trim: true
|
|
232
|
+
};
|
|
233
|
+
function formatText(text, options = {}) {
|
|
234
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
235
|
+
if (!text) return "";
|
|
236
|
+
let normalized = text.replace(/_/g, " ").replace(/-/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\s+/g, " ");
|
|
237
|
+
if (opts.trim) {
|
|
238
|
+
normalized = normalized.trim();
|
|
239
|
+
}
|
|
240
|
+
let caseTransformed = normalized;
|
|
241
|
+
switch (opts.textCase) {
|
|
242
|
+
case "title":
|
|
243
|
+
caseTransformed = normalized.replace(
|
|
244
|
+
/\w\S*/g,
|
|
245
|
+
(word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
|
246
|
+
);
|
|
247
|
+
break;
|
|
248
|
+
case "sentence":
|
|
249
|
+
if (normalized.length > 0) {
|
|
250
|
+
caseTransformed = normalized.charAt(0).toUpperCase() + normalized.slice(1).toLowerCase();
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
case "lower":
|
|
254
|
+
caseTransformed = normalized.toLowerCase();
|
|
255
|
+
break;
|
|
256
|
+
case "upper":
|
|
257
|
+
caseTransformed = normalized.toUpperCase();
|
|
258
|
+
break;
|
|
259
|
+
case "normal":
|
|
260
|
+
default:
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
let result = caseTransformed;
|
|
264
|
+
if (opts.wordReplacements) {
|
|
265
|
+
Object.entries(opts.wordReplacements).forEach(([key, value]) => {
|
|
266
|
+
const regex = new RegExp(`\\b${key}\\b`, "gi");
|
|
267
|
+
result = result.replace(regex, value);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
function createFormatter(defaultOptions = {}) {
|
|
273
|
+
return (text, overrideOptions = {}) => formatText(text, { ...defaultOptions, ...overrideOptions });
|
|
274
|
+
}
|
|
275
|
+
var formatTitleCase = createFormatter({ textCase: "title" });
|
|
276
|
+
var formatSentenceCase = createFormatter({ textCase: "sentence" });
|
|
277
|
+
var formatNormalCase = createFormatter({ textCase: "normal" });
|
|
278
|
+
var formatUpperCase = createFormatter({ textCase: "upper" });
|
|
279
|
+
var formatLowerCase = createFormatter({ textCase: "lower" });
|
|
280
|
+
var formatWithoutReplacements = createFormatter({ wordReplacements: {} });
|
|
281
|
+
export {
|
|
282
|
+
DEFAULT_WORD_REPLACEMENTS,
|
|
283
|
+
createFormatter,
|
|
284
|
+
formatLowerCase,
|
|
285
|
+
formatNormalCase,
|
|
286
|
+
formatSentenceCase,
|
|
287
|
+
formatText,
|
|
288
|
+
formatTitleCase,
|
|
289
|
+
formatUpperCase,
|
|
290
|
+
formatWithoutReplacements
|
|
291
|
+
};
|
|
292
|
+
//# sourceMappingURL=text-case.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/text-case.ts"],"sourcesContent":["/**\n * Text formatting options\n */\nexport type TextCaseOption = 'title' | 'sentence' | 'normal' | 'lower' | 'upper';\n\nexport interface TextFormatterOptions {\n /**\n * Text case to apply after normalization\n * - title: First Letter Of Each Word Capitalized\n * - sentence: First letter of first word capitalized\n * - normal: No case transformation after normalization\n * - lower: all text lowercase\n * - upper: ALL TEXT UPPERCASE\n */\n textCase?: TextCaseOption;\n \n /**\n * Map of words to replace with specific formatting\n * Example: { 'api': 'API', 'ui': 'UI' }\n */\n wordReplacements?: Record<string, string>;\n \n /**\n * Whether to trim the result\n */\n trim?: boolean;\n}\n\n/**\n * Default word replacements for common acronyms and terms\n */\nexport type ReplacementMap = Readonly<Record<string, string>>;\n\nexport const DEFAULT_WORD_REPLACEMENTS: ReplacementMap = {\n // Acronyms & initialisms\n 'api': 'API',\n 'apis': 'APIs',\n 'ui': 'UI',\n 'ux': 'UX',\n 'id': 'ID',\n 'ids': 'IDs',\n 'qr': 'QR',\n 'ssr': 'SSR',\n 'csr': 'CSR',\n 'ssg': 'SSG',\n 'isr': 'ISR',\n 'spa': 'SPA',\n 'pwa': 'PWA',\n 'sdk': 'SDK',\n 'sdks': 'SDKs',\n 'cli': 'CLI',\n 'tty': 'TTY',\n 'repl': 'REPL',\n 'ci': 'CI',\n 'cd': 'CD',\n 'cpu': 'CPU',\n 'cpus': 'CPUs',\n 'gpu': 'GPU',\n 'gpus': 'GPUs',\n 'ram': 'RAM',\n 'rom': 'ROM',\n 'ssd': 'SSD',\n 'ssds': 'SSDs',\n 'hdd': 'HDD',\n 'hdds': 'HDDs',\n 'kpi': 'KPI',\n 'kpis': 'KPIs',\n 'sla': 'SLA',\n 'slas': 'SLAs',\n 'slo': 'SLO',\n 'slos': 'SLOs',\n 'sli': 'SLI',\n 'slis': 'SLIs',\n 'dom': 'DOM',\n\n // Web, formats, protocols\n 'url': 'URL',\n 'urls': 'URLs',\n 'uri': 'URI',\n 'uris': 'URIs',\n 'http': 'HTTP',\n 'https': 'HTTPS',\n 'html': 'HTML',\n 'css': 'CSS',\n 'json': 'JSON',\n 'yaml': 'YAML',\n 'yml': 'YML',\n 'toml': 'TOML',\n 'csv': 'CSV',\n 'pdf': 'PDF',\n 'tsv': 'TSV',\n 'jpg': 'JPG',\n 'jpeg': 'JPEG',\n 'png': 'PNG',\n 'gif': 'GIF',\n 'webp': 'WebP',\n 'heic': 'HEIC',\n 'heif': 'HEIF',\n 'bmp': 'BMP',\n 'tiff': 'TIFF',\n 'ico': 'ICO',\n 'xml': 'XML',\n 'sql': 'SQL',\n 'db': 'DB',\n 'dbs': 'DBs',\n 'nosql': 'NoSQL',\n 'graphql': 'GraphQL',\n 'grpc': 'gRPC',\n 'rest': 'REST',\n 'restful': 'RESTful',\n 'websocket': 'WebSocket',\n 'websockets': 'WebSockets',\n 'webrtc': 'WebRTC',\n\n // Networking\n 'ip': 'IP',\n 'ipv4': 'IPv4',\n 'ipv6': 'IPv6',\n 'dns': 'DNS',\n 'dhcp': 'DHCP',\n 'nat': 'NAT',\n 'tcp': 'TCP',\n 'udp': 'UDP',\n 'icmp': 'ICMP',\n 'ttl': 'TTL',\n 'lan': 'LAN',\n 'wan': 'WAN',\n 'vlan': 'VLAN',\n 'cdn': 'CDN',\n 'ftp': 'FTP',\n 'ssh': 'SSH',\n 'tls': 'TLS',\n 'ssl': 'SSL',\n\n // Security & crypto\n 'jwt': 'JWT',\n 'jws': 'JWS',\n 'jwe': 'JWE',\n 'hmac': 'HMAC',\n 'rsa': 'RSA',\n 'ecdsa': 'ECDSA',\n 'aes': 'AES',\n 'pbkdf2': 'PBKDF2',\n 'argon2': 'Argon2',\n 'scrypt': 'scrypt',\n 'totp': 'TOTP',\n 'hotp': 'HOTP',\n 'mfa': 'MFA',\n '2fa': '2FA',\n 'csrf': 'CSRF',\n 'xss': 'XSS',\n 'ssrf': 'SSRF',\n 'rce': 'RCE',\n 'dos': 'DoS',\n 'ddos': 'DDoS',\n 'mitm': 'MITM',\n 'csp': 'CSP',\n 'cors': 'CORS',\n 'pii': 'PII',\n 'phi': 'PHI',\n 'gdpr': 'GDPR',\n 'ccpa': 'CCPA',\n 'hipaa': 'HIPAA',\n 'rfc': 'RFC',\n\n // Platforms, langs, tools (single-token)\n 'javascript': 'JavaScript',\n 'typescript': 'TypeScript',\n 'jsx': 'JSX',\n 'tsx': 'TSX',\n 'node': 'Node', // (used when tokenized alone)\n 'deno': 'Deno',\n 'bun': 'Bun',\n 'react': 'React',\n 'nextjs': 'Next.js', // if your tokenizer drops dots, keep this\n 'nodejs': 'Node.js',\n 'postgresql': 'PostgreSQL',\n 'postgres': 'Postgres',\n 'mysql': 'MySQL',\n 'sqlite': 'SQLite',\n 'redis': 'Redis',\n 'supabase': 'Supabase',\n 'docker': 'Docker',\n 'kubernetes': 'Kubernetes',\n 'k8s': 'Kubernetes',\n 'helm': 'Helm',\n 'npm': 'npm',\n 'pnpm': 'pnpm',\n 'yarn': 'Yarn',\n 'eslint': 'ESLint',\n 'prettier': 'Prettier',\n 'vite': 'Vite',\n 'webpack': 'Webpack',\n 'babel': 'Babel',\n\n // OS & vendors\n 'macos': 'macOS',\n 'ios': 'iOS',\n 'ipados': 'iPadOS',\n 'watchos': 'watchOS',\n 'tvos': 'tvOS',\n 'windows': 'Windows',\n 'linux': 'Linux',\n 'ubuntu': 'Ubuntu',\n 'github': 'GitHub',\n 'gitlab': 'GitLab',\n 'bitbucket': 'Bitbucket',\n\n // Data & analytics\n 'etl': 'ETL',\n 'elt': 'ELT',\n 'olap': 'OLAP',\n 'oltp': 'OLTP',\n 'bi': 'BI',\n\n // Time & locales\n 'utc': 'UTC',\n 'gmt': 'GMT',\n 'pst': 'PST',\n 'pdt': 'PDT',\n 'pt': 'PT',\n\n // Common “small words” to keep lowercase (unless first/last word)\n 'or': 'or',\n 'and': 'and',\n 'the': 'the',\n 'of': 'of',\n 'in': 'in',\n 'to': 'to',\n 'with': 'with',\n 'as': 'as',\n 'by': 'by',\n 'for': 'for',\n 'on': 'on',\n 'at': 'at',\n 'up': 'up',\n 'a': 'a',\n 'an': 'an',\n 'is': 'is',\n 'are': 'are',\n 'was': 'was',\n 'were': 'were',\n 'be': 'be',\n 'but': 'but',\n 'nor': 'nor',\n 'so': 'so',\n 'yet': 'yet',\n 'per': 'per',\n 'via': 'via',\n\n // Latin abbreviations (tokenized as words in some pipelines)\n 'eg': 'e.g.',\n 'ie': 'i.e.',\n 'etc': 'etc.',\n 'aka': 'aka',\n 'vs': 'vs.',\n 'v': 'v.',\n\n // Client abbreviations\n 'CIC': 'CIC',\n 'AGR': 'AGR',\n 'AGER': 'AGER',\n 'DD': 'DD',\n 'TS': 'TS',\n 'TM': 'TM',\n 'arman': \"Arman\",\n};\n\n/**\n * Default options for text formatting\n */\nconst DEFAULT_OPTIONS: TextFormatterOptions = {\n textCase: 'title',\n wordReplacements: DEFAULT_WORD_REPLACEMENTS,\n trim: true,\n};\n\n/**\n * Formats text by normalizing case styles, applying case transformations,\n * and replacing specific words with custom formatting.\n * \n * @param text The input text to format\n * @param options Formatting options\n * @returns Formatted text\n */\nexport function formatText(text: string, options: TextFormatterOptions = {}): string {\n // Merge provided options with defaults\n const opts = { ...DEFAULT_OPTIONS, ...options };\n \n // Handle empty text\n if (!text) return '';\n \n // Step 1: Normalize various case styles to space-separated words\n let normalized = text\n // Convert snake_case to space-separated\n .replace(/_/g, ' ')\n // Convert kebab-case to space-separated\n .replace(/-/g, ' ')\n // Convert camelCase and PascalCase to space-separated\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Replace multiple spaces with a single space\n .replace(/\\s+/g, ' ');\n \n // Step 2: Apply trim if needed\n if (opts.trim) {\n normalized = normalized.trim();\n }\n \n // Step 3: Apply the specified text case\n let caseTransformed = normalized;\n switch (opts.textCase) {\n case 'title':\n caseTransformed = normalized.replace(/\\w\\S*/g, (word) => \n word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()\n );\n break;\n case 'sentence':\n if (normalized.length > 0) {\n caseTransformed = normalized.charAt(0).toUpperCase() + normalized.slice(1).toLowerCase();\n }\n break;\n case 'lower':\n caseTransformed = normalized.toLowerCase();\n break;\n case 'upper':\n caseTransformed = normalized.toUpperCase();\n break;\n case 'normal':\n default:\n // No case transformation\n break;\n }\n \n // Step 4: Apply word replacements if provided\n let result = caseTransformed;\n if (opts.wordReplacements) {\n Object.entries(opts.wordReplacements).forEach(([key, value]) => {\n // Create a regex that matches the key as a whole word (case insensitive)\n const regex = new RegExp(`\\\\b${key}\\\\b`, 'gi');\n result = result.replace(regex, value);\n });\n }\n \n return result;\n}\n\n/**\n * Creates a pre-configured formatter function with specific options\n * \n * @param defaultOptions Default options for the formatter\n * @returns A formatter function with the specified default options\n */\nexport function createFormatter(defaultOptions: TextFormatterOptions = {}) {\n return (text: string, overrideOptions: TextFormatterOptions = {}) => \n formatText(text, { ...defaultOptions, ...overrideOptions });\n}\n\n// Some pre-configured formatters for common use cases\nexport const formatTitleCase = createFormatter({ textCase: 'title' });\nexport const formatSentenceCase = createFormatter({ textCase: 'sentence' });\nexport const formatNormalCase = createFormatter({ textCase: 'normal' });\nexport const formatUpperCase = createFormatter({ textCase: 'upper' });\nexport const formatLowerCase = createFormatter({ textCase: 'lower' });\nexport const formatWithoutReplacements = createFormatter({ wordReplacements: {} });\n"],"mappings":"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","names":[]}
|
package/dist/toast.cjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/toast.ts
|
|
22
|
+
var toast_exports = {};
|
|
23
|
+
__export(toast_exports, {
|
|
24
|
+
createMatrxToast: () => createMatrxToast
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(toast_exports);
|
|
27
|
+
function messageText(message, data) {
|
|
28
|
+
const description = data && typeof data.description === "string" ? data.description : "";
|
|
29
|
+
const title = typeof message === "string" ? message : "";
|
|
30
|
+
return [title, description].filter(Boolean).join(" \u2014 ") || "Error toast";
|
|
31
|
+
}
|
|
32
|
+
function createMatrxToast({
|
|
33
|
+
toast: hostToast,
|
|
34
|
+
capture
|
|
35
|
+
}) {
|
|
36
|
+
if (typeof hostToast !== "function") {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"createMatrxToast: options.toast must be the sonner `toast` object (or a structural equivalent) \u2014 got " + typeof hostToast
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
function captureToast(kind, message, data) {
|
|
42
|
+
if (!capture) return;
|
|
43
|
+
try {
|
|
44
|
+
capture({
|
|
45
|
+
source: "user-toast",
|
|
46
|
+
message: `${kind === "warning" ? "[warning] " : ""}${messageText(message, data)}`,
|
|
47
|
+
userMessage: messageText(message, data),
|
|
48
|
+
raw: {
|
|
49
|
+
kind,
|
|
50
|
+
message: typeof message === "string" ? message : void 0,
|
|
51
|
+
data
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const error = (message, data) => {
|
|
58
|
+
captureToast("error", message, data);
|
|
59
|
+
return hostToast.error(message, data);
|
|
60
|
+
};
|
|
61
|
+
const warning = (message, data) => {
|
|
62
|
+
captureToast("warning", message, data);
|
|
63
|
+
return hostToast.warning(message, data);
|
|
64
|
+
};
|
|
65
|
+
const forward = hostToast;
|
|
66
|
+
const toast = Object.assign(
|
|
67
|
+
((...args) => forward(...args)),
|
|
68
|
+
hostToast,
|
|
69
|
+
{ error, warning }
|
|
70
|
+
);
|
|
71
|
+
const toastErrorAlreadyCaptured = ((message, data) => hostToast.error(message, data));
|
|
72
|
+
return { toast, toastErrorAlreadyCaptured };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=toast.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/toast.ts"],"sourcesContent":["/**\n * @ai-matrx/kit/toast — the captured sonner wrapper, as a factory.\n *\n * A bare `toast.error(...)` from \"sonner\" is INVISIBLE to any error-capture\n * sink — every modern sonner call site silently bypasses error capture (the\n * exact hole matrx-frontend found in its marketing feature, 2026-07-20).\n * `createMatrxToast` returns a drop-in `toast` whose API is identical to the\n * one you pass in — `error` and `warning` additionally feed the injected\n * capture sink. A user seeing the failure is not evidence that it is minor,\n * so error toasts stay red unless a specific downgrade rule says otherwise.\n * Success/info/etc. pass straight through untouched.\n *\n * Ported from matrx-frontend `lib/toast.ts` with the two seams inverted:\n *\n * - `sonner` is NOT imported: the host passes its own `toast` object into the\n * factory (`createMatrxToast({ toast })`). That removes the peer-resolution\n * problem entirely — this module has zero dependencies — and the input is\n * typed STRUCTURALLY (callable + `.error` + `.warning`) so the returned\n * `toast` keeps the host's full sonner type, and no `.d.ts` in this package\n * references \"sonner\". The `sonner` entry in `peerDependencies` is\n * advisory-only (optional; nothing resolves it at runtime).\n * - `captureError` from the app's diagnostics store becomes the injected\n * `capture?: (info) => void`. Omitted, capture is a no-op and every call\n * forwards identically (the original's payload shape is preserved exactly:\n * `source: \"user-toast\"`, the `[warning] ` prefix, the \"Error toast\"\n * fallback, `raw: { kind, message?, data }`). A throwing `capture` never\n * breaks the toast.\n *\n * Usage (once, in the host app):\n * import { toast as sonnerToast } from \"sonner\";\n * export const { toast, toastErrorAlreadyCaptured } =\n * createMatrxToast({ toast: sonnerToast, capture: captureError });\n */\n\nimport type { ReactNode } from \"react\";\n\n/** What sonner accepts as a toast title (structural: sonner's `titleT`). */\nexport type ToastMessage = ReactNode | (() => ReactNode);\n\n/** Structural stand-in for sonner's `ExternalToast` options bag. */\nexport interface ToastData {\n description?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * The structural surface this factory needs from the injected toast object:\n * callable, with `error` and `warning` methods. sonner's `toast` satisfies\n * this for every version this package targets. Deliberate typing choices so\n * the REAL sonner object is assignable without a cast under\n * `strictFunctionTypes`: the call signature uses `never[]` (accepts any\n * function — consumers call through their own `T`, never this signature),\n * and `error`/`warning` use METHOD syntax for bivariant parameter checks\n * against sonner's `ExternalToast`.\n */\nexport interface SonnerLikeToast {\n (...args: never[]): string | number;\n error(message: ToastMessage, data?: ToastData): string | number;\n warning(message: ToastMessage, data?: ToastData): string | number;\n}\n\n/** The payload handed to the injected capture sink — the original's shape. */\nexport interface CapturedToastInfo {\n source: \"user-toast\";\n message: string;\n userMessage: string;\n raw: {\n kind: \"error\" | \"warning\";\n message: string | undefined;\n data: ToastData | undefined;\n };\n}\n\nexport interface CreateMatrxToastOptions<T extends SonnerLikeToast> {\n /** The host's sonner `toast` object (or any structural equivalent). */\n toast: T;\n /**\n * Error-capture sink fed by `.error` / `.warning`. Omitted: no-op.\n * Must never be load-bearing — a throw here is swallowed.\n */\n capture?: (info: CapturedToastInfo) => void;\n}\n\nexport interface MatrxToast<T extends SonnerLikeToast> {\n /** Drop-in replacement for the injected `toast`, with error/warning capture. */\n toast: T;\n /**\n * Render an error toast when the originating failure was already captured\n * at its canonical boundary. Only for aggregate/derived UI notices; the\n * caller must be able to name the upstream capture seam.\n */\n toastErrorAlreadyCaptured: T[\"error\"];\n}\n\nfunction messageText(message: ToastMessage, data?: ToastData): string {\n const description =\n data && typeof data.description === \"string\" ? data.description : \"\";\n const title = typeof message === \"string\" ? message : \"\";\n return [title, description].filter(Boolean).join(\" — \") || \"Error toast\";\n}\n\n/** Build the captured toast pair around the host's sonner `toast` object. */\nexport function createMatrxToast<T extends SonnerLikeToast>({\n toast: hostToast,\n capture,\n}: CreateMatrxToastOptions<T>): MatrxToast<T> {\n if (typeof hostToast !== \"function\") {\n throw new Error(\n \"createMatrxToast: options.toast must be the sonner `toast` object (or a structural equivalent) — got \" +\n typeof hostToast,\n );\n }\n\n function captureToast(\n kind: \"error\" | \"warning\",\n message: ToastMessage,\n data?: ToastData,\n ): void {\n if (!capture) return;\n try {\n capture({\n source: \"user-toast\",\n message: `${kind === \"warning\" ? \"[warning] \" : \"\"}${messageText(message, data)}`,\n userMessage: messageText(message, data),\n raw: {\n kind,\n message: typeof message === \"string\" ? message : undefined,\n data,\n },\n });\n } catch {\n /* capture must never break the toast */\n }\n }\n\n const error: SonnerLikeToast[\"error\"] = (message, data) => {\n captureToast(\"error\", message, data);\n return hostToast.error(message, data);\n };\n\n const warning: SonnerLikeToast[\"warning\"] = (message, data) => {\n captureToast(\"warning\", message, data);\n return hostToast.warning(message, data);\n };\n\n // The constraint's call signature is `never[]` (see SonnerLikeToast), so\n // forwarding the base call goes through a widened alias of the host object.\n const forward = hostToast as unknown as (\n ...args: Parameters<T>\n ) => ReturnType<T>;\n const toast: T = Object.assign(\n ((...args: Parameters<T>) => forward(...args)) as unknown as T,\n hostToast,\n { error, warning },\n );\n\n const toastErrorAlreadyCaptured = ((\n message: ToastMessage,\n data?: ToastData,\n ) => hostToast.error(message, data)) as unknown as T[\"error\"];\n\n return { toast, toastErrorAlreadyCaptured };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8FA,SAAS,YAAY,SAAuB,MAA0B;AACpE,QAAM,cACJ,QAAQ,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AACpE,QAAM,QAAQ,OAAO,YAAY,WAAW,UAAU;AACtD,SAAO,CAAC,OAAO,WAAW,EAAE,OAAO,OAAO,EAAE,KAAK,UAAK,KAAK;AAC7D;AAGO,SAAS,iBAA4C;AAAA,EAC1D,OAAO;AAAA,EACP;AACF,GAA8C;AAC5C,MAAI,OAAO,cAAc,YAAY;AACnC,UAAM,IAAI;AAAA,MACR,+GACE,OAAO;AAAA,IACX;AAAA,EACF;AAEA,WAAS,aACP,MACA,SACA,MACM;AACN,QAAI,CAAC,QAAS;AACd,QAAI;AACF,cAAQ;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,GAAG,SAAS,YAAY,eAAe,EAAE,GAAG,YAAY,SAAS,IAAI,CAAC;AAAA,QAC/E,aAAa,YAAY,SAAS,IAAI;AAAA,QACtC,KAAK;AAAA,UACH;AAAA,UACA,SAAS,OAAO,YAAY,WAAW,UAAU;AAAA,UACjD;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,QAAkC,CAAC,SAAS,SAAS;AACzD,iBAAa,SAAS,SAAS,IAAI;AACnC,WAAO,UAAU,MAAM,SAAS,IAAI;AAAA,EACtC;AAEA,QAAM,UAAsC,CAAC,SAAS,SAAS;AAC7D,iBAAa,WAAW,SAAS,IAAI;AACrC,WAAO,UAAU,QAAQ,SAAS,IAAI;AAAA,EACxC;AAIA,QAAM,UAAU;AAGhB,QAAM,QAAW,OAAO;AAAA,KACrB,IAAI,SAAwB,QAAQ,GAAG,IAAI;AAAA,IAC5C;AAAA,IACA,EAAE,OAAO,QAAQ;AAAA,EACnB;AAEA,QAAM,6BAA6B,CACjC,SACA,SACG,UAAU,MAAM,SAAS,IAAI;AAElC,SAAO,EAAE,OAAO,0BAA0B;AAC5C;","names":[]}
|
package/dist/toast.d.cts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @ai-matrx/kit/toast — the captured sonner wrapper, as a factory.
|
|
5
|
+
*
|
|
6
|
+
* A bare `toast.error(...)` from "sonner" is INVISIBLE to any error-capture
|
|
7
|
+
* sink — every modern sonner call site silently bypasses error capture (the
|
|
8
|
+
* exact hole matrx-frontend found in its marketing feature, 2026-07-20).
|
|
9
|
+
* `createMatrxToast` returns a drop-in `toast` whose API is identical to the
|
|
10
|
+
* one you pass in — `error` and `warning` additionally feed the injected
|
|
11
|
+
* capture sink. A user seeing the failure is not evidence that it is minor,
|
|
12
|
+
* so error toasts stay red unless a specific downgrade rule says otherwise.
|
|
13
|
+
* Success/info/etc. pass straight through untouched.
|
|
14
|
+
*
|
|
15
|
+
* Ported from matrx-frontend `lib/toast.ts` with the two seams inverted:
|
|
16
|
+
*
|
|
17
|
+
* - `sonner` is NOT imported: the host passes its own `toast` object into the
|
|
18
|
+
* factory (`createMatrxToast({ toast })`). That removes the peer-resolution
|
|
19
|
+
* problem entirely — this module has zero dependencies — and the input is
|
|
20
|
+
* typed STRUCTURALLY (callable + `.error` + `.warning`) so the returned
|
|
21
|
+
* `toast` keeps the host's full sonner type, and no `.d.ts` in this package
|
|
22
|
+
* references "sonner". The `sonner` entry in `peerDependencies` is
|
|
23
|
+
* advisory-only (optional; nothing resolves it at runtime).
|
|
24
|
+
* - `captureError` from the app's diagnostics store becomes the injected
|
|
25
|
+
* `capture?: (info) => void`. Omitted, capture is a no-op and every call
|
|
26
|
+
* forwards identically (the original's payload shape is preserved exactly:
|
|
27
|
+
* `source: "user-toast"`, the `[warning] ` prefix, the "Error toast"
|
|
28
|
+
* fallback, `raw: { kind, message?, data }`). A throwing `capture` never
|
|
29
|
+
* breaks the toast.
|
|
30
|
+
*
|
|
31
|
+
* Usage (once, in the host app):
|
|
32
|
+
* import { toast as sonnerToast } from "sonner";
|
|
33
|
+
* export const { toast, toastErrorAlreadyCaptured } =
|
|
34
|
+
* createMatrxToast({ toast: sonnerToast, capture: captureError });
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** What sonner accepts as a toast title (structural: sonner's `titleT`). */
|
|
38
|
+
type ToastMessage = ReactNode | (() => ReactNode);
|
|
39
|
+
/** Structural stand-in for sonner's `ExternalToast` options bag. */
|
|
40
|
+
interface ToastData {
|
|
41
|
+
description?: unknown;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The structural surface this factory needs from the injected toast object:
|
|
46
|
+
* callable, with `error` and `warning` methods. sonner's `toast` satisfies
|
|
47
|
+
* this for every version this package targets. Deliberate typing choices so
|
|
48
|
+
* the REAL sonner object is assignable without a cast under
|
|
49
|
+
* `strictFunctionTypes`: the call signature uses `never[]` (accepts any
|
|
50
|
+
* function — consumers call through their own `T`, never this signature),
|
|
51
|
+
* and `error`/`warning` use METHOD syntax for bivariant parameter checks
|
|
52
|
+
* against sonner's `ExternalToast`.
|
|
53
|
+
*/
|
|
54
|
+
interface SonnerLikeToast {
|
|
55
|
+
(...args: never[]): string | number;
|
|
56
|
+
error(message: ToastMessage, data?: ToastData): string | number;
|
|
57
|
+
warning(message: ToastMessage, data?: ToastData): string | number;
|
|
58
|
+
}
|
|
59
|
+
/** The payload handed to the injected capture sink — the original's shape. */
|
|
60
|
+
interface CapturedToastInfo {
|
|
61
|
+
source: "user-toast";
|
|
62
|
+
message: string;
|
|
63
|
+
userMessage: string;
|
|
64
|
+
raw: {
|
|
65
|
+
kind: "error" | "warning";
|
|
66
|
+
message: string | undefined;
|
|
67
|
+
data: ToastData | undefined;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
interface CreateMatrxToastOptions<T extends SonnerLikeToast> {
|
|
71
|
+
/** The host's sonner `toast` object (or any structural equivalent). */
|
|
72
|
+
toast: T;
|
|
73
|
+
/**
|
|
74
|
+
* Error-capture sink fed by `.error` / `.warning`. Omitted: no-op.
|
|
75
|
+
* Must never be load-bearing — a throw here is swallowed.
|
|
76
|
+
*/
|
|
77
|
+
capture?: (info: CapturedToastInfo) => void;
|
|
78
|
+
}
|
|
79
|
+
interface MatrxToast<T extends SonnerLikeToast> {
|
|
80
|
+
/** Drop-in replacement for the injected `toast`, with error/warning capture. */
|
|
81
|
+
toast: T;
|
|
82
|
+
/**
|
|
83
|
+
* Render an error toast when the originating failure was already captured
|
|
84
|
+
* at its canonical boundary. Only for aggregate/derived UI notices; the
|
|
85
|
+
* caller must be able to name the upstream capture seam.
|
|
86
|
+
*/
|
|
87
|
+
toastErrorAlreadyCaptured: T["error"];
|
|
88
|
+
}
|
|
89
|
+
/** Build the captured toast pair around the host's sonner `toast` object. */
|
|
90
|
+
declare function createMatrxToast<T extends SonnerLikeToast>({ toast: hostToast, capture, }: CreateMatrxToastOptions<T>): MatrxToast<T>;
|
|
91
|
+
|
|
92
|
+
export { type CapturedToastInfo, type CreateMatrxToastOptions, type MatrxToast, type SonnerLikeToast, type ToastData, type ToastMessage, createMatrxToast };
|
package/dist/toast.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @ai-matrx/kit/toast — the captured sonner wrapper, as a factory.
|
|
5
|
+
*
|
|
6
|
+
* A bare `toast.error(...)` from "sonner" is INVISIBLE to any error-capture
|
|
7
|
+
* sink — every modern sonner call site silently bypasses error capture (the
|
|
8
|
+
* exact hole matrx-frontend found in its marketing feature, 2026-07-20).
|
|
9
|
+
* `createMatrxToast` returns a drop-in `toast` whose API is identical to the
|
|
10
|
+
* one you pass in — `error` and `warning` additionally feed the injected
|
|
11
|
+
* capture sink. A user seeing the failure is not evidence that it is minor,
|
|
12
|
+
* so error toasts stay red unless a specific downgrade rule says otherwise.
|
|
13
|
+
* Success/info/etc. pass straight through untouched.
|
|
14
|
+
*
|
|
15
|
+
* Ported from matrx-frontend `lib/toast.ts` with the two seams inverted:
|
|
16
|
+
*
|
|
17
|
+
* - `sonner` is NOT imported: the host passes its own `toast` object into the
|
|
18
|
+
* factory (`createMatrxToast({ toast })`). That removes the peer-resolution
|
|
19
|
+
* problem entirely — this module has zero dependencies — and the input is
|
|
20
|
+
* typed STRUCTURALLY (callable + `.error` + `.warning`) so the returned
|
|
21
|
+
* `toast` keeps the host's full sonner type, and no `.d.ts` in this package
|
|
22
|
+
* references "sonner". The `sonner` entry in `peerDependencies` is
|
|
23
|
+
* advisory-only (optional; nothing resolves it at runtime).
|
|
24
|
+
* - `captureError` from the app's diagnostics store becomes the injected
|
|
25
|
+
* `capture?: (info) => void`. Omitted, capture is a no-op and every call
|
|
26
|
+
* forwards identically (the original's payload shape is preserved exactly:
|
|
27
|
+
* `source: "user-toast"`, the `[warning] ` prefix, the "Error toast"
|
|
28
|
+
* fallback, `raw: { kind, message?, data }`). A throwing `capture` never
|
|
29
|
+
* breaks the toast.
|
|
30
|
+
*
|
|
31
|
+
* Usage (once, in the host app):
|
|
32
|
+
* import { toast as sonnerToast } from "sonner";
|
|
33
|
+
* export const { toast, toastErrorAlreadyCaptured } =
|
|
34
|
+
* createMatrxToast({ toast: sonnerToast, capture: captureError });
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** What sonner accepts as a toast title (structural: sonner's `titleT`). */
|
|
38
|
+
type ToastMessage = ReactNode | (() => ReactNode);
|
|
39
|
+
/** Structural stand-in for sonner's `ExternalToast` options bag. */
|
|
40
|
+
interface ToastData {
|
|
41
|
+
description?: unknown;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The structural surface this factory needs from the injected toast object:
|
|
46
|
+
* callable, with `error` and `warning` methods. sonner's `toast` satisfies
|
|
47
|
+
* this for every version this package targets. Deliberate typing choices so
|
|
48
|
+
* the REAL sonner object is assignable without a cast under
|
|
49
|
+
* `strictFunctionTypes`: the call signature uses `never[]` (accepts any
|
|
50
|
+
* function — consumers call through their own `T`, never this signature),
|
|
51
|
+
* and `error`/`warning` use METHOD syntax for bivariant parameter checks
|
|
52
|
+
* against sonner's `ExternalToast`.
|
|
53
|
+
*/
|
|
54
|
+
interface SonnerLikeToast {
|
|
55
|
+
(...args: never[]): string | number;
|
|
56
|
+
error(message: ToastMessage, data?: ToastData): string | number;
|
|
57
|
+
warning(message: ToastMessage, data?: ToastData): string | number;
|
|
58
|
+
}
|
|
59
|
+
/** The payload handed to the injected capture sink — the original's shape. */
|
|
60
|
+
interface CapturedToastInfo {
|
|
61
|
+
source: "user-toast";
|
|
62
|
+
message: string;
|
|
63
|
+
userMessage: string;
|
|
64
|
+
raw: {
|
|
65
|
+
kind: "error" | "warning";
|
|
66
|
+
message: string | undefined;
|
|
67
|
+
data: ToastData | undefined;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
interface CreateMatrxToastOptions<T extends SonnerLikeToast> {
|
|
71
|
+
/** The host's sonner `toast` object (or any structural equivalent). */
|
|
72
|
+
toast: T;
|
|
73
|
+
/**
|
|
74
|
+
* Error-capture sink fed by `.error` / `.warning`. Omitted: no-op.
|
|
75
|
+
* Must never be load-bearing — a throw here is swallowed.
|
|
76
|
+
*/
|
|
77
|
+
capture?: (info: CapturedToastInfo) => void;
|
|
78
|
+
}
|
|
79
|
+
interface MatrxToast<T extends SonnerLikeToast> {
|
|
80
|
+
/** Drop-in replacement for the injected `toast`, with error/warning capture. */
|
|
81
|
+
toast: T;
|
|
82
|
+
/**
|
|
83
|
+
* Render an error toast when the originating failure was already captured
|
|
84
|
+
* at its canonical boundary. Only for aggregate/derived UI notices; the
|
|
85
|
+
* caller must be able to name the upstream capture seam.
|
|
86
|
+
*/
|
|
87
|
+
toastErrorAlreadyCaptured: T["error"];
|
|
88
|
+
}
|
|
89
|
+
/** Build the captured toast pair around the host's sonner `toast` object. */
|
|
90
|
+
declare function createMatrxToast<T extends SonnerLikeToast>({ toast: hostToast, capture, }: CreateMatrxToastOptions<T>): MatrxToast<T>;
|
|
91
|
+
|
|
92
|
+
export { type CapturedToastInfo, type CreateMatrxToastOptions, type MatrxToast, type SonnerLikeToast, type ToastData, type ToastMessage, createMatrxToast };
|
package/dist/toast.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/toast.ts
|
|
4
|
+
function messageText(message, data) {
|
|
5
|
+
const description = data && typeof data.description === "string" ? data.description : "";
|
|
6
|
+
const title = typeof message === "string" ? message : "";
|
|
7
|
+
return [title, description].filter(Boolean).join(" \u2014 ") || "Error toast";
|
|
8
|
+
}
|
|
9
|
+
function createMatrxToast({
|
|
10
|
+
toast: hostToast,
|
|
11
|
+
capture
|
|
12
|
+
}) {
|
|
13
|
+
if (typeof hostToast !== "function") {
|
|
14
|
+
throw new Error(
|
|
15
|
+
"createMatrxToast: options.toast must be the sonner `toast` object (or a structural equivalent) \u2014 got " + typeof hostToast
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
function captureToast(kind, message, data) {
|
|
19
|
+
if (!capture) return;
|
|
20
|
+
try {
|
|
21
|
+
capture({
|
|
22
|
+
source: "user-toast",
|
|
23
|
+
message: `${kind === "warning" ? "[warning] " : ""}${messageText(message, data)}`,
|
|
24
|
+
userMessage: messageText(message, data),
|
|
25
|
+
raw: {
|
|
26
|
+
kind,
|
|
27
|
+
message: typeof message === "string" ? message : void 0,
|
|
28
|
+
data
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const error = (message, data) => {
|
|
35
|
+
captureToast("error", message, data);
|
|
36
|
+
return hostToast.error(message, data);
|
|
37
|
+
};
|
|
38
|
+
const warning = (message, data) => {
|
|
39
|
+
captureToast("warning", message, data);
|
|
40
|
+
return hostToast.warning(message, data);
|
|
41
|
+
};
|
|
42
|
+
const forward = hostToast;
|
|
43
|
+
const toast = Object.assign(
|
|
44
|
+
((...args) => forward(...args)),
|
|
45
|
+
hostToast,
|
|
46
|
+
{ error, warning }
|
|
47
|
+
);
|
|
48
|
+
const toastErrorAlreadyCaptured = ((message, data) => hostToast.error(message, data));
|
|
49
|
+
return { toast, toastErrorAlreadyCaptured };
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
createMatrxToast
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=toast.js.map
|