@sonicjs-cms/core 2.19.0 → 3.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -52
- package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
- package/dist/{admin-layout-catalyst.template-UMTIN66R.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
- package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-HFD37TY5.cjs.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs.map +1 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js.map +1 -0
- package/dist/app-Bo0X1OWX.d.ts +1268 -0
- package/dist/app-Do66yCcV.d.cts +1268 -0
- package/dist/cache-DDARE4QE.js +4 -0
- package/dist/cache-DDARE4QE.js.map +1 -0
- package/dist/cache-LVYS4BPL.cjs +33 -0
- package/dist/cache-LVYS4BPL.cjs.map +1 -0
- package/dist/chunk-2CB4KY7I.cjs +771 -0
- package/dist/chunk-2CB4KY7I.cjs.map +1 -0
- package/dist/{chunk-4NPCDK6B.js → chunk-3PU4WVU6.js} +557 -90
- package/dist/chunk-3PU4WVU6.js.map +1 -0
- package/dist/chunk-4BTBSXMR.cjs +912 -0
- package/dist/chunk-4BTBSXMR.cjs.map +1 -0
- package/dist/{chunk-55RDMDOP.js → chunk-5V62WT6M.js} +181 -57
- package/dist/chunk-5V62WT6M.js.map +1 -0
- package/dist/chunk-6H66MSSL.js +273 -0
- package/dist/chunk-6H66MSSL.js.map +1 -0
- package/dist/chunk-AI663NBO.js +821 -0
- package/dist/chunk-AI663NBO.js.map +1 -0
- package/dist/chunk-BLMTL57B.js +767 -0
- package/dist/chunk-BLMTL57B.js.map +1 -0
- package/dist/{chunk-4ZSNJDLS.cjs → chunk-CRGUD4KC.cjs} +9 -9
- package/dist/chunk-CRGUD4KC.cjs.map +1 -0
- package/dist/chunk-GCDZZNIN.js +192 -0
- package/dist/chunk-GCDZZNIN.js.map +1 -0
- package/dist/chunk-HIKBY7MS.cjs +70 -0
- package/dist/chunk-HIKBY7MS.cjs.map +1 -0
- package/dist/chunk-HPAJKZAQ.js +387 -0
- package/dist/chunk-HPAJKZAQ.js.map +1 -0
- package/dist/chunk-IESEVHXL.js +66 -0
- package/dist/chunk-IESEVHXL.js.map +1 -0
- package/dist/chunk-IVPRUGTY.js +242 -0
- package/dist/chunk-IVPRUGTY.js.map +1 -0
- package/dist/{chunk-JZVHLLSI.cjs → chunk-IXUHXTHW.cjs} +2 -151
- package/dist/chunk-IXUHXTHW.cjs.map +1 -0
- package/dist/chunk-J6JTWD2A.cjs +100 -0
- package/dist/chunk-J6JTWD2A.cjs.map +1 -0
- package/dist/chunk-JEQ7FLOD.cjs +199 -0
- package/dist/chunk-JEQ7FLOD.cjs.map +1 -0
- package/dist/{chunk-ON5ZMSU4.js → chunk-JQISFW6U.js} +3 -3
- package/dist/chunk-JQISFW6U.js.map +1 -0
- package/dist/chunk-K25XHMM3.js +566 -0
- package/dist/chunk-K25XHMM3.js.map +1 -0
- package/dist/{chunk-R4FOLLFB.cjs → chunk-K342JMA3.cjs} +8730 -11520
- package/dist/chunk-K342JMA3.cjs.map +1 -0
- package/dist/{chunk-UYJ6TJHX.cjs → chunk-K623Q6WD.cjs} +181 -56
- package/dist/chunk-K623Q6WD.cjs.map +1 -0
- package/dist/chunk-KV3CM5RK.cjs +158 -0
- package/dist/chunk-KV3CM5RK.cjs.map +1 -0
- package/dist/{chunk-ABB34XUS.cjs → chunk-MKKGA3C4.cjs} +667 -19
- package/dist/chunk-MKKGA3C4.cjs.map +1 -0
- package/dist/chunk-N32OWET6.cjs +327 -0
- package/dist/chunk-N32OWET6.cjs.map +1 -0
- package/dist/chunk-NUKJ54GA.cjs +245 -0
- package/dist/chunk-NUKJ54GA.cjs.map +1 -0
- package/dist/{chunk-XWIA3HVX.js → chunk-OBA2RYZN.js} +6 -1249
- package/dist/chunk-OBA2RYZN.js.map +1 -0
- package/dist/chunk-ORF4CT74.cjs +276 -0
- package/dist/chunk-ORF4CT74.cjs.map +1 -0
- package/dist/{chunk-TFNTM3OA.js → chunk-PDYRDYXI.js} +645 -15
- package/dist/chunk-PDYRDYXI.js.map +1 -0
- package/dist/{chunk-OHYBNCVL.cjs → chunk-PXNTCCPE.cjs} +10 -1256
- package/dist/chunk-PXNTCCPE.cjs.map +1 -0
- package/dist/{chunk-E4YFJBM2.cjs → chunk-QJNKSFDJ.cjs} +876 -829
- package/dist/chunk-QJNKSFDJ.cjs.map +1 -0
- package/dist/chunk-QLFTG3QJ.js +1828 -0
- package/dist/chunk-QLFTG3QJ.js.map +1 -0
- package/dist/{chunk-BU7SFHGP.js → chunk-QZGABF2M.js} +3 -149
- package/dist/chunk-QZGABF2M.js.map +1 -0
- package/dist/chunk-RMRJGMDE.js +323 -0
- package/dist/chunk-RMRJGMDE.js.map +1 -0
- package/dist/chunk-RNZFGN4R.js +88 -0
- package/dist/chunk-RNZFGN4R.js.map +1 -0
- package/dist/chunk-RQ6N3FTV.js +900 -0
- package/dist/chunk-RQ6N3FTV.js.map +1 -0
- package/dist/{chunk-OCL3HMEG.js → chunk-SXLVXD2X.js} +7004 -9807
- package/dist/chunk-SXLVXD2X.js.map +1 -0
- package/dist/chunk-UHRHZXVR.cjs +408 -0
- package/dist/chunk-UHRHZXVR.cjs.map +1 -0
- package/dist/chunk-YA3TJ65D.cjs +575 -0
- package/dist/chunk-YA3TJ65D.cjs.map +1 -0
- package/dist/{chunk-7A4CB7T3.cjs → chunk-YJEBDJDV.cjs} +561 -91
- package/dist/chunk-YJEBDJDV.cjs.map +1 -0
- package/dist/chunk-YP7GW2G5.cjs +866 -0
- package/dist/chunk-YP7GW2G5.cjs.map +1 -0
- package/dist/chunk-ZUEIQFE5.js +154 -0
- package/dist/chunk-ZUEIQFE5.js.map +1 -0
- package/dist/{collection-config-B4PG-AaF.d.cts → collection-config-JgHOpFCG.d.cts} +30 -2
- package/dist/{collection-config-B4PG-AaF.d.ts → collection-config-JgHOpFCG.d.ts} +30 -2
- package/dist/config-HFXANXCC.js +6 -0
- package/dist/config-HFXANXCC.js.map +1 -0
- package/dist/config-ON6FNMYX.cjs +19 -0
- package/dist/config-ON6FNMYX.cjs.map +1 -0
- package/dist/define-plugin-BzNHc1ZI.d.ts +1321 -0
- package/dist/define-plugin-IWDKYaVm.d.cts +1321 -0
- package/dist/document-projection-TDWRJX3Z.cjs +13 -0
- package/dist/document-projection-TDWRJX3Z.cjs.map +1 -0
- package/dist/document-projection-YYMC6I4U.js +4 -0
- package/dist/document-projection-YYMC6I4U.js.map +1 -0
- package/dist/index.cjs +13739 -4328
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +331 -493
- package/dist/index.d.ts +331 -493
- package/dist/index.js +13456 -4067
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +38 -32
- package/dist/middleware.d.cts +50 -7
- package/dist/middleware.d.ts +50 -7
- package/dist/middleware.js +9 -3
- package/dist/migrations-XQLBY7E5.js +4 -0
- package/dist/{migrations-H5IXZNCO.js.map → migrations-XQLBY7E5.js.map} +1 -1
- package/dist/migrations-ZXJEUTFA.cjs +13 -0
- package/dist/{migrations-566IIPS2.cjs.map → migrations-ZXJEUTFA.cjs.map} +1 -1
- package/dist/{plugin-bootstrap-DfVerYV4.d.cts → plugin-bootstrap-B8ThJU21.d.cts} +4315 -1661
- package/dist/{plugin-bootstrap-P_ciLp_C.d.ts → plugin-bootstrap-qu8hJgUt.d.ts} +4315 -1661
- package/dist/plugins.cjs +171 -12
- package/dist/plugins.d.cts +36 -2
- package/dist/plugins.d.ts +36 -2
- package/dist/plugins.js +5 -2
- package/dist/rbac-O73MFKDA.js +5 -0
- package/dist/rbac-O73MFKDA.js.map +1 -0
- package/dist/rbac-VONLJJKB.cjs +14 -0
- package/dist/rbac-VONLJJKB.cjs.map +1 -0
- package/dist/routes.cjs +42 -46
- package/dist/routes.d.cts +56 -146
- package/dist/routes.d.ts +56 -146
- package/dist/routes.js +18 -10
- package/dist/services.cjs +43 -76
- package/dist/services.d.cts +93 -55
- package/dist/services.d.ts +93 -55
- package/dist/services.js +6 -3
- package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
- package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
- package/dist/templates.cjs +17 -29
- package/dist/templates.d.cts +2 -89
- package/dist/templates.d.ts +2 -89
- package/dist/templates.js +3 -3
- package/dist/types-Dea1eNxU.d.cts +286 -0
- package/dist/types-Dea1eNxU.d.ts +286 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils.cjs +21 -20
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +3 -2
- package/migrations/0001_core.sql +184 -0
- package/migrations/0002_documents.sql +163 -0
- package/package.json +12 -7
- package/dist/admin-layout-catalyst.template-HFD37TY5.cjs +0 -17
- package/dist/admin-layout-catalyst.template-UMTIN66R.js +0 -7
- package/dist/app-C9esKLmh.d.cts +0 -112
- package/dist/app-C9esKLmh.d.ts +0 -112
- package/dist/chunk-4NPCDK6B.js.map +0 -1
- package/dist/chunk-4ZSNJDLS.cjs.map +0 -1
- package/dist/chunk-55RDMDOP.js.map +0 -1
- package/dist/chunk-635JAMSE.cjs +0 -653
- package/dist/chunk-635JAMSE.cjs.map +0 -1
- package/dist/chunk-7A4CB7T3.cjs.map +0 -1
- package/dist/chunk-ABB34XUS.cjs.map +0 -1
- package/dist/chunk-BU7SFHGP.js.map +0 -1
- package/dist/chunk-E4YFJBM2.cjs.map +0 -1
- package/dist/chunk-EXNEW5US.js +0 -648
- package/dist/chunk-EXNEW5US.js.map +0 -1
- package/dist/chunk-JZV22DEV.js +0 -1783
- package/dist/chunk-JZV22DEV.js.map +0 -1
- package/dist/chunk-JZVHLLSI.cjs.map +0 -1
- package/dist/chunk-OCL3HMEG.js.map +0 -1
- package/dist/chunk-OHYBNCVL.cjs.map +0 -1
- package/dist/chunk-ON5ZMSU4.js.map +0 -1
- package/dist/chunk-QFWHAFEO.js +0 -1843
- package/dist/chunk-QFWHAFEO.js.map +0 -1
- package/dist/chunk-R4FOLLFB.cjs.map +0 -1
- package/dist/chunk-RLMUFFUD.cjs +0 -2219
- package/dist/chunk-RLMUFFUD.cjs.map +0 -1
- package/dist/chunk-TFNTM3OA.js.map +0 -1
- package/dist/chunk-UYJ6TJHX.cjs.map +0 -1
- package/dist/chunk-WAEQXGCX.cjs +0 -1898
- package/dist/chunk-WAEQXGCX.cjs.map +0 -1
- package/dist/chunk-XWIA3HVX.js.map +0 -1
- package/dist/chunk-ZYAYUIZE.js +0 -2217
- package/dist/chunk-ZYAYUIZE.js.map +0 -1
- package/dist/migrations-566IIPS2.cjs +0 -13
- package/dist/migrations-H5IXZNCO.js +0 -4
- package/dist/plugin-manager-BoM3Q7o7.d.cts +0 -328
- package/dist/plugin-manager-Efx9RyDX.d.ts +0 -328
- package/migrations/001_initial_schema.sql +0 -170
- package/migrations/002_faq_plugin.sql +0 -86
- package/migrations/003_stage5_enhancements.sql +0 -121
- package/migrations/004_stage6_user_management.sql +0 -183
- package/migrations/005_stage7_workflow_automation.sql +0 -294
- package/migrations/006_plugin_system.sql +0 -155
- package/migrations/007_demo_login_plugin.sql +0 -23
- package/migrations/008_fix_slug_validation.sql +0 -22
- package/migrations/009_system_logging.sql +0 -57
- package/migrations/011_config_managed_collections.sql +0 -15
- package/migrations/012_testimonials_plugin.sql +0 -80
- package/migrations/013_code_examples_plugin.sql +0 -177
- package/migrations/014_fix_plugin_registry.sql +0 -88
- package/migrations/015_add_remaining_plugins.sql +0 -89
- package/migrations/016_remove_duplicate_cache_plugin.sql +0 -17
- package/migrations/017_auth_configurable_fields.sql +0 -49
- package/migrations/018_settings_table.sql +0 -23
- package/migrations/019_remove_blog_posts_collection.sql +0 -15
- package/migrations/020_add_email_plugin.sql +0 -22
- package/migrations/021_add_magic_link_auth_plugin.sql +0 -42
- package/migrations/022_add_tinymce_plugin.sql +0 -25
- package/migrations/023_add_easy_mdx_plugin.sql +0 -25
- package/migrations/024_add_quill_editor_plugin.sql +0 -25
- package/migrations/025_add_easymde_plugin.sql +0 -25
- package/migrations/026_add_otp_login.sql +0 -42
- package/migrations/027_fix_slug_field_type.sql +0 -18
- package/migrations/028_fix_slug_field_type_in_schemas.sql +0 -30
- package/migrations/029_add_forms_system.sql +0 -184
- package/migrations/030_add_turnstile_to_forms.sql +0 -14
- package/migrations/031_ai_search_plugin.sql +0 -45
- package/migrations/032_user_profiles.sql +0 -37
- package/migrations/033_form_content_integration.sql +0 -19
- package/migrations/034_security_audit_plugin.sql +0 -27
- package/migrations/035_user_profiles_data_column.sql +0 -16
- package/migrations/036_analytics_events.sql +0 -22
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkK623Q6WD_cjs = require('./chunk-K623Q6WD.cjs');
|
|
4
|
+
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
5
|
+
|
|
6
|
+
// src/templates/pages/admin-documents-form.template.ts
|
|
7
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
8
|
+
|
|
9
|
+
// src/templates/components/alert.template.ts
|
|
10
|
+
function renderAlert(data) {
|
|
11
|
+
const typeClasses = {
|
|
12
|
+
success: "bg-green-50 dark:bg-green-500/10 border border-green-600/20 dark:border-green-500/20",
|
|
13
|
+
error: "bg-error/10 border border-red-600/20 dark:border-red-500/20",
|
|
14
|
+
warning: "bg-amber-50 dark:bg-amber-500/10 border border-amber-600/20 dark:border-amber-500/20",
|
|
15
|
+
info: "bg-blue-50 dark:bg-blue-500/10 border border-blue-600/20 dark:border-blue-500/20"
|
|
16
|
+
};
|
|
17
|
+
const iconClasses = {
|
|
18
|
+
success: "text-green-600 dark:text-green-400",
|
|
19
|
+
error: "text-red-600 dark:text-red-400",
|
|
20
|
+
warning: "text-amber-600 dark:text-amber-400",
|
|
21
|
+
info: "text-blue-600 dark:text-blue-400"
|
|
22
|
+
};
|
|
23
|
+
const textClasses = {
|
|
24
|
+
success: "text-green-900 dark:text-green-300",
|
|
25
|
+
error: "text-red-900 dark:text-red-300",
|
|
26
|
+
warning: "text-amber-900 dark:text-amber-300",
|
|
27
|
+
info: "text-blue-900 dark:text-blue-300"
|
|
28
|
+
};
|
|
29
|
+
const messageTextClasses = {
|
|
30
|
+
success: "text-green-700 dark:text-green-400",
|
|
31
|
+
error: "text-red-700 dark:text-red-400",
|
|
32
|
+
warning: "text-amber-700 dark:text-amber-400",
|
|
33
|
+
info: "text-blue-700 dark:text-blue-400"
|
|
34
|
+
};
|
|
35
|
+
const icons = {
|
|
36
|
+
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" />`,
|
|
37
|
+
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" />`,
|
|
38
|
+
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" />`,
|
|
39
|
+
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" />`
|
|
40
|
+
};
|
|
41
|
+
return `
|
|
42
|
+
<div class="rounded-lg p-4 ${typeClasses[data.type]} ${data.className || ""}" ${data.dismissible ? 'id="dismissible-alert"' : ""}>
|
|
43
|
+
<div class="flex">
|
|
44
|
+
${data.icon !== false ? `
|
|
45
|
+
<div class="flex-shrink-0">
|
|
46
|
+
<svg class="h-5 w-5 ${iconClasses[data.type]}" viewBox="0 0 20 20" fill="currentColor">
|
|
47
|
+
${icons[data.type]}
|
|
48
|
+
</svg>
|
|
49
|
+
</div>
|
|
50
|
+
` : ""}
|
|
51
|
+
<div class="${data.icon !== false ? "ml-3" : ""}">
|
|
52
|
+
${data.title ? `
|
|
53
|
+
<h3 class="text-sm font-semibold ${textClasses[data.type]}">
|
|
54
|
+
${chunkMNWKYY5E_cjs.escapeHtml(data.title)}
|
|
55
|
+
</h3>
|
|
56
|
+
` : ""}
|
|
57
|
+
<div class="${data.title ? "mt-1 text-sm" : "text-sm"} ${messageTextClasses[data.type]}">
|
|
58
|
+
<p>${chunkMNWKYY5E_cjs.escapeHtml(data.message)}</p>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
${data.dismissible ? `
|
|
62
|
+
<div class="ml-auto pl-3">
|
|
63
|
+
<div class="-mx-1.5 -my-1.5">
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
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"
|
|
67
|
+
onclick="document.getElementById('dismissible-alert').remove()"
|
|
68
|
+
>
|
|
69
|
+
<span class="sr-only">Dismiss</span>
|
|
70
|
+
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
71
|
+
<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" />
|
|
72
|
+
</svg>
|
|
73
|
+
</button>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
` : ""}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/templates/pages/admin-documents-form.template.ts
|
|
83
|
+
function inputClass(error) {
|
|
84
|
+
const base = "block w-full rounded-lg border bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white placeholder:text-zinc-400 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors";
|
|
85
|
+
return error ? `${base} border-red-400 dark:border-red-500` : `${base} border-zinc-300 dark:border-zinc-700`;
|
|
86
|
+
}
|
|
87
|
+
function renderFieldInput(field, value, error) {
|
|
88
|
+
const id = `data_${field.name}`;
|
|
89
|
+
const name = `data[${field.name}]`;
|
|
90
|
+
const label = field.name.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase());
|
|
91
|
+
const strVal = value != null ? String(value) : "";
|
|
92
|
+
let input;
|
|
93
|
+
if (field.type === "integer" || field.type === "number") {
|
|
94
|
+
input = `<input type="number" id="${id}" name="${name}" value="${chunkMNWKYY5E_cjs.escapeHtml(strVal)}"
|
|
95
|
+
step="${field.type === "integer" ? "1" : "any"}"
|
|
96
|
+
class="${inputClass(error)}">`;
|
|
97
|
+
} else if (field.type === "boolean") {
|
|
98
|
+
input = `<div class="flex items-center gap-2">
|
|
99
|
+
<input type="hidden" name="${name}" value="false">
|
|
100
|
+
<input type="checkbox" id="${id}" name="${name}" value="true" ${strVal === "true" ? "checked" : ""}
|
|
101
|
+
class="h-4 w-4 rounded border-zinc-300 dark:border-zinc-600 text-blue-600 focus:ring-blue-500">
|
|
102
|
+
<span class="text-sm text-zinc-700 dark:text-zinc-300">${label}</span>
|
|
103
|
+
</div>`;
|
|
104
|
+
return `
|
|
105
|
+
<div>
|
|
106
|
+
${input}
|
|
107
|
+
${error ? `<p class="mt-1 text-xs text-red-500">${chunkMNWKYY5E_cjs.escapeHtml(error)}</p>` : ""}
|
|
108
|
+
</div>`;
|
|
109
|
+
} else if (field.kind === "facet") {
|
|
110
|
+
const arrVal = Array.isArray(value) ? value.join(", ") : strVal;
|
|
111
|
+
input = `<input type="text" id="${id}" name="${name}" value="${chunkMNWKYY5E_cjs.escapeHtml(arrVal)}"
|
|
112
|
+
placeholder="Comma-separated values"
|
|
113
|
+
class="${inputClass(error)}">`;
|
|
114
|
+
} else {
|
|
115
|
+
input = `<input type="text" id="${id}" name="${name}" value="${chunkMNWKYY5E_cjs.escapeHtml(strVal)}"
|
|
116
|
+
class="${inputClass(error)}">`;
|
|
117
|
+
}
|
|
118
|
+
return `
|
|
119
|
+
<div>
|
|
120
|
+
<label for="${id}" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">
|
|
121
|
+
${label}
|
|
122
|
+
</label>
|
|
123
|
+
${input}
|
|
124
|
+
${error ? `<p class="mt-1 text-xs text-red-500">${chunkMNWKYY5E_cjs.escapeHtml(error)}</p>` : ""}
|
|
125
|
+
</div>`;
|
|
126
|
+
}
|
|
127
|
+
function renderRemainingFields(allData, queryableFields, errors) {
|
|
128
|
+
const knownNames = new Set(queryableFields.map((f) => f.name));
|
|
129
|
+
const remainingKeys = Object.keys(allData).filter((k) => !knownNames.has(k));
|
|
130
|
+
if (remainingKeys.length === 0) return "";
|
|
131
|
+
const inputs = remainingKeys.map((key) => {
|
|
132
|
+
const val = allData[key];
|
|
133
|
+
const id = `data_${key}`;
|
|
134
|
+
const name = `data[${key}]`;
|
|
135
|
+
const label = key.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase());
|
|
136
|
+
const strVal = typeof val === "object" ? JSON.stringify(val, null, 2) : String(val ?? "");
|
|
137
|
+
const isMultiline = strVal.includes("\n") || strVal.length > 100;
|
|
138
|
+
return `
|
|
139
|
+
<div>
|
|
140
|
+
<label for="${id}" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">${chunkMNWKYY5E_cjs.escapeHtml(label)}</label>
|
|
141
|
+
${isMultiline ? `<textarea id="${id}" name="${name}" rows="4" class="${inputClass(errors[key])}">${chunkMNWKYY5E_cjs.escapeHtml(strVal)}</textarea>` : `<input type="text" id="${id}" name="${name}" value="${chunkMNWKYY5E_cjs.escapeHtml(strVal)}" class="${inputClass(errors[key])}">`}
|
|
142
|
+
${errors[key] ? `<p class="mt-1 text-xs text-red-500">${chunkMNWKYY5E_cjs.escapeHtml(errors[key])}</p>` : ""}
|
|
143
|
+
</div>`;
|
|
144
|
+
}).join("");
|
|
145
|
+
return `
|
|
146
|
+
<div class="border-t border-zinc-200 dark:border-zinc-700 pt-6">
|
|
147
|
+
<h3 class="text-sm font-medium text-zinc-500 dark:text-zinc-400 mb-4">Additional Fields</h3>
|
|
148
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">${inputs}</div>
|
|
149
|
+
</div>`;
|
|
150
|
+
}
|
|
151
|
+
function renderDocumentFormPage(data) {
|
|
152
|
+
const { docType, doc, publishedDoc, isEdit, errors = {} } = data;
|
|
153
|
+
const queryableFields = docType.queryableFields ?? [];
|
|
154
|
+
const docData = doc?.data ?? {};
|
|
155
|
+
const isAdmin = data.user?.role === "admin";
|
|
156
|
+
const isEditor = isAdmin || data.user?.role === "editor";
|
|
157
|
+
const hasNewerDraft = isEdit && doc && !doc.isPublished && publishedDoc;
|
|
158
|
+
const isPublishedAndDraft = isEdit && doc?.isPublished && doc?.isCurrentDraft;
|
|
159
|
+
const formAction = isEdit ? `/admin/content/documents/${chunkMNWKYY5E_cjs.escapeHtml(docType.id)}/${chunkMNWKYY5E_cjs.escapeHtml(doc.rootId)}` : `/admin/content/documents/${chunkMNWKYY5E_cjs.escapeHtml(docType.id)}/new`;
|
|
160
|
+
const publishBannerHtml = (() => {
|
|
161
|
+
if (!isEdit || !doc) return "";
|
|
162
|
+
if (isPublishedAndDraft) {
|
|
163
|
+
return renderAlert({
|
|
164
|
+
type: "success",
|
|
165
|
+
message: 'This document is live. Saving creates a new draft. Use "Publish" to push changes live.'
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (hasNewerDraft) {
|
|
169
|
+
return renderAlert({
|
|
170
|
+
type: "info",
|
|
171
|
+
message: `A published version (v${publishedDoc.versionNumber}) is still live. This is an unpublished draft (v${doc.versionNumber}).`
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return "";
|
|
175
|
+
})();
|
|
176
|
+
const queryableInputs = queryableFields.filter((f) => f.kind !== "reference").map((f) => renderFieldInput(f, docData[f.name], errors[`data.${f.name}`])).join("");
|
|
177
|
+
const remainingHtml = renderRemainingFields(docData, queryableFields, errors);
|
|
178
|
+
const content = `
|
|
179
|
+
<div class="w-full px-4 sm:px-6 lg:px-8 py-6 space-y-6">
|
|
180
|
+
<!-- Header -->
|
|
181
|
+
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between">
|
|
182
|
+
<div>
|
|
183
|
+
<div class="flex items-center gap-2 text-sm text-zinc-500 dark:text-zinc-400 mb-1">
|
|
184
|
+
<a href="/admin/content" class="hover:text-zinc-950 dark:hover:text-white">Content</a>
|
|
185
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd"/></svg>
|
|
186
|
+
<a href="/admin/content?model=doc:${chunkMNWKYY5E_cjs.escapeHtml(docType.id)}" class="hover:text-zinc-950 dark:hover:text-white">${chunkMNWKYY5E_cjs.escapeHtml(docType.displayName)}</a>
|
|
187
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd"/></svg>
|
|
188
|
+
<span class="text-zinc-950 dark:text-white font-medium">${isEdit ? "Edit" : "New"}</span>
|
|
189
|
+
</div>
|
|
190
|
+
<h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">
|
|
191
|
+
${isEdit ? `Edit ${chunkMNWKYY5E_cjs.escapeHtml(docType.displayName)}` : `New ${chunkMNWKYY5E_cjs.escapeHtml(docType.displayName)}`}
|
|
192
|
+
</h1>
|
|
193
|
+
${isEdit && doc ? `<p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">v${doc.versionNumber} \xB7 root: <code class="font-mono">${chunkMNWKYY5E_cjs.escapeHtml(doc.rootId)}</code></p>` : ""}
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<!-- Publish controls (edit mode, versioning types only) -->
|
|
197
|
+
${isEdit && doc && isEditor && data.versioningEnabled ? `
|
|
198
|
+
<div class="mt-4 sm:mt-0 flex gap-2">
|
|
199
|
+
${!doc.isPublished ? `
|
|
200
|
+
<form method="POST" action="/admin/content/documents/${chunkMNWKYY5E_cjs.escapeHtml(docType.id)}/${chunkMNWKYY5E_cjs.escapeHtml(doc.id)}/publish">
|
|
201
|
+
<button type="submit"
|
|
202
|
+
class="inline-flex items-center rounded-lg bg-green-600 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-green-500 transition-colors shadow-sm">
|
|
203
|
+
Publish
|
|
204
|
+
</button>
|
|
205
|
+
</form>` : `
|
|
206
|
+
<form method="POST" action="/admin/content/documents/${chunkMNWKYY5E_cjs.escapeHtml(docType.id)}/${chunkMNWKYY5E_cjs.escapeHtml(doc.id)}/unpublish">
|
|
207
|
+
<button type="submit"
|
|
208
|
+
class="inline-flex items-center rounded-lg bg-amber-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-amber-400 transition-colors shadow-sm">
|
|
209
|
+
Unpublish
|
|
210
|
+
</button>
|
|
211
|
+
</form>`}
|
|
212
|
+
</div>` : ""}
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
${publishBannerHtml}
|
|
216
|
+
${data.message ? renderAlert({ type: data.messageType ?? "info", message: data.message, dismissible: true }) : ""}
|
|
217
|
+
|
|
218
|
+
<!-- Form -->
|
|
219
|
+
<form method="POST" action="${formAction}">
|
|
220
|
+
${isEdit ? `<input type="hidden" name="_method" value="PUT">` : ""}
|
|
221
|
+
|
|
222
|
+
<div class="relative rounded-xl">
|
|
223
|
+
<div class="absolute inset-0 bg-gradient-to-br from-blue-500/5 to-purple-500/5 dark:from-blue-400/10 dark:to-purple-400/10 rounded-xl"></div>
|
|
224
|
+
<div class="relative bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 rounded-xl p-6 space-y-6">
|
|
225
|
+
|
|
226
|
+
<!-- Standard fields -->
|
|
227
|
+
<div>
|
|
228
|
+
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-200 mb-4">Document</h3>
|
|
229
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
230
|
+
<div>
|
|
231
|
+
<label for="title" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">Title</label>
|
|
232
|
+
<input type="text" id="title" name="title" value="${chunkMNWKYY5E_cjs.escapeHtml(doc?.title ?? "")}"
|
|
233
|
+
class="${inputClass(errors.title)}">
|
|
234
|
+
${errors.title ? `<p class="mt-1 text-xs text-red-500">${chunkMNWKYY5E_cjs.escapeHtml(errors.title)}</p>` : ""}
|
|
235
|
+
</div>
|
|
236
|
+
<div>
|
|
237
|
+
<label for="slug" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">Slug</label>
|
|
238
|
+
<input type="text" id="slug" name="slug" value="${chunkMNWKYY5E_cjs.escapeHtml(doc?.slug ?? "")}"
|
|
239
|
+
placeholder="auto-generated-if-empty"
|
|
240
|
+
class="${inputClass(errors.slug)}">
|
|
241
|
+
${errors.slug ? `<p class="mt-1 text-xs text-red-500">${chunkMNWKYY5E_cjs.escapeHtml(errors.slug)}</p>` : ""}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<!-- Queryable data fields -->
|
|
247
|
+
${queryableFields.length > 0 ? `
|
|
248
|
+
<div class="border-t border-zinc-200 dark:border-zinc-700 pt-6">
|
|
249
|
+
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-200 mb-4">Content</h3>
|
|
250
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
251
|
+
${queryableInputs}
|
|
252
|
+
</div>
|
|
253
|
+
</div>` : ""}
|
|
254
|
+
|
|
255
|
+
<!-- Remaining data fields not in queryable fields -->
|
|
256
|
+
${remainingHtml}
|
|
257
|
+
|
|
258
|
+
<!-- Actions -->
|
|
259
|
+
<div class="border-t border-zinc-200 dark:border-zinc-700 pt-6 flex items-center justify-between">
|
|
260
|
+
<a href="/admin/content?model=doc:${chunkMNWKYY5E_cjs.escapeHtml(docType.id)}"
|
|
261
|
+
class="inline-flex items-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-700 dark:text-zinc-200 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors">
|
|
262
|
+
Cancel
|
|
263
|
+
</a>
|
|
264
|
+
<div class="flex gap-3">
|
|
265
|
+
<button type="submit"
|
|
266
|
+
class="inline-flex items-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm">
|
|
267
|
+
${isEdit ? data.versioningEnabled ? "Save Draft" : "Update" : "Create"}
|
|
268
|
+
</button>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
</form>
|
|
274
|
+
|
|
275
|
+
<!-- Version history (edit mode, versioning opt-in only) -->
|
|
276
|
+
${isEdit && doc && data.versioningEnabled ? `
|
|
277
|
+
<details class="group">
|
|
278
|
+
<summary class="cursor-pointer text-sm text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white flex items-center gap-2 py-2">
|
|
279
|
+
<svg class="h-4 w-4 transition-transform group-open:rotate-90" viewBox="0 0 20 20" fill="currentColor">
|
|
280
|
+
<path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd"/>
|
|
281
|
+
</svg>
|
|
282
|
+
Version history
|
|
283
|
+
</summary>
|
|
284
|
+
<div class="mt-3 rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden">
|
|
285
|
+
<div id="version-history-placeholder" class="px-6 py-4 text-sm text-zinc-500 dark:text-zinc-400"
|
|
286
|
+
hx-get="/admin/versioning/${chunkMNWKYY5E_cjs.escapeHtml(doc.rootId)}"
|
|
287
|
+
hx-trigger="revealed"
|
|
288
|
+
hx-swap="outerHTML">
|
|
289
|
+
Loading version history\u2026
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
</details>` : ""}
|
|
293
|
+
</div>
|
|
294
|
+
`;
|
|
295
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
|
|
296
|
+
title: `${isEdit ? "Edit" : "New"} ${docType.displayName} \u2014 Documents`,
|
|
297
|
+
currentPath: "/admin/content",
|
|
298
|
+
user: data.user,
|
|
299
|
+
version: data.version,
|
|
300
|
+
content
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function renderVersionHistoryFragment(data) {
|
|
304
|
+
if (data.versions.length === 0) {
|
|
305
|
+
return `<div class="px-6 py-4 text-sm text-zinc-500 dark:text-zinc-400">No versions found.</div>`;
|
|
306
|
+
}
|
|
307
|
+
const rows = data.versions.map((v) => `
|
|
308
|
+
<div class="flex items-center justify-between px-6 py-3 border-b border-zinc-100 dark:border-zinc-800 last:border-0">
|
|
309
|
+
<div class="flex items-center gap-3">
|
|
310
|
+
<span class="text-sm font-medium text-zinc-950 dark:text-white">v${v.versionNumber}</span>
|
|
311
|
+
${v.isPublished ? `<span class="inline-flex items-center rounded-md bg-green-50 dark:bg-green-500/10 px-1.5 py-0.5 text-xs font-medium text-green-700 dark:text-green-400">live</span>` : ""}
|
|
312
|
+
${v.isCurrentDraft ? `<span class="inline-flex items-center rounded-md bg-blue-50 dark:bg-blue-500/10 px-1.5 py-0.5 text-xs font-medium text-blue-700 dark:text-blue-400">draft</span>` : ""}
|
|
313
|
+
</div>
|
|
314
|
+
<div class="flex items-center gap-4 text-xs text-zinc-500 dark:text-zinc-400">
|
|
315
|
+
<span>${v.createdBy ?? "\u2014"}</span>
|
|
316
|
+
<span>${new Date(v.updatedAt * 1e3).toLocaleString("en-US", { dateStyle: "short", timeStyle: "short" })}</span>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
`).join("");
|
|
320
|
+
return `<div>${rows}</div>`;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
exports.renderAlert = renderAlert;
|
|
324
|
+
exports.renderDocumentFormPage = renderDocumentFormPage;
|
|
325
|
+
exports.renderVersionHistoryFragment = renderVersionHistoryFragment;
|
|
326
|
+
//# sourceMappingURL=chunk-N32OWET6.cjs.map
|
|
327
|
+
//# sourceMappingURL=chunk-N32OWET6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/templates/pages/admin-documents-form.template.ts","../src/templates/components/alert.template.ts"],"names":["init_admin_layout_catalyst_template","escapeHtml","renderAdminLayoutCatalyst"],"mappings":";;;;;;AAAAA,qDAAA,EAAA;;;ACaO,SAAS,YAAY,IAAA,EAAyB;AACnD,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,OAAA,EAAS,sFAAA;AAAA,IACT,KAAA,EAAO,6DAAA;AAAA,IACP,OAAA,EAAS,sFAAA;AAAA,IACT,IAAA,EAAM;AAAA,GACR;AAEA,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,OAAA,EAAS,oCAAA;AAAA,IACT,KAAA,EAAO,gCAAA;AAAA,IACP,OAAA,EAAS,oCAAA;AAAA,IACT,IAAA,EAAM;AAAA,GACR;AAEA,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,OAAA,EAAS,oCAAA;AAAA,IACT,KAAA,EAAO,gCAAA;AAAA,IACP,OAAA,EAAS,oCAAA;AAAA,IACT,IAAA,EAAM;AAAA,GACR;AAEA,EAAA,MAAM,kBAAA,GAAqB;AAAA,IACzB,OAAA,EAAS,oCAAA;AAAA,IACT,KAAA,EAAO,gCAAA;AAAA,IACP,OAAA,EAAS,oCAAA;AAAA,IACT,IAAA,EAAM;AAAA,GACR;AAEA,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,OAAA,EAAS,CAAA,0LAAA,CAAA;AAAA,IACT,KAAA,EAAO,CAAA,4QAAA,CAAA;AAAA,IACP,OAAA,EAAS,CAAA,sQAAA,CAAA;AAAA,IACT,IAAA,EAAM,CAAA,qLAAA;AAAA,GACR;AAEA,EAAA,OAAO;AAAA,+BAAA,EACwB,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,IAAa,EAAE,CAAA,EAAA,EAAK,IAAA,CAAK,WAAA,GAAc,wBAAA,GAA2B,EAAE,CAAA;AAAA;AAAA,QAAA,EAE1H,IAAA,CAAK,SAAS,KAAA,GAAQ;AAAA;AAAA,gCAAA,EAEE,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,cAAA,EACxC,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC;AAAA;AAAA;AAAA,QAAA,CAAA,GAGpB,EAAE;AAAA,oBAAA,EACQ,IAAA,CAAK,IAAA,KAAS,KAAA,GAAQ,MAAA,GAAS,EAAE,CAAA;AAAA,UAAA,EAC3C,KAAK,KAAA,GAAQ;AAAA,6CAAA,EACsB,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,cAAA,EACrDC,4BAAA,CAAW,IAAA,CAAK,KAAK,CAAC;AAAA;AAAA,UAAA,CAAA,GAExB,EAAE;AAAA,sBAAA,EACQ,IAAA,CAAK,QAAQ,cAAA,GAAiB,SAAS,IAAI,kBAAA,CAAmB,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,eAAA,EAC/EA,4BAAA,CAAW,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA;AAAA;AAAA,QAAA,EAG/B,KAAK,WAAA,GAAc;AAAA;AAAA;AAAA;AAAA;AAAA,oDAAA,EAKyB,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,GAUhE,EAAE;AAAA;AAAA;AAAA,EAAA,CAAA;AAId;;;ADtEA,SAAS,WAAW,KAAA,EAAwB;AAC1C,EAAA,MAAM,IAAA,GAAO,0MAAA;AACb,EAAA,OAAO,KAAA,GACH,CAAA,EAAG,IAAI,CAAA,mCAAA,CAAA,GACP,GAAG,IAAI,CAAA,qCAAA,CAAA;AACb;AAEA,SAAS,gBAAA,CAAiB,KAAA,EAAuB,KAAA,EAAgB,KAAA,EAAwB;AACvF,EAAA,MAAM,EAAA,GAAK,CAAA,KAAA,EAAQ,KAAA,CAAM,IAAI,CAAA,CAAA;AAC7B,EAAA,MAAM,IAAA,GAAO,CAAA,KAAA,EAAQ,KAAA,CAAM,IAAI,CAAA,CAAA,CAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,KAAK,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,EAAa,CAAA;AACtF,EAAA,MAAM,MAAA,GAAS,KAAA,IAAS,IAAA,GAAO,MAAA,CAAO,KAAK,CAAA,GAAI,EAAA;AAE/C,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,KAAA,CAAM,IAAA,KAAS,SAAA,IAAa,KAAA,CAAM,SAAS,QAAA,EAAU;AACvD,IAAA,KAAA,GAAQ,4BAA4B,EAAE,CAAA,QAAA,EAAW,IAAI,CAAA,SAAA,EAAYA,4BAAA,CAAW,MAAM,CAAC,CAAA;AAAA,oBAAA,EACjE,KAAA,CAAM,IAAA,KAAS,SAAA,GAAY,GAAA,GAAM,KAAK,CAAA;AAAA,qBAAA,EACrC,UAAA,CAAW,KAAK,CAAC,CAAA,EAAA,CAAA;AAAA,EACtC,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,SAAA,EAAW;AAGnC,IAAA,KAAA,GAAQ,CAAA;AAAA,0CAAA,EACgC,IAAI,CAAA;AAAA,0CAAA,EACJ,EAAE,CAAA,QAAA,EAAW,IAAI,kBAAkB,MAAA,KAAW,MAAA,GAAS,YAAY,EAAE;AAAA;AAAA,sEAAA,EAEzC,KAAK,CAAA;AAAA,mBAAA,CAAA;AAEzE,IAAA,OAAO;AAAA;AAAA,QAAA,EAED,KAAK;AAAA,QAAA,EACL,QAAQ,CAAA,qCAAA,EAAwCA,4BAAA,CAAW,KAAK,CAAC,SAAS,EAAE;AAAA,YAAA,CAAA;AAAA,EAEpF,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,OAAA,EAAS;AAEjC,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAK,IAAK,KAAA,CAAmB,IAAA,CAAK,IAAI,CAAA,GAAI,MAAA;AACvE,IAAA,KAAA,GAAQ,0BAA0B,EAAE,CAAA,QAAA,EAAW,IAAI,CAAA,SAAA,EAAYA,4BAAA,CAAW,MAAM,CAAC,CAAA;AAAA;AAAA,qBAAA,EAE9D,UAAA,CAAW,KAAK,CAAC,CAAA,EAAA,CAAA;AAAA,EACtC,CAAA,MAAO;AACL,IAAA,KAAA,GAAQ,0BAA0B,EAAE,CAAA,QAAA,EAAW,IAAI,CAAA,SAAA,EAAYA,4BAAA,CAAW,MAAM,CAAC,CAAA;AAAA,qBAAA,EAC9D,UAAA,CAAW,KAAK,CAAC,CAAA,EAAA,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO;AAAA;AAAA,kBAAA,EAEW,EAAE,CAAA;AAAA,QAAA,EACZ,KAAK;AAAA;AAAA,MAAA,EAEP,KAAK;AAAA,MAAA,EACL,QAAQ,CAAA,qCAAA,EAAwCA,4BAAA,CAAW,KAAK,CAAC,SAAS,EAAE;AAAA,UAAA,CAAA;AAEpF;AAEA,SAAS,qBAAA,CACP,OAAA,EACA,eAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAI,CAAC,CAAA;AAC3D,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,CAAO,CAAA,CAAA,KAAK,CAAC,UAAA,CAAW,GAAA,CAAI,CAAC,CAAC,CAAA;AACzE,EAAA,IAAI,aAAA,CAAc,MAAA,KAAW,CAAA,EAAG,OAAO,EAAA;AAEvC,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,GAAA,CAAI,CAAA,GAAA,KAAO;AACtC,IAAA,MAAM,GAAA,GAAM,QAAQ,GAAG,CAAA;AACvB,IAAA,MAAM,EAAA,GAAK,QAAQ,GAAG,CAAA,CAAA;AACtB,IAAA,MAAM,IAAA,GAAO,QAAQ,GAAG,CAAA,CAAA,CAAA;AACxB,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,OAAA,CAAQ,UAAA,EAAY,KAAK,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,EAAa,CAAA;AAC/E,IAAA,MAAM,MAAA,GAAS,OAAO,GAAA,KAAQ,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,IAAA,EAAM,CAAC,CAAA,GAAI,MAAA,CAAO,GAAA,IAAO,EAAE,CAAA;AACxF,IAAA,MAAM,cAAc,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,IAAK,OAAO,MAAA,GAAS,GAAA;AAE7D,IAAA,OAAO;AAAA;AAAA,oBAAA,EAEW,EAAE,CAAA,0EAAA,EAA6EA,4BAAA,CAAW,KAAK,CAAC,CAAA;AAAA,QAAA,EAC5G,WAAA,GACE,CAAA,cAAA,EAAiB,EAAE,CAAA,QAAA,EAAW,IAAI,CAAA,kBAAA,EAAqB,UAAA,CAAW,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA,EAAA,EAAKA,6BAAW,MAAM,CAAC,CAAA,WAAA,CAAA,GACrG,CAAA,uBAAA,EAA0B,EAAE,CAAA,QAAA,EAAW,IAAI,CAAA,SAAA,EAAYA,4BAAA,CAAW,MAAM,CAAC,CAAA,SAAA,EAAY,UAAA,CAAW,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA,EAAA,CAChH;AAAA,QAAA,EACE,MAAA,CAAO,GAAG,CAAA,GAAI,CAAA,qCAAA,EAAwCA,4BAAA,CAAW,OAAO,GAAG,CAAC,CAAC,CAAA,IAAA,CAAA,GAAS,EAAE;AAAA,YAAA,CAAA;AAAA,EAEhG,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAEV,EAAA,OAAO;AAAA;AAAA;AAAA,yDAAA,EAGkD,MAAM,CAAA;AAAA,UAAA,CAAA;AAEjE;AAEO,SAAS,uBAAuB,IAAA,EAAgC;AACrE,EAAA,MAAM,EAAE,SAAS,GAAA,EAAK,YAAA,EAAc,QAAQ,MAAA,GAAS,IAAG,GAAI,IAAA;AAC5D,EAAA,MAAM,eAAA,GAAkB,OAAA,CAAQ,eAAA,IAAmB,EAAC;AACpD,EAAA,MAAM,OAAA,GAAW,GAAA,EAAK,IAAA,IAAQ,EAAC;AAE/B,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,EAAM,IAAA,KAAS,OAAA;AACpC,EAAA,MAAM,QAAA,GAAW,OAAA,IAAW,IAAA,CAAK,IAAA,EAAM,IAAA,KAAS,QAAA;AAEhD,EAAA,MAAM,aAAA,GAAgB,MAAA,IAAU,GAAA,IAAO,CAAC,IAAI,WAAA,IAAe,YAAA;AAC3D,EAAA,MAAM,mBAAA,GAAsB,MAAA,IAAU,GAAA,EAAK,WAAA,IAAe,GAAA,EAAK,cAAA;AAI/D,EAAA,MAAM,aAAa,MAAA,GACf,CAAA,yBAAA,EAA4BA,4BAAA,CAAW,OAAA,CAAQ,EAAE,CAAC,CAAA,CAAA,EAAIA,4BAAA,CAAW,GAAA,CAAK,MAAM,CAAC,CAAA,CAAA,GAC7E,4BAA4BA,4BAAA,CAAW,OAAA,CAAQ,EAAE,CAAC,CAAA,IAAA,CAAA;AAEtD,EAAA,MAAM,qBAAqB,MAAM;AAC/B,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,GAAA,EAAK,OAAO,EAAA;AAC5B,IAAA,IAAI,mBAAA,EAAqB;AACvB,MAAA,OAAO,WAAA,CAAY;AAAA,QACjB,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AACA,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,OAAO,WAAA,CAAY;AAAA,QACjB,IAAA,EAAM,MAAA;AAAA,QACN,SAAS,CAAA,sBAAA,EAAyB,YAAA,CAAc,aAAa,CAAA,gDAAA,EAAmD,IAAI,aAAa,CAAA,EAAA;AAAA,OAClI,CAAA;AAAA,IACH;AACA,IAAA,OAAO,EAAA;AAAA,EACT,CAAA,GAAG;AAIH,EAAA,MAAM,eAAA,GAAkB,eAAA,CACrB,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,WAAW,CAAA,CAClC,GAAA,CAAI,CAAA,CAAA,KAAK,gBAAA,CAAiB,CAAA,EAAG,QAAQ,CAAA,CAAE,IAAI,CAAA,EAAG,MAAA,CAAO,CAAA,KAAA,EAAQ,CAAA,CAAE,IAAI,CAAA,CAAE,CAAC,CAAC,CAAA,CACvE,IAAA,CAAK,EAAE,CAAA;AAEV,EAAA,MAAM,aAAA,GAAgB,qBAAA,CAAsB,OAAA,EAAS,eAAA,EAAiB,MAAM,CAAA;AAE5E,EAAA,MAAM,OAAA,GAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8CAAA,EAQ8BA,4BAAA,CAAW,QAAQ,EAAE,CAAC,uDAAuDA,4BAAA,CAAW,OAAA,CAAQ,WAAW,CAAC,CAAA;AAAA;AAAA,oEAAA,EAEtF,MAAA,GAAS,SAAS,KAAK,CAAA;AAAA;AAAA;AAAA,YAAA,EAG/E,MAAA,GAAS,CAAA,KAAA,EAAQA,4BAAA,CAAW,OAAA,CAAQ,WAAW,CAAC,CAAA,CAAA,GAAK,CAAA,IAAA,EAAOA,4BAAA,CAAW,OAAA,CAAQ,WAAW,CAAC,CAAA,CAAE;AAAA;AAAA,UAAA,EAE/F,MAAA,IAAU,GAAA,GAAM,CAAA,0DAAA,EAA6D,GAAA,CAAI,aAAa,CAAA,oCAAA,EAAoCA,4BAAA,CAAW,GAAA,CAAI,MAAM,CAAC,CAAA,WAAA,CAAA,GAAgB,EAAE;AAAA;;AAAA;AAAA,QAAA,EAI5K,MAAA,IAAU,GAAA,IAAO,QAAA,IAAY,IAAA,CAAK,iBAAA,GAAoB;AAAA;AAAA,UAAA,EAEpD,CAAC,IAAI,WAAA,GAAc;AAAA,+DAAA,EACkCA,4BAAA,CAAW,QAAQ,EAAE,CAAC,IAAIA,4BAAA,CAAW,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAA,CAAA,GAKxF;AAAA,+DAAA,EAC4CA,4BAAA,CAAW,QAAQ,EAAE,CAAC,IAAIA,4BAAA,CAAW,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAA,CAK3F;AAAA,cAAA,CAAA,GACA,EAAE;AAAA;;AAAA,MAAA,EAGZ,iBAAiB;AAAA,MAAA,EACjB,IAAA,CAAK,OAAA,GAAU,WAAA,CAAY,EAAE,MAAM,IAAA,CAAK,WAAA,IAAe,MAAA,EAAQ,OAAA,EAAS,KAAK,OAAA,EAAS,WAAA,EAAa,IAAA,EAAM,IAAI,EAAE;;AAAA;AAAA,kCAAA,EAGnF,UAAU,CAAA;AAAA,QAAA,EACpC,MAAA,GAAS,qDAAqD,EAAE;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oEAAA,EAYJA,4BAAA,CAAW,GAAA,EAAK,KAAA,IAAS,EAAE,CAAC,CAAA;AAAA,2BAAA,EACrE,UAAA,CAAW,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,kBAAA,EACjC,MAAA,CAAO,QAAQ,CAAA,qCAAA,EAAwCA,4BAAA,CAAW,OAAO,KAAK,CAAC,SAAS,EAAE;AAAA;AAAA;AAAA;AAAA,kEAAA,EAI1CA,4BAAA,CAAW,GAAA,EAAK,IAAA,IAAQ,EAAE,CAAC,CAAA;AAAA;AAAA,2BAAA,EAElE,UAAA,CAAW,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,kBAAA,EAChC,MAAA,CAAO,OAAO,CAAA,qCAAA,EAAwCA,4BAAA,CAAW,OAAO,IAAI,CAAC,SAAS,EAAE;AAAA;AAAA;AAAA;;AAAA;AAAA,YAAA,EAM9F,eAAA,CAAgB,SAAS,CAAA,GAAI;AAAA;AAAA;AAAA;AAAA,gBAAA,EAIzB,eAAe;AAAA;AAAA,kBAAA,CAAA,GAEX,EAAE;;AAAA;AAAA,YAAA,EAGV,aAAa;;AAAA;AAAA;AAAA,gDAAA,EAIuBA,4BAAA,CAAW,OAAA,CAAQ,EAAE,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAA,EAOpD,MAAA,GAAU,IAAA,CAAK,iBAAA,GAAoB,YAAA,GAAe,WAAY,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,MAAA,EASlF,MAAA,IAAU,GAAA,IAAO,IAAA,CAAK,iBAAA,GAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EAUPA,4BAAA,CAAW,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAA,CAAA,GAM7C,EAAE;AAAA;AAAA,EAAA,CAAA;AAIpB,EAAA,OAAOC,2CAAA,CAA0B;AAAA,IAC/B,OAAO,CAAA,EAAG,MAAA,GAAS,SAAS,KAAK,CAAA,CAAA,EAAI,QAAQ,WAAW,CAAA,iBAAA,CAAA;AAAA,IACxD,WAAA,EAAa,gBAAA;AAAA,IACb,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,SAAS,IAAA,CAAK,OAAA;AAAA,IACd;AAAA,GACD,CAAA;AACH;AAkBO,SAAS,6BAA6B,IAAA,EAAkC;AAC7E,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AAC9B,IAAA,OAAO,CAAA,wFAAA,CAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK;AAAA;AAAA;AAAA,yEAAA,EAGqC,EAAE,aAAa,CAAA;AAAA,QAAA,EAChF,CAAA,CAAE,WAAA,GAAc,CAAA,mKAAA,CAAA,GAAwK,EAAE;AAAA,QAAA,EAC1L,CAAA,CAAE,cAAA,GAAiB,CAAA,gKAAA,CAAA,GAAqK,EAAE;AAAA;AAAA;AAAA,cAAA,EAGpL,CAAA,CAAE,aAAa,QAAG,CAAA;AAAA,cAAA,EAClB,IAAI,IAAA,CAAK,CAAA,CAAE,SAAA,GAAY,GAAI,CAAA,CAAE,cAAA,CAAe,OAAA,EAAS,EAAE,SAAA,EAAW,OAAA,EAAS,SAAA,EAAW,OAAA,EAAS,CAAC,CAAA;AAAA;AAAA;AAAA,EAAA,CAG7G,CAAA,CAAE,KAAK,EAAE,CAAA;AAEV,EAAA,OAAO,QAAQ,IAAI,CAAA,MAAA,CAAA;AACrB","file":"chunk-N32OWET6.cjs","sourcesContent":["import { renderAdminLayoutCatalyst } from '../layouts/admin-layout-catalyst.template'\nimport { renderAlert } from '../components/alert.template'\nimport { escapeHtml } from '../../utils/sanitize'\nimport type { Document, DocumentType, QueryableField } from '../../schemas/document'\n\nexport interface DocumentFormData {\n docType: DocumentType\n doc?: Document\n publishedDoc?: Document | null // Published revision when different from current draft\n isEdit: boolean\n errors?: Record<string, string>\n message?: string\n messageType?: 'success' | 'error' | 'warning' | 'info'\n user?: { name: string; email: string; role: string }\n version?: string\n versioningEnabled?: boolean // Whether versioning is opt-in for this document type\n}\n\nfunction inputClass(error?: string): string {\n const base = 'block w-full rounded-lg border bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white placeholder:text-zinc-400 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors'\n return error\n ? `${base} border-red-400 dark:border-red-500`\n : `${base} border-zinc-300 dark:border-zinc-700`\n}\n\nfunction renderFieldInput(field: QueryableField, value: unknown, error?: string): string {\n const id = `data_${field.name}`\n const name = `data[${field.name}]`\n const label = field.name.replace(/([A-Z])/g, ' $1').replace(/^./, s => s.toUpperCase())\n const strVal = value != null ? String(value) : ''\n\n let input: string\n if (field.type === 'integer' || field.type === 'number') {\n input = `<input type=\"number\" id=\"${id}\" name=\"${name}\" value=\"${escapeHtml(strVal)}\"\n step=\"${field.type === 'integer' ? '1' : 'any'}\"\n class=\"${inputClass(error)}\">`\n } else if (field.type === 'boolean') {\n // Hidden 'false' before the checkbox: an unchecked checkbox submits nothing, so without this a\n // boolean could never be set back to false (D15). When checked, the checkbox value wins.\n input = `<div class=\"flex items-center gap-2\">\n <input type=\"hidden\" name=\"${name}\" value=\"false\">\n <input type=\"checkbox\" id=\"${id}\" name=\"${name}\" value=\"true\" ${strVal === 'true' ? 'checked' : ''}\n class=\"h-4 w-4 rounded border-zinc-300 dark:border-zinc-600 text-blue-600 focus:ring-blue-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">${label}</span>\n </div>`\n return `\n <div>\n ${input}\n ${error ? `<p class=\"mt-1 text-xs text-red-500\">${escapeHtml(error)}</p>` : ''}\n </div>`\n } else if (field.kind === 'facet') {\n // Multi-value: comma-separated list\n const arrVal = Array.isArray(value) ? (value as string[]).join(', ') : strVal\n input = `<input type=\"text\" id=\"${id}\" name=\"${name}\" value=\"${escapeHtml(arrVal)}\"\n placeholder=\"Comma-separated values\"\n class=\"${inputClass(error)}\">`\n } else {\n input = `<input type=\"text\" id=\"${id}\" name=\"${name}\" value=\"${escapeHtml(strVal)}\"\n class=\"${inputClass(error)}\">`\n }\n\n return `\n <div>\n <label for=\"${id}\" class=\"block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1\">\n ${label}\n </label>\n ${input}\n ${error ? `<p class=\"mt-1 text-xs text-red-500\">${escapeHtml(error)}</p>` : ''}\n </div>`\n}\n\nfunction renderRemainingFields(\n allData: Record<string, unknown>,\n queryableFields: QueryableField[],\n errors: Record<string, string>,\n): string {\n const knownNames = new Set(queryableFields.map(f => f.name))\n const remainingKeys = Object.keys(allData).filter(k => !knownNames.has(k))\n if (remainingKeys.length === 0) return ''\n\n const inputs = remainingKeys.map(key => {\n const val = allData[key]\n const id = `data_${key}`\n const name = `data[${key}]`\n const label = key.replace(/([A-Z])/g, ' $1').replace(/^./, s => s.toUpperCase())\n const strVal = typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val ?? '')\n const isMultiline = strVal.includes('\\n') || strVal.length > 100\n\n return `\n <div>\n <label for=\"${id}\" class=\"block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1\">${escapeHtml(label)}</label>\n ${isMultiline\n ? `<textarea id=\"${id}\" name=\"${name}\" rows=\"4\" class=\"${inputClass(errors[key])}\">${escapeHtml(strVal)}</textarea>`\n : `<input type=\"text\" id=\"${id}\" name=\"${name}\" value=\"${escapeHtml(strVal)}\" class=\"${inputClass(errors[key])}\">`\n }\n ${errors[key] ? `<p class=\"mt-1 text-xs text-red-500\">${escapeHtml(errors[key])}</p>` : ''}\n </div>`\n }).join('')\n\n return `\n <div class=\"border-t border-zinc-200 dark:border-zinc-700 pt-6\">\n <h3 class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400 mb-4\">Additional Fields</h3>\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">${inputs}</div>\n </div>`\n}\n\nexport function renderDocumentFormPage(data: DocumentFormData): string {\n const { docType, doc, publishedDoc, isEdit, errors = {} } = data\n const queryableFields = docType.queryableFields ?? []\n const docData = (doc?.data ?? {}) as Record<string, unknown>\n\n const isAdmin = data.user?.role === 'admin'\n const isEditor = isAdmin || data.user?.role === 'editor'\n\n const hasNewerDraft = isEdit && doc && !doc.isPublished && publishedDoc\n const isPublishedAndDraft = isEdit && doc?.isPublished && doc?.isCurrentDraft\n\n // Real document CRUD lives under /admin/content/documents/:typeId/... (admin-content.ts), NOT\n // /admin/documents/ui (those are GET redirects only). Edit/save POSTs to :rootId; create to /new.\n const formAction = isEdit\n ? `/admin/content/documents/${escapeHtml(docType.id)}/${escapeHtml(doc!.rootId)}`\n : `/admin/content/documents/${escapeHtml(docType.id)}/new`\n\n const publishBannerHtml = (() => {\n if (!isEdit || !doc) return ''\n if (isPublishedAndDraft) {\n return renderAlert({\n type: 'success',\n message: 'This document is live. Saving creates a new draft. Use \"Publish\" to push changes live.',\n })\n }\n if (hasNewerDraft) {\n return renderAlert({\n type: 'info',\n message: `A published version (v${publishedDoc!.versionNumber}) is still live. This is an unpublished draft (v${doc.versionNumber}).`,\n })\n }\n return ''\n })()\n\n // Reference-kind fields are intentionally not rendered yet (D27) — fine for FAQ/testimonial, which\n // have none. When media references land (Phase 6), render a root-id picker here.\n const queryableInputs = queryableFields\n .filter(f => f.kind !== 'reference')\n .map(f => renderFieldInput(f, docData[f.name], errors[`data.${f.name}`]))\n .join('')\n\n const remainingHtml = renderRemainingFields(docData, queryableFields, errors)\n\n const content = `\n <div class=\"w-full px-4 sm:px-6 lg:px-8 py-6 space-y-6\">\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <div class=\"flex items-center gap-2 text-sm text-zinc-500 dark:text-zinc-400 mb-1\">\n <a href=\"/admin/content\" class=\"hover:text-zinc-950 dark:hover:text-white\">Content</a>\n <svg class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\"/></svg>\n <a href=\"/admin/content?model=doc:${escapeHtml(docType.id)}\" class=\"hover:text-zinc-950 dark:hover:text-white\">${escapeHtml(docType.displayName)}</a>\n <svg class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\"/></svg>\n <span class=\"text-zinc-950 dark:text-white font-medium\">${isEdit ? 'Edit' : 'New'}</span>\n </div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">\n ${isEdit ? `Edit ${escapeHtml(docType.displayName)}` : `New ${escapeHtml(docType.displayName)}`}\n </h1>\n ${isEdit && doc ? `<p class=\"mt-1 text-xs text-zinc-500 dark:text-zinc-400\">v${doc.versionNumber} · root: <code class=\"font-mono\">${escapeHtml(doc.rootId)}</code></p>` : ''}\n </div>\n\n <!-- Publish controls (edit mode, versioning types only) -->\n ${isEdit && doc && isEditor && data.versioningEnabled ? `\n <div class=\"mt-4 sm:mt-0 flex gap-2\">\n ${!doc.isPublished ? `\n <form method=\"POST\" action=\"/admin/content/documents/${escapeHtml(docType.id)}/${escapeHtml(doc.id)}/publish\">\n <button type=\"submit\"\n class=\"inline-flex items-center rounded-lg bg-green-600 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-green-500 transition-colors shadow-sm\">\n Publish\n </button>\n </form>` : `\n <form method=\"POST\" action=\"/admin/content/documents/${escapeHtml(docType.id)}/${escapeHtml(doc.id)}/unpublish\">\n <button type=\"submit\"\n class=\"inline-flex items-center rounded-lg bg-amber-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-amber-400 transition-colors shadow-sm\">\n Unpublish\n </button>\n </form>`}\n </div>` : ''}\n </div>\n\n ${publishBannerHtml}\n ${data.message ? renderAlert({ type: data.messageType ?? 'info', message: data.message, dismissible: true }) : ''}\n\n <!-- Form -->\n <form method=\"POST\" action=\"${formAction}\">\n ${isEdit ? `<input type=\"hidden\" name=\"_method\" value=\"PUT\">` : ''}\n\n <div class=\"relative rounded-xl\">\n <div class=\"absolute inset-0 bg-gradient-to-br from-blue-500/5 to-purple-500/5 dark:from-blue-400/10 dark:to-purple-400/10 rounded-xl\"></div>\n <div class=\"relative bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 rounded-xl p-6 space-y-6\">\n\n <!-- Standard fields -->\n <div>\n <h3 class=\"text-sm font-semibold text-zinc-700 dark:text-zinc-200 mb-4\">Document</h3>\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label for=\"title\" class=\"block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1\">Title</label>\n <input type=\"text\" id=\"title\" name=\"title\" value=\"${escapeHtml(doc?.title ?? '')}\"\n class=\"${inputClass(errors.title)}\">\n ${errors.title ? `<p class=\"mt-1 text-xs text-red-500\">${escapeHtml(errors.title)}</p>` : ''}\n </div>\n <div>\n <label for=\"slug\" class=\"block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1\">Slug</label>\n <input type=\"text\" id=\"slug\" name=\"slug\" value=\"${escapeHtml(doc?.slug ?? '')}\"\n placeholder=\"auto-generated-if-empty\"\n class=\"${inputClass(errors.slug)}\">\n ${errors.slug ? `<p class=\"mt-1 text-xs text-red-500\">${escapeHtml(errors.slug)}</p>` : ''}\n </div>\n </div>\n </div>\n\n <!-- Queryable data fields -->\n ${queryableFields.length > 0 ? `\n <div class=\"border-t border-zinc-200 dark:border-zinc-700 pt-6\">\n <h3 class=\"text-sm font-semibold text-zinc-700 dark:text-zinc-200 mb-4\">Content</h3>\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n ${queryableInputs}\n </div>\n </div>` : ''}\n\n <!-- Remaining data fields not in queryable fields -->\n ${remainingHtml}\n\n <!-- Actions -->\n <div class=\"border-t border-zinc-200 dark:border-zinc-700 pt-6 flex items-center justify-between\">\n <a href=\"/admin/content?model=doc:${escapeHtml(docType.id)}\"\n class=\"inline-flex items-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-700 dark:text-zinc-200 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Cancel\n </a>\n <div class=\"flex gap-3\">\n <button type=\"submit\"\n class=\"inline-flex items-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n ${isEdit ? (data.versioningEnabled ? 'Save Draft' : 'Update') : 'Create'}\n </button>\n </div>\n </div>\n </div>\n </div>\n </form>\n\n <!-- Version history (edit mode, versioning opt-in only) -->\n ${isEdit && doc && data.versioningEnabled ? `\n <details class=\"group\">\n <summary class=\"cursor-pointer text-sm text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white flex items-center gap-2 py-2\">\n <svg class=\"h-4 w-4 transition-transform group-open:rotate-90\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\"/>\n </svg>\n Version history\n </summary>\n <div class=\"mt-3 rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden\">\n <div id=\"version-history-placeholder\" class=\"px-6 py-4 text-sm text-zinc-500 dark:text-zinc-400\"\n hx-get=\"/admin/versioning/${escapeHtml(doc.rootId)}\"\n hx-trigger=\"revealed\"\n hx-swap=\"outerHTML\">\n Loading version history…\n </div>\n </div>\n </details>` : ''}\n </div>\n `\n\n return renderAdminLayoutCatalyst({\n title: `${isEdit ? 'Edit' : 'New'} ${docType.displayName} — Documents`,\n currentPath: '/admin/content',\n user: data.user,\n version: data.version,\n content,\n })\n}\n\n// ─── Version history fragment (HTMX target) ──────────────────────────────────\n\nexport interface VersionHistoryData {\n versions: Array<{\n id: string\n versionNumber: number\n isCurrentDraft: boolean\n isPublished: boolean\n status: string\n updatedAt: number\n createdBy: string | null\n }>\n docType: DocumentType\n rootId: string\n}\n\nexport function renderVersionHistoryFragment(data: VersionHistoryData): string {\n if (data.versions.length === 0) {\n return `<div class=\"px-6 py-4 text-sm text-zinc-500 dark:text-zinc-400\">No versions found.</div>`\n }\n\n const rows = data.versions.map(v => `\n <div class=\"flex items-center justify-between px-6 py-3 border-b border-zinc-100 dark:border-zinc-800 last:border-0\">\n <div class=\"flex items-center gap-3\">\n <span class=\"text-sm font-medium text-zinc-950 dark:text-white\">v${v.versionNumber}</span>\n ${v.isPublished ? `<span class=\"inline-flex items-center rounded-md bg-green-50 dark:bg-green-500/10 px-1.5 py-0.5 text-xs font-medium text-green-700 dark:text-green-400\">live</span>` : ''}\n ${v.isCurrentDraft ? `<span class=\"inline-flex items-center rounded-md bg-blue-50 dark:bg-blue-500/10 px-1.5 py-0.5 text-xs font-medium text-blue-700 dark:text-blue-400\">draft</span>` : ''}\n </div>\n <div class=\"flex items-center gap-4 text-xs text-zinc-500 dark:text-zinc-400\">\n <span>${v.createdBy ?? '—'}</span>\n <span>${new Date(v.updatedAt * 1000).toLocaleString('en-US', { dateStyle: 'short', timeStyle: 'short' })}</span>\n </div>\n </div>\n `).join('')\n\n return `<div>${rows}</div>`\n}\n","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}\n"]}
|