@sonicjs-cms/core 3.0.0-beta.24 → 3.0.0-beta.25
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/bin/db-reset.js +39 -22
- package/dist/admin-documents-form.template-JWV5GITD.js +6 -0
- package/dist/{admin-documents-form.template-55V2ZGWT.js.map → admin-documents-form.template-JWV5GITD.js.map} +1 -1
- package/dist/admin-documents-form.template-UWKGVAMW.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-6UQGLCKI.js.map → admin-documents-form.template-UWKGVAMW.cjs.map} +1 -1
- package/dist/admin-layout-catalyst.template-MOQ3BBXA.cjs +21 -0
- package/dist/{admin-layout-catalyst.template-3XZXDGF7.cjs.map → admin-layout-catalyst.template-MOQ3BBXA.cjs.map} +1 -1
- package/dist/admin-layout-catalyst.template-WCYMQVTZ.js +7 -0
- package/dist/{admin-documents-form.template-YNAVMJCV.cjs.map → admin-layout-catalyst.template-WCYMQVTZ.js.map} +1 -1
- package/dist/{chunk-RJ2O5IIE.js → chunk-2D3A4X52.js} +2 -2
- package/dist/{chunk-RJ2O5IIE.js.map → chunk-2D3A4X52.js.map} +1 -1
- package/dist/{chunk-FHPEM77Y.js → chunk-2OXFMMA3.js} +11 -10
- package/dist/chunk-2OXFMMA3.js.map +1 -0
- package/dist/{chunk-SOZUG52O.js → chunk-3KGY4IBW.js} +3 -3
- package/dist/{chunk-SOZUG52O.js.map → chunk-3KGY4IBW.js.map} +1 -1
- package/dist/{chunk-I767LVN7.cjs → chunk-6OA77UM7.cjs} +757 -471
- package/dist/chunk-6OA77UM7.cjs.map +1 -0
- package/dist/{chunk-URIBTX27.js → chunk-73RTFFMX.js} +3 -3
- package/dist/{chunk-URIBTX27.js.map → chunk-73RTFFMX.js.map} +1 -1
- package/dist/{chunk-VC5XVPLM.js → chunk-7P5OCUPS.js} +424 -138
- package/dist/chunk-7P5OCUPS.js.map +1 -0
- package/dist/{chunk-3TMTYJAJ.js → chunk-BDQ55MWV.js} +18 -2
- package/dist/chunk-BDQ55MWV.js.map +1 -0
- package/dist/{chunk-KKNEYIZJ.cjs → chunk-BJ6NJL2E.cjs} +7 -12
- package/dist/chunk-BJ6NJL2E.cjs.map +1 -0
- package/dist/{chunk-VGEZNFWH.js → chunk-C54MH5UI.js} +5 -4
- package/dist/chunk-C54MH5UI.js.map +1 -0
- package/dist/{chunk-BBEKHLTW.cjs → chunk-CN3T3TDI.cjs} +9 -9
- package/dist/{chunk-BBEKHLTW.cjs.map → chunk-CN3T3TDI.cjs.map} +1 -1
- package/dist/{chunk-LNI3FYSI.js → chunk-CWIGQYRR.js} +7 -12
- package/dist/chunk-CWIGQYRR.js.map +1 -0
- package/dist/{chunk-BP52BFIV.cjs → chunk-D6FWEYQE.cjs} +6 -5
- package/dist/chunk-D6FWEYQE.cjs.map +1 -0
- package/dist/{chunk-UIHIXTIS.js → chunk-D7RLBBHE.js} +2 -2
- package/dist/{chunk-UIHIXTIS.js.map → chunk-D7RLBBHE.js.map} +1 -1
- package/dist/{chunk-IXUHXTHW.cjs → chunk-DLTT7QZU.cjs} +17 -6
- package/dist/chunk-DLTT7QZU.cjs.map +1 -0
- package/dist/{chunk-BHND5PEV.js → chunk-E3TQG7AA.js} +3 -3
- package/dist/{chunk-BHND5PEV.js.map → chunk-E3TQG7AA.js.map} +1 -1
- package/dist/{chunk-37V3RET3.cjs → chunk-E7E3NL3Y.cjs} +24 -23
- package/dist/chunk-E7E3NL3Y.cjs.map +1 -0
- package/dist/{chunk-VYQVDL2M.js → chunk-F26HP3B6.js} +36 -5
- package/dist/chunk-F26HP3B6.js.map +1 -0
- package/dist/{chunk-QZGABF2M.js → chunk-FVAK4C6L.js} +17 -6
- package/dist/chunk-FVAK4C6L.js.map +1 -0
- package/dist/{chunk-BJROXF4N.js → chunk-HSDJDWLV.js} +19 -4
- package/dist/chunk-HSDJDWLV.js.map +1 -0
- package/dist/{chunk-QJUJNTIU.cjs → chunk-I7MIRRFJ.cjs} +43 -12
- package/dist/chunk-I7MIRRFJ.cjs.map +1 -0
- package/dist/{chunk-LTZ5WYOK.cjs → chunk-JCBDXEY2.cjs} +18 -2
- package/dist/chunk-JCBDXEY2.cjs.map +1 -0
- package/dist/{chunk-UYJQDDEE.cjs → chunk-MI2YXCK4.cjs} +14 -8
- package/dist/chunk-MI2YXCK4.cjs.map +1 -0
- package/dist/{chunk-A2SN3RVL.cjs → chunk-MOGK3U4A.cjs} +2 -2
- package/dist/{chunk-A2SN3RVL.cjs.map → chunk-MOGK3U4A.cjs.map} +1 -1
- package/dist/{chunk-E66UVONV.cjs → chunk-OUBUS74I.cjs} +24 -9
- package/dist/chunk-OUBUS74I.cjs.map +1 -0
- package/dist/{chunk-GMMCCIQO.cjs → chunk-RSBZITK3.cjs} +3 -3
- package/dist/{chunk-GMMCCIQO.cjs.map → chunk-RSBZITK3.cjs.map} +1 -1
- package/dist/{chunk-THFZSDIU.js → chunk-SXC4HPK6.js} +14 -8
- package/dist/chunk-SXC4HPK6.js.map +1 -0
- package/dist/{chunk-JMJM7DMM.cjs → chunk-TT3TQSCZ.cjs} +5 -5
- package/dist/{chunk-JMJM7DMM.cjs.map → chunk-TT3TQSCZ.cjs.map} +1 -1
- package/dist/{chunk-QCJHCSOK.cjs → chunk-YAURVGUK.cjs} +2 -2
- package/dist/{chunk-QCJHCSOK.cjs.map → chunk-YAURVGUK.cjs.map} +1 -1
- package/dist/config-4TIHSNW6.js +6 -0
- package/dist/{config-6FB2BXMP.js.map → config-4TIHSNW6.js.map} +1 -1
- package/dist/{config-OCH7S4WK.cjs → config-XN2ETAJ3.cjs} +5 -5
- package/dist/{config-OCH7S4WK.cjs.map → config-XN2ETAJ3.cjs.map} +1 -1
- package/dist/{define-plugin-D_6D9vVZ.d.ts → define-plugin-DDe8a_bh.d.ts} +3 -0
- package/dist/{define-plugin-DMcvEy_C.d.cts → define-plugin-rjXmGOgu.d.cts} +3 -0
- package/dist/index.cjs +408 -370
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +67 -29
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +35 -35
- package/dist/middleware.d.cts +4 -1
- package/dist/middleware.d.ts +4 -1
- package/dist/middleware.js +6 -6
- package/dist/migrations-JAHMI5MK.js +4 -0
- package/dist/{migrations-Z6D27NAW.js.map → migrations-JAHMI5MK.js.map} +1 -1
- package/dist/migrations-KU4V6T73.cjs +13 -0
- package/dist/{migrations-FGXZPKDC.cjs.map → migrations-KU4V6T73.cjs.map} +1 -1
- package/dist/plugins.cjs +40 -40
- package/dist/plugins.d.cts +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/plugins.js +3 -3
- package/dist/rbac-AORZ6O3N.cjs +14 -0
- package/dist/{rbac-7QZ4JZ2E.cjs.map → rbac-AORZ6O3N.cjs.map} +1 -1
- package/dist/rbac-P44772FP.js +5 -0
- package/dist/{rbac-Y43IEQOP.js.map → rbac-P44772FP.js.map} +1 -1
- package/dist/routes.cjs +31 -31
- package/dist/routes.js +11 -11
- package/dist/services.cjs +18 -18
- package/dist/services.d.cts +1 -1
- package/dist/services.d.ts +1 -1
- package/dist/services.js +2 -2
- package/dist/{telemetry-Cku1ax74.d.cts → telemetry-QFlTv9f8.d.cts} +1 -1
- package/dist/{telemetry-Cku1ax74.d.ts → telemetry-QFlTv9f8.d.ts} +1 -1
- package/dist/templates.cjs +17 -17
- package/dist/templates.js +3 -3
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils.cjs +12 -12
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +2 -2
- package/package.json +5 -10
- package/dist/admin-documents-form.template-55V2ZGWT.js +0 -6
- package/dist/admin-documents-form.template-YNAVMJCV.cjs +0 -19
- package/dist/admin-layout-catalyst.template-3XZXDGF7.cjs +0 -21
- package/dist/admin-layout-catalyst.template-6UQGLCKI.js +0 -7
- package/dist/chunk-37V3RET3.cjs.map +0 -1
- package/dist/chunk-3TMTYJAJ.js.map +0 -1
- package/dist/chunk-BJROXF4N.js.map +0 -1
- package/dist/chunk-BP52BFIV.cjs.map +0 -1
- package/dist/chunk-E66UVONV.cjs.map +0 -1
- package/dist/chunk-FHPEM77Y.js.map +0 -1
- package/dist/chunk-I767LVN7.cjs.map +0 -1
- package/dist/chunk-IXUHXTHW.cjs.map +0 -1
- package/dist/chunk-KKNEYIZJ.cjs.map +0 -1
- package/dist/chunk-LNI3FYSI.js.map +0 -1
- package/dist/chunk-LTZ5WYOK.cjs.map +0 -1
- package/dist/chunk-QJUJNTIU.cjs.map +0 -1
- package/dist/chunk-QZGABF2M.js.map +0 -1
- package/dist/chunk-THFZSDIU.js.map +0 -1
- package/dist/chunk-UYJQDDEE.cjs.map +0 -1
- package/dist/chunk-VC5XVPLM.js.map +0 -1
- package/dist/chunk-VGEZNFWH.js.map +0 -1
- package/dist/chunk-VYQVDL2M.js.map +0 -1
- package/dist/config-6FB2BXMP.js +0 -6
- package/dist/migrations-FGXZPKDC.cjs +0 -13
- package/dist/migrations-Z6D27NAW.js +0 -4
- package/dist/rbac-7QZ4JZ2E.cjs +0 -14
- package/dist/rbac-Y43IEQOP.js +0 -5
|
@@ -476,6 +476,11 @@ function getBlocksFieldConfig(fieldOptions) {
|
|
|
476
476
|
discriminator
|
|
477
477
|
};
|
|
478
478
|
}
|
|
479
|
+
function generateBlockId() {
|
|
480
|
+
const bytes = new Uint8Array(6);
|
|
481
|
+
crypto.getRandomValues(bytes);
|
|
482
|
+
return "blk_" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
483
|
+
}
|
|
479
484
|
function parseBlocksValue(value, config) {
|
|
480
485
|
const errors = [];
|
|
481
486
|
let rawValue = value;
|
|
@@ -497,17 +502,23 @@ function parseBlocksValue(value, config) {
|
|
|
497
502
|
errors.push(`Block #${index + 1} must be an object`);
|
|
498
503
|
return null;
|
|
499
504
|
}
|
|
505
|
+
let block;
|
|
500
506
|
if (item.blockType && item.data && typeof item.data === "object") {
|
|
501
|
-
|
|
507
|
+
block = { [config.discriminator]: item.blockType, ...item.data };
|
|
508
|
+
} else {
|
|
509
|
+
if (!(config.discriminator in item)) {
|
|
510
|
+
errors.push(`Block #${index + 1} is missing "${config.discriminator}"`);
|
|
511
|
+
}
|
|
512
|
+
block = item;
|
|
502
513
|
}
|
|
503
|
-
if (!
|
|
504
|
-
|
|
514
|
+
if (!block.blockId) {
|
|
515
|
+
block = { blockId: generateBlockId(), ...block };
|
|
505
516
|
}
|
|
506
|
-
return
|
|
517
|
+
return block;
|
|
507
518
|
}).filter((item) => item !== null);
|
|
508
519
|
return { value: normalized, errors };
|
|
509
520
|
}
|
|
510
521
|
|
|
511
522
|
export { QueryFilterBuilder, TemplateRenderer, buildQuery, generateSlug, getBlocksFieldConfig, parseBlocksValue, renderTemplate, templateRenderer };
|
|
512
|
-
//# sourceMappingURL=chunk-
|
|
513
|
-
//# sourceMappingURL=chunk-
|
|
523
|
+
//# sourceMappingURL=chunk-FVAK4C6L.js.map
|
|
524
|
+
//# sourceMappingURL=chunk-FVAK4C6L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/slug-utils.ts","../src/utils/template-renderer.ts","../src/utils/query-filter.ts","../src/utils/blocks.ts"],"names":[],"mappings":"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","file":"chunk-FVAK4C6L.js","sourcesContent":["/**\n * Slug generation utilities for creating URL-friendly slugs\n */\n\n/**\n * Generate URL-friendly slug from text\n * \n * Features:\n * - Converts to lowercase\n * - Handles accented characters (NFD normalization)\n * - Removes diacritics\n * - Keeps only alphanumeric, spaces, underscores, and hyphens\n * - Replaces spaces with hyphens\n * - Collapses multiple hyphens/underscores\n * - Trims leading/trailing hyphens/underscores\n * - Limits length to 100 characters\n * \n * @param text - Text to slugify\n * @returns URL-safe slug\n * \n * @example\n * generateSlug('Hello World!') // 'hello-world'\n * generateSlug('Café París 2024') // 'cafe-paris-2024'\n * generateSlug('Multiple Spaces') // 'multiple-spaces'\n */\nexport function generateSlug(text: string): string {\n if (!text) return '';\n \n return text\n .toLowerCase()\n .normalize('NFD') // Decompose combined characters (e.g., é -> e + ́)\n .replace(/[\\u0300-\\u036f]/g, '') // Remove diacritics\n .replace(/[^a-z0-9\\s_-]/g, '') // Keep only alphanumeric, spaces, underscores, hyphens\n .replace(/\\s+/g, '-') // Replace spaces with hyphens\n .replace(/[-_]+/g, '-') // Collapse multiple hyphens/underscores\n .replace(/^[-_]+|[-_]+$/g, '') // Trim leading/trailing hyphens/underscores\n .substring(0, 100); // Limit length for URL safety\n}\n","// Template renderer compatible with Cloudflare Workers\n// No filesystem access available\n\ninterface TemplateData {\n [key: string]: any\n}\n\nexport class TemplateRenderer {\n private templateCache = new Map<string, string>()\n\n constructor() {\n // Cloudflare Workers compatible - no filesystem access\n }\n\n /**\n * Simple Handlebars-like template engine\n */\n private renderTemplate(template: string, data: TemplateData): string {\n let rendered = template\n\n // Handle each loops - process outermost loops first for proper nesting\n rendered = rendered.replace(/\\{\\{#each\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/each\\}\\}/g, (_match, arrayName, content) => {\n const array = this.getNestedValue(data, arrayName.trim())\n if (!Array.isArray(array)) return ''\n \n return array.map((item, index) => {\n // Create context with array item and special variables\n const itemContext = {\n ...data,\n // Handle primitive items (for {{.}} syntax)\n '.': item,\n // Spread item properties if it's an object\n ...(typeof item === 'object' && item !== null ? item : {}),\n '@index': index,\n '@first': index === 0,\n '@last': index === array.length - 1\n }\n return this.renderTemplate(content, itemContext)\n }).join('')\n })\n\n // Second pass: Handle conditionals\n let ifCount = 0\n while (rendered.includes('{{#if ') && ifCount < 100) {\n const previousRendered = rendered\n rendered = rendered.replace(/\\{\\{#if\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g, (_match, condition, content) => {\n const value = this.getNestedValue(data, condition.trim())\n // Handle boolean values properly - @first/@last are explicitly boolean\n const isTruthy = value === true || (value && value !== 0 && value !== '' && value !== null && value !== undefined)\n return isTruthy ? this.renderTemplate(content, data) : ''\n })\n if (previousRendered === rendered) break\n ifCount++\n }\n\n // Third pass: Handle triple braces for raw HTML {{{variable}}}\n rendered = rendered.replace(/\\{\\{\\{([^}]+)\\}\\}\\}/g, (_match, variable) => {\n const value = this.getNestedValue(data, variable.trim())\n return value !== undefined && value !== null ? String(value) : ''\n })\n\n // Fourth pass: Handle helper functions like {{titleCase field}}\n rendered = rendered.replace(/\\{\\{([^}#\\/]+)\\s+([^}]+)\\}\\}/g, (match, helper, variable) => {\n const helperName = helper.trim()\n const varName = variable.trim()\n \n if (helperName === 'titleCase') {\n const value = this.getNestedValue(data, varName)\n if (value !== undefined && value !== null) {\n return this.titleCase(String(value))\n }\n }\n \n return match // Return original if helper not found\n })\n\n // Final pass: Handle simple variables {{variable}}\n rendered = rendered.replace(/\\{\\{([^}#\\/]+)\\}\\}/g, (match, variable) => {\n const trimmed = variable.trim()\n \n // Skip if it's a helper function (has spaces)\n if (trimmed.includes(' ')) {\n return match\n }\n \n const value = this.getNestedValue(data, trimmed)\n if (value === null) return ''\n if (value === undefined) return ''\n return String(value)\n })\n\n return rendered\n }\n\n /**\n * Get nested value from object using dot notation\n */\n private getNestedValue(obj: any, path: string): any {\n if (!obj || path === '') return undefined\n \n return path.split('.').reduce((current, key) => {\n if (current === null || current === undefined) return undefined\n return current[key]\n }, obj)\n }\n\n /**\n * Title case helper function\n */\n private titleCase(str: string): string {\n return str\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, l => l.toUpperCase())\n }\n\n /**\n * Render a template string with data\n */\n render(template: string, data: TemplateData = {}): string {\n return this.renderTemplate(template, data)\n }\n\n /**\n * Clear template cache (useful for development)\n */\n clearCache(): void {\n this.templateCache.clear()\n }\n}\n\n// Export singleton instance\nexport const templateRenderer = new TemplateRenderer()\n\n// Utility function to render template strings directly\nexport function renderTemplate(template: string, data: TemplateData = {}): string {\n return templateRenderer.render(template, data)\n}","/**\n * Query Filter Builder for SonicJS AI\n * Supports comprehensive filtering with AND/OR logic\n * Compatible with D1 Database (SQLite)\n */\n\nexport type FilterOperator =\n | 'equals'\n | 'not_equals'\n | 'greater_than'\n | 'greater_than_equal'\n | 'less_than'\n | 'less_than_equal'\n | 'like'\n | 'contains'\n | 'starts_with'\n | 'ends_with'\n | 'in'\n | 'not_in'\n | 'all'\n | 'exists'\n | 'near'\n | 'within'\n | 'intersects'\n\nconst VALID_FILTER_OPERATORS: ReadonlySet<FilterOperator> = new Set<FilterOperator>([\n 'equals',\n 'not_equals',\n 'greater_than',\n 'greater_than_equal',\n 'less_than',\n 'less_than_equal',\n 'like',\n 'contains',\n 'starts_with',\n 'ends_with',\n 'in',\n 'not_in',\n 'all',\n 'exists',\n 'near',\n 'within',\n 'intersects'\n])\n\nexport interface FilterCondition {\n field: string\n operator: FilterOperator\n value: any\n}\n\nexport interface FilterGroup {\n and?: FilterCondition[]\n or?: FilterCondition[]\n}\n\nexport interface QueryFilter {\n where?: FilterGroup\n limit?: number\n offset?: number\n sort?: {\n field: string\n order: 'asc' | 'desc'\n }[]\n}\n\nexport interface QueryResult {\n sql: string\n params: any[]\n errors: string[]\n}\n\n/**\n * Validate sort order value - only 'asc' or 'desc' are allowed.\n * Returns the validated lowercase value, defaulting to 'asc' for invalid input.\n */\nexport function validateSortOrder(order: any): 'asc' | 'desc' {\n if (typeof order === 'string') {\n const normalized = order.toLowerCase().trim()\n if (normalized === 'asc' || normalized === 'desc') {\n return normalized\n }\n }\n return 'asc'\n}\n\n/**\n * Query Filter Builder\n * Converts filter objects into SQL WHERE clauses with parameterized queries\n */\nexport class QueryFilterBuilder {\n private params: any[] = []\n private errors: string[] = []\n\n /**\n * Build a complete SQL query from filter object\n */\n build(baseTable: string, filter: QueryFilter): QueryResult {\n this.params = []\n this.errors = []\n\n let sql = `SELECT * FROM ${baseTable}`\n\n // Build WHERE clause\n if (filter.where) {\n const whereClause = this.buildWhereClause(filter.where)\n if (whereClause) {\n sql += ` WHERE ${whereClause}`\n }\n }\n\n // Build ORDER BY clause\n if (filter.sort && filter.sort.length > 0) {\n const orderClauses = filter.sort\n .map(s => `${this.sanitizeFieldName(s.field)} ${this.sanitizeSortOrder(s.order)}`)\n .join(', ')\n sql += ` ORDER BY ${orderClauses}`\n }\n\n // Build LIMIT clause\n if (filter.limit) {\n sql += ` LIMIT ?`\n this.params.push(filter.limit)\n }\n\n // Build OFFSET clause\n if (filter.offset) {\n sql += ` OFFSET ?`\n this.params.push(filter.offset)\n }\n\n return {\n sql,\n params: this.params,\n errors: this.errors\n }\n }\n\n /**\n * Build WHERE clause from filter group\n */\n private buildWhereClause(group: FilterGroup): string {\n const clauses: string[] = []\n\n // Handle AND conditions\n if (group.and && group.and.length > 0) {\n const andClauses = group.and\n .map(condition => this.buildCondition(condition))\n .filter(clause => clause !== null)\n\n if (andClauses.length > 0) {\n clauses.push(`(${andClauses.join(' AND ')})`)\n }\n }\n\n // Handle OR conditions\n if (group.or && group.or.length > 0) {\n const orClauses = group.or\n .map(condition => this.buildCondition(condition))\n .filter(clause => clause !== null)\n\n if (orClauses.length > 0) {\n clauses.push(`(${orClauses.join(' OR ')})`)\n }\n }\n\n return clauses.join(' AND ')\n }\n\n /**\n * Build a single condition\n */\n private buildCondition(condition: FilterCondition): string | null {\n const field = this.sanitizeFieldName(condition.field)\n\n switch (condition.operator) {\n case 'equals':\n return this.buildEquals(field, condition.value)\n\n case 'not_equals':\n return this.buildNotEquals(field, condition.value)\n\n case 'greater_than':\n return this.buildComparison(field, '>', condition.value)\n\n case 'greater_than_equal':\n return this.buildComparison(field, '>=', condition.value)\n\n case 'less_than':\n return this.buildComparison(field, '<', condition.value)\n\n case 'less_than_equal':\n return this.buildComparison(field, '<=', condition.value)\n\n case 'like':\n return this.buildLike(field, condition.value)\n\n case 'contains':\n return this.buildContains(field, condition.value)\n\n case 'starts_with':\n return this.buildStartsWith(field, condition.value)\n\n case 'ends_with':\n return this.buildEndsWith(field, condition.value)\n\n case 'in':\n return this.buildIn(field, condition.value)\n\n case 'not_in':\n return this.buildNotIn(field, condition.value)\n\n case 'all':\n return this.buildAll(field, condition.value)\n\n case 'exists':\n return this.buildExists(field, condition.value)\n\n case 'near':\n this.errors.push(`'near' operator not supported in SQLite. Use spatial extension or application-level filtering.`)\n return null\n\n case 'within':\n this.errors.push(`'within' operator not supported in SQLite. Use spatial extension or application-level filtering.`)\n return null\n\n case 'intersects':\n this.errors.push(`'intersects' operator not supported in SQLite. Use spatial extension or application-level filtering.`)\n return null\n\n default:\n this.errors.push(`Unknown operator: ${condition.operator}`)\n return null\n }\n }\n\n /**\n * Build equals condition\n */\n private buildEquals(field: string, value: any): string {\n if (value === null) {\n return `${field} IS NULL`\n }\n this.params.push(value)\n return `${field} = ?`\n }\n\n /**\n * Build not equals condition\n */\n private buildNotEquals(field: string, value: any): string {\n if (value === null) {\n return `${field} IS NOT NULL`\n }\n this.params.push(value)\n return `${field} != ?`\n }\n\n /**\n * Build comparison condition (>, >=, <, <=)\n */\n private buildComparison(field: string, operator: string, value: any): string {\n this.params.push(value)\n return `${field} ${operator} ?`\n }\n\n /**\n * Build LIKE condition (case-insensitive, all words must be present)\n */\n private buildLike(field: string, value: string): string {\n const words = value.split(/\\s+/).filter(w => w.length > 0)\n\n if (words.length === 0) {\n return `1=1` // No-op condition\n }\n\n const conditions = words.map(word => {\n this.params.push(`%${word}%`)\n return `${field} LIKE ?`\n })\n\n return `(${conditions.join(' AND ')})`\n }\n\n /**\n * Build CONTAINS condition (case-insensitive substring)\n */\n private buildContains(field: string, value: string): string {\n this.params.push(`%${value}%`)\n return `${field} LIKE ?`\n }\n\n /**\n * Build STARTS_WITH condition (case-insensitive prefix match)\n */\n private buildStartsWith(field: string, value: string): string {\n this.params.push(`${value}%`)\n return `${field} LIKE ?`\n }\n\n /**\n * Build ENDS_WITH condition (case-insensitive suffix match)\n */\n private buildEndsWith(field: string, value: string): string {\n this.params.push(`%${value}`)\n return `${field} LIKE ?`\n }\n\n /**\n * Build IN condition\n */\n private buildIn(field: string, value: any): string {\n let values: any[]\n\n if (typeof value === 'string') {\n // Parse comma-delimited string\n values = value.split(',').map(v => v.trim()).filter(v => v.length > 0)\n } else if (Array.isArray(value)) {\n values = value\n } else {\n values = [value]\n }\n\n if (values.length === 0) {\n return `1=0` // No values means no matches\n }\n\n const placeholders = values.map(v => {\n this.params.push(v)\n return '?'\n }).join(', ')\n\n return `${field} IN (${placeholders})`\n }\n\n /**\n * Build NOT IN condition\n */\n private buildNotIn(field: string, value: any): string {\n let values: any[]\n\n if (typeof value === 'string') {\n // Parse comma-delimited string\n values = value.split(',').map(v => v.trim()).filter(v => v.length > 0)\n } else if (Array.isArray(value)) {\n values = value\n } else {\n values = [value]\n }\n\n if (values.length === 0) {\n return `1=1` // No values means all match\n }\n\n const placeholders = values.map(v => {\n this.params.push(v)\n return '?'\n }).join(', ')\n\n return `${field} NOT IN (${placeholders})`\n }\n\n /**\n * Build ALL condition (value must contain all items in list)\n * For SQLite, we'll check if a JSON array contains all values\n */\n private buildAll(field: string, value: any): string {\n let values: any[]\n\n if (typeof value === 'string') {\n values = value.split(',').map(v => v.trim()).filter(v => v.length > 0)\n } else if (Array.isArray(value)) {\n values = value\n } else {\n values = [value]\n }\n\n if (values.length === 0) {\n return `1=1`\n }\n\n // For SQLite, check if field contains all values using JSON functions\n // This assumes the field is a JSON array or comma-separated string\n const conditions = values.map(val => {\n this.params.push(`%${val}%`)\n return `${field} LIKE ?`\n })\n\n return `(${conditions.join(' AND ')})`\n }\n\n /**\n * Build EXISTS condition\n */\n private buildExists(field: string, value: boolean): string {\n if (value) {\n return `${field} IS NOT NULL AND ${field} != ''`\n } else {\n return `(${field} IS NULL OR ${field} = '')`\n }\n }\n\n /**\n * Sanitize field names to prevent SQL injection\n */\n private sanitizeFieldName(field: string): string {\n // Allow alphanumeric, underscores, dots (for JSON fields)\n const sanitized = field.replace(/[^a-zA-Z0-9_$.]/g, '')\n\n // Handle JSON field access (e.g., data.title -> json_extract(data, '$.title'))\n if (sanitized.includes('.')) {\n const [table, ...path] = sanitized.split('.')\n return `json_extract(${table}, '$.${path.join('.')}')`\n }\n\n return sanitized\n }\n\n /**\n * Sanitize sort order to prevent SQL injection\n * Only allows 'ASC' or 'DESC', defaults to 'ASC' for any other value\n */\n private sanitizeSortOrder(order: string): string {\n const normalized = String(order).toUpperCase().trim()\n if (normalized === 'ASC' || normalized === 'DESC') {\n return normalized\n }\n return 'ASC'\n }\n\n /**\n * Parse filter from query string\n */\n static parseFromQuery(query: Record<string, any>): QueryFilter {\n const filter: QueryFilter = {}\n\n // Parse where clause from 'where' parameter (JSON string)\n if (query.where) {\n try {\n filter.where = typeof query.where === 'string'\n ? JSON.parse(query.where)\n : query.where\n } catch (e) {\n console.error('Failed to parse where clause:', e)\n }\n }\n\n // Initialize where clause if not present\n if (!filter.where) {\n filter.where = { and: [] }\n }\n if (!filter.where.and) {\n filter.where.and = []\n }\n\n // Parse simple field filters (status, collection_id, etc.)\n // These are convenience parameters that get converted to WHERE conditions\n const simpleFieldMappings: Record<string, string> = {\n 'status': 'status',\n 'collection_id': 'collection_id'\n }\n\n for (const [queryParam, dbField] of Object.entries(simpleFieldMappings)) {\n if (query[queryParam]) {\n filter.where.and.push({\n field: dbField,\n operator: 'equals',\n value: query[queryParam]\n })\n }\n }\n\n // Parse bracket-syntax filters: filter[field][operator]=value or filter[field]=value\n const bracketFilterRegex = /^filter\\[([^\\]]+)\\](?:\\[([^\\]]+)\\])?$/\n for (const [key, rawValue] of Object.entries(query)) {\n const match = key.match(bracketFilterRegex)\n if (!match) continue\n\n const field = match[1]\n const operator = (match[2] || 'equals') as FilterOperator\n\n if (!field || !VALID_FILTER_OPERATORS.has(operator)) continue\n if (rawValue === undefined || rawValue === null) continue\n\n let value: any = rawValue\n if (operator === 'exists') {\n value = value === 'true' || value === true || value === '1' || value === 1\n }\n\n filter.where.and.push({ field, operator, value })\n }\n\n // Parse limit\n if (query.limit) {\n filter.limit = Math.min(parseInt(query.limit), 1000) // Max 1000\n }\n\n // Parse offset\n if (query.offset) {\n filter.offset = parseInt(query.offset)\n }\n\n // Parse sort\n if (query.sort) {\n try {\n const parsed = typeof query.sort === 'string'\n ? JSON.parse(query.sort)\n : query.sort\n // Validate and sanitize sort entries\n if (Array.isArray(parsed)) {\n filter.sort = parsed\n .filter((s: any) => s && typeof s.field === 'string')\n .map((s: any) => ({\n field: s.field,\n order: validateSortOrder(s.order)\n }))\n }\n } catch (e) {\n console.error('Failed to parse sort clause:', e)\n }\n }\n\n return filter\n }\n}\n\n/**\n * Helper function to build query from filter\n */\nexport function buildQuery(table: string, filter: QueryFilter): QueryResult {\n const builder = new QueryFilterBuilder()\n return builder.build(table, filter)\n}\n","import type { BlockDefinitions } from '../types/collection-config'\n\nexport type BlocksFieldConfig = {\n blocks: BlockDefinitions\n discriminator: string\n}\n\nexport function getBlocksFieldConfig(fieldOptions: any): BlocksFieldConfig | null {\n if (!fieldOptions || typeof fieldOptions !== 'object') return null\n\n const itemsConfig = fieldOptions.items && typeof fieldOptions.items === 'object'\n ? fieldOptions.items\n : null\n\n if (!itemsConfig || !itemsConfig.blocks || typeof itemsConfig.blocks !== 'object') {\n return null\n }\n\n const discriminator = typeof itemsConfig.discriminator === 'string' && itemsConfig.discriminator\n ? itemsConfig.discriminator\n : 'blockType'\n\n return {\n blocks: itemsConfig.blocks as BlockDefinitions,\n discriminator\n }\n}\n\nfunction generateBlockId(): string {\n const bytes = new Uint8Array(6)\n crypto.getRandomValues(bytes)\n return 'blk_' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')\n}\n\nexport function parseBlocksValue(value: unknown, config: BlocksFieldConfig) {\n const errors: string[] = []\n let rawValue = value\n\n if (rawValue === null || rawValue === undefined || rawValue === '') {\n return { value: [] as any[], errors }\n }\n\n if (typeof rawValue === 'string') {\n try {\n rawValue = JSON.parse(rawValue)\n } catch {\n return { value: [] as any[], errors: ['Blocks value must be valid JSON'] }\n }\n }\n\n if (!Array.isArray(rawValue)) {\n return { value: [] as any[], errors: ['Blocks value must be an array'] }\n }\n\n const normalized = rawValue.map((item, index) => {\n if (!item || typeof item !== 'object') {\n errors.push(`Block #${index + 1} must be an object`)\n return null\n }\n\n let block: any\n if ((item as any).blockType && (item as any).data && typeof (item as any).data === 'object') {\n block = { [config.discriminator]: (item as any).blockType, ...(item as any).data }\n } else {\n if (!(config.discriminator in (item as any))) {\n errors.push(`Block #${index + 1} is missing \"${config.discriminator}\"`)\n }\n block = item as any\n }\n\n // Preserve existing blockId or generate a stable one for new blocks\n if (!block.blockId) {\n block = { blockId: generateBlockId(), ...block }\n }\n\n return block\n }).filter((item) => item !== null)\n\n return { value: normalized, errors }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { init_logo_template, init_admin_layout_catalyst_template, admin_layout_catalyst_template_exports, renderLogo, renderAdminLayoutCatalyst } from './chunk-
|
|
1
|
+
import { init_logo_template, init_admin_layout_catalyst_template, admin_layout_catalyst_template_exports, renderLogo, renderAdminLayoutCatalyst } from './chunk-SXC4HPK6.js';
|
|
2
2
|
import { escapeHtml } from './chunk-TQABQWOP.js';
|
|
3
3
|
import { __toCommonJS } from './chunk-V4OQ3NZ2.js';
|
|
4
4
|
|
|
@@ -1006,6 +1006,12 @@ function adminLayoutV2(data) {
|
|
|
1006
1006
|
</html>`;
|
|
1007
1007
|
}
|
|
1008
1008
|
function renderSidebar(currentPath, user, dynamicMenuItems) {
|
|
1009
|
+
const userRole = user?.role ?? "viewer";
|
|
1010
|
+
const isAdmin = userRole === "admin";
|
|
1011
|
+
const isEditor = userRole === "editor";
|
|
1012
|
+
const canManageUsers = isAdmin;
|
|
1013
|
+
const canAccessSettings = isAdmin || isEditor;
|
|
1014
|
+
const canAccessPlugins = isAdmin;
|
|
1009
1015
|
const baseMenuItems = [
|
|
1010
1016
|
{
|
|
1011
1017
|
label: "Content",
|
|
@@ -1086,7 +1092,16 @@ function renderSidebar(currentPath, user, dynamicMenuItems) {
|
|
|
1086
1092
|
</svg>`
|
|
1087
1093
|
}
|
|
1088
1094
|
];
|
|
1089
|
-
const
|
|
1095
|
+
const filteredBaseItems = baseMenuItems.filter((item) => {
|
|
1096
|
+
if (item.path === "/admin/users") return canManageUsers;
|
|
1097
|
+
if (item.path === "/admin/plugins") return canAccessPlugins;
|
|
1098
|
+
if (item.path === "/admin/settings") return canAccessSettings;
|
|
1099
|
+
if (item.path === "/admin/cache") return canAccessSettings;
|
|
1100
|
+
if (item.path === "/admin/logs") return canAccessSettings;
|
|
1101
|
+
if (item.path === "/admin/field-types") return canAccessSettings;
|
|
1102
|
+
return true;
|
|
1103
|
+
});
|
|
1104
|
+
const allMenuItems = [...filteredBaseItems];
|
|
1090
1105
|
if (dynamicMenuItems && dynamicMenuItems.length > 0) {
|
|
1091
1106
|
const usersIndex = allMenuItems.findIndex(
|
|
1092
1107
|
(item) => item.path === "/admin/users"
|
|
@@ -1690,5 +1705,5 @@ function renderFormField(field) {
|
|
|
1690
1705
|
}
|
|
1691
1706
|
|
|
1692
1707
|
export { adminLayoutV2, getConfirmationDialogScript, renderAdminLayout, renderAlert, renderCheckboxPage, renderConfirmationDialog, renderForm, renderFormField, renderPagination, renderTable };
|
|
1693
|
-
//# sourceMappingURL=chunk-
|
|
1694
|
-
//# sourceMappingURL=chunk-
|
|
1708
|
+
//# sourceMappingURL=chunk-HSDJDWLV.js.map
|
|
1709
|
+
//# sourceMappingURL=chunk-HSDJDWLV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/templates/alert.template.ts","../src/templates/confirmation-dialog.template.ts","../src/templates/pagination.template.ts","../src/templates/table.template.ts","../src/templates/layouts/admin-layout-v2.template.ts","../src/templates/pages/admin-checkboxes.template.ts","../src/templates/form.template.ts"],"names":["renderAdminLayoutCatalyst"],"mappings":"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","file":"chunk-HSDJDWLV.js","sourcesContent":["import { escapeHtml } from '../utils/sanitize'\n\nexport type AlertType = 'success' | 'error' | 'warning' | 'info'\n\nexport interface AlertData {\n type: AlertType\n title?: string\n message: string\n dismissible?: boolean\n className?: string\n icon?: boolean\n}\n\nexport function renderAlert(data: AlertData): string {\n const typeClasses = {\n success: 'bg-green-50 dark:bg-green-500/10 border border-green-600/20 dark:border-green-500/20',\n error: 'bg-error/10 border border-red-600/20 dark:border-red-500/20',\n warning: 'bg-amber-50 dark:bg-amber-500/10 border border-amber-600/20 dark:border-amber-500/20',\n info: 'bg-blue-50 dark:bg-blue-500/10 border border-blue-600/20 dark:border-blue-500/20'\n }\n\n const iconClasses = {\n success: 'text-green-600 dark:text-green-400',\n error: 'text-red-600 dark:text-red-400',\n warning: 'text-amber-600 dark:text-amber-400',\n info: 'text-blue-600 dark:text-blue-400'\n }\n\n const textClasses = {\n success: 'text-green-900 dark:text-green-300',\n error: 'text-red-900 dark:text-red-300',\n warning: 'text-amber-900 dark:text-amber-300',\n info: 'text-blue-900 dark:text-blue-300'\n }\n\n const messageTextClasses = {\n success: 'text-green-700 dark:text-green-400',\n error: 'text-red-700 dark:text-red-400',\n warning: 'text-amber-700 dark:text-amber-400',\n info: 'text-blue-700 dark:text-blue-400'\n }\n\n const icons = {\n success: `<path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\" />`,\n error: `<path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clip-rule=\"evenodd\" />`,\n warning: `<path fill-rule=\"evenodd\" d=\"M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z\" clip-rule=\"evenodd\" />`,\n info: `<path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z\" clip-rule=\"evenodd\" />`\n }\n\n return `\n <div class=\"rounded-lg p-4 ${typeClasses[data.type]} ${data.className || ''}\" ${data.dismissible ? 'id=\"dismissible-alert\"' : ''}>\n <div class=\"flex\">\n ${data.icon !== false ? `\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 ${iconClasses[data.type]}\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n ${icons[data.type]}\n </svg>\n </div>\n ` : ''}\n <div class=\"${data.icon !== false ? 'ml-3' : ''}\">\n ${data.title ? `\n <h3 class=\"text-sm font-semibold ${textClasses[data.type]}\">\n ${escapeHtml(data.title)}\n </h3>\n ` : ''}\n <div class=\"${data.title ? 'mt-1 text-sm' : 'text-sm'} ${messageTextClasses[data.type]}\">\n <p>${escapeHtml(data.message)}</p>\n </div>\n </div>\n ${data.dismissible ? `\n <div class=\"ml-auto pl-3\">\n <div class=\"-mx-1.5 -my-1.5\">\n <button\n type=\"button\"\n class=\"inline-flex rounded-md p-1.5 ${iconClasses[data.type]} hover:bg-opacity-20 focus:outline-none focus:ring-2 focus:ring-offset-2\"\n onclick=\"document.getElementById('dismissible-alert').remove()\"\n >\n <span class=\"sr-only\">Dismiss</span>\n <svg class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n `\n}\n\nexport function renderSuccessAlert(message: string, title?: string): string {\n return renderAlert({ type: 'success', message, title })\n}\n\nexport function renderErrorAlert(message: string, title?: string): string {\n return renderAlert({ type: 'error', message, title })\n}\n\nexport function renderWarningAlert(message: string, title?: string): string {\n return renderAlert({ type: 'warning', message, title })\n}\n\nexport function renderInfoAlert(message: string, title?: string): string {\n return renderAlert({ type: 'info', message, title })\n}","export interface ConfirmationDialogOptions {\n id: string\n title: string\n message: string\n confirmText?: string\n cancelText?: string\n confirmClass?: string\n iconColor?: 'red' | 'yellow' | 'blue'\n onConfirm?: string // JavaScript code to execute on confirm\n}\n\nexport function renderConfirmationDialog(options: ConfirmationDialogOptions): string {\n const {\n id,\n title,\n message,\n confirmText = 'Confirm',\n cancelText = 'Cancel',\n confirmClass = 'bg-red-500 hover:bg-red-400',\n iconColor = 'red',\n onConfirm = ''\n } = options\n\n const iconColorClasses = {\n red: 'bg-red-500/10 text-red-400',\n yellow: 'bg-yellow-500/10 text-yellow-400',\n blue: 'bg-blue-500/10 text-blue-400'\n }\n\n return `\n <el-dialog>\n <dialog\n id=\"${id}\"\n aria-labelledby=\"${id}-title\"\n class=\"fixed inset-0 m-0 size-auto max-h-none max-w-none overflow-y-auto bg-transparent p-0 backdrop:bg-transparent\"\n >\n <el-dialog-backdrop class=\"fixed inset-0 bg-gray-900/50 transition-opacity data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in\"></el-dialog-backdrop>\n\n <div tabindex=\"0\" class=\"flex min-h-full items-end justify-center p-4 text-center focus:outline focus:outline-0 sm:items-center sm:p-0\">\n <el-dialog-panel class=\"relative transform overflow-hidden rounded-lg bg-gray-800 px-4 pb-4 pt-5 text-left shadow-xl outline outline-1 -outline-offset-1 outline-white/10 transition-all data-[closed]:translate-y-4 data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in sm:my-8 sm:w-full sm:max-w-lg sm:p-6 data-[closed]:sm:translate-y-0 data-[closed]:sm:scale-95\">\n <div class=\"sm:flex sm:items-start\">\n <div class=\"mx-auto flex size-12 shrink-0 items-center justify-center rounded-full ${iconColorClasses[iconColor]} sm:mx-0 sm:size-10\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" data-slot=\"icon\" aria-hidden=\"true\" class=\"size-6\">\n <path d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n <div class=\"mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left\">\n <h3 id=\"${id}-title\" class=\"text-base font-semibold text-white\">${title}</h3>\n <div class=\"mt-2\">\n <p class=\"text-sm text-gray-400\">${message}</p>\n </div>\n </div>\n </div>\n <div class=\"mt-5 sm:mt-4 sm:flex sm:flex-row-reverse\">\n <button\n type=\"button\"\n onclick=\"${onConfirm}; document.getElementById('${id}').close()\"\n command=\"close\"\n commandfor=\"${id}\"\n class=\"confirm-button inline-flex w-full justify-center rounded-md ${confirmClass} px-3 py-2 text-sm font-semibold text-white sm:ml-3 sm:w-auto\"\n >\n ${confirmText}\n </button>\n <button\n type=\"button\"\n command=\"close\"\n commandfor=\"${id}\"\n class=\"mt-3 inline-flex w-full justify-center rounded-md bg-white/10 px-3 py-2 text-sm font-semibold text-white ring-1 ring-inset ring-white/5 hover:bg-white/20 sm:mt-0 sm:w-auto\"\n >\n ${cancelText}\n </button>\n </div>\n </el-dialog-panel>\n </div>\n </dialog>\n </el-dialog>\n `\n}\n\n/**\n * Helper function to show a confirmation dialog programmatically\n * Usage in templates: Add this script and call showConfirmDialog()\n */\nexport function getConfirmationDialogScript(): string {\n return `\n <script src=\"https://cdn.jsdelivr.net/npm/@tailwindplus/elements@1\" type=\"module\"></script>\n <script>\n function showConfirmDialog(dialogId) {\n const dialog = document.getElementById(dialogId);\n if (dialog) {\n dialog.showModal();\n }\n }\n </script>\n `\n}\n","export interface PaginationData {\n currentPage: number\n totalPages: number\n totalItems: number\n itemsPerPage: number\n startItem: number\n endItem: number\n baseUrl: string\n queryParams?: Record<string, string>\n showPageNumbers?: boolean\n maxPageNumbers?: number\n showPageSizeSelector?: boolean\n pageSizeOptions?: number[]\n}\n\nexport function renderPagination(data: PaginationData): string {\n // Show pagination if there are multiple pages OR if page size selector is enabled\n const shouldShowPagination = data.totalPages > 1 || (data.showPageSizeSelector !== false && data.totalItems > 0)\n\n if (!shouldShowPagination) {\n return ''\n }\n\n const buildUrl = (page: number, limit?: number): string => {\n const params = new URLSearchParams(data.queryParams || {})\n params.set('page', page.toString())\n if (limit) {\n params.set('limit', limit.toString())\n } else if (data.itemsPerPage !== 20) {\n params.set('limit', data.itemsPerPage.toString())\n }\n return `${data.baseUrl}?${params.toString()}`\n }\n\n const buildPageSizeUrl = (limit: number): string => {\n const params = new URLSearchParams(data.queryParams || {})\n params.set('page', '1') // Reset to page 1 when changing page size\n params.set('limit', limit.toString())\n return `${data.baseUrl}?${params.toString()}`\n }\n\n const generatePageNumbers = (): number[] => {\n const maxNumbers = data.maxPageNumbers || 5\n const half = Math.floor(maxNumbers / 2)\n let start = Math.max(1, data.currentPage - half)\n let end = Math.min(data.totalPages, start + maxNumbers - 1)\n\n // Adjust start if we're near the end\n if (end - start + 1 < maxNumbers) {\n start = Math.max(1, end - maxNumbers + 1)\n }\n\n const pages: number[] = []\n for (let i = start; i <= end; i++) {\n pages.push(i)\n }\n return pages\n }\n\n return `\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 px-4 py-3 flex items-center justify-between mt-4\">\n ${data.totalPages > 1 ? `\n <!-- Mobile Pagination -->\n <div class=\"flex-1 flex justify-between sm:hidden\">\n ${data.currentPage > 1 ? `\n <a href=\"${buildUrl(data.currentPage - 1)}\" class=\"inline-flex items-center rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Previous\n </a>\n ` : `\n <span class=\"inline-flex items-center rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-400 dark:text-zinc-600 shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 opacity-50 cursor-not-allowed\">Previous</span>\n `}\n\n ${data.currentPage < data.totalPages ? `\n <a href=\"${buildUrl(data.currentPage + 1)}\" class=\"inline-flex items-center rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Next\n </a>\n ` : `\n <span class=\"inline-flex items-center rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-400 dark:text-zinc-600 shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 opacity-50 cursor-not-allowed\">Next</span>\n `}\n </div>\n ` : ''}\n\n <!-- Desktop Pagination -->\n <div class=\"hidden sm:flex-1 sm:flex sm:items-center sm:justify-between\">\n <div class=\"flex items-center gap-4\">\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">\n Showing <span class=\"font-medium text-zinc-950 dark:text-white\">${data.startItem}</span> to\n <span class=\"font-medium text-zinc-950 dark:text-white\">${data.endItem}</span> of\n <span class=\"font-medium text-zinc-950 dark:text-white\">${data.totalItems}</span> results\n </p>\n ${data.showPageSizeSelector !== false ? `\n <div class=\"flex items-center gap-2\">\n <label for=\"page-size\" class=\"text-sm text-zinc-500 dark:text-zinc-400\">Per page:</label>\n <div class=\"grid grid-cols-1\">\n <select\n id=\"page-size\"\n onchange=\"window.location.href = this.value\"\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-sm text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400\"\n >\n ${(data.pageSizeOptions || [10, 20, 50, 100]).map(size => `\n <option value=\"${buildPageSizeUrl(size)}\" ${size === data.itemsPerPage ? 'selected' : ''}>\n ${size}\n </option>\n `).join('')}\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-4 self-center justify-self-end text-zinc-600 dark:text-zinc-400\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n ` : ''}\n </div>\n\n ${data.totalPages > 1 ? `\n <div class=\"flex items-center gap-x-1\">\n <!-- Previous Button -->\n ${data.currentPage > 1 ? `\n <a href=\"${buildUrl(data.currentPage - 1)}\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Previous\n </a>\n ` : ''}\n\n <!-- Page Numbers -->\n ${data.showPageNumbers !== false ? `\n <!-- First page if not in range -->\n ${(() => {\n const pageNumbers = generatePageNumbers()\n const firstPage = pageNumbers.length > 0 ? pageNumbers[0] : null\n return firstPage && firstPage > 1 ? `\n <a href=\"${buildUrl(1)}\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n 1\n </a>\n ${firstPage > 2 ? `\n <span class=\"px-2 text-sm text-zinc-500 dark:text-zinc-400\">...</span>\n ` : ''}\n ` : ''\n })()}\n\n <!-- Page number buttons -->\n ${generatePageNumbers().map(pageNum => `\n ${pageNum === data.currentPage ? `\n <span class=\"rounded-lg bg-zinc-950 dark:bg-white px-3 py-2 text-sm font-semibold text-white dark:text-zinc-950\">\n ${pageNum}\n </span>\n ` : `\n <a href=\"${buildUrl(pageNum)}\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n ${pageNum}\n </a>\n `}\n `).join('')}\n\n <!-- Last page if not in range -->\n ${(() => {\n const pageNumbers = generatePageNumbers()\n const lastPageNum = pageNumbers.length > 0 ? pageNumbers.slice(-1)[0] : null\n return lastPageNum && lastPageNum < data.totalPages ? `\n ${lastPageNum < data.totalPages - 1 ? `\n <span class=\"px-2 text-sm text-zinc-500 dark:text-zinc-400\">...</span>\n ` : ''}\n <a href=\"${buildUrl(data.totalPages)}\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n ${data.totalPages}\n </a>\n ` : ''\n })()}\n ` : ''}\n\n <!-- Next Button -->\n ${data.currentPage < data.totalPages ? `\n <a href=\"${buildUrl(data.currentPage + 1)}\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Next\n </a>\n ` : ''}\n </div>\n ` : ''}\n </div>\n </div>\n `\n}","export interface TableColumn {\n key: string\n label: string\n sortable?: boolean\n className?: string\n sortType?: 'string' | 'number' | 'date' | 'boolean'\n render?: (value: any, row: any) => string\n}\n\nexport interface TableData<T = any> {\n columns: TableColumn[]\n rows: T[]\n selectable?: boolean\n className?: string\n emptyMessage?: string\n tableId?: string\n title?: string\n rowClickable?: boolean\n rowClickUrl?: (row: T) => string\n}\n\nexport function renderTable<T = any>(data: TableData<T>): string {\n const tableId = data.tableId || `table-${Math.random().toString(36).substr(2, 9)}`\n\n if (data.rows.length === 0) {\n return `\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-8 text-center\">\n <div class=\"text-zinc-500 dark:text-zinc-400\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n <p class=\"mt-2 text-sm text-zinc-500 dark:text-zinc-400\">${data.emptyMessage || 'No data available'}</p>\n </div>\n </div>\n `\n }\n\n return `\n <div class=\"${data.className || ''}\" id=\"${tableId}\">\n ${data.title ? `\n <div class=\"px-4 sm:px-0 mb-4\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white\">${data.title}</h3>\n </div>\n ` : ''}\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full sortable-table\">\n <thead>\n <tr>\n ${data.selectable ? `\n <th class=\"px-4 py-3.5 text-center sm:pl-0\">\n <div class=\"flex items-center justify-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"checkbox\" id=\"select-all-${tableId}\" class=\"col-start-1 row-start-1 appearance-none rounded border border-white/10 bg-white/5 checked:border-cyan-500 checked:bg-cyan-500 indeterminate:border-cyan-500 indeterminate:bg-cyan-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-500 disabled:border-white/5 disabled:bg-white/10 disabled:checked:bg-white/10 forced-colors:appearance-auto row-checkbox\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n </th>\n ` : ''}\n ${data.columns.map((column, index) => {\n const isFirst = index === 0 && !data.selectable\n const isLast = index === data.columns.length - 1\n return `\n <th class=\"px-4 py-3.5 text-left text-sm font-semibold text-zinc-950 dark:text-white ${isFirst ? 'sm:pl-0' : ''} ${isLast ? 'sm:pr-0' : ''} ${column.className || ''}\">\n ${column.sortable ? `\n <button\n class=\"flex items-center gap-x-2 hover:text-zinc-700 dark:hover:text-zinc-300 transition-colors sort-btn text-left\"\n data-column=\"${column.key}\"\n data-sort-type=\"${column.sortType || 'string'}\"\n data-sort-direction=\"none\"\n onclick=\"sortTable('${tableId}', '${column.key}', '${column.sortType || 'string'}')\"\n >\n <span>${column.label}</span>\n <div class=\"sort-icons flex flex-col\">\n <svg class=\"w-3 h-3 sort-up opacity-30\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M14.707 12.707a1 1 0 01-1.414 0L10 9.414l-3.293 3.293a1 1 0 01-1.414-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 010 1.414z\" clip-rule=\"evenodd\" />\n </svg>\n <svg class=\"w-3 h-3 sort-down opacity-30 -mt-1\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n </button>\n ` : column.label}\n </th>\n `}).join('')}\n </tr>\n </thead>\n <tbody>\n ${data.rows.map((row) => {\n if (!row) return ''\n const clickableClass = data.rowClickable ? 'cursor-pointer' : ''\n const clickHandler = data.rowClickable && data.rowClickUrl ? `onclick=\"window.location.href='${data.rowClickUrl(row)}'\"` : ''\n return `\n <tr class=\"group border-t border-zinc-950/5 dark:border-white/5 hover:bg-gradient-to-r hover:from-cyan-50/50 hover:via-blue-50/30 hover:to-purple-50/50 dark:hover:from-cyan-900/20 dark:hover:via-blue-900/10 dark:hover:to-purple-900/20 hover:shadow-sm hover:shadow-cyan-500/5 dark:hover:shadow-cyan-400/5 transition-all duration-300 ${clickableClass}\" ${clickHandler}>\n ${data.selectable ? `\n <td class=\"px-4 py-4 sm:pl-0\" onclick=\"event.stopPropagation()\">\n <div class=\"flex items-center justify-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"checkbox\" value=\"${(row as any).id || ''}\" class=\"col-start-1 row-start-1 appearance-none rounded border border-white/10 bg-white/5 checked:border-cyan-500 checked:bg-cyan-500 indeterminate:border-cyan-500 indeterminate:bg-cyan-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-500 disabled:border-white/5 disabled:bg-white/10 disabled:checked:bg-white/10 forced-colors:appearance-auto row-checkbox\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n </td>\n ` : ''}\n ${data.columns.map((column, colIndex) => {\n const value = (row as any)[column.key]\n const displayValue = column.render ? column.render(value, row) : value\n const stopPropagation = column.key === 'actions' ? 'onclick=\"event.stopPropagation()\"' : ''\n const isFirst = colIndex === 0 && !data.selectable\n const isLast = colIndex === data.columns.length - 1\n return `\n <td class=\"px-4 py-4 text-sm text-zinc-500 dark:text-zinc-400 ${isFirst ? 'sm:pl-0 font-medium text-zinc-950 dark:text-white' : ''} ${isLast ? 'sm:pr-0' : ''} ${column.className || ''}\" ${stopPropagation}>\n ${displayValue || ''}\n </td>\n `\n }).join('')}\n </tr>\n `\n }).join('')}\n </tbody>\n </table>\n </div>\n\n <script>\n // Table sorting functionality\n window.sortTable = function(tableId, column, sortType) {\n const tableContainer = document.getElementById(tableId);\n const table = tableContainer.querySelector('.sortable-table');\n const tbody = table.querySelector('tbody');\n const rows = Array.from(tbody.querySelectorAll('tr'));\n const headerBtn = table.querySelector(\\`[data-column=\"\\${column}\"]\\`);\n\n // Get current sort direction\n let direction = headerBtn.getAttribute('data-sort-direction');\n\n // Reset all sort indicators\n table.querySelectorAll('.sort-btn').forEach(btn => {\n btn.setAttribute('data-sort-direction', 'none');\n btn.querySelectorAll('.sort-up, .sort-down').forEach(icon => {\n icon.classList.add('opacity-30');\n icon.classList.remove('opacity-100', 'text-zinc-950', 'dark:text-white');\n });\n });\n\n // Determine new direction\n if (direction === 'none' || direction === 'desc') {\n direction = 'asc';\n } else {\n direction = 'desc';\n }\n\n // Update current header\n headerBtn.setAttribute('data-sort-direction', direction);\n const upIcon = headerBtn.querySelector('.sort-up');\n const downIcon = headerBtn.querySelector('.sort-down');\n\n if (direction === 'asc') {\n upIcon.classList.remove('opacity-30');\n upIcon.classList.add('opacity-100', 'text-zinc-950', 'dark:text-white');\n downIcon.classList.add('opacity-30');\n downIcon.classList.remove('opacity-100', 'text-zinc-950', 'dark:text-white');\n } else {\n downIcon.classList.remove('opacity-30');\n downIcon.classList.add('opacity-100', 'text-zinc-950', 'dark:text-white');\n upIcon.classList.add('opacity-30');\n upIcon.classList.remove('opacity-100', 'text-zinc-950', 'dark:text-white');\n }\n\n // Find column index (accounting for potential select column)\n const headers = Array.from(table.querySelectorAll('th'));\n const selectableOffset = table.querySelector('input[id^=\"select-all\"]') ? 1 : 0;\n const columnIndex = headers.findIndex(th => th.querySelector(\\`[data-column=\"\\${column}\"]\\`)) - selectableOffset;\n\n // Sort rows\n rows.sort((a, b) => {\n const aCell = a.children[columnIndex + selectableOffset];\n const bCell = b.children[columnIndex + selectableOffset];\n\n if (!aCell || !bCell) return 0;\n\n let aValue = aCell.textContent.trim();\n let bValue = bCell.textContent.trim();\n\n // Handle different sort types\n switch (sortType) {\n case 'number':\n aValue = parseFloat(aValue.replace(/[^0-9.-]/g, '')) || 0;\n bValue = parseFloat(bValue.replace(/[^0-9.-]/g, '')) || 0;\n break;\n case 'date':\n aValue = new Date(aValue).getTime() || 0;\n bValue = new Date(bValue).getTime() || 0;\n break;\n case 'boolean':\n aValue = aValue.toLowerCase() === 'true' || aValue.toLowerCase() === 'published' || aValue.toLowerCase() === 'active';\n bValue = bValue.toLowerCase() === 'true' || bValue.toLowerCase() === 'published' || bValue.toLowerCase() === 'active';\n break;\n default: // string\n aValue = aValue.toLowerCase();\n bValue = bValue.toLowerCase();\n }\n\n if (aValue < bValue) return direction === 'asc' ? -1 : 1;\n if (aValue > bValue) return direction === 'asc' ? 1 : -1;\n return 0;\n });\n\n // Re-append sorted rows\n rows.forEach(row => tbody.appendChild(row));\n };\n\n // Select all functionality\n document.addEventListener('DOMContentLoaded', function() {\n document.querySelectorAll('[id^=\"select-all\"]').forEach(selectAll => {\n selectAll.addEventListener('change', function() {\n const tableId = this.id.replace('select-all-', '');\n const table = document.getElementById(tableId);\n if (table) {\n const checkboxes = table.querySelectorAll('.row-checkbox');\n checkboxes.forEach(checkbox => {\n checkbox.checked = this.checked;\n });\n }\n });\n });\n });\n </script>\n </div>\n `\n}","import { HtmlEscapedString } from \"hono/utils/html\";\nimport { renderLogo } from \"../components/logo.template\";\n\nexport interface AdminLayoutData {\n title: string;\n pageTitle?: string;\n currentPath?: string;\n version?: string;\n enableExperimentalFeatures?: boolean;\n user?: {\n name: string;\n email: string;\n role: string;\n };\n scripts?: string[];\n styles?: string[];\n content: string | HtmlEscapedString;\n dynamicMenuItems?: Array<{\n label: string;\n path: string;\n icon: string;\n }>;\n}\n\nexport function renderAdminLayout(data: AdminLayoutData): string {\n // Import and use the new Catalyst layout\n const {\n renderAdminLayoutCatalyst,\n } = require(\"./admin-layout-catalyst.template\");\n return renderAdminLayoutCatalyst(data);\n}\n\nexport function adminLayoutV2(data: AdminLayoutData): string {\n return `<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${data.title} - SonicJS AI Admin</title>\n <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\">\n \n <!-- Tailwind CSS -->\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <script>\n tailwind.config = {\n darkMode: 'class',\n theme: {\n extend: {\n backdropBlur: {\n xs: '2px',\n },\n colors: {\n primary: '#465FFF',\n secondary: '#212A3E',\n dark: '#1C1C24',\n 'dark-2': '#1A1A27',\n 'dark-3': '#2C2C54',\n 'dark-4': '#40407A',\n 'dark-5': '#706FD3',\n 'gray-1': '#F7F9FC',\n 'gray-2': '#E4E6EA',\n 'gray-3': '#D2D4D9',\n 'gray-4': '#9CA3AF',\n 'gray-5': '#6B7280',\n 'gray-6': '#4B5563',\n 'gray-7': '#374151',\n 'gray-8': '#1F2937',\n 'gray-9': '#111827',\n success: '#10B981',\n warning: '#F59E0B',\n error: '#EF4444',\n info: '#3B82F6'\n },\n fontFamily: {\n satoshi: ['Satoshi', 'sans-serif'],\n },\n spacing: {\n '4.5': '1.125rem',\n '5.5': '1.375rem',\n '6.5': '1.625rem',\n '7.5': '1.875rem'\n },\n boxShadow: {\n 'default': '0px 8px 13px -3px rgba(0, 0, 0, 0.07)',\n 'card': '0px 1px 3px rgba(0, 0, 0, 0.12)',\n 'card-2': '0px 1px 2px rgba(0, 0, 0, 0.05)',\n 'switcher': '0px 2px 4px rgba(0, 0, 0, 0.2), inset 0px 2px 2px #FFFFFF, inset 0px -1px 1px rgba(0, 0, 0, 0.1)',\n },\n dropShadow: {\n 1: '0px 1px 0px #E2E8F0',\n 2: '0px 1px 4px rgba(0, 0, 0, 0.12)',\n }\n }\n }\n }\n </script>\n \n <!-- Additional Styles -->\n <style>\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');\n \n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n \n body {\n font-family: 'Inter', system-ui, -apple-system, sans-serif;\n }\n \n /* Custom scrollbar */\n ::-webkit-scrollbar {\n width: 6px;\n }\n \n ::-webkit-scrollbar-track {\n background: #1F2937;\n }\n \n ::-webkit-scrollbar-thumb {\n background: #465FFF;\n border-radius: 3px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: #3B4EE8;\n }\n \n /* Sidebar animations */\n .sidebar-item {\n transition: all 0.3s ease;\n }\n \n .sidebar-item:hover {\n transform: translateX(4px);\n }\n \n /* Card animations */\n .card-hover {\n transition: all 0.3s ease;\n }\n \n .card-hover:hover {\n transform: translateY(-2px);\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n }\n \n /* Button gradients */\n .btn-gradient {\n background: linear-gradient(135deg, #465FFF 0%, #9333EA 100%);\n }\n \n .btn-gradient:hover {\n background: linear-gradient(135deg, #3B4EE8 0%, #7C2D12 100%);\n }\n \n /* Dark mode form elements */\n .form-input {\n background-color: #1F2937;\n border-color: #374151;\n color: #F9FAFB;\n }\n \n .form-input:focus {\n border-color: #465FFF;\n box-shadow: 0 0 0 3px rgba(70, 95, 255, 0.1);\n }\n \n /* Notification styles */\n .notification {\n -webkit-backdrop-filter: blur(15px);\n backdrop-filter: blur(15px);\n animation: slideInRight 0.3s ease-out;\n }\n \n @keyframes slideInRight {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n }\n \n /* Custom slider styles */\n .slider::-webkit-slider-thumb {\n appearance: none;\n height: 16px;\n width: 16px;\n border-radius: 50%;\n background: #465FFF;\n cursor: pointer;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n \n .slider::-moz-range-thumb {\n height: 16px;\n width: 16px;\n border-radius: 50%;\n background: #465FFF;\n cursor: pointer;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n \n .slider::-webkit-slider-track {\n height: 8px;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.2);\n }\n \n .slider::-moz-range-track {\n height: 8px;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.2);\n border: none;\n }\n \n /* PNG Background Images */\n .svg-pattern-blue-waves {\n background-color: #111827;\n background-image: url('/images/backgrounds/blue-waves.png');\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n }\n \n .svg-pattern-blue-crescent {\n background-color: #111827;\n background-image: url('/images/backgrounds/blue-crescent.png');\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n }\n \n .svg-pattern-blue-stars {\n background-color: #111827;\n background-image: url('/images/backgrounds/blue-stars.png');\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n }\n \n .svg-pattern-blue-waves-3d {\n background-color: #111827;\n background-image: url('/images/backgrounds/blue-waves-3d.png');\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n }\n </style>\n \n <!-- Scripts -->\n <script src=\"https://unpkg.com/htmx.org@2.0.3\"></script>\n <script src=\"https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js\" defer></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js\"></script>\n \n ${data.styles ? data.styles.map((style) => `<link rel=\"stylesheet\" href=\"${style}\">`).join(\"\\n \") : \"\"}\n ${data.scripts ? data.scripts.map((script) => `<script src=\"${script}\"></script>`).join(\"\\n \") : \"\"}\n</head>\n<body class=\"bg-gradient-to-br from-slate-900 via-gray-900 to-black min-h-screen text-gray-1\">\n <!-- Background overlay with glass effect -->\n <div id=\"background-overlay\" class=\"fixed inset-0 backdrop-blur-sm\" style=\"background-color: rgba(0, 0, 0, 0.2);\"></div>\n <!-- Main container -->\n <div class=\"relative z-10 min-h-screen\">\n <!-- Header -->\n ${renderTopBar(data.pageTitle || \"Dashboard\", data.user)}\n\n <!-- Main content area -->\n <div class=\"px-4 sm:px-6 lg:px-8 py-8\">\n <div class=\"grid grid-cols-1 lg:grid-cols-5 gap-6\">\n <!-- Sidebar -->\n <div class=\"lg:col-span-1\">\n ${renderSidebar(data.currentPath || \"/\", data.user, data.dynamicMenuItems)}\n </div>\n \n <!-- Main content -->\n <div class=\"lg:col-span-4\">\n ${data.content}\n </div>\n </div>\n </div>\n </div>\n \n <!-- Notification Container -->\n <div id=\"notification-container\" class=\"fixed top-4 right-4 z-50 space-y-2\"></div>\n \n <script>\n // Dark mode toggle functionality\n function toggleDarkMode() {\n document.documentElement.classList.toggle('dark');\n localStorage.setItem('darkMode', document.documentElement.classList.contains('dark'));\n }\n \n // Initialize dark mode from localStorage\n if (localStorage.getItem('darkMode') === 'true' || (!('darkMode' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {\n document.documentElement.classList.add('dark');\n }\n \n // Sidebar toggle for mobile\n function toggleSidebar() {\n const sidebar = document.getElementById('sidebar');\n const overlay = document.getElementById('sidebar-overlay');\n sidebar.classList.toggle('-translate-x-full');\n overlay.classList.toggle('hidden');\n }\n \n // Close sidebar on overlay click\n function closeSidebar() {\n const sidebar = document.getElementById('sidebar');\n const overlay = document.getElementById('sidebar-overlay');\n sidebar.classList.add('-translate-x-full');\n overlay.classList.add('hidden');\n }\n \n // User dropdown toggle\n function toggleUserDropdown() {\n const dropdowns = document.querySelectorAll('.userDropdown');\n dropdowns.forEach(function(dropdown) {\n dropdown.classList.toggle('hidden');\n });\n }\n \n // Close dropdown when clicking outside\n document.addEventListener('click', function(event) {\n const dropdowns = document.querySelectorAll('.userDropdown');\n const button = event.target.closest('button');\n if (!button || !button.getAttribute('onclick')) {\n dropdowns.forEach(function(dropdown) {\n dropdown.classList.add('hidden');\n });\n }\n });\n \n // Show notification\n function showNotification(message, type = 'info') {\n const container = document.getElementById('notification-container');\n const notification = document.createElement('div');\n const colors = {\n success: 'bg-success text-white',\n error: 'bg-error text-white',\n warning: 'bg-warning text-white',\n info: 'bg-info text-white'\n };\n \n notification.className = \\`notification px-6 py-4 rounded-lg shadow-lg \\${colors[type] || colors.info} max-w-sm\\`;\n notification.innerHTML = \\`\n <div class=\"flex items-center justify-between\">\n <span>\\${message}</span>\n <button onclick=\"this.parentElement.parentElement.remove()\" class=\"ml-4 text-white/80 hover:text-white\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n \\`;\n \n container.appendChild(notification);\n \n // Auto remove after 5 seconds\n setTimeout(() => {\n if (notification.parentElement) {\n notification.remove();\n }\n }, 5000);\n }\n \n // Background customizer functionality\n function toggleBackgroundCustomizer() {\n const dropdown = document.getElementById('backgroundCustomizer');\n dropdown.classList.toggle('hidden');\n }\n \n // Background themes\n const backgroundThemes = {\n 'default': 'bg-gradient-to-br from-slate-900 via-gray-900 to-black',\n 'cosmic-blue': 'bg-gradient-to-br from-slate-900 via-blue-900 to-indigo-900',\n 'matrix-green': 'bg-gradient-to-br from-gray-900 via-emerald-900 to-green-900',\n 'cyber-pink': 'bg-gradient-to-br from-gray-900 via-pink-900 to-rose-900',\n 'neon-orange': 'bg-gradient-to-br from-gray-900 via-orange-900 to-amber-900',\n 'purple-space': 'bg-gradient-to-br from-gray-900 via-purple-900 to-violet-800',\n 'blue-waves': 'svg-pattern-blue-waves',\n 'blue-crescent': 'svg-pattern-blue-crescent',\n 'blue-stars': 'svg-pattern-blue-stars',\n 'blue-waves-3d': 'svg-pattern-blue-waves-3d'\n };\n \n // Set background theme\n function setBackground(theme) {\n const body = document.body;\n \n // Remove all existing background classes and SVG patterns\n Object.values(backgroundThemes).forEach(bgClass => {\n if (bgClass.startsWith('svg-pattern-')) {\n body.classList.remove(bgClass);\n } else {\n body.classList.remove(...bgClass.split(' ').slice(1)); // Remove 'bg-gradient-to-br' prefix\n }\n });\n body.classList.remove('bg-gradient-to-br');\n \n // Add new background\n const themeClass = backgroundThemes[theme];\n if (themeClass.startsWith('svg-pattern-')) {\n body.classList.add(themeClass);\n } else {\n const newClasses = themeClass.split(' ').slice(1); // Remove 'bg-gradient-to-br' prefix\n body.classList.add('bg-gradient-to-br', ...newClasses);\n }\n \n // Save preference\n localStorage.setItem('backgroundTheme', theme);\n \n // Close dropdown\n toggleBackgroundCustomizer();\n \n // Show notification\n showNotification('Background changed to ' + theme.replace('-', ' '), 'success');\n }\n \n // Adjust background darkness\n function adjustDarkness(value) {\n const overlay = document.getElementById('background-overlay');\n if (overlay) {\n const opacity = value / 100; // Convert percentage to decimal\n overlay.style.backgroundColor = 'rgba(0, 0, 0, ' + opacity + ')';\n localStorage.setItem('backgroundDarkness', value);\n console.log('Darkness adjusted to:', value + '%', 'Opacity:', opacity);\n } else {\n console.log('Overlay element not found');\n }\n }\n \n // Initialize background on page load\n function initializeBackground() {\n const savedTheme = localStorage.getItem('backgroundTheme') || 'default';\n const savedDarkness = localStorage.getItem('backgroundDarkness') || '20';\n \n // Set background theme\n if (savedTheme !== 'default') {\n const body = document.body;\n const themeClass = backgroundThemes[savedTheme];\n \n // Remove all existing backgrounds first\n Object.values(backgroundThemes).forEach(bgClass => {\n if (bgClass.startsWith('svg-pattern-')) {\n body.classList.remove(bgClass);\n } else {\n body.classList.remove(...bgClass.split(' ').slice(1));\n }\n });\n body.classList.remove('bg-gradient-to-br');\n \n // Apply saved theme\n if (themeClass.startsWith('svg-pattern-')) {\n body.classList.add(themeClass);\n } else {\n const newClasses = themeClass.split(' ').slice(1);\n body.classList.add('bg-gradient-to-br', ...newClasses);\n }\n }\n \n // Set darkness\n const overlay = document.getElementById('background-overlay');\n if (overlay) {\n const opacity = savedDarkness / 100;\n overlay.style.backgroundColor = 'rgba(0, 0, 0, ' + opacity + ')';\n }\n \n // Set slider value\n const slider = document.getElementById('darknessSlider');\n if (slider) {\n slider.value = savedDarkness;\n }\n }\n \n // Close dropdown when clicking outside\n document.addEventListener('click', function(event) {\n const dropdown = document.getElementById('backgroundCustomizer');\n const button = event.target.closest('button');\n const slider = event.target.closest('#darknessSlider');\n const dropdownContainer = event.target.closest('#backgroundCustomizer');\n \n // Don't close if clicking inside the dropdown, on the toggle button, or on the slider\n if (!button?.getAttribute('onclick')?.includes('toggleBackgroundCustomizer') && \n !slider && !dropdownContainer) {\n dropdown?.classList.add('hidden');\n }\n });\n \n // Initialize background when page loads\n document.addEventListener('DOMContentLoaded', initializeBackground);\n </script>\n</body>\n</html>`;\n}\n\nfunction renderSidebar(\n currentPath: string,\n user?: any,\n dynamicMenuItems?: Array<{\n label: string;\n path: string;\n icon: string;\n }>\n): string {\n const userRole: string = user?.role ?? 'viewer';\n const isAdmin = userRole === 'admin';\n const isEditor = userRole === 'editor';\n const canManageUsers = isAdmin;\n const canAccessSettings = isAdmin || isEditor;\n const canAccessPlugins = isAdmin;\n\n const baseMenuItems = [\n {\n label: \"Content\",\n path: \"/admin/content\",\n icon: `<svg class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"/>\n </svg>`,\n },\n {\n label: \"Collections\",\n path: \"/admin/collections\",\n icon: `<svg class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3z\"/>\n </svg>`,\n },\n {\n label: \"Media\",\n path: \"/admin/media\",\n icon: `<svg class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M3 3a1 1 0 000 2v8a2 2 0 002 2h2.586l-1.293 1.293a1 1 0 101.414 1.414L10 15.414l2.293 2.293a1 1 0 001.414-1.414L12.414 15H15a2 2 0 002-2V5a1 1 0 100-2H3zm11.707 4.707a1 1 0 00-1.414-1.414L10 9.586 8.707 8.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"/>\n </svg>`,\n },\n {\n label: \"Users\",\n path: \"/admin/users\",\n icon: `<svg class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3z\"/>\n </svg>`,\n },\n {\n label: \"Plugins\",\n path: \"/admin/plugins\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"/>\n </svg>`,\n },\n {\n label: \"Cache\",\n path: \"/admin/cache\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\"/>\n </svg>`,\n },\n {\n label: \"Logs\",\n path: \"/admin/logs\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"/>\n </svg>`,\n },\n {\n label: \"Settings\",\n path: \"/admin/settings\",\n icon: `<svg class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z\" clip-rule=\"evenodd\"/>\n </svg>`,\n },\n {\n label: \"API Reference\",\n path: \"/admin/api-reference\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\"/>\n </svg>`,\n },\n {\n label: \"Field Types\",\n path: \"/admin/field-types\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"/>\n </svg>`,\n },\n {\n label: \"API Spec\",\n path: \"/api\",\n target: \"_blank\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"/>\n </svg>`,\n },\n ];\n\n // Filter based on role: viewers see content/collections/media only\n const filteredBaseItems = baseMenuItems.filter(item => {\n if (item.path === '/admin/users') return canManageUsers;\n if (item.path === '/admin/plugins') return canAccessPlugins;\n if (item.path === '/admin/settings') return canAccessSettings;\n if (item.path === '/admin/cache') return canAccessSettings;\n if (item.path === '/admin/logs') return canAccessSettings;\n if (item.path === '/admin/field-types') return canAccessSettings;\n return true;\n });\n\n // Combine base menu items with dynamic menu items from active plugins\n const allMenuItems = [...filteredBaseItems];\n\n // Insert dynamic menu items after \"Users\"\n if (dynamicMenuItems && dynamicMenuItems.length > 0) {\n const usersIndex = allMenuItems.findIndex(\n (item) => item.path === \"/admin/users\"\n );\n if (usersIndex !== -1) {\n allMenuItems.splice(usersIndex + 1, 0, ...dynamicMenuItems);\n } else {\n // Fallback: add to end if Users not found\n allMenuItems.push(...dynamicMenuItems);\n }\n }\n\n return `\n <nav class=\"backdrop-blur-md bg-black/30 rounded-xl border border-white/10 shadow-xl p-6 h-[calc(100vh-9.5rem)] sticky top-8\">\n <div class=\"space-y-4\">\n ${allMenuItems\n .map((item) => {\n const isActive =\n currentPath === item.path ||\n (item.path !== \"/admin\" && currentPath.startsWith(item.path));\n const targetAttr = (item as any).target\n ? ` target=\"${(item as any).target}\"`\n : \"\";\n return `\n <a href=\"${item.path}\"${targetAttr} class=\"flex items-center space-x-3 ${isActive ? \"text-white bg-white/20\" : \"text-gray-300 hover:text-white\"} rounded-lg px-3 py-2 transition-all hover:bg-white/10\">\n ${item.icon}\n <span>${item.label}</span>\n </a>\n `;\n })\n .join(\"\")}\n </div>\n </nav>\n `;\n}\n\nfunction renderTopBar(pageTitle: string, user?: any): string {\n return `\n <header class=\"backdrop-blur-md bg-white/10 border-b border-white/20 shadow-lg relative z-[9998]\">\n <div class=\"px-4 sm:px-6 lg:px-8\">\n <div class=\"flex justify-between items-center py-4\">\n <div class=\"flex items-center space-x-4\">\n ${renderLogo({ size: \"md\", showText: true, variant: \"white\" })}\n </div>\n \n <div class=\"flex items-center space-x-4\">\n <!-- Notifications -->\n <button class=\"p-2 text-gray-300 hover:text-white transition-colors rounded-lg hover:bg-white/10 relative\">\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9\"/>\n </svg>\n <span class=\"absolute top-1 right-1 w-2 h-2 bg-red-400 rounded-full\"></span>\n </button>\n\n <!-- Background Customizer -->\n <div class=\"relative z-[9999]\">\n <button class=\"p-2 text-gray-300 hover:text-white transition-colors rounded-lg hover:bg-white/10\" onclick=\"toggleBackgroundCustomizer()\">\n <svg class=\"w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.098 19.902a3.75 3.75 0 0 0 5.304 0l6.401-6.402M6.75 21A3.75 3.75 0 0 1 3 17.25V4.125C3 3.504 3.504 3 4.125 3h5.25c.621 0 1.125.504 1.125 1.125v4.072M6.75 21a3.75 3.75 0 0 0 3.75-3.75V8.197M6.75 21h13.125c.621 0 1.125-.504 1.125-1.125v-5.25c0-.621-.504-1.125-1.125-1.125h-4.072M10.5 8.197l2.88-2.88c.438-.439 1.15-.439 1.59 0l3.712 3.713c.44.44.44 1.152 0 1.59l-2.879 2.88M6.75 17.25h.008v.008H6.75v-.008Z\" />\n </svg>\n </button>\n \n <!-- Background Customizer Dropdown -->\n <div id=\"backgroundCustomizer\" class=\"hidden absolute right-0 mt-2 w-80 backdrop-blur-md bg-black/95 rounded-xl border border-white/10 shadow-xl z-[9999]\">\n <div class=\"p-6\">\n <div class=\"flex items-center justify-between mb-4\">\n <h3 class=\"text-lg font-semibold text-white\">Background Themes</h3>\n <button onclick=\"toggleBackgroundCustomizer()\" class=\"text-gray-400 hover:text-white\">\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n \n <!-- Background Options -->\n <div class=\"space-y-3 mb-6\">\n <div class=\"grid grid-cols-2 gap-3\">\n <!-- Default (Deep Space) -->\n <button onclick=\"setBackground('default')\" class=\"bg-preview bg-gradient-to-br from-slate-900 via-gray-900 to-black h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group\">\n <div class=\"absolute inset-0 bg-black/20 rounded-lg\"></div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium\">Default</div>\n </button>\n \n <!-- Cosmic Blue -->\n <button onclick=\"setBackground('cosmic-blue')\" class=\"bg-preview bg-gradient-to-br from-slate-900 via-blue-900 to-indigo-900 h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group\">\n <div class=\"absolute inset-0 bg-black/20 rounded-lg\"></div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium\">Cosmic</div>\n </button>\n \n <!-- Matrix Green -->\n <button onclick=\"setBackground('matrix-green')\" class=\"bg-preview bg-gradient-to-br from-gray-900 via-emerald-900 to-green-900 h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group\">\n <div class=\"absolute inset-0 bg-black/20 rounded-lg\"></div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium\">Matrix</div>\n </button>\n \n <!-- Cyber Pink -->\n <button onclick=\"setBackground('cyber-pink')\" class=\"bg-preview bg-gradient-to-br from-gray-900 via-pink-900 to-rose-900 h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group\">\n <div class=\"absolute inset-0 bg-black/20 rounded-lg\"></div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium\">Cyber</div>\n </button>\n \n <!-- Neon Orange -->\n <button onclick=\"setBackground('neon-orange')\" class=\"bg-preview bg-gradient-to-br from-gray-900 via-orange-900 to-amber-900 h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group\">\n <div class=\"absolute inset-0 bg-black/20 rounded-lg\"></div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium\">Neon</div>\n </button>\n \n <!-- Purple Space -->\n <button onclick=\"setBackground('purple-space')\" class=\"bg-preview bg-gradient-to-br from-gray-900 via-purple-900 to-violet-800 h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group\">\n <div class=\"absolute inset-0 bg-black/20 rounded-lg\"></div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium\">Purple</div>\n </button>\n </div>\n \n <!-- Custom Backgrounds -->\n <div class=\"mt-4\">\n <h4 class=\"text-sm font-medium text-gray-300 mb-3\">Custom Backgrounds</h4>\n <div class=\"grid grid-cols-2 gap-3\">\n <!-- Blue Waves -->\n <button onclick=\"setBackground('blue-waves')\" class=\"h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group overflow-hidden\">\n <div class=\"absolute inset-0\">\n <img src=\"/images/backgrounds/blue-waves.png\" alt=\"Blue Waves\" class=\"w-full h-full object-cover opacity-60\">\n </div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium bg-black/50 px-2 py-1 rounded\">Waves</div>\n </button>\n \n <!-- Blue Crescent -->\n <button onclick=\"setBackground('blue-crescent')\" class=\"h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group overflow-hidden\">\n <div class=\"absolute inset-0\">\n <img src=\"/images/backgrounds/blue-crescent.png\" alt=\"Blue Crescent\" class=\"w-full h-full object-cover opacity-60\">\n </div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium bg-black/50 px-2 py-1 rounded\">Crescent</div>\n </button>\n \n <!-- Blue Stars -->\n <button onclick=\"setBackground('blue-stars')\" class=\"h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group overflow-hidden\">\n <div class=\"absolute inset-0\">\n <img src=\"/images/backgrounds/blue-stars.png\" alt=\"Blue Stars\" class=\"w-full h-full object-cover opacity-60\">\n </div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium bg-black/50 px-2 py-1 rounded\">Stars</div>\n </button>\n \n <!-- Blue Waves 3D -->\n <button onclick=\"setBackground('blue-waves-3d')\" class=\"h-16 rounded-lg border-2 border-white/20 hover:border-white/40 transition-all relative group overflow-hidden\">\n <div class=\"absolute inset-0\">\n <img src=\"/images/backgrounds/blue-waves-3d.png\" alt=\"Blue Waves 3D\" class=\"w-full h-full object-cover opacity-60\">\n </div>\n <div class=\"absolute bottom-1 left-2 text-xs text-white font-medium bg-black/50 px-2 py-1 rounded\">3D Waves</div>\n </button>\n </div>\n </div>\n </div>\n \n <!-- Darkness Slider -->\n <div class=\"space-y-3\">\n <label class=\"block text-sm font-medium text-white\">Background Darkness</label>\n <div class=\"flex items-center space-x-3\">\n <svg class=\"w-4 h-4 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707\"/>\n </svg>\n <input \n type=\"range\" \n id=\"darknessSlider\" \n min=\"10\" \n max=\"100\" \n value=\"20\" \n class=\"flex-1 h-2 bg-white/20 rounded-lg appearance-none cursor-pointer slider\"\n oninput=\"adjustDarkness(this.value)\"\n onchange=\"adjustDarkness(this.value)\"\n >\n <svg class=\"w-4 h-4 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z\"/>\n </svg>\n </div>\n <div class=\"text-xs text-gray-400 text-center\">Adjust overlay darkness</div>\n </div>\n </div>\n </div>\n </div>\n \n <!-- User Dropdown -->\n ${\n user\n ? `\n <div class=\"relative z-[9999]\">\n <button class=\"flex items-center space-x-3 p-2 rounded-lg hover:bg-white/10 transition-colors group\" onclick=\"toggleUserDropdown()\">\n <div class=\"w-8 h-8 bg-gradient-to-br from-green-400 to-blue-500 rounded-full flex items-center justify-center\">\n <span class=\"text-white text-sm font-medium\">${(user.name || user.email || \"U\").charAt(0).toUpperCase()}</span>\n </div>\n <div class=\"hidden md:block text-left\">\n <div class=\"text-white text-sm font-medium\">${user.name || user.email || \"User\"}</div>\n <div class=\"text-gray-400 text-xs\">${user.role || \"Administrator\"}</div>\n </div>\n <svg class=\"w-4 h-4 text-gray-400 group-hover:text-white transition-colors\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"/>\n </svg>\n </button>\n \n <!-- Dropdown Menu -->\n <div class=\"userDropdown hidden absolute right-0 mt-2 w-48 backdrop-blur-md bg-black/95 rounded-xl border border-white/10 shadow-xl z-[9999]\">\n <div class=\"py-2\">\n <div class=\"px-4 py-2 border-b border-white/10\">\n <p class=\"text-sm font-medium text-gray-1\">${user.name || user.email || \"User\"}</p>\n <p class=\"text-xs text-gray-4\">${user.email || \"\"}</p>\n </div>\n <a href=\"/admin/profile\" class=\"flex items-center gap-3 px-4 py-2 text-sm text-gray-300 hover:bg-white/10 hover:text-white transition-colors\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z\"/>\n </svg>\n My Profile\n </a>\n <a href=\"/auth/logout\" class=\"flex items-center gap-3 px-4 py-2 text-sm text-red-300 hover:bg-red-500/10 hover:text-red-200 transition-colors\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1\"/>\n </svg>\n Sign Out\n </a>\n </div>\n </div>\n </div>\n `\n : `\n <a href=\"/auth/login\" class=\"backdrop-blur-md bg-white/10 px-4 py-2 rounded-lg text-white font-medium hover:bg-white/20 transition-all\">\n Sign In\n </a>\n `\n }\n </div>\n </div>\n </header>\n `;\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\n\nexport interface CheckboxPageData {\n user?: {\n name: string\n email: string\n role: string\n }\n}\n\nexport function renderCheckboxPage(data: CheckboxPageData): string {\n const pageContent = `\n <div class=\"space-y-8\">\n <!-- Header -->\n <div class=\"sm:flex sm:items-center sm:justify-between\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Catalyst Checkboxes</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Interactive examples using the official Catalyst checkbox component\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0\">\n <a\n href=\"/admin\"\n class=\"inline-flex items-center gap-x-2 rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\"/>\n </svg>\n Back to Admin\n </a>\n </div>\n </div>\n\n <!-- Example 1: Discoverability -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-8\">\n <h3 class=\"text-base/6 font-semibold text-zinc-950 dark:text-white mb-2\">Discoverability</h3>\n <p class=\"text-sm/6 text-zinc-500 dark:text-zinc-400 mb-6\">Decide where your events can be found across the web.</p>\n\n <fieldset>\n <legend class=\"sr-only\">Discoverability</legend>\n <div class=\"space-y-5\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"show_on_events_page\" type=\"checkbox\" name=\"discoverability\" checked aria-describedby=\"show-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"show_on_events_page\" class=\"font-medium text-zinc-950 dark:text-white\">Show on events page</label>\n <p id=\"show-description\" class=\"text-zinc-500 dark:text-zinc-400\">Make this event visible on your profile.</p>\n </div>\n </div>\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"allow_embedding\" type=\"checkbox\" name=\"discoverability\" aria-describedby=\"embedding-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"allow_embedding\" class=\"font-medium text-zinc-950 dark:text-white\">Allow embedding</label>\n <p id=\"embedding-description\" class=\"text-zinc-500 dark:text-zinc-400\">Allow others to embed your event details on their own site.</p>\n </div>\n </div>\n </div>\n </fieldset>\n </div>\n\n <!-- Example 2: Newsletter Preferences -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-8\">\n <h3 class=\"text-base/6 font-semibold text-zinc-950 dark:text-white mb-2\">Newsletter Preferences</h3>\n <p class=\"text-sm/6 text-zinc-500 dark:text-zinc-400 mb-6\">Choose which updates you'd like to receive.</p>\n\n <fieldset>\n <legend class=\"sr-only\">Newsletter Preferences</legend>\n <div class=\"space-y-5\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"product_updates\" type=\"checkbox\" name=\"newsletter\" checked aria-describedby=\"product-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"product_updates\" class=\"font-medium text-zinc-950 dark:text-white\">Product Updates</label>\n <p id=\"product-description\" class=\"text-zinc-500 dark:text-zinc-400\">Get notified about new features and improvements.</p>\n </div>\n </div>\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"weekly_digest\" type=\"checkbox\" name=\"newsletter\" aria-describedby=\"weekly-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"weekly_digest\" class=\"font-medium text-zinc-950 dark:text-white\">Weekly Digest</label>\n <p id=\"weekly-description\" class=\"text-zinc-500 dark:text-zinc-400\">Receive a summary of activity every week.</p>\n </div>\n </div>\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"marketing\" type=\"checkbox\" name=\"newsletter\" aria-describedby=\"marketing-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"marketing\" class=\"font-medium text-zinc-950 dark:text-white\">Marketing Emails</label>\n <p id=\"marketing-description\" class=\"text-zinc-500 dark:text-zinc-400\">Special offers and promotional content.</p>\n </div>\n </div>\n </div>\n </fieldset>\n </div>\n\n <!-- Example 3: Privacy Settings -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-8\">\n <h3 class=\"text-base/6 font-semibold text-zinc-950 dark:text-white mb-2\">Privacy Settings</h3>\n <p class=\"text-sm/6 text-zinc-500 dark:text-zinc-400 mb-6\">Control your privacy and data sharing preferences.</p>\n\n <fieldset>\n <legend class=\"sr-only\">Privacy Settings</legend>\n <div class=\"space-y-5\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"profile_public\" type=\"checkbox\" name=\"privacy\" checked aria-describedby=\"profile-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"profile_public\" class=\"font-medium text-zinc-950 dark:text-white\">Public Profile</label>\n <p id=\"profile-description\" class=\"text-zinc-500 dark:text-zinc-400\">Make your profile visible to other users.</p>\n </div>\n </div>\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"show_activity\" type=\"checkbox\" name=\"privacy\" checked aria-describedby=\"activity-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"show_activity\" class=\"font-medium text-zinc-950 dark:text-white\">Show Activity</label>\n <p id=\"activity-description\" class=\"text-zinc-500 dark:text-zinc-400\">Display your recent activity on your profile.</p>\n </div>\n </div>\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input id=\"analytics\" type=\"checkbox\" name=\"privacy\" aria-describedby=\"analytics-description\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white dark:stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"analytics\" class=\"font-medium text-zinc-950 dark:text-white\">Analytics</label>\n <p id=\"analytics-description\" class=\"text-zinc-500 dark:text-zinc-400\">Help us improve by sharing anonymous usage data.</p>\n </div>\n </div>\n </div>\n </fieldset>\n </div>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Catalyst Checkboxes',\n pageTitle: 'Catalyst Checkboxes',\n currentPath: '/admin/checkboxes',\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","export interface FormField {\n name: string\n label: string\n type: 'text' | 'email' | 'textarea' | 'select' | 'checkbox' | 'rich_text' | 'number' | 'date' | 'multi_select' | 'file'\n value?: any\n placeholder?: string\n required?: boolean\n readonly?: boolean\n helpText?: string\n options?: Array<{ value: string; label: string; selected?: boolean }>\n rows?: number\n className?: string\n validation?: {\n min?: number\n max?: number\n pattern?: string\n }\n}\n\nexport interface FormData {\n id?: string\n action?: string\n method?: string\n hxPost?: string\n hxPut?: string\n hxTarget?: string\n fields: FormField[]\n submitButtons: Array<{\n label: string\n type?: 'submit' | 'button'\n value?: string\n name?: string\n className?: string\n onclick?: string\n }>\n title?: string\n description?: string\n className?: string\n csrfToken?: string\n}\n\nexport function renderForm(data: FormData): string {\n return `\n <form \n ${data.id ? `id=\"${data.id}\"` : ''}\n ${data.hxPost ? `hx-post=\"${data.hxPost}\"` : data.hxPut ? `hx-put=\"${data.hxPut}\"` : data.action ? `action=\"${data.action}\"` : ''}\n ${data.hxTarget ? `hx-target=\"${data.hxTarget}\"` : ''}\n method=\"${data.method || 'POST'}\"\n class=\"${data.className || 'space-y-6'}\"\n ${data.fields.some(f => f.type === 'file') ? 'enctype=\"multipart/form-data\"' : ''}\n >\n ${data.csrfToken ? `<input type=\"hidden\" name=\"_csrf\" value=\"${data.csrfToken}\">` : ''}\n ${data.title ? `\n <div class=\"mb-6\">\n <h2 class=\"text-lg font-medium text-gray-1\">${data.title}</h2>\n ${data.description ? `<p class=\"mt-1 text-sm text-gray-4\">${data.description}</p>` : ''}\n </div>\n ` : ''}\n \n <div id=\"form-messages\"></div>\n \n ${data.fields.map(field => renderFormField(field)).join('')}\n \n <div class=\"flex justify-between items-center pt-6 border-t border-gray-7\">\n <div class=\"flex space-x-4\">\n ${data.submitButtons.map(button => `\n <button \n type=\"${button.type || 'submit'}\"\n ${button.name ? `name=\"${button.name}\"` : ''}\n ${button.value ? `value=\"${button.value}\"` : ''}\n ${button.onclick ? `onclick=\"${button.onclick}\"` : ''}\n class=\"btn ${button.className || 'btn-primary'}\"\n >\n ${button.label}\n </button>\n `).join('')}\n </div>\n </div>\n </form>\n `\n}\n\nexport function renderFormField(field: FormField): string {\n const fieldId = `field-${field.name}`\n const required = field.required ? 'required' : ''\n const readonly = field.readonly ? 'readonly' : ''\n const placeholder = field.placeholder ? `placeholder=\"${field.placeholder}\"` : ''\n\n let fieldHTML = ''\n\n switch (field.type) {\n case 'text':\n case 'email':\n case 'number':\n case 'date':\n fieldHTML = `\n <input\n type=\"${field.type === 'date' ? 'datetime-local' : field.type}\"\n id=\"${fieldId}\"\n name=\"${field.name}\"\n value=\"${field.value || ''}\"\n class=\"form-input ${field.className || ''}\"\n ${placeholder}\n ${required}\n ${readonly}\n ${field.validation?.min !== undefined ? `min=\"${field.validation.min}\"` : ''}\n ${field.validation?.max !== undefined ? `max=\"${field.validation.max}\"` : ''}\n ${field.validation?.pattern ? `pattern=\"${field.validation.pattern}\"` : ''}\n >\n `\n break\n \n case 'textarea':\n fieldHTML = `\n <textarea \n id=\"${fieldId}\"\n name=\"${field.name}\" \n class=\"form-textarea ${field.className || ''}\" \n rows=\"${field.rows || 4}\"\n ${placeholder}\n ${required}\n >${field.value || ''}</textarea>\n `\n break\n \n case 'rich_text':\n const uniqueId = `${field.name}-${Date.now()}`\n fieldHTML = `\n <div class=\"markdown-field\">\n <textarea id=\"${uniqueId}\" name=\"${field.name}\" class=\"form-textarea\" rows=\"8\">${field.value || ''}</textarea>\n <script>\n if (typeof EasyMDE !== 'undefined') {\n new EasyMDE({\n element: document.getElementById('${uniqueId}'),\n minHeight: '300px',\n spellChecker: false,\n status: ['autosave', 'lines', 'words', 'cursor'],\n autosave: {\n enabled: true,\n uniqueId: '${uniqueId}',\n delay: 1000\n },\n renderingConfig: {\n singleLineBreaks: false,\n codeSyntaxHighlighting: true\n }\n });\n }\n </script>\n </div>\n `\n break\n \n case 'select':\n fieldHTML = `\n <select \n id=\"${fieldId}\"\n name=\"${field.name}\" \n class=\"form-input ${field.className || ''}\" \n ${required}\n >\n ${field.options ? field.options.map(option => `\n <option value=\"${option.value}\" ${option.selected || field.value === option.value ? 'selected' : ''}>\n ${option.label}\n </option>\n `).join('') : ''}\n </select>\n `\n break\n \n case 'multi_select':\n fieldHTML = `\n <select \n id=\"${fieldId}\"\n name=\"${field.name}\" \n class=\"form-input ${field.className || ''}\" \n multiple \n ${required}\n >\n ${field.options ? field.options.map(option => `\n <option value=\"${option.value}\" ${option.selected ? 'selected' : ''}>\n ${option.label}\n </option>\n `).join('') : ''}\n </select>\n `\n break\n \n case 'checkbox':\n fieldHTML = `\n <input\n type=\"checkbox\"\n id=\"${fieldId}\"\n name=\"${field.name}\"\n value=\"1\"\n class=\"size-4 rounded border border-white/15 bg-white/5 checked:border-transparent checked:bg-white disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-white/20 focus:ring-offset-2 ${field.className || ''}\"\n ${field.value ? 'checked' : ''}\n ${required}\n >\n <label for=\"${fieldId}\" class=\"ml-2 text-sm text-white\">${field.label}</label>\n `\n break\n \n default:\n fieldHTML = `\n <input \n type=\"text\" \n id=\"${fieldId}\"\n name=\"${field.name}\" \n value=\"${field.value || ''}\"\n class=\"form-input ${field.className || ''}\" \n ${placeholder} \n ${required}\n >\n `\n break\n }\n \n // For checkbox, we handle the label differently\n if (field.type === 'checkbox') {\n return `\n <div class=\"form-group\">\n <div class=\"flex items-center\">\n ${fieldHTML}\n </div>\n ${field.helpText ? `<p class=\"text-sm text-zinc-500 dark:text-zinc-400 mt-1 ml-6\">${field.helpText}</p>` : ''}\n </div>\n `\n }\n\n return `\n <div class=\"form-group\">\n <label for=\"${fieldId}\" class=\"form-label\">\n ${field.label}${field.required ? ' *' : ''}\n </label>\n ${fieldHTML}\n ${field.helpText ? `<p class=\"text-sm text-zinc-500 dark:text-zinc-400 mt-1\">${field.helpText}</p>` : ''}\n </div>\n `\n}"]}
|