@djangocfg/ui-core 2.1.101 → 2.1.103

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/dist/lib.cjs ADDED
@@ -0,0 +1,277 @@
1
+ 'use strict';
2
+
3
+ var clsx = require('clsx');
4
+ var tailwindMerge = require('tailwind-merge');
5
+ var consola = require('consola');
6
+ var zustand = require('zustand');
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
+ function cn(...inputs) {
11
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
12
+ }
13
+ __name(cn, "cn");
14
+
15
+ // src/lib/og-image.ts
16
+ var DEFAULT_OG_IMAGE_BASE_URL = "https://djangocfg.com/api/og";
17
+ function encodeBase64(str) {
18
+ if (typeof Buffer !== "undefined") {
19
+ return Buffer.from(str, "utf-8").toString("base64");
20
+ }
21
+ const utf8Bytes = new TextEncoder().encode(str);
22
+ const binaryString = Array.from(utf8Bytes, (byte) => String.fromCharCode(byte)).join("");
23
+ return btoa(binaryString);
24
+ }
25
+ __name(encodeBase64, "encodeBase64");
26
+ function generateOgImageUrl(params, options = {}) {
27
+ const { baseUrl = DEFAULT_OG_IMAGE_BASE_URL, useBase64 = true } = options;
28
+ if (useBase64) {
29
+ const cleanParams = {};
30
+ Object.entries(params).forEach(([key, value]) => {
31
+ if (value !== void 0 && value !== null && value !== "") {
32
+ cleanParams[key] = value;
33
+ }
34
+ });
35
+ const jsonString = JSON.stringify(cleanParams);
36
+ const base64Data = encodeBase64(jsonString);
37
+ return `${baseUrl}/${base64Data}`;
38
+ } else {
39
+ const searchParams = new URLSearchParams();
40
+ Object.entries(params).forEach(([key, value]) => {
41
+ if (value !== void 0 && value !== null && value !== "") {
42
+ searchParams.append(key, String(value));
43
+ }
44
+ });
45
+ const query = searchParams.toString();
46
+ return query ? `${baseUrl}?${query}` : baseUrl;
47
+ }
48
+ }
49
+ __name(generateOgImageUrl, "generateOgImageUrl");
50
+ function getAbsoluteOgImageUrl(relativePath, siteUrl) {
51
+ if (relativePath.startsWith("http://") || relativePath.startsWith("https://")) {
52
+ return relativePath;
53
+ }
54
+ const cleanSiteUrl = siteUrl.replace(/\/$/, "");
55
+ const cleanPath = relativePath.startsWith("/") ? relativePath : `/${relativePath}`;
56
+ return `${cleanSiteUrl}${cleanPath}`;
57
+ }
58
+ __name(getAbsoluteOgImageUrl, "getAbsoluteOgImageUrl");
59
+ function createOgImageUrlBuilder(defaults = {}, options = {}) {
60
+ return (params) => {
61
+ return generateOgImageUrl({ ...defaults, ...params }, options);
62
+ };
63
+ }
64
+ __name(createOgImageUrlBuilder, "createOgImageUrlBuilder");
65
+ var DEFAULT_FILTER = {
66
+ levels: ["debug", "info", "warn", "error", "success"],
67
+ component: void 0,
68
+ search: void 0,
69
+ since: void 0
70
+ };
71
+ var MAX_LOGS = 1e3;
72
+ function generateId() {
73
+ return `log-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
74
+ }
75
+ __name(generateId, "generateId");
76
+ function matchesFilter(entry, filter) {
77
+ if (!filter.levels.includes(entry.level)) {
78
+ return false;
79
+ }
80
+ if (filter.component) {
81
+ const comp = filter.component.toLowerCase();
82
+ if (!entry.component.toLowerCase().includes(comp)) {
83
+ return false;
84
+ }
85
+ }
86
+ if (filter.search) {
87
+ const search = filter.search.toLowerCase();
88
+ const inMessage = entry.message.toLowerCase().includes(search);
89
+ const inData = entry.data ? JSON.stringify(entry.data).toLowerCase().includes(search) : false;
90
+ if (!inMessage && !inData) {
91
+ return false;
92
+ }
93
+ }
94
+ if (filter.since && entry.timestamp < filter.since) {
95
+ return false;
96
+ }
97
+ return true;
98
+ }
99
+ __name(matchesFilter, "matchesFilter");
100
+ var useLogStore = zustand.create((set, get) => ({
101
+ logs: [],
102
+ filter: DEFAULT_FILTER,
103
+ maxLogs: MAX_LOGS,
104
+ addLog: /* @__PURE__ */ __name((entry) => {
105
+ const newEntry = {
106
+ ...entry,
107
+ id: generateId(),
108
+ timestamp: /* @__PURE__ */ new Date()
109
+ };
110
+ set((state) => {
111
+ const newLogs = [...state.logs, newEntry];
112
+ if (newLogs.length > state.maxLogs) {
113
+ return { logs: newLogs.slice(-state.maxLogs) };
114
+ }
115
+ return { logs: newLogs };
116
+ });
117
+ }, "addLog"),
118
+ clearLogs: /* @__PURE__ */ __name(() => {
119
+ set({ logs: [] });
120
+ }, "clearLogs"),
121
+ setFilter: /* @__PURE__ */ __name((filter) => {
122
+ set((state) => ({
123
+ filter: { ...state.filter, ...filter }
124
+ }));
125
+ }, "setFilter"),
126
+ resetFilter: /* @__PURE__ */ __name(() => {
127
+ set({ filter: DEFAULT_FILTER });
128
+ }, "resetFilter"),
129
+ getFilteredLogs: /* @__PURE__ */ __name(() => {
130
+ const { logs, filter } = get();
131
+ return logs.filter((entry) => matchesFilter(entry, filter));
132
+ }, "getFilteredLogs"),
133
+ exportLogs: /* @__PURE__ */ __name(() => {
134
+ const { logs } = get();
135
+ return JSON.stringify(logs, null, 2);
136
+ }, "exportLogs")
137
+ }));
138
+ var useFilteredLogs = /* @__PURE__ */ __name(() => {
139
+ const logs = useLogStore((state) => state.logs);
140
+ const filter = useLogStore((state) => state.filter);
141
+ return logs.filter((entry) => matchesFilter(entry, filter));
142
+ }, "useFilteredLogs");
143
+ var useLogCount = /* @__PURE__ */ __name(() => {
144
+ return useLogStore((state) => state.logs.length);
145
+ }, "useLogCount");
146
+ var useErrorCount = /* @__PURE__ */ __name(() => {
147
+ return useLogStore(
148
+ (state) => state.logs.filter((log2) => log2.level === "error").length
149
+ );
150
+ }, "useErrorCount");
151
+ var isBrowser = typeof window !== "undefined";
152
+ var baseConsola = consola.consola.create({
153
+ level: 4
154
+ // 4 = debug, 2 = warn
155
+ });
156
+ function extractErrorData(data) {
157
+ if (!data) return { cleanData: void 0, stack: void 0 };
158
+ const cleanData = { ...data };
159
+ let stack;
160
+ if (data.error instanceof Error) {
161
+ stack = data.error.stack;
162
+ cleanData.error = {
163
+ name: data.error.name,
164
+ message: data.error.message
165
+ };
166
+ } else if (typeof data.error === "object" && data.error !== null) {
167
+ const errObj = data.error;
168
+ if (typeof errObj.stack === "string") {
169
+ stack = errObj.stack;
170
+ }
171
+ if (typeof errObj.message === "string") {
172
+ cleanData.error = errObj.message;
173
+ }
174
+ }
175
+ return { cleanData, stack };
176
+ }
177
+ __name(extractErrorData, "extractErrorData");
178
+ function formatBufferRanges(buffered, duration) {
179
+ if (buffered.length === 0) return "empty";
180
+ const ranges = [];
181
+ for (let i = 0; i < buffered.length; i++) {
182
+ const start = buffered.start(i);
183
+ const end = buffered.end(i);
184
+ const percent = ((end - start) / duration * 100).toFixed(1);
185
+ ranges.push(`${start.toFixed(1)}-${end.toFixed(1)}s (${percent}%)`);
186
+ }
187
+ return ranges.join(", ");
188
+ }
189
+ __name(formatBufferRanges, "formatBufferRanges");
190
+ function createLogger(component) {
191
+ const consolaTagged = baseConsola.withTag(component);
192
+ const log2 = /* @__PURE__ */ __name((level, message, data) => {
193
+ const { cleanData, stack } = extractErrorData(data);
194
+ if (isBrowser) {
195
+ useLogStore.getState().addLog({
196
+ level,
197
+ component,
198
+ message,
199
+ data: cleanData,
200
+ stack
201
+ });
202
+ }
203
+ {
204
+ const consolaMethod = level === "success" ? "success" : level;
205
+ if (cleanData) {
206
+ consolaTagged[consolaMethod](message, cleanData);
207
+ } else {
208
+ consolaTagged[consolaMethod](message);
209
+ }
210
+ }
211
+ }, "log");
212
+ return {
213
+ debug: /* @__PURE__ */ __name((message, data) => log2("debug", message, data), "debug"),
214
+ info: /* @__PURE__ */ __name((message, data) => log2("info", message, data), "info"),
215
+ warn: /* @__PURE__ */ __name((message, data) => log2("warn", message, data), "warn"),
216
+ error: /* @__PURE__ */ __name((message, data) => log2("error", message, data), "error"),
217
+ success: /* @__PURE__ */ __name((message, data) => log2("success", message, data), "success")
218
+ };
219
+ }
220
+ __name(createLogger, "createLogger");
221
+ function createMediaLogger(component) {
222
+ const baseLogger = createLogger(component);
223
+ return {
224
+ ...baseLogger,
225
+ load: /* @__PURE__ */ __name((src, type) => {
226
+ const typeStr = type ? ` (${type})` : "";
227
+ baseLogger.info(`LOAD: ${src}${typeStr}`);
228
+ }, "load"),
229
+ state: /* @__PURE__ */ __name((state, details) => {
230
+ baseLogger.debug(`STATE: ${state}`, details);
231
+ }, "state"),
232
+ seek: /* @__PURE__ */ __name((from, to, duration) => {
233
+ baseLogger.debug(`SEEK: ${from.toFixed(2)}s -> ${to.toFixed(2)}s`, {
234
+ from,
235
+ to,
236
+ duration,
237
+ progress: `${(to / duration * 100).toFixed(1)}%`
238
+ });
239
+ }, "seek"),
240
+ buffer: /* @__PURE__ */ __name((buffered, duration) => {
241
+ if (buffered.length > 0) {
242
+ baseLogger.debug(`BUFFER: ${formatBufferRanges(buffered, duration)}`);
243
+ }
244
+ }, "buffer"),
245
+ event: /* @__PURE__ */ __name((name, data) => {
246
+ if (data !== void 0) {
247
+ baseLogger.debug(`EVENT: ${name}`, { data });
248
+ } else {
249
+ baseLogger.debug(`EVENT: ${name}`);
250
+ }
251
+ }, "event")
252
+ };
253
+ }
254
+ __name(createMediaLogger, "createMediaLogger");
255
+ var logger = createLogger("App");
256
+ var log = {
257
+ debug: /* @__PURE__ */ __name((component, message, data) => createLogger(component).debug(message, data), "debug"),
258
+ info: /* @__PURE__ */ __name((component, message, data) => createLogger(component).info(message, data), "info"),
259
+ warn: /* @__PURE__ */ __name((component, message, data) => createLogger(component).warn(message, data), "warn"),
260
+ error: /* @__PURE__ */ __name((component, message, data) => createLogger(component).error(message, data), "error"),
261
+ success: /* @__PURE__ */ __name((component, message, data) => createLogger(component).success(message, data), "success")
262
+ };
263
+
264
+ exports.cn = cn;
265
+ exports.createLogger = createLogger;
266
+ exports.createMediaLogger = createMediaLogger;
267
+ exports.createOgImageUrlBuilder = createOgImageUrlBuilder;
268
+ exports.generateOgImageUrl = generateOgImageUrl;
269
+ exports.getAbsoluteOgImageUrl = getAbsoluteOgImageUrl;
270
+ exports.log = log;
271
+ exports.logger = logger;
272
+ exports.useErrorCount = useErrorCount;
273
+ exports.useFilteredLogs = useFilteredLogs;
274
+ exports.useLogCount = useLogCount;
275
+ exports.useLogStore = useLogStore;
276
+ //# sourceMappingURL=lib.cjs.map
277
+ //# sourceMappingURL=lib.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/lib/og-image.ts","../src/lib/logger/logStore.ts","../src/lib/logger/logger.ts"],"names":["twMerge","clsx","create","log","consola"],"mappings":"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","file":"lib.cjs","sourcesContent":["import { ClassValue, clsx} from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","/**\n * OG Image URL Generation Utilities\n *\n * Client-side utilities for generating OG image URLs.\n */\n\n/** Default OG Image API base URL */\nconst DEFAULT_OG_IMAGE_BASE_URL = 'https://djangocfg.com/api/og';\n\n/**\n * Encode string to base64 with Unicode support\n * Works in both browser and Node.js environments\n */\nfunction encodeBase64(str: string): string {\n // Node.js environment\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(str, 'utf-8').toString('base64');\n }\n // Browser environment - handle Unicode via UTF-8 encoding\n const utf8Bytes = new TextEncoder().encode(str);\n const binaryString = Array.from(utf8Bytes, byte => String.fromCharCode(byte)).join('');\n return btoa(binaryString);\n}\n\n/**\n * OG Image URL parameters\n */\nexport interface OgImageUrlParams {\n /** Page title */\n title: string;\n /** Page description (optional) */\n description?: string;\n /** Site name (optional) */\n siteName?: string;\n /** Logo URL (optional) */\n logo?: string;\n /** Background type: 'gradient' or 'solid' */\n backgroundType?: 'gradient' | 'solid';\n /** Gradient start color (hex) */\n gradientStart?: string;\n /** Gradient end color (hex) */\n gradientEnd?: string;\n /** Background color (for solid type) */\n backgroundColor?: string;\n /** Title font size (px) */\n titleSize?: number;\n /** Title font weight */\n titleWeight?: number;\n /** Title text color */\n titleColor?: string;\n /** Description font size (px) */\n descriptionSize?: number;\n /** Description text color */\n descriptionColor?: string;\n /** Site name font size (px) */\n siteNameSize?: number;\n /** Site name text color */\n siteNameColor?: string;\n /** Padding (px) */\n padding?: number;\n /** Logo size (px) */\n logoSize?: number;\n /** Show logo flag */\n showLogo?: boolean;\n /** Show site name flag */\n showSiteName?: boolean;\n /** Additional custom parameters */\n [key: string]: string | number | boolean | undefined;\n}\n\n/**\n * Options for generating OG image URL\n */\nexport interface GenerateOgImageUrlOptions {\n /**\n * Base URL of the OG image API route\n * @default 'https://djangocfg.com/api/og'\n */\n baseUrl?: string;\n /**\n * If true, encode params as base64 for safer URLs\n * @default true\n */\n useBase64?: boolean;\n}\n\n/**\n * Generate OG image URL with query parameters or base64 encoding\n *\n * @example\n * ```typescript\n * // Using default baseUrl (https://djangocfg.com/api/og)\n * const url = generateOgImageUrl({ title: 'My Page Title' });\n *\n * // With custom baseUrl\n * const url = generateOgImageUrl({ title: 'My Page' }, { baseUrl: '/api/og' });\n * ```\n */\nexport function generateOgImageUrl(\n params: OgImageUrlParams,\n options: GenerateOgImageUrlOptions = {}\n): string {\n const { baseUrl = DEFAULT_OG_IMAGE_BASE_URL, useBase64 = true } = options;\n\n if (useBase64) {\n const cleanParams: Record<string, string | number | boolean> = {};\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null && value !== '') {\n cleanParams[key] = value;\n }\n });\n\n const jsonString = JSON.stringify(cleanParams);\n const base64Data = encodeBase64(jsonString);\n return `${baseUrl}/${base64Data}`;\n } else {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null && value !== '') {\n searchParams.append(key, String(value));\n }\n });\n const query = searchParams.toString();\n return query ? `${baseUrl}?${query}` : baseUrl;\n }\n}\n\n/**\n * Get absolute OG image URL from relative path\n */\nexport function getAbsoluteOgImageUrl(relativePath: string, siteUrl: string): string {\n // If path is already an absolute URL, return as-is\n if (relativePath.startsWith('http://') || relativePath.startsWith('https://')) {\n return relativePath;\n }\n const cleanSiteUrl = siteUrl.replace(/\\/$/, '');\n const cleanPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`;\n return `${cleanSiteUrl}${cleanPath}`;\n}\n\n/**\n * Create OG image URL builder with preset configuration\n */\nexport function createOgImageUrlBuilder(\n defaults: Partial<OgImageUrlParams> = {},\n options: GenerateOgImageUrlOptions = {}\n) {\n return (params: OgImageUrlParams): string => {\n return generateOgImageUrl({ ...defaults, ...params }, options);\n };\n}\n","/**\n * Log Store\n *\n * Zustand store for log accumulation and filtering.\n * Keeps logs in memory for Console panel display.\n */\n\n'use client';\n\nimport { create } from 'zustand';\nimport type { LogStore, LogEntry, LogFilter } from './types';\n\nconst DEFAULT_FILTER: LogFilter = {\n levels: ['debug', 'info', 'warn', 'error', 'success'],\n component: undefined,\n search: undefined,\n since: undefined,\n};\n\nconst MAX_LOGS = 1000;\n\nfunction generateId(): string {\n return `log-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nfunction matchesFilter(entry: LogEntry, filter: LogFilter): boolean {\n // Level filter\n if (!filter.levels.includes(entry.level)) {\n return false;\n }\n\n // Component filter (case-insensitive partial match)\n if (filter.component) {\n const comp = filter.component.toLowerCase();\n if (!entry.component.toLowerCase().includes(comp)) {\n return false;\n }\n }\n\n // Search filter (case-insensitive, searches message and data)\n if (filter.search) {\n const search = filter.search.toLowerCase();\n const inMessage = entry.message.toLowerCase().includes(search);\n const inData = entry.data\n ? JSON.stringify(entry.data).toLowerCase().includes(search)\n : false;\n if (!inMessage && !inData) {\n return false;\n }\n }\n\n // Time filter\n if (filter.since && entry.timestamp < filter.since) {\n return false;\n }\n\n return true;\n}\n\nexport const useLogStore = create<LogStore>((set, get) => ({\n logs: [],\n filter: DEFAULT_FILTER,\n maxLogs: MAX_LOGS,\n\n addLog: (entry) => {\n const newEntry: LogEntry = {\n ...entry,\n id: generateId(),\n timestamp: new Date(),\n };\n\n set((state) => {\n const newLogs = [...state.logs, newEntry];\n // Trim to max size\n if (newLogs.length > state.maxLogs) {\n return { logs: newLogs.slice(-state.maxLogs) };\n }\n return { logs: newLogs };\n });\n },\n\n clearLogs: () => {\n set({ logs: [] });\n },\n\n setFilter: (filter) => {\n set((state) => ({\n filter: { ...state.filter, ...filter },\n }));\n },\n\n resetFilter: () => {\n set({ filter: DEFAULT_FILTER });\n },\n\n getFilteredLogs: () => {\n const { logs, filter } = get();\n return logs.filter((entry) => matchesFilter(entry, filter));\n },\n\n exportLogs: () => {\n const { logs } = get();\n return JSON.stringify(logs, null, 2);\n },\n}));\n\n// Selector hooks for performance\nexport const useFilteredLogs = () => {\n const logs = useLogStore((state) => state.logs);\n const filter = useLogStore((state) => state.filter);\n return logs.filter((entry) => matchesFilter(entry, filter));\n};\n\nexport const useLogCount = () => {\n return useLogStore((state) => state.logs.length);\n};\n\nexport const useErrorCount = () => {\n return useLogStore((state) =>\n state.logs.filter((log) => log.level === 'error').length\n );\n};\n","/**\n * Logger\n *\n * Universal logger with consola + zustand store integration.\n * Logs are accumulated for Console panel display.\n * In production, only logs to store (no console output).\n */\n\n'use client';\n\nimport { consola, type ConsolaInstance } from 'consola';\nimport { useLogStore } from './logStore';\nimport type { Logger, LogLevel, MediaLogger } from './types';\n\n// Check environment\nconst isDev = process.env.NODE_ENV !== 'production';\nconst isBrowser = typeof window !== 'undefined';\n\n// Create base consola instance\nconst baseConsola = consola.create({\n level: isDev ? 4 : 2, // 4 = debug, 2 = warn\n});\n\n/**\n * Extract error details from unknown error type\n */\nfunction extractErrorData(data?: Record<string, unknown>): {\n cleanData: Record<string, unknown> | undefined;\n stack: string | undefined;\n} {\n if (!data) return { cleanData: undefined, stack: undefined };\n\n const cleanData = { ...data };\n let stack: string | undefined;\n\n // Extract stack from error object\n if (data.error instanceof Error) {\n stack = data.error.stack;\n cleanData.error = {\n name: data.error.name,\n message: data.error.message,\n };\n } else if (typeof data.error === 'object' && data.error !== null) {\n const errObj = data.error as Record<string, unknown>;\n if (typeof errObj.stack === 'string') {\n stack = errObj.stack;\n }\n if (typeof errObj.message === 'string') {\n cleanData.error = errObj.message;\n }\n }\n\n return { cleanData, stack };\n}\n\n/**\n * Format buffer ranges for logging\n */\nfunction formatBufferRanges(buffered: TimeRanges, duration: number): string {\n if (buffered.length === 0) return 'empty';\n\n const ranges: string[] = [];\n for (let i = 0; i < buffered.length; i++) {\n const start = buffered.start(i);\n const end = buffered.end(i);\n const percent = ((end - start) / duration * 100).toFixed(1);\n ranges.push(`${start.toFixed(1)}-${end.toFixed(1)}s (${percent}%)`);\n }\n return ranges.join(', ');\n}\n\n/**\n * Create a logger for a specific component/module\n */\nexport function createLogger(component: string): Logger {\n const consolaTagged = baseConsola.withTag(component);\n\n const log = (level: LogLevel, message: string, data?: Record<string, unknown>) => {\n const { cleanData, stack } = extractErrorData(data);\n\n // Add to store (for Console panel)\n if (isBrowser) {\n useLogStore.getState().addLog({\n level,\n component,\n message,\n data: cleanData,\n stack,\n });\n }\n\n // Log to console via consola (in dev mode)\n if (isDev) {\n const consolaMethod = level === 'success' ? 'success' : level;\n if (cleanData) {\n consolaTagged[consolaMethod](message, cleanData);\n } else {\n consolaTagged[consolaMethod](message);\n }\n }\n };\n\n return {\n debug: (message, data) => log('debug', message, data),\n info: (message, data) => log('info', message, data),\n warn: (message, data) => log('warn', message, data),\n error: (message, data) => log('error', message, data),\n success: (message, data) => log('success', message, data),\n };\n}\n\n/**\n * Create a media-specific logger with helper methods\n * for AudioPlayer, VideoPlayer, ImageViewer\n */\nexport function createMediaLogger(component: string): MediaLogger {\n const baseLogger = createLogger(component);\n\n return {\n ...baseLogger,\n\n load: (src: string, type?: string) => {\n const typeStr = type ? ` (${type})` : '';\n baseLogger.info(`LOAD: ${src}${typeStr}`);\n },\n\n state: (state: string, details?: Record<string, unknown>) => {\n baseLogger.debug(`STATE: ${state}`, details);\n },\n\n seek: (from: number, to: number, duration: number) => {\n baseLogger.debug(`SEEK: ${from.toFixed(2)}s -> ${to.toFixed(2)}s`, {\n from,\n to,\n duration,\n progress: `${((to / duration) * 100).toFixed(1)}%`,\n });\n },\n\n buffer: (buffered: TimeRanges, duration: number) => {\n if (buffered.length > 0) {\n baseLogger.debug(`BUFFER: ${formatBufferRanges(buffered, duration)}`);\n }\n },\n\n event: (name: string, data?: unknown) => {\n if (data !== undefined) {\n baseLogger.debug(`EVENT: ${name}`, { data });\n } else {\n baseLogger.debug(`EVENT: ${name}`);\n }\n },\n };\n}\n\n/**\n * Global logger for non-component code\n */\nexport const logger = createLogger('App');\n\n/**\n * Quick access for one-off logs\n */\nexport const log = {\n debug: (component: string, message: string, data?: Record<string, unknown>) =>\n createLogger(component).debug(message, data),\n info: (component: string, message: string, data?: Record<string, unknown>) =>\n createLogger(component).info(message, data),\n warn: (component: string, message: string, data?: Record<string, unknown>) =>\n createLogger(component).warn(message, data),\n error: (component: string, message: string, data?: Record<string, unknown>) =>\n createLogger(component).error(message, data),\n success: (component: string, message: string, data?: Record<string, unknown>) =>\n createLogger(component).success(message, data),\n};\n"]}
package/dist/lib.d.mts ADDED
@@ -0,0 +1,206 @@
1
+ import { ClassValue } from 'clsx';
2
+ import * as zustand from 'zustand';
3
+
4
+ declare function cn(...inputs: ClassValue[]): string;
5
+
6
+ /**
7
+ * OG Image URL Generation Utilities
8
+ *
9
+ * Client-side utilities for generating OG image URLs.
10
+ */
11
+ /**
12
+ * OG Image URL parameters
13
+ */
14
+ interface OgImageUrlParams {
15
+ /** Page title */
16
+ title: string;
17
+ /** Page description (optional) */
18
+ description?: string;
19
+ /** Site name (optional) */
20
+ siteName?: string;
21
+ /** Logo URL (optional) */
22
+ logo?: string;
23
+ /** Background type: 'gradient' or 'solid' */
24
+ backgroundType?: 'gradient' | 'solid';
25
+ /** Gradient start color (hex) */
26
+ gradientStart?: string;
27
+ /** Gradient end color (hex) */
28
+ gradientEnd?: string;
29
+ /** Background color (for solid type) */
30
+ backgroundColor?: string;
31
+ /** Title font size (px) */
32
+ titleSize?: number;
33
+ /** Title font weight */
34
+ titleWeight?: number;
35
+ /** Title text color */
36
+ titleColor?: string;
37
+ /** Description font size (px) */
38
+ descriptionSize?: number;
39
+ /** Description text color */
40
+ descriptionColor?: string;
41
+ /** Site name font size (px) */
42
+ siteNameSize?: number;
43
+ /** Site name text color */
44
+ siteNameColor?: string;
45
+ /** Padding (px) */
46
+ padding?: number;
47
+ /** Logo size (px) */
48
+ logoSize?: number;
49
+ /** Show logo flag */
50
+ showLogo?: boolean;
51
+ /** Show site name flag */
52
+ showSiteName?: boolean;
53
+ /** Additional custom parameters */
54
+ [key: string]: string | number | boolean | undefined;
55
+ }
56
+ /**
57
+ * Options for generating OG image URL
58
+ */
59
+ interface GenerateOgImageUrlOptions {
60
+ /**
61
+ * Base URL of the OG image API route
62
+ * @default 'https://djangocfg.com/api/og'
63
+ */
64
+ baseUrl?: string;
65
+ /**
66
+ * If true, encode params as base64 for safer URLs
67
+ * @default true
68
+ */
69
+ useBase64?: boolean;
70
+ }
71
+ /**
72
+ * Generate OG image URL with query parameters or base64 encoding
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * // Using default baseUrl (https://djangocfg.com/api/og)
77
+ * const url = generateOgImageUrl({ title: 'My Page Title' });
78
+ *
79
+ * // With custom baseUrl
80
+ * const url = generateOgImageUrl({ title: 'My Page' }, { baseUrl: '/api/og' });
81
+ * ```
82
+ */
83
+ declare function generateOgImageUrl(params: OgImageUrlParams, options?: GenerateOgImageUrlOptions): string;
84
+ /**
85
+ * Get absolute OG image URL from relative path
86
+ */
87
+ declare function getAbsoluteOgImageUrl(relativePath: string, siteUrl: string): string;
88
+ /**
89
+ * Create OG image URL builder with preset configuration
90
+ */
91
+ declare function createOgImageUrlBuilder(defaults?: Partial<OgImageUrlParams>, options?: GenerateOgImageUrlOptions): (params: OgImageUrlParams) => string;
92
+
93
+ /**
94
+ * Logger Types
95
+ *
96
+ * Type definitions for the universal logging system.
97
+ * Compatible with Console panel in FileWorkspace IDE layout.
98
+ */
99
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'success';
100
+ interface LogEntry {
101
+ /** Unique log ID */
102
+ id: string;
103
+ /** Timestamp when log was created */
104
+ timestamp: Date;
105
+ /** Log level */
106
+ level: LogLevel;
107
+ /** Component/module name that created the log */
108
+ component: string;
109
+ /** Log message */
110
+ message: string;
111
+ /** Additional data (objects, errors, etc.) */
112
+ data?: Record<string, unknown>;
113
+ /** Error stack trace (for error level) */
114
+ stack?: string;
115
+ }
116
+ interface LogFilter {
117
+ /** Filter by log levels */
118
+ levels: LogLevel[];
119
+ /** Filter by component name (partial match) */
120
+ component?: string;
121
+ /** Filter by message text (partial match) */
122
+ search?: string;
123
+ /** Filter by time range */
124
+ since?: Date;
125
+ }
126
+ interface LogStore {
127
+ /** All accumulated logs */
128
+ logs: LogEntry[];
129
+ /** Current filter settings */
130
+ filter: LogFilter;
131
+ /** Maximum logs to keep */
132
+ maxLogs: number;
133
+ /** Add new log entry */
134
+ addLog: (entry: Omit<LogEntry, 'id' | 'timestamp'>) => void;
135
+ /** Clear all logs */
136
+ clearLogs: () => void;
137
+ /** Update filter settings */
138
+ setFilter: (filter: Partial<LogFilter>) => void;
139
+ /** Reset filter to defaults */
140
+ resetFilter: () => void;
141
+ /** Get filtered logs */
142
+ getFilteredLogs: () => LogEntry[];
143
+ /** Export logs as JSON string */
144
+ exportLogs: () => string;
145
+ }
146
+ interface Logger {
147
+ debug: (message: string, data?: Record<string, unknown>) => void;
148
+ info: (message: string, data?: Record<string, unknown>) => void;
149
+ warn: (message: string, data?: Record<string, unknown>) => void;
150
+ error: (message: string, data?: Record<string, unknown>) => void;
151
+ success: (message: string, data?: Record<string, unknown>) => void;
152
+ }
153
+ /**
154
+ * Media-specific log helper methods
155
+ */
156
+ interface MediaLogger extends Logger {
157
+ /** Log source load event */
158
+ load: (src: string, type?: string) => void;
159
+ /** Log state change */
160
+ state: (state: string, details?: Record<string, unknown>) => void;
161
+ /** Log seek event */
162
+ seek: (from: number, to: number, duration: number) => void;
163
+ /** Log buffer ranges */
164
+ buffer: (buffered: TimeRanges, duration: number) => void;
165
+ /** Log generic event */
166
+ event: (name: string, data?: unknown) => void;
167
+ }
168
+
169
+ /**
170
+ * Logger
171
+ *
172
+ * Universal logger with consola + zustand store integration.
173
+ * Logs are accumulated for Console panel display.
174
+ * In production, only logs to store (no console output).
175
+ */
176
+
177
+ /**
178
+ * Create a logger for a specific component/module
179
+ */
180
+ declare function createLogger(component: string): Logger;
181
+ /**
182
+ * Create a media-specific logger with helper methods
183
+ * for AudioPlayer, VideoPlayer, ImageViewer
184
+ */
185
+ declare function createMediaLogger(component: string): MediaLogger;
186
+ /**
187
+ * Global logger for non-component code
188
+ */
189
+ declare const logger: Logger;
190
+ /**
191
+ * Quick access for one-off logs
192
+ */
193
+ declare const log: {
194
+ debug: (component: string, message: string, data?: Record<string, unknown>) => void;
195
+ info: (component: string, message: string, data?: Record<string, unknown>) => void;
196
+ warn: (component: string, message: string, data?: Record<string, unknown>) => void;
197
+ error: (component: string, message: string, data?: Record<string, unknown>) => void;
198
+ success: (component: string, message: string, data?: Record<string, unknown>) => void;
199
+ };
200
+
201
+ declare const useLogStore: zustand.UseBoundStore<zustand.StoreApi<LogStore>>;
202
+ declare const useFilteredLogs: () => LogEntry[];
203
+ declare const useLogCount: () => number;
204
+ declare const useErrorCount: () => number;
205
+
206
+ export { type GenerateOgImageUrlOptions, type LogEntry, type LogFilter, type LogLevel, type LogStore, type Logger, type MediaLogger, type OgImageUrlParams, cn, createLogger, createMediaLogger, createOgImageUrlBuilder, generateOgImageUrl, getAbsoluteOgImageUrl, log, logger, useErrorCount, useFilteredLogs, useLogCount, useLogStore };