@templatical/editor 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AiChatSidebar-ftdKHSR-.js → AiChatSidebar-CkHJ28sf.js} +3 -3
- package/dist/{AiFeatureMenu-aNeCRlil.js → AiFeatureMenu-DWdKguDN.js} +3 -3
- package/dist/{BlockIssueBadge-bTDu6W_2.js → BlockIssueBadge-DcyHTAqw.js} +2 -2
- package/dist/{BlockPreviewCanvas-BsOuOfzB.js → BlockPreviewCanvas-B621ANn9.js} +4 -4
- package/dist/{CloudHeaderExtras-BNpFohqt.js → CloudHeaderExtras-BJ3Cebhv.js} +2 -2
- package/dist/{CloudPanels-xoGWwqSH.js → CloudPanels-BGz9ygo6.js} +6 -6
- package/dist/{CollaboratorBar-mEqXkdEi.js → CollaboratorBar-KphmSQeZ.js} +2 -2
- package/dist/{ColorPicker-FL5Vb9bE.js → ColorPicker-C6EOwtHC.js} +5 -5
- package/dist/{CommentsPanel-slfi74ng.js → CommentsPanel-DmWh8f08.js} +1 -1
- package/dist/{CommentsSidebar-Dea4spMl.js → CommentsSidebar-CL_tffzT.js} +4 -4
- package/dist/{CountdownBlock-DQTwaRxP.js → CountdownBlock-D1fsNsyS.js} +1 -1
- package/dist/{CountdownToolbar-C7xwJoqh.js → CountdownToolbar-B8J4i5Xp.js} +2 -2
- package/dist/{DesignReferenceSidebar-BtBd7bbz.js → DesignReferenceSidebar-BDhEeaAh.js} +4 -4
- package/dist/{IssuesPanel-Ci2H36L2.js → IssuesPanel-CiOjeRFI.js} +4 -4
- package/dist/MergeTagInput-RytOlh1A.js +448 -0
- package/dist/{MergeTagModeToggle-Cdi_DmVw.js → MergeTagModeToggle-Bi-FydXj.js} +2 -2
- package/dist/{ParagraphEditor-DQEOFc0K.js → ParagraphEditor-C87tkmtE.js} +12 -12
- package/dist/{RestoreVersionDialog-CHwngBae.js → RestoreVersionDialog-Db5rZRMA.js} +2 -2
- package/dist/RichTextEditorContent-BmTcV2-a.js +152 -0
- package/dist/{SaveBlockDialog-tZqZzPjW.js → SaveBlockDialog-CDCzx6Bo.js} +15 -15
- package/dist/{SavedBlocksBrowserModal-Bdj3GOD_.js → SavedBlocksBrowserModal-DQR6kJB1.js} +101 -101
- package/dist/{SavedBlocksPanels-2sBxAH9w.js → SavedBlocksPanels-DFzV0CRD.js} +1 -1
- package/dist/{SavedBlocksPickBar-DTjQBR00.js → SavedBlocksPickBar-XyXmnSnO.js} +2 -2
- package/dist/{TemplateScoringPanel-B6nHSrBD.js → TemplateScoringPanel-CpyEKMzC.js} +4 -4
- package/dist/{TestEmailModal-DuHbzO37.js → TestEmailModal-DIfJy9eE.js} +8 -8
- package/dist/{TestEmailPanel-TpwP-eK_.js → TestEmailPanel-C8Wx5yPS.js} +1 -1
- package/dist/{TitleEditor-C0JQJu38.js → TitleEditor-iNFOisr4.js} +11 -11
- package/dist/{TplModal-BMGmhquu.js → TplModal-CowM3o_F.js} +5 -5
- package/dist/{VersionHistoryMenu-D2x6MMYx.js → VersionHistoryMenu-CV90OhXs.js} +2 -2
- package/dist/{VersionHistoryPanels-aGlUVEGF.js → VersionHistoryPanels-BE3pplJG.js} +1 -1
- package/dist/{VersionPreviewBanner-61t3_Z-a.js → VersionPreviewBanner-BwUWBtlH.js} +1 -1
- package/dist/{blockTypeIcons-BsNup009.js → blockTypeIcons-DQsKtHik.js} +1 -1
- package/dist/bundle-stats.json +6 -6
- package/dist/cdn/chunks/{AiChatSidebar-CqWvtRwB.js → AiChatSidebar-BEnIWn6s.js} +4 -4
- package/dist/cdn/chunks/AiChatSidebar-BEnIWn6s.js.map +1 -0
- package/dist/cdn/chunks/{AiFeatureMenu-DoFrLcXJ.js → AiFeatureMenu-DMl23akc.js} +4 -4
- package/dist/cdn/chunks/{AiFeatureMenu-DoFrLcXJ.js.map → AiFeatureMenu-DMl23akc.js.map} +1 -1
- package/dist/cdn/chunks/{BlockIssueBadge-B_mUH69a.js → BlockIssueBadge-CloK4k3M.js} +3 -3
- package/dist/cdn/chunks/{BlockIssueBadge-B_mUH69a.js.map → BlockIssueBadge-CloK4k3M.js.map} +1 -1
- package/dist/cdn/chunks/{BlockPreviewCanvas-CSIxs7hr.js → BlockPreviewCanvas-DSiJFJa0.js} +5 -5
- package/dist/cdn/chunks/{BlockPreviewCanvas-CSIxs7hr.js.map → BlockPreviewCanvas-DSiJFJa0.js.map} +1 -1
- package/dist/cdn/chunks/{CloudHeaderExtras-Dgtr7WaE.js → CloudHeaderExtras-b4KpVeUN.js} +3 -3
- package/dist/cdn/chunks/{CloudHeaderExtras-Dgtr7WaE.js.map → CloudHeaderExtras-b4KpVeUN.js.map} +1 -1
- package/dist/cdn/chunks/{CloudPanels-B91lUmof.js → CloudPanels-DzwOq9lp.js} +7 -7
- package/dist/cdn/chunks/CloudPanels-DzwOq9lp.js.map +1 -0
- package/dist/cdn/chunks/{CollaboratorBar-CQwPWoFu.js → CollaboratorBar-WXKvpoGK.js} +3 -3
- package/dist/cdn/chunks/{CollaboratorBar-CQwPWoFu.js.map → CollaboratorBar-WXKvpoGK.js.map} +1 -1
- package/dist/cdn/chunks/{ColorPicker-CdrKX48J.js → ColorPicker-BubTDiS1.js} +6 -6
- package/dist/cdn/chunks/{ColorPicker-CdrKX48J.js.map → ColorPicker-BubTDiS1.js.map} +1 -1
- package/dist/cdn/chunks/{CommentsPanel-BJNgTmAA.js → CommentsPanel-DAA2VqX4.js} +2 -2
- package/dist/cdn/chunks/{CommentsPanel-BJNgTmAA.js.map → CommentsPanel-DAA2VqX4.js.map} +1 -1
- package/dist/cdn/chunks/{CommentsSidebar-D6VIIPhB.js → CommentsSidebar-Ci0M2ePp.js} +5 -5
- package/dist/cdn/chunks/CommentsSidebar-Ci0M2ePp.js.map +1 -0
- package/dist/cdn/chunks/{CountdownBlock-BRwXUvGU.js → CountdownBlock-rK055jpy.js} +2 -2
- package/dist/cdn/chunks/{CountdownBlock-BRwXUvGU.js.map → CountdownBlock-rK055jpy.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownToolbar-CVaU5WG6.js → CountdownToolbar-CzZq26Vp.js} +3 -3
- package/dist/cdn/chunks/{CountdownToolbar-CVaU5WG6.js.map → CountdownToolbar-CzZq26Vp.js.map} +1 -1
- package/dist/cdn/chunks/{DesignReferenceSidebar-BvOwE1kg.js → DesignReferenceSidebar-C_ehdX5C.js} +5 -5
- package/dist/cdn/chunks/DesignReferenceSidebar-C_ehdX5C.js.map +1 -0
- package/dist/cdn/chunks/{IssuesPanel-MJZxkScz.js → IssuesPanel-BXAN2_al.js} +5 -5
- package/dist/cdn/chunks/{IssuesPanel-MJZxkScz.js.map → IssuesPanel-BXAN2_al.js.map} +1 -1
- package/dist/cdn/chunks/MergeTagInput-1vcI9uQH.js +419 -0
- package/dist/cdn/chunks/MergeTagInput-1vcI9uQH.js.map +1 -0
- package/dist/cdn/chunks/{MergeTagModeToggle-bNuN6PTV.js → MergeTagModeToggle-B_mUYJo4.js} +3 -3
- package/dist/cdn/chunks/{MergeTagModeToggle-bNuN6PTV.js.map → MergeTagModeToggle-B_mUYJo4.js.map} +1 -1
- package/dist/cdn/chunks/{ParagraphEditor-BU8tlFbL.js → ParagraphEditor-DCDHMcmx.js} +10 -10
- package/dist/cdn/chunks/ParagraphEditor-DCDHMcmx.js.map +1 -0
- package/dist/cdn/chunks/{RestoreVersionDialog-vdRFfyy0.js → RestoreVersionDialog-BkSSwf-Q.js} +3 -3
- package/dist/cdn/chunks/{RestoreVersionDialog-vdRFfyy0.js.map → RestoreVersionDialog-BkSSwf-Q.js.map} +1 -1
- package/dist/cdn/chunks/RichTextEditorContent-S4KogjIj.js +122 -0
- package/dist/cdn/chunks/RichTextEditorContent-S4KogjIj.js.map +1 -0
- package/dist/cdn/chunks/{SaveBlockDialog-DWaeqcM8.js → SaveBlockDialog-BH774Nt0.js} +14 -14
- package/dist/cdn/chunks/{SaveBlockDialog-DWaeqcM8.js.map → SaveBlockDialog-BH774Nt0.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-qC7UhW74.js → SavedBlocksBrowserModal-CSUqw_dD.js} +6 -6
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-qC7UhW74.js.map → SavedBlocksBrowserModal-CSUqw_dD.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPanels-BvtjtdsY.js → SavedBlocksPanels-B6ApbCjG.js} +2 -2
- package/dist/cdn/chunks/{SavedBlocksPanels-BvtjtdsY.js.map → SavedBlocksPanels-B6ApbCjG.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPickBar-CxXjF3RN.js → SavedBlocksPickBar-C9MXSRcR.js} +3 -3
- package/dist/cdn/chunks/{SavedBlocksPickBar-CxXjF3RN.js.map → SavedBlocksPickBar-C9MXSRcR.js.map} +1 -1
- package/dist/cdn/chunks/{TemplateScoringPanel-CroWaWqy.js → TemplateScoringPanel-QVOxc9TZ.js} +50 -50
- package/dist/cdn/chunks/TemplateScoringPanel-QVOxc9TZ.js.map +1 -0
- package/dist/cdn/chunks/{TestEmailModal-iWxAZRRq.js → TestEmailModal-_CZvaO58.js} +9 -9
- package/dist/cdn/chunks/{TestEmailModal-iWxAZRRq.js.map → TestEmailModal-_CZvaO58.js.map} +1 -1
- package/dist/cdn/chunks/{TestEmailPanel-CGUtEuwp.js → TestEmailPanel-DXLxvyrD.js} +2 -2
- package/dist/cdn/chunks/{TestEmailPanel-CGUtEuwp.js.map → TestEmailPanel-DXLxvyrD.js.map} +1 -1
- package/dist/cdn/chunks/{TitleEditor-DvXUW2j-.js → TitleEditor-BuCOahW3.js} +9 -9
- package/dist/cdn/chunks/TitleEditor-BuCOahW3.js.map +1 -0
- package/dist/cdn/chunks/{TplModal-X-qNoLGZ.js → TplModal-CqY8R3hn.js} +6 -6
- package/dist/cdn/chunks/TplModal-CqY8R3hn.js.map +1 -0
- package/dist/cdn/chunks/{VersionHistoryMenu-yKzwxf7n.js → VersionHistoryMenu-DDjIBvad.js} +3 -3
- package/dist/cdn/chunks/{VersionHistoryMenu-yKzwxf7n.js.map → VersionHistoryMenu-DDjIBvad.js.map} +1 -1
- package/dist/cdn/chunks/{VersionHistoryPanels--hQaanjH.js → VersionHistoryPanels-BuTw04T5.js} +2 -2
- package/dist/cdn/chunks/{VersionHistoryPanels--hQaanjH.js.map → VersionHistoryPanels-BuTw04T5.js.map} +1 -1
- package/dist/cdn/chunks/{VersionPreviewBanner-DWU_SqMd.js → VersionPreviewBanner-fGAv20qI.js} +2 -2
- package/dist/cdn/chunks/{VersionPreviewBanner-DWU_SqMd.js.map → VersionPreviewBanner-fGAv20qI.js.map} +1 -1
- package/dist/cdn/chunks/{createCloudRuntime-DD6ppb71.js → createCloudRuntime-JFE-sxbT.js} +2 -2
- package/dist/cdn/chunks/{createCloudRuntime-DD6ppb71.js.map → createCloudRuntime-JFE-sxbT.js.map} +1 -1
- package/dist/cdn/chunks/{extensions-BUPHNpKD.js → extensions-7z04EIGg.js} +3 -3
- package/dist/cdn/chunks/{extensions-BUPHNpKD.js.map → extensions-7z04EIGg.js.map} +1 -1
- package/dist/cdn/chunks/keys-DQp8x7Nx.js +12 -0
- package/dist/cdn/chunks/keys-DQp8x7Nx.js.map +1 -0
- package/dist/cdn/chunks/src-CLoCCDfs.js.map +1 -1
- package/dist/cdn/chunks/{src-DtnvR_Hl.js → src-CiAi5oRe.js} +2 -2
- package/dist/cdn/chunks/{src-DtnvR_Hl.js.map → src-CiAi5oRe.js.map} +1 -1
- package/dist/cdn/chunks/{useCloudI18n-DbsLlCbZ.js → useCloudI18n-MxgHWrV6.js} +2 -2
- package/dist/cdn/chunks/{useCloudI18n-DbsLlCbZ.js.map → useCloudI18n-MxgHWrV6.js.map} +1 -1
- package/dist/cdn/chunks/{useEditorCore-ChlgO2GN.js → useEditorCore-ehUSEsbw.js} +548 -511
- package/dist/cdn/chunks/useEditorCore-ehUSEsbw.js.map +1 -0
- package/dist/cdn/chunks/{useEditorRoot-BlF1WPeu.js → useEditorRoot-CteADR3y.js} +2 -2
- package/dist/cdn/chunks/{useEditorRoot-BlF1WPeu.js.map → useEditorRoot-CteADR3y.js.map} +1 -1
- package/dist/cdn/chunks/{useI18n-BdxNNw6j.js → useI18n-Ct1VIFcf.js} +2 -2
- package/dist/cdn/chunks/{useI18n-BdxNNw6j.js.map → useI18n-Ct1VIFcf.js.map} +1 -1
- package/dist/cdn/chunks/useMergeTag-TLhF2fGK.js +46 -0
- package/dist/cdn/chunks/useMergeTag-TLhF2fGK.js.map +1 -0
- package/dist/cdn/chunks/{usePopoverPosition-Dw1nTSNx.js → usePopoverPosition-BxVWE5_0.js} +2 -2
- package/dist/cdn/chunks/{usePopoverPosition-Dw1nTSNx.js.map → usePopoverPosition-BxVWE5_0.js.map} +1 -1
- package/dist/cdn/chunks/{useScrollToBlock-BMis3-PR.js → useScrollToBlock-Cz3fpgTK.js} +2 -2
- package/dist/cdn/chunks/{useScrollToBlock-BMis3-PR.js.map → useScrollToBlock-Cz3fpgTK.js.map} +1 -1
- package/dist/cdn/editor.css +1 -1
- package/dist/cdn/editor.js +1722 -2071
- package/dist/cdn/editor.js.map +1 -1
- package/dist/{createCloudRuntime-zNcMjRgb.js → createCloudRuntime-DbTFm1ES.js} +1 -1
- package/dist/{extensions-kOYwOh72.js → extensions-Mf8iHey9.js} +2 -2
- package/dist/index.d.ts +41 -0
- package/dist/keys-C3P1yxnr.js +10 -0
- package/dist/style.css +1 -1
- package/dist/templatical-editor.js +1890 -2240
- package/dist/{useCloudI18n-BlMajbKp.js → useCloudI18n-BKoiYsWZ.js} +1 -1
- package/dist/{useEditorCore-CwQYCSXO.js → useEditorCore-DdkQuTHl.js} +1101 -1064
- package/dist/{useEditorRoot-C92q8uV-.js → useEditorRoot-DkRGTQRs.js} +1 -1
- package/dist/{useI18n-Ce_BRzYv.js → useI18n-CL6RfPzK.js} +1 -1
- package/dist/useMergeTag-gSuYus-M.js +44 -0
- package/dist/{usePopoverPosition-CPk7Twye.js → usePopoverPosition-CWxaIWd3.js} +1 -1
- package/dist/{useScrollToBlock-DvpMfWs2.js → useScrollToBlock-CdI8fGqt.js} +1 -1
- package/package.json +7 -7
- package/dist/RichTextEditorContent-C_9xi7dD.js +0 -153
- package/dist/cdn/chunks/AiChatSidebar-CqWvtRwB.js.map +0 -1
- package/dist/cdn/chunks/CloudPanels-B91lUmof.js.map +0 -1
- package/dist/cdn/chunks/CommentsSidebar-D6VIIPhB.js.map +0 -1
- package/dist/cdn/chunks/DesignReferenceSidebar-BvOwE1kg.js.map +0 -1
- package/dist/cdn/chunks/ParagraphEditor-BU8tlFbL.js.map +0 -1
- package/dist/cdn/chunks/RichTextEditorContent-C1-5I8Df.js +0 -123
- package/dist/cdn/chunks/RichTextEditorContent-C1-5I8Df.js.map +0 -1
- package/dist/cdn/chunks/TemplateScoringPanel-CroWaWqy.js.map +0 -1
- package/dist/cdn/chunks/TitleEditor-DvXUW2j-.js.map +0 -1
- package/dist/cdn/chunks/TplModal-X-qNoLGZ.js.map +0 -1
- package/dist/cdn/chunks/keys-BOn5i9jV.js +0 -12
- package/dist/cdn/chunks/keys-BOn5i9jV.js.map +0 -1
- package/dist/cdn/chunks/useEditorCore-ChlgO2GN.js.map +0 -1
- package/dist/cdn/chunks/useMergeTag-CI2WUNrR.js +0 -46
- package/dist/cdn/chunks/useMergeTag-CI2WUNrR.js.map +0 -1
- package/dist/keys-BOhFlHsv.js +0 -10
- package/dist/scan-line-E7w4yQyv.js +0 -31
- package/dist/useMergeTag-CrXJ49lr.js +0 -44
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { D as e, E as t, N as n, R as r, S as i, U as a, at as o, b as s, d as c, f as l, g as u, h as d, l as f, lt as p, m, o as h, p as g, ut as _, y as v, z as y } from "./draggable-kbOhCgnk.js";
|
|
2
|
-
import { B as b, U as x, h as S } from "./keys-BOn5i9jV.js";
|
|
3
|
-
import { t as C } from "./useI18n-BdxNNw6j.js";
|
|
4
|
-
import { n as w } from "./usePopoverPosition-Dw1nTSNx.js";
|
|
5
|
-
import { n as T } from "./icons-SP5Itd-A.js";
|
|
6
|
-
import { t as E } from "./ColorPicker-CdrKX48J.js";
|
|
7
|
-
//#region src/components/blocks/RichTextLinkDialog.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
-
var D = ["data-tpl-theme"], O = { class: "tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-5 tpl:py-4" }, k = {
|
|
9
|
-
id: "tpl-link-dialog-title",
|
|
10
|
-
class: "tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]"
|
|
11
|
-
}, A = ["aria-label"], j = { class: "tpl:p-5" }, M = { class: "tpl:mb-4 tpl:last:mb-0" }, N = {
|
|
12
|
-
for: "tpl-link-dialog-url",
|
|
13
|
-
class: "tpl:mb-1.5 tpl:block tpl:text-xs tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase"
|
|
14
|
-
}, P = ["placeholder"], F = { class: "tpl:mb-4 tpl:last:mb-0" }, I = { class: "tpl:mb-1.5 tpl:block tpl:text-xs tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase" }, L = { class: "tpl:flex tpl:items-center tpl:justify-between tpl:border-t tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:px-5 tpl:py-4" }, R = { class: "tpl:ml-auto tpl:flex tpl:gap-2" }, z = /* @__PURE__ */ i({
|
|
15
|
-
__name: "RichTextLinkDialog",
|
|
16
|
-
props: /*@__PURE__*/ e({
|
|
17
|
-
visible: { type: Boolean },
|
|
18
|
-
isEditingLink: { type: Boolean }
|
|
19
|
-
}, {
|
|
20
|
-
linkUrl: { required: !0 },
|
|
21
|
-
linkUrlModifiers: {},
|
|
22
|
-
linkColor: { default: "" },
|
|
23
|
-
linkColorModifiers: {},
|
|
24
|
-
dialogRef: { required: !0 },
|
|
25
|
-
dialogRefModifiers: {}
|
|
26
|
-
}),
|
|
27
|
-
emits: /*@__PURE__*/ e([
|
|
28
|
-
"close",
|
|
29
|
-
"insert",
|
|
30
|
-
"remove",
|
|
31
|
-
"keydown"
|
|
32
|
-
], [
|
|
33
|
-
"update:linkUrl",
|
|
34
|
-
"update:linkColor",
|
|
35
|
-
"update:dialogRef"
|
|
36
|
-
]),
|
|
37
|
-
setup(e, { emit: r }) {
|
|
38
|
-
let i = y(e, "linkUrl"), v = y(e, "linkColor"), z = y(e, "dialogRef"), B = r, V = t(b, null), H = t(x, null), U = w(), W = t(S, null), G = l(() => W?.content.value.settings.linkColor || "#2c85de"), { t: K } = C();
|
|
39
|
-
return (t, r) => o(U) ? (n(), m(c, {
|
|
40
|
-
key: 0,
|
|
41
|
-
to: o(U)
|
|
42
|
-
}, [e.visible ? (n(), u("div", {
|
|
43
|
-
key: 0,
|
|
44
|
-
"data-tpl-theme": o(H),
|
|
45
|
-
class: "tpl tpl-link-dialog tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center",
|
|
46
|
-
style: p(o(V)),
|
|
47
|
-
onClick: r[7] ||= f((e) => B("close"), ["self"])
|
|
48
|
-
}, [g("div", {
|
|
49
|
-
ref: (e) => z.value = e,
|
|
50
|
-
role: "dialog",
|
|
51
|
-
"aria-modal": "true",
|
|
52
|
-
"aria-labelledby": "tpl-link-dialog-title",
|
|
53
|
-
class: "tpl:w-[400px] tpl:overflow-hidden tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow-lg)]"
|
|
54
|
-
}, [
|
|
55
|
-
g("div", O, [g("h4", k, _(e.isEditingLink ? o(K).linkDialog.editLink : o(K).linkDialog.insertLink), 1), g("button", {
|
|
56
|
-
type: "button",
|
|
57
|
-
"aria-label": o(K).linkDialog.cancel,
|
|
58
|
-
class: "tpl:flex tpl:size-7 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-muted)] tpl:hover:bg-[var(--tpl-bg-hover)] tpl:hover:text-[var(--tpl-text)]",
|
|
59
|
-
onClick: r[0] ||= (e) => B("close")
|
|
60
|
-
}, [s(o(T), {
|
|
61
|
-
size: 16,
|
|
62
|
-
"stroke-width": 2
|
|
63
|
-
})], 8, A)]),
|
|
64
|
-
g("div", j, [g("div", M, [g("label", N, _(o(K).linkDialog.urlLabel), 1), a(g("input", {
|
|
65
|
-
id: "tpl-link-dialog-url",
|
|
66
|
-
"onUpdate:modelValue": r[1] ||= (e) => i.value = e,
|
|
67
|
-
type: "url",
|
|
68
|
-
class: "tpl:w-full tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2.5 tpl:text-sm tpl:text-[var(--tpl-text)] tpl:transition-all tpl:outline-none tpl:placeholder:text-[var(--tpl-text-dim)] tpl:focus:border-[var(--tpl-primary)] tpl:focus:shadow-[0_0_0_3px_var(--tpl-primary-light)]",
|
|
69
|
-
placeholder: o(K).linkDialog.urlPlaceholder,
|
|
70
|
-
autofocus: "",
|
|
71
|
-
onKeydown: r[2] ||= (e) => B("keydown", e)
|
|
72
|
-
}, null, 40, P), [[h, i.value]])]), g("div", F, [g("label", I, _(o(K).linkDialog.colorLabel), 1), s(E, {
|
|
73
|
-
"model-value": v.value,
|
|
74
|
-
"seed-color": G.value,
|
|
75
|
-
"onUpdate:modelValue": r[3] ||= (e) => v.value = e
|
|
76
|
-
}, null, 8, ["model-value", "seed-color"])])]),
|
|
77
|
-
g("div", L, [e.isEditingLink ? (n(), u("button", {
|
|
78
|
-
key: 0,
|
|
79
|
-
type: "button",
|
|
80
|
-
class: "tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border tpl:border-[var(--tpl-danger)] tpl:bg-transparent tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:text-[var(--tpl-danger)] tpl:transition-all tpl:hover:bg-[var(--tpl-danger-light)]",
|
|
81
|
-
onClick: r[4] ||= (e) => B("remove")
|
|
82
|
-
}, _(o(K).linkDialog.removeLink), 1)) : d("", !0), g("div", R, [g("button", {
|
|
83
|
-
type: "button",
|
|
84
|
-
class: "tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-transparent tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-hover)] tpl:hover:text-[var(--tpl-text)]",
|
|
85
|
-
onClick: r[5] ||= (e) => B("close")
|
|
86
|
-
}, _(o(K).linkDialog.cancel), 1), g("button", {
|
|
87
|
-
type: "button",
|
|
88
|
-
class: "tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border-none tpl:bg-[var(--tpl-primary)] tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:transition-all tpl:hover:bg-[var(--tpl-primary-hover)] tpl:text-[var(--tpl-on-primary)]",
|
|
89
|
-
onClick: r[6] ||= (e) => B("insert")
|
|
90
|
-
}, _(e.isEditingLink ? o(K).linkDialog.updateLink : o(K).linkDialog.insertLink), 1)])])
|
|
91
|
-
], 512)], 12, D)) : d("", !0)], 8, ["to"])) : d("", !0);
|
|
92
|
-
}
|
|
93
|
-
}), B = {
|
|
94
|
-
key: 0,
|
|
95
|
-
class: "tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:border-[var(--tpl-primary)] tpl:p-2"
|
|
96
|
-
}, V = { class: "tpl:animate-pulse tpl:text-[var(--tpl-text-dim)]" }, H = {
|
|
97
|
-
key: 1,
|
|
98
|
-
class: "tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:p-2 tpl:text-center tpl:text-xs tpl:border-[var(--tpl-danger)] tpl:text-[var(--tpl-text-muted)]"
|
|
99
|
-
}, U = /* @__PURE__ */ i({
|
|
100
|
-
__name: "RichTextEditorContent",
|
|
101
|
-
props: {
|
|
102
|
-
editor: {},
|
|
103
|
-
editorContent: {},
|
|
104
|
-
isLoading: { type: Boolean },
|
|
105
|
-
initError: {}
|
|
106
|
-
},
|
|
107
|
-
emits: ["retry"],
|
|
108
|
-
setup(e, { emit: t }) {
|
|
109
|
-
let i = t, { t: a } = C();
|
|
110
|
-
return (t, s) => e.isLoading ? (n(), u("div", B, [g("div", V, _(o(a).errors.editorLoading), 1)])) : e.initError ? (n(), u("div", H, [v(_(o(a).errors.editorLoadFailed) + " ", 1), g("button", {
|
|
111
|
-
class: "tpl:ml-1 tpl:cursor-pointer tpl:border-none tpl:bg-transparent tpl:p-0 tpl:underline tpl:text-[var(--tpl-primary)]",
|
|
112
|
-
onClick: s[0] ||= (e) => i("retry")
|
|
113
|
-
}, _(o(a).errors.retry), 1)])) : e.editorContent && e.editor ? (n(), m(r(e.editorContent), {
|
|
114
|
-
key: 2,
|
|
115
|
-
editor: e.editor,
|
|
116
|
-
class: "tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:border-[var(--tpl-primary)] tpl:p-2"
|
|
117
|
-
}, null, 8, ["editor"])) : d("", !0);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
//#endregion
|
|
121
|
-
export { z as n, U as t };
|
|
122
|
-
|
|
123
|
-
//# sourceMappingURL=RichTextEditorContent-C1-5I8Df.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditorContent-C1-5I8Df.js","names":[],"sources":["../../../src/components/blocks/RichTextLinkDialog.vue","../../../src/components/blocks/RichTextLinkDialog.vue","../../../src/components/blocks/RichTextEditorContent.vue","../../../src/components/blocks/RichTextEditorContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables/useI18n\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport ColorPicker from \"../ColorPicker.vue\";\nimport { X } from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport { EDITOR_KEY, THEME_STYLES_KEY, UI_THEME_KEY } from \"../../keys\";\n\ndefineProps<{\n visible: boolean;\n isEditingLink: boolean;\n}>();\n\nconst linkUrl = defineModel<string>(\"linkUrl\", { required: true });\nconst linkColor = defineModel<string>(\"linkColor\", { default: \"\" });\nconst dialogRef = defineModel<HTMLElement | null>(\"dialogRef\", {\n required: true,\n});\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"insert\"): void;\n (e: \"remove\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\nconst editorReturn = inject(EDITOR_KEY, null);\n// Seed the picker at the document link color so opening it starts from the\n// color an unset link would inherit; an explicit value paints the swatch.\nconst documentLinkColor = computed(\n () => editorReturn?.content.value.settings.linkColor || \"#2c85de\",\n);\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl-link-dialog tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center\"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n >\n <div\n :ref=\"(el) => (dialogRef = el as HTMLElement | null)\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"tpl-link-dialog-title\"\n class=\"tpl:w-[400px] tpl:overflow-hidden tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow-lg)]\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-5 tpl:py-4\"\n >\n <h4\n id=\"tpl-link-dialog-title\"\n class=\"tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]\"\n >\n {{\n isEditingLink ? t.linkDialog.editLink : t.linkDialog.insertLink\n }}\n </h4>\n <button\n type=\"button\"\n :aria-label=\"t.linkDialog.cancel\"\n class=\"tpl:flex tpl:size-7 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-muted)] tpl:hover:bg-[var(--tpl-bg-hover)] tpl:hover:text-[var(--tpl-text)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"16\" :stroke-width=\"2\" />\n </button>\n </div>\n <div class=\"tpl:p-5\">\n <div class=\"tpl:mb-4 tpl:last:mb-0\">\n <label\n for=\"tpl-link-dialog-url\"\n class=\"tpl:mb-1.5 tpl:block tpl:text-xs tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase\"\n >{{ t.linkDialog.urlLabel }}</label\n >\n <input\n id=\"tpl-link-dialog-url\"\n v-model=\"linkUrl\"\n type=\"url\"\n class=\"tpl:w-full tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2.5 tpl:text-sm tpl:text-[var(--tpl-text)] tpl:transition-all tpl:outline-none tpl:placeholder:text-[var(--tpl-text-dim)] tpl:focus:border-[var(--tpl-primary)] tpl:focus:shadow-[0_0_0_3px_var(--tpl-primary-light)]\"\n :placeholder=\"t.linkDialog.urlPlaceholder\"\n autofocus\n @keydown=\"emit('keydown', $event)\"\n />\n </div>\n <div class=\"tpl:mb-4 tpl:last:mb-0\">\n <label\n class=\"tpl:mb-1.5 tpl:block tpl:text-xs tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase\"\n >{{ t.linkDialog.colorLabel }}</label\n >\n <ColorPicker\n :model-value=\"linkColor\"\n :seed-color=\"documentLinkColor\"\n @update:model-value=\"linkColor = $event\"\n />\n </div>\n </div>\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-t tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:px-5 tpl:py-4\"\n >\n <button\n v-if=\"isEditingLink\"\n type=\"button\"\n class=\"tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border tpl:border-[var(--tpl-danger)] tpl:bg-transparent tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:text-[var(--tpl-danger)] tpl:transition-all tpl:hover:bg-[var(--tpl-danger-light)]\"\n @click=\"emit('remove')\"\n >\n {{ t.linkDialog.removeLink }}\n </button>\n <div class=\"tpl:ml-auto tpl:flex tpl:gap-2\">\n <button\n type=\"button\"\n class=\"tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-transparent tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-hover)] tpl:hover:text-[var(--tpl-text)]\"\n @click=\"emit('close')\"\n >\n {{ t.linkDialog.cancel }}\n </button>\n <button\n type=\"button\"\n class=\"tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border-none tpl:bg-[var(--tpl-primary)] tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:transition-all tpl:hover:bg-[var(--tpl-primary-hover)] tpl:text-[var(--tpl-on-primary)]\"\n @click=\"emit('insert')\"\n >\n {{\n isEditingLink\n ? t.linkDialog.updateLink\n : t.linkDialog.insertLink\n }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables/useI18n\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport ColorPicker from \"../ColorPicker.vue\";\nimport { X } from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport { EDITOR_KEY, THEME_STYLES_KEY, UI_THEME_KEY } from \"../../keys\";\n\ndefineProps<{\n visible: boolean;\n isEditingLink: boolean;\n}>();\n\nconst linkUrl = defineModel<string>(\"linkUrl\", { required: true });\nconst linkColor = defineModel<string>(\"linkColor\", { default: \"\" });\nconst dialogRef = defineModel<HTMLElement | null>(\"dialogRef\", {\n required: true,\n});\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"insert\"): void;\n (e: \"remove\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\nconst editorReturn = inject(EDITOR_KEY, null);\n// Seed the picker at the document link color so opening it starts from the\n// color an unset link would inherit; an explicit value paints the swatch.\nconst documentLinkColor = computed(\n () => editorReturn?.content.value.settings.linkColor || \"#2c85de\",\n);\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl-link-dialog tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center\"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n >\n <div\n :ref=\"(el) => (dialogRef = el as HTMLElement | null)\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"tpl-link-dialog-title\"\n class=\"tpl:w-[400px] tpl:overflow-hidden tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow-lg)]\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-5 tpl:py-4\"\n >\n <h4\n id=\"tpl-link-dialog-title\"\n class=\"tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]\"\n >\n {{\n isEditingLink ? t.linkDialog.editLink : t.linkDialog.insertLink\n }}\n </h4>\n <button\n type=\"button\"\n :aria-label=\"t.linkDialog.cancel\"\n class=\"tpl:flex tpl:size-7 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-muted)] tpl:hover:bg-[var(--tpl-bg-hover)] tpl:hover:text-[var(--tpl-text)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"16\" :stroke-width=\"2\" />\n </button>\n </div>\n <div class=\"tpl:p-5\">\n <div class=\"tpl:mb-4 tpl:last:mb-0\">\n <label\n for=\"tpl-link-dialog-url\"\n class=\"tpl:mb-1.5 tpl:block tpl:text-xs tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase\"\n >{{ t.linkDialog.urlLabel }}</label\n >\n <input\n id=\"tpl-link-dialog-url\"\n v-model=\"linkUrl\"\n type=\"url\"\n class=\"tpl:w-full tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2.5 tpl:text-sm tpl:text-[var(--tpl-text)] tpl:transition-all tpl:outline-none tpl:placeholder:text-[var(--tpl-text-dim)] tpl:focus:border-[var(--tpl-primary)] tpl:focus:shadow-[0_0_0_3px_var(--tpl-primary-light)]\"\n :placeholder=\"t.linkDialog.urlPlaceholder\"\n autofocus\n @keydown=\"emit('keydown', $event)\"\n />\n </div>\n <div class=\"tpl:mb-4 tpl:last:mb-0\">\n <label\n class=\"tpl:mb-1.5 tpl:block tpl:text-xs tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase\"\n >{{ t.linkDialog.colorLabel }}</label\n >\n <ColorPicker\n :model-value=\"linkColor\"\n :seed-color=\"documentLinkColor\"\n @update:model-value=\"linkColor = $event\"\n />\n </div>\n </div>\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-t tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:px-5 tpl:py-4\"\n >\n <button\n v-if=\"isEditingLink\"\n type=\"button\"\n class=\"tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border tpl:border-[var(--tpl-danger)] tpl:bg-transparent tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:text-[var(--tpl-danger)] tpl:transition-all tpl:hover:bg-[var(--tpl-danger-light)]\"\n @click=\"emit('remove')\"\n >\n {{ t.linkDialog.removeLink }}\n </button>\n <div class=\"tpl:ml-auto tpl:flex tpl:gap-2\">\n <button\n type=\"button\"\n class=\"tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-transparent tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-hover)] tpl:hover:text-[var(--tpl-text)]\"\n @click=\"emit('close')\"\n >\n {{ t.linkDialog.cancel }}\n </button>\n <button\n type=\"button\"\n class=\"tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:rounded-md tpl:border-none tpl:bg-[var(--tpl-primary)] tpl:px-4 tpl:py-2 tpl:text-[13px] tpl:font-medium tpl:transition-all tpl:hover:bg-[var(--tpl-primary-hover)] tpl:text-[var(--tpl-on-primary)]\"\n @click=\"emit('insert')\"\n >\n {{\n isEditingLink\n ? t.linkDialog.updateLink\n : t.linkDialog.insertLink\n }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables/useI18n\";\nimport type { Editor } from \"@tiptap/vue-3\";\nimport type { Component } from \"vue\";\n\ndefineProps<{\n editor: Editor | null;\n editorContent: Component | null;\n isLoading: boolean;\n initError: string | null;\n}>();\n\nconst emit = defineEmits<{\n (e: \"retry\"): void;\n}>();\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <div\n v-if=\"isLoading\"\n class=\"tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:border-[var(--tpl-primary)] tpl:p-2\"\n >\n <div class=\"tpl:animate-pulse tpl:text-[var(--tpl-text-dim)]\">\n {{ t.errors.editorLoading }}\n </div>\n </div>\n <div\n v-else-if=\"initError\"\n class=\"tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:p-2 tpl:text-center tpl:text-xs tpl:border-[var(--tpl-danger)] tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.errors.editorLoadFailed }}\n <button\n class=\"tpl:ml-1 tpl:cursor-pointer tpl:border-none tpl:bg-transparent tpl:p-0 tpl:underline tpl:text-[var(--tpl-primary)]\"\n @click=\"emit('retry')\"\n >\n {{ t.errors.retry }}\n </button>\n </div>\n <component\n :is=\"editorContent\"\n v-else-if=\"editorContent && editor\"\n :editor=\"editor as Editor\"\n class=\"tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:border-[var(--tpl-primary)] tpl:p-2\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables/useI18n\";\nimport type { Editor } from \"@tiptap/vue-3\";\nimport type { Component } from \"vue\";\n\ndefineProps<{\n editor: Editor | null;\n editorContent: Component | null;\n isLoading: boolean;\n initError: string | null;\n}>();\n\nconst emit = defineEmits<{\n (e: \"retry\"): void;\n}>();\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <div\n v-if=\"isLoading\"\n class=\"tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:border-[var(--tpl-primary)] tpl:p-2\"\n >\n <div class=\"tpl:animate-pulse tpl:text-[var(--tpl-text-dim)]\">\n {{ t.errors.editorLoading }}\n </div>\n </div>\n <div\n v-else-if=\"initError\"\n class=\"tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:p-2 tpl:text-center tpl:text-xs tpl:border-[var(--tpl-danger)] tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.errors.editorLoadFailed }}\n <button\n class=\"tpl:ml-1 tpl:cursor-pointer tpl:border-none tpl:bg-transparent tpl:p-0 tpl:underline tpl:text-[var(--tpl-primary)]\"\n @click=\"emit('retry')\"\n >\n {{ t.errors.retry }}\n </button>\n </div>\n <component\n :is=\"editorContent\"\n v-else-if=\"editorContent && editor\"\n :editor=\"editor as Editor\"\n class=\"tpl-text-editable tpl:min-h-[1.5em] tpl:rounded tpl:border tpl:border-dashed tpl:border-[var(--tpl-primary)] tpl:p-2\"\n />\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TemplateScoringPanel-CroWaWqy.js","names":[],"sources":["../../../src/cloud/utils/scoringStyles.ts","../../../src/cloud/components/TemplateScoringPanel.vue","../../../src/cloud/components/TemplateScoringPanel.vue"],"sourcesContent":["export type ScoringSeverity = \"high\" | \"medium\" | \"low\" | string;\n\nexport function scoreColor(score: number): string {\n if (score >= 80) return \"var(--tpl-success)\";\n if (score >= 60) return \"var(--tpl-warning)\";\n return \"var(--tpl-danger)\";\n}\n\nexport function scoreBgColor(score: number): string {\n if (score >= 80) return \"var(--tpl-success-light)\";\n if (score >= 60) return \"var(--tpl-warning-light)\";\n return \"var(--tpl-danger-light)\";\n}\n\nexport function severityColor(severity: ScoringSeverity): string {\n if (severity === \"high\") return \"var(--tpl-danger)\";\n if (severity === \"medium\") return \"var(--tpl-warning)\";\n return \"var(--tpl-text-muted)\";\n}\n\nexport function severityBgColor(severity: ScoringSeverity): string {\n if (severity === \"high\") return \"var(--tpl-danger-light)\";\n if (severity === \"medium\") return \"var(--tpl-warning-light)\";\n return \"var(--tpl-bg-hover)\";\n}\n","<script setup lang=\"ts\">\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport {\n EDITOR_KEY,\n SCORING_KEY,\n MERGE_TAGS_KEY,\n requireInject,\n} from \"../../keys\";\nimport {\n scoreColor,\n scoreBgColor,\n severityColor,\n severityBgColor,\n} from \"../utils/scoringStyles\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { ScoringCategory, ScoringFinding } from \"@templatical/types\";\nimport {\n CircleAlert,\n TriangleAlert,\n ChevronDown,\n Eye,\n Info,\n LoaderCircle,\n RefreshCw,\n ShieldCheck,\n ShieldX,\n Sparkles,\n X,\n Zap,\n} from \"@lucide/vue\";\nimport { inject, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"TemplateScoringPanel\");\nconst scoring = requireInject(SCORING_KEY, \"TemplateScoringPanel\");\nconst mergeTags = inject(MERGE_TAGS_KEY, []);\n\nconst expandedCategories = ref<Record<string, boolean>>({\n spam: true,\n readability: true,\n accessibility: true,\n bestPractices: true,\n});\n\nfunction toggleCategory(category: string): void {\n expandedCategories.value[category] = !expandedCategories.value[category];\n}\n\nconst categoryOrder: ScoringCategory[] = [\n \"spam\",\n \"readability\",\n \"accessibility\",\n \"bestPractices\",\n];\n\nconst categoryIcons: Record<ScoringCategory, typeof ShieldCheck> = {\n spam: ShieldX,\n readability: Eye,\n accessibility: Sparkles,\n bestPractices: Zap,\n};\n\nfunction triggerScore(): void {\n scoring.score(editor.content.value, mergeTags);\n}\n\nwatch(\n () => props.visible,\n (isVisible) => {\n if (isVisible && !scoring.scoringResult.value && !scoring.isScoring.value) {\n triggerScore();\n }\n },\n);\n\nasync function handleFix(finding: ScoringFinding): Promise<void> {\n if (!finding.blockId) {\n return;\n }\n\n // Get the block content from the editor\n const block = editor.content.value.blocks.find(\n (b) => b.id === finding.blockId,\n );\n if (!block) {\n return;\n }\n\n // Extract HTML content from the block (text blocks have content property)\n const blockContent = (block as unknown as Record<string, unknown>).content as\n string | undefined;\n if (!blockContent) {\n return;\n }\n\n const fixedContent = await scoring.fixFinding(\n blockContent,\n finding,\n mergeTags,\n );\n\n if (fixedContent) {\n editor.updateBlock(finding.blockId, { content: fixedContent });\n scoring.removeFinding(finding.category, finding.id);\n }\n}\n\nfunction totalFindings(): number {\n if (!scoring.scoringResult.value) {\n return 0;\n }\n return categoryOrder.reduce((sum, cat) => {\n return (\n sum + (scoring.scoringResult.value?.categories[cat]?.findings.length ?? 0)\n );\n }, 0);\n}\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-scoring-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-scoring-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-scoring-panel tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ShieldCheck :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.scoring.title }}</span>\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-1\">\n <button\n v-if=\"scoring.scoringResult.value && !scoring.isScoring.value\"\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n :title=\"cloudT.scoring.rescore\"\n @click=\"triggerScore()\"\n >\n <RefreshCw :size=\"14\" :stroke-width=\"2\" />\n </button>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"scoring.isScoring.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.scoring.scoring }}\n </p>\n <LoadingTrack class=\"tpl:w-3/4\" />\n </div>\n\n <!-- Error state -->\n <div\n v-else-if=\"scoring.error.value && !scoring.scoringResult.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <CircleAlert\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-danger)]\"\n />\n <p\n class=\"tpl:max-w-[240px] tpl:text-sm tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.scoring.error }}\n </p>\n <button\n class=\"tpl:mt-2 tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text-muted)]\"\n @click=\"triggerScore()\"\n >\n <RefreshCw :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.scoring.rescore }}\n </button>\n </div>\n\n <!-- Results -->\n <div\n v-else-if=\"scoring.scoringResult.value\"\n class=\"tpl:flex tpl:flex-col tpl:gap-4\"\n >\n <!-- Overall score -->\n <div\n class=\"tpl:flex tpl:flex-col tpl:items-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:p-5\"\n :style=\"{\n backgroundColor: scoreBgColor(scoring.scoringResult.value.score),\n }\"\n >\n <span\n class=\"tpl:text-4xl tpl:font-bold tpl:tabular-nums\"\n :style=\"{\n color: scoreColor(scoring.scoringResult.value.score),\n }\"\n >\n {{ scoring.scoringResult.value.score }}\n </span>\n <span\n class=\"tpl:text-xs tpl:font-medium tpl:uppercase tpl:tracking-wider tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.scoring.overallScore }}\n </span>\n <span\n v-if=\"totalFindings() > 0\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ totalFindings() }}\n {{ cloudT.scoring.findings }}\n </span>\n </div>\n\n <!-- Fix error -->\n <div\n v-if=\"scoring.fixError.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.scoring.fixError }}</span>\n </div>\n\n <!-- Category cards -->\n <div\n v-for=\"category in categoryOrder\"\n :key=\"category\"\n class=\"tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)]\"\n >\n <!-- Category header -->\n <button\n class=\"tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:gap-2.5 tpl:px-3 tpl:py-2.5 tpl:text-left tpl:transition-colors tpl:bg-[var(--tpl-bg)]\"\n @click=\"toggleCategory(category)\"\n >\n <component\n :is=\"categoryIcons[category]\"\n :size=\"14\"\n :stroke-width=\"2\"\n :style=\"{\n color: scoreColor(\n scoring.scoringResult.value.categories[category].score,\n ),\n }\"\n />\n <span\n class=\"tpl:flex-1 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]\"\n >\n {{ cloudT.scoring.categories[category] }}\n </span>\n <span\n class=\"tpl:rounded-full tpl:px-2 tpl:py-0.5 tpl:text-xs tpl:font-semibold tpl:tabular-nums\"\n :style=\"{\n color: scoreColor(\n scoring.scoringResult.value.categories[category].score,\n ),\n backgroundColor: scoreBgColor(\n scoring.scoringResult.value.categories[category].score,\n ),\n }\"\n >\n {{ scoring.scoringResult.value.categories[category].score }}\n </span>\n <span\n v-if=\"\n scoring.scoringResult.value.categories[category].findings\n .length > 0\n \"\n class=\"tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n scoring.scoringResult.value.categories[category].findings\n .length\n }}\n </span>\n <ChevronDown\n :size=\"12\"\n :stroke-width=\"2\"\n class=\"tpl:transition-transform tpl:duration-200 tpl:text-[var(--tpl-text-dim)]\"\n :class=\"\n expandedCategories[category]\n ? 'tpl:rotate-0'\n : 'tpl:-rotate-90'\n \"\n />\n </button>\n\n <!-- Findings list -->\n <div\n v-if=\"expandedCategories[category]\"\n class=\"tpl:border-t tpl:border-[var(--tpl-border)]\"\n >\n <div\n v-if=\"\n scoring.scoringResult.value.categories[category].findings\n .length === 0\n \"\n class=\"tpl:px-3 tpl:py-3 tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.scoring.noFindings }}\n </div>\n <div\n v-for=\"finding in scoring.scoringResult.value.categories[\n category\n ].findings\"\n :key=\"finding.id\"\n class=\"tpl:border-t tpl:px-3 tpl:py-2.5 tpl:first:border-t-0 tpl:border-[var(--tpl-border-light)]\"\n >\n <div class=\"tpl:flex tpl:items-start tpl:gap-2\">\n <!-- Severity icon -->\n <component\n :is=\"\n finding.severity === 'high'\n ? CircleAlert\n : finding.severity === 'medium'\n ? TriangleAlert\n : Info\n \"\n :size=\"13\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n :style=\"{\n color: severityColor(finding.severity),\n }\"\n />\n <div class=\"tpl:flex-1 tpl:min-w-0\">\n <!-- Severity badge + message -->\n <div class=\"tpl:flex tpl:items-start tpl:gap-1.5\">\n <span\n class=\"tpl:mt-0.5 tpl:shrink-0 tpl:rounded tpl:px-1 tpl:py-px tpl:text-[10px] tpl:font-medium tpl:leading-tight\"\n :style=\"{\n color: severityColor(finding.severity),\n backgroundColor: severityBgColor(finding.severity),\n }\"\n >\n {{ cloudT.scoring.severity[finding.severity] }}\n </span>\n <span\n class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\"\n >\n {{ finding.message }}\n </span>\n </div>\n <!-- Suggestion -->\n <p\n v-if=\"finding.suggestion\"\n class=\"tpl:mt-1 tpl:text-[11px] tpl:leading-snug tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ finding.suggestion }}\n </p>\n <!-- Fix button -->\n <div\n v-if=\"finding.blockId\"\n class=\"tpl:mt-2 tpl:flex tpl:justify-center\"\n >\n <button\n class=\"tpl-scoring-fix-btn tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded tpl:border tpl:px-3 tpl:py-1.5 tpl:text-[11px] tpl:font-medium tpl:transition-all tpl:disabled:opacity-50 tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-primary)]\"\n style=\"background-color: transparent\"\n :disabled=\"scoring.fixingFindingId.value !== null\"\n @click=\"handleFix(finding)\"\n >\n <LoaderCircle\n v-if=\"scoring.fixingFindingId.value === finding.id\"\n class=\"tpl-spinner\"\n :size=\"11\"\n :stroke-width=\"2\"\n />\n <Sparkles v-else :size=\"11\" :stroke-width=\"2\" />\n {{\n scoring.fixingFindingId.value === finding.id\n ? cloudT.scoring.fixing\n : cloudT.scoring.fix\n }}\n </button>\n <p\n v-if=\"scoring.fixError.value\"\n class=\"tpl:mt-1.5 tpl:text-[11px] tpl:text-[var(--tpl-danger)]\"\n >\n {{ scoring.fixError.value }}\n </p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Empty state (no result, no loading, no error) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <ShieldCheck\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <p\n class=\"tpl:max-w-[240px] tpl:text-sm tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.scoring.emptyState }}\n </p>\n </div>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:px-4 tpl:pb-2 tpl:pt-2 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-scoring-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-scoring-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-scoring-fix-btn:not(:disabled):hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport {\n EDITOR_KEY,\n SCORING_KEY,\n MERGE_TAGS_KEY,\n requireInject,\n} from \"../../keys\";\nimport {\n scoreColor,\n scoreBgColor,\n severityColor,\n severityBgColor,\n} from \"../utils/scoringStyles\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { ScoringCategory, ScoringFinding } from \"@templatical/types\";\nimport {\n CircleAlert,\n TriangleAlert,\n ChevronDown,\n Eye,\n Info,\n LoaderCircle,\n RefreshCw,\n ShieldCheck,\n ShieldX,\n Sparkles,\n X,\n Zap,\n} from \"@lucide/vue\";\nimport { inject, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"TemplateScoringPanel\");\nconst scoring = requireInject(SCORING_KEY, \"TemplateScoringPanel\");\nconst mergeTags = inject(MERGE_TAGS_KEY, []);\n\nconst expandedCategories = ref<Record<string, boolean>>({\n spam: true,\n readability: true,\n accessibility: true,\n bestPractices: true,\n});\n\nfunction toggleCategory(category: string): void {\n expandedCategories.value[category] = !expandedCategories.value[category];\n}\n\nconst categoryOrder: ScoringCategory[] = [\n \"spam\",\n \"readability\",\n \"accessibility\",\n \"bestPractices\",\n];\n\nconst categoryIcons: Record<ScoringCategory, typeof ShieldCheck> = {\n spam: ShieldX,\n readability: Eye,\n accessibility: Sparkles,\n bestPractices: Zap,\n};\n\nfunction triggerScore(): void {\n scoring.score(editor.content.value, mergeTags);\n}\n\nwatch(\n () => props.visible,\n (isVisible) => {\n if (isVisible && !scoring.scoringResult.value && !scoring.isScoring.value) {\n triggerScore();\n }\n },\n);\n\nasync function handleFix(finding: ScoringFinding): Promise<void> {\n if (!finding.blockId) {\n return;\n }\n\n // Get the block content from the editor\n const block = editor.content.value.blocks.find(\n (b) => b.id === finding.blockId,\n );\n if (!block) {\n return;\n }\n\n // Extract HTML content from the block (text blocks have content property)\n const blockContent = (block as unknown as Record<string, unknown>).content as\n string | undefined;\n if (!blockContent) {\n return;\n }\n\n const fixedContent = await scoring.fixFinding(\n blockContent,\n finding,\n mergeTags,\n );\n\n if (fixedContent) {\n editor.updateBlock(finding.blockId, { content: fixedContent });\n scoring.removeFinding(finding.category, finding.id);\n }\n}\n\nfunction totalFindings(): number {\n if (!scoring.scoringResult.value) {\n return 0;\n }\n return categoryOrder.reduce((sum, cat) => {\n return (\n sum + (scoring.scoringResult.value?.categories[cat]?.findings.length ?? 0)\n );\n }, 0);\n}\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-scoring-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-scoring-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-scoring-panel tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ShieldCheck :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.scoring.title }}</span>\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-1\">\n <button\n v-if=\"scoring.scoringResult.value && !scoring.isScoring.value\"\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n :title=\"cloudT.scoring.rescore\"\n @click=\"triggerScore()\"\n >\n <RefreshCw :size=\"14\" :stroke-width=\"2\" />\n </button>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"scoring.isScoring.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.scoring.scoring }}\n </p>\n <LoadingTrack class=\"tpl:w-3/4\" />\n </div>\n\n <!-- Error state -->\n <div\n v-else-if=\"scoring.error.value && !scoring.scoringResult.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <CircleAlert\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-danger)]\"\n />\n <p\n class=\"tpl:max-w-[240px] tpl:text-sm tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.scoring.error }}\n </p>\n <button\n class=\"tpl:mt-2 tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text-muted)]\"\n @click=\"triggerScore()\"\n >\n <RefreshCw :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.scoring.rescore }}\n </button>\n </div>\n\n <!-- Results -->\n <div\n v-else-if=\"scoring.scoringResult.value\"\n class=\"tpl:flex tpl:flex-col tpl:gap-4\"\n >\n <!-- Overall score -->\n <div\n class=\"tpl:flex tpl:flex-col tpl:items-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:p-5\"\n :style=\"{\n backgroundColor: scoreBgColor(scoring.scoringResult.value.score),\n }\"\n >\n <span\n class=\"tpl:text-4xl tpl:font-bold tpl:tabular-nums\"\n :style=\"{\n color: scoreColor(scoring.scoringResult.value.score),\n }\"\n >\n {{ scoring.scoringResult.value.score }}\n </span>\n <span\n class=\"tpl:text-xs tpl:font-medium tpl:uppercase tpl:tracking-wider tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.scoring.overallScore }}\n </span>\n <span\n v-if=\"totalFindings() > 0\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ totalFindings() }}\n {{ cloudT.scoring.findings }}\n </span>\n </div>\n\n <!-- Fix error -->\n <div\n v-if=\"scoring.fixError.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.scoring.fixError }}</span>\n </div>\n\n <!-- Category cards -->\n <div\n v-for=\"category in categoryOrder\"\n :key=\"category\"\n class=\"tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)]\"\n >\n <!-- Category header -->\n <button\n class=\"tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:gap-2.5 tpl:px-3 tpl:py-2.5 tpl:text-left tpl:transition-colors tpl:bg-[var(--tpl-bg)]\"\n @click=\"toggleCategory(category)\"\n >\n <component\n :is=\"categoryIcons[category]\"\n :size=\"14\"\n :stroke-width=\"2\"\n :style=\"{\n color: scoreColor(\n scoring.scoringResult.value.categories[category].score,\n ),\n }\"\n />\n <span\n class=\"tpl:flex-1 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]\"\n >\n {{ cloudT.scoring.categories[category] }}\n </span>\n <span\n class=\"tpl:rounded-full tpl:px-2 tpl:py-0.5 tpl:text-xs tpl:font-semibold tpl:tabular-nums\"\n :style=\"{\n color: scoreColor(\n scoring.scoringResult.value.categories[category].score,\n ),\n backgroundColor: scoreBgColor(\n scoring.scoringResult.value.categories[category].score,\n ),\n }\"\n >\n {{ scoring.scoringResult.value.categories[category].score }}\n </span>\n <span\n v-if=\"\n scoring.scoringResult.value.categories[category].findings\n .length > 0\n \"\n class=\"tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n scoring.scoringResult.value.categories[category].findings\n .length\n }}\n </span>\n <ChevronDown\n :size=\"12\"\n :stroke-width=\"2\"\n class=\"tpl:transition-transform tpl:duration-200 tpl:text-[var(--tpl-text-dim)]\"\n :class=\"\n expandedCategories[category]\n ? 'tpl:rotate-0'\n : 'tpl:-rotate-90'\n \"\n />\n </button>\n\n <!-- Findings list -->\n <div\n v-if=\"expandedCategories[category]\"\n class=\"tpl:border-t tpl:border-[var(--tpl-border)]\"\n >\n <div\n v-if=\"\n scoring.scoringResult.value.categories[category].findings\n .length === 0\n \"\n class=\"tpl:px-3 tpl:py-3 tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.scoring.noFindings }}\n </div>\n <div\n v-for=\"finding in scoring.scoringResult.value.categories[\n category\n ].findings\"\n :key=\"finding.id\"\n class=\"tpl:border-t tpl:px-3 tpl:py-2.5 tpl:first:border-t-0 tpl:border-[var(--tpl-border-light)]\"\n >\n <div class=\"tpl:flex tpl:items-start tpl:gap-2\">\n <!-- Severity icon -->\n <component\n :is=\"\n finding.severity === 'high'\n ? CircleAlert\n : finding.severity === 'medium'\n ? TriangleAlert\n : Info\n \"\n :size=\"13\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n :style=\"{\n color: severityColor(finding.severity),\n }\"\n />\n <div class=\"tpl:flex-1 tpl:min-w-0\">\n <!-- Severity badge + message -->\n <div class=\"tpl:flex tpl:items-start tpl:gap-1.5\">\n <span\n class=\"tpl:mt-0.5 tpl:shrink-0 tpl:rounded tpl:px-1 tpl:py-px tpl:text-[10px] tpl:font-medium tpl:leading-tight\"\n :style=\"{\n color: severityColor(finding.severity),\n backgroundColor: severityBgColor(finding.severity),\n }\"\n >\n {{ cloudT.scoring.severity[finding.severity] }}\n </span>\n <span\n class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\"\n >\n {{ finding.message }}\n </span>\n </div>\n <!-- Suggestion -->\n <p\n v-if=\"finding.suggestion\"\n class=\"tpl:mt-1 tpl:text-[11px] tpl:leading-snug tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ finding.suggestion }}\n </p>\n <!-- Fix button -->\n <div\n v-if=\"finding.blockId\"\n class=\"tpl:mt-2 tpl:flex tpl:justify-center\"\n >\n <button\n class=\"tpl-scoring-fix-btn tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded tpl:border tpl:px-3 tpl:py-1.5 tpl:text-[11px] tpl:font-medium tpl:transition-all tpl:disabled:opacity-50 tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-primary)]\"\n style=\"background-color: transparent\"\n :disabled=\"scoring.fixingFindingId.value !== null\"\n @click=\"handleFix(finding)\"\n >\n <LoaderCircle\n v-if=\"scoring.fixingFindingId.value === finding.id\"\n class=\"tpl-spinner\"\n :size=\"11\"\n :stroke-width=\"2\"\n />\n <Sparkles v-else :size=\"11\" :stroke-width=\"2\" />\n {{\n scoring.fixingFindingId.value === finding.id\n ? cloudT.scoring.fixing\n : cloudT.scoring.fix\n }}\n </button>\n <p\n v-if=\"scoring.fixError.value\"\n class=\"tpl:mt-1.5 tpl:text-[11px] tpl:text-[var(--tpl-danger)]\"\n >\n {{ scoring.fixError.value }}\n </p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Empty state (no result, no loading, no error) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <ShieldCheck\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <p\n class=\"tpl:max-w-[240px] tpl:text-sm tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.scoring.emptyState }}\n </p>\n </div>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:px-4 tpl:pb-2 tpl:pt-2 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-scoring-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-scoring-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-scoring-fix-btn:not(:disabled):hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TitleEditor-DvXUW2j-.js","names":[],"sources":["../../../src/components/blocks/TitleEditor.vue","../../../src/components/blocks/TitleEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables\";\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { TitleBlock as TitleBlockType } from \"@templatical/types\";\nimport {\n Bold,\n Braces,\n Italic,\n Link,\n LoaderCircle,\n ScanLine,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n} from \"../../keys\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: TitleBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\n// Hide the floating toolbar while either built-in picker modal is open — see\n// ParagraphToolbar.vue for the same rationale.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"TitleEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { MergeTagNode, MergeTagSuggestion, LogicMergeTagNode, LineBoundaryKeys },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n strike: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n }),\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n LineBoundaryKeys,\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.titleEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:absolute tpl:z-popover tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-[var(--tpl-shadow-lg)]\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Bold -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('bold'),\n }\"\n :aria-label=\"t.titleEditor.bold\"\n :title=\"t.titleEditor.bold\"\n @click=\"editor?.chain().focus().toggleBold().run()\"\n >\n <Bold :size=\"16\" :stroke-width=\"2.5\" />\n </button>\n <!-- Italic -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('italic'),\n }\"\n :aria-label=\"t.titleEditor.italic\"\n :title=\"t.titleEditor.italic\"\n @click=\"editor?.chain().focus().toggleItalic().run()\"\n >\n <Italic :size=\"16\" :stroke-width=\"2\" />\n </button>\n <span\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n aria-hidden=\"true\"\n ></span>\n <!-- Link -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('link'),\n }\"\n :aria-label=\"t.titleEditor.addLink\"\n :title=\"t.titleEditor.addLink\"\n @click=\"openLinkDialog\"\n >\n <Link :size=\"16\" :stroke-width=\"2\" />\n </button>\n <!-- Add Merge Tag -->\n <span\n v-if=\"canRequestMergeTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canRequestMergeTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"handleAddMergeTag\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n <!-- Insert Logic -->\n <span\n v-if=\"canInsertLogicTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canInsertLogicTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"handleAddLogicTag\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables\";\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { TitleBlock as TitleBlockType } from \"@templatical/types\";\nimport {\n Bold,\n Braces,\n Italic,\n Link,\n LoaderCircle,\n ScanLine,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n} from \"../../keys\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: TitleBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\n// Hide the floating toolbar while either built-in picker modal is open — see\n// ParagraphToolbar.vue for the same rationale.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"TitleEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { MergeTagNode, MergeTagSuggestion, LogicMergeTagNode, LineBoundaryKeys },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n strike: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n }),\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n LineBoundaryKeys,\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.titleEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:absolute tpl:z-popover tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-[var(--tpl-shadow-lg)]\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Bold -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('bold'),\n }\"\n :aria-label=\"t.titleEditor.bold\"\n :title=\"t.titleEditor.bold\"\n @click=\"editor?.chain().focus().toggleBold().run()\"\n >\n <Bold :size=\"16\" :stroke-width=\"2.5\" />\n </button>\n <!-- Italic -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('italic'),\n }\"\n :aria-label=\"t.titleEditor.italic\"\n :title=\"t.titleEditor.italic\"\n @click=\"editor?.chain().focus().toggleItalic().run()\"\n >\n <Italic :size=\"16\" :stroke-width=\"2\" />\n </button>\n <span\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n aria-hidden=\"true\"\n ></span>\n <!-- Link -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('link'),\n }\"\n :aria-label=\"t.titleEditor.addLink\"\n :title=\"t.titleEditor.addLink\"\n @click=\"openLinkDialog\"\n >\n <Link :size=\"16\" :stroke-width=\"2\" />\n </button>\n <!-- Add Merge Tag -->\n <span\n v-if=\"canRequestMergeTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canRequestMergeTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"handleAddMergeTag\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n <!-- Insert Logic -->\n <span\n v-if=\"canInsertLogicTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canInsertLogicTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"handleAddLogicTag\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TplModal-X-qNoLGZ.js","names":[],"sources":["../../../src/components/TplModal.vue","../../../src/components/TplModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFocusTrap } from \"../composables\";\nimport { usePopoverRoot } from \"../composables/usePopoverRoot\";\nimport { THEME_STYLES_KEY, UI_THEME_KEY } from \"../keys\";\nimport { computed, inject, ref } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst dialogRef = ref<HTMLElement | null>(null);\nconst isVisible = computed(() => props.visible);\nuseFocusTrap(dialogRef, isVisible);\n\nconst tplUiTheme = inject(UI_THEME_KEY);\n\n// The backdrop below carries the bare `tpl` class, which re-declares every\n// `--tpl-*` token from the base `.tpl` rule. A custom property declared on an\n// element beats one inherited from an ancestor, so that re-declaration shadows\n// the consumer's `theme` config — which lives as inline styles on the editor\n// root — for this whole teleported subtree. Re-applying `themeStyles` here is\n// what restores it, and doing it on the backdrop covers every dialog rendered\n// through this wrapper rather than each one remembering to. `data-tpl-theme`\n// does the same job for the dark token block. See the invariant in\n// `tests/theme-token-scope.test.ts` (issue #487).\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst popoverRoot = usePopoverRoot();\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Escape\") {\n emit(\"close\");\n }\n emit(\"keydown\", event);\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <Transition\n enter-active-class=\"tpl:transition\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <!-- The backdrop is the reference box every slotted panel caps against,\n which is why it owns the gutter (`p-4`) rather than each panel\n carrying its own margin. `inset-0` gives it a definite height; the\n wrapper below spans that height so a panel's percentage cap\n (`max-h-[90%]` / `max-h-[80%]`) has an unbroken chain to resolve\n through. Those numbers are the `vh` values they replaced, so an\n untrapped editor renders exactly as before.\n\n Panels must never cap in `vh`. `fixed` covers the viewport only while\n nothing traps it, and an ancestor with `transform`, `filter`,\n `backdrop-filter`, `will-change: transform`, `contain: paint`,\n `container-type` or a transform animation becomes the containing\n block for fixed descendants. The editor is embedded in someone\n else's page, so any of those can sit above it: `inset-0` then\n resolves to that ancestor's box while a `vh` cap still resolves to\n the viewport, and the panel overflows a container that usually also\n has `overflow: hidden`. That is issue #575 — in a 420px host inside a\n 720px viewport, a 648px panel clipped ~113px off both the top and the\n bottom, with no scrollbar to reach the buttons. Capping against the\n backdrop is self-correcting whether or not the trap is present.\n Locked by `tests/overlay-height-scope.test.ts`.\n\n The padding belongs here and not on the wrapper: preflight is\n omitted, so non-form elements keep `content-box` and padding on an\n `h-full` element would add to 100% and overflow by exactly the\n padding (the trap behind issue #115). Insets size the backdrop's\n border box, so padding here safely shrinks the content box instead. -->\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center tpl:p-4\"\n style=\"\n background-color: var(--tpl-overlay);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n @keydown=\"handleKeydown\"\n >\n <!-- `h-full` only, deliberately no `w-full`: height is what has to\n become definite, and widening this element would change what\n `w-full` on a panel resolves against. Panels are shrink-to-fit\n horizontally — the test-email dialog stays compact until its\n preview opens, and the saved-blocks browser pins an explicit width\n precisely because this wrapper is shrink-to-fit. Constraining one\n axis leaves all of that intact.\n\n It repeats `@click.self` because it now covers the backdrop's full\n height: clicks in the gap above or below the panel land here, so\n without it click-outside-to-close would only work on the padding\n ring and the columns either side. -->\n <div\n ref=\"dialogRef\"\n class=\"tpl:flex tpl:h-full tpl:items-center tpl:justify-center\"\n @click.self=\"emit('close')\"\n >\n <slot />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { useFocusTrap } from \"../composables\";\nimport { usePopoverRoot } from \"../composables/usePopoverRoot\";\nimport { THEME_STYLES_KEY, UI_THEME_KEY } from \"../keys\";\nimport { computed, inject, ref } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst dialogRef = ref<HTMLElement | null>(null);\nconst isVisible = computed(() => props.visible);\nuseFocusTrap(dialogRef, isVisible);\n\nconst tplUiTheme = inject(UI_THEME_KEY);\n\n// The backdrop below carries the bare `tpl` class, which re-declares every\n// `--tpl-*` token from the base `.tpl` rule. A custom property declared on an\n// element beats one inherited from an ancestor, so that re-declaration shadows\n// the consumer's `theme` config — which lives as inline styles on the editor\n// root — for this whole teleported subtree. Re-applying `themeStyles` here is\n// what restores it, and doing it on the backdrop covers every dialog rendered\n// through this wrapper rather than each one remembering to. `data-tpl-theme`\n// does the same job for the dark token block. See the invariant in\n// `tests/theme-token-scope.test.ts` (issue #487).\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst popoverRoot = usePopoverRoot();\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Escape\") {\n emit(\"close\");\n }\n emit(\"keydown\", event);\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <Transition\n enter-active-class=\"tpl:transition\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <!-- The backdrop is the reference box every slotted panel caps against,\n which is why it owns the gutter (`p-4`) rather than each panel\n carrying its own margin. `inset-0` gives it a definite height; the\n wrapper below spans that height so a panel's percentage cap\n (`max-h-[90%]` / `max-h-[80%]`) has an unbroken chain to resolve\n through. Those numbers are the `vh` values they replaced, so an\n untrapped editor renders exactly as before.\n\n Panels must never cap in `vh`. `fixed` covers the viewport only while\n nothing traps it, and an ancestor with `transform`, `filter`,\n `backdrop-filter`, `will-change: transform`, `contain: paint`,\n `container-type` or a transform animation becomes the containing\n block for fixed descendants. The editor is embedded in someone\n else's page, so any of those can sit above it: `inset-0` then\n resolves to that ancestor's box while a `vh` cap still resolves to\n the viewport, and the panel overflows a container that usually also\n has `overflow: hidden`. That is issue #575 — in a 420px host inside a\n 720px viewport, a 648px panel clipped ~113px off both the top and the\n bottom, with no scrollbar to reach the buttons. Capping against the\n backdrop is self-correcting whether or not the trap is present.\n Locked by `tests/overlay-height-scope.test.ts`.\n\n The padding belongs here and not on the wrapper: preflight is\n omitted, so non-form elements keep `content-box` and padding on an\n `h-full` element would add to 100% and overflow by exactly the\n padding (the trap behind issue #115). Insets size the backdrop's\n border box, so padding here safely shrinks the content box instead. -->\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center tpl:p-4\"\n style=\"\n background-color: var(--tpl-overlay);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n @keydown=\"handleKeydown\"\n >\n <!-- `h-full` only, deliberately no `w-full`: height is what has to\n become definite, and widening this element would change what\n `w-full` on a panel resolves against. Panels are shrink-to-fit\n horizontally — the test-email dialog stays compact until its\n preview opens, and the saved-blocks browser pins an explicit width\n precisely because this wrapper is shrink-to-fit. Constraining one\n axis leaves all of that intact.\n\n It repeats `@click.self` because it now covers the backdrop's full\n height: clicks in the gap above or below the panel land here, so\n without it click-outside-to-close would only work on the padding\n ring and the columns either side. -->\n <div\n ref=\"dialogRef\"\n class=\"tpl:flex tpl:h-full tpl:items-center tpl:justify-center\"\n @click.self=\"emit('close')\"\n >\n <slot />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;EAMA,IAAM,IAAQ,GAIR,IAAO,GAKP,IAAY,EAAwB,IAAI,GACxC,IAAY,QAAe,EAAM,OAAO;EAC9C,EAAa,GAAW,CAAS;EAEjC,IAAM,IAAa,EAAO,CAAY,GAWhC,IAAc,EAAO,GAAkB,IAAI,GAC3C,IAAc,EAAe;EAEnC,SAAS,EAAc,GAA4B;GAIjD,AAHI,EAAM,QAAQ,YAChB,EAAK,OAAO,GAEd,EAAK,WAAW,CAAK;EACvB;mBAIkB,EAAA,CAAA,KAAhB,EAAA,GAAA,EAsEW,GAAA;;GAtEmB,IAAI,EAAA,CAAA;EAChC,GAAA,CAAA,EAoEa,GAAA;GAnEX,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;GACf,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;;GA6Bf,SAAA,QAgCM,CA/BE,EAAA,WADR,EAAA,GAAA,EAgCM,OAAA;;IA9BH,kBAAgB,EAAA,CAAA;IACjB,OAAM;IACN,OAIC,EAAA,CAJD;KAAA,oBAAA;KAAA,mBAAA;KAAA,2BAAA;IAAA,GAKQ,EAAA,CAAA,CAAW,CAAA;IAClB,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,EAAI,OAAA,GAAA,CAAA,MAAA,CAAA;IAChB,WAAS;GAcV,GAAA,CAAA,EAMM,OAAA;IALA,SAAA;IAAJ,KAAI;IACJ,OAAM;IACL,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,EAAI,OAAA,GAAA,CAAA,MAAA,CAAA;GAEjB,GAAA,CAAA,EAAQ,EAAA,QAAA,SAAA,CAAA,GAAA,GAAA,CAAA,GAAA,IAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { E as e } from "./draggable-kbOhCgnk.js";
|
|
2
|
-
//#region src/keys.ts
|
|
3
|
-
var t = Symbol("translations"), n = Symbol("editor"), r = Symbol("history"), i = Symbol("blockActions"), a = Symbol("conditionPreview"), o = Symbol("appliesConditionFilter"), s = Symbol("fontsManager"), c = Symbol("themeStyles"), l = Symbol("tplUiTheme"), u = Symbol("tplUiLocale"), d = Symbol("blockDefaults"), f = Symbol("blockRegistry"), p = Symbol("customBlockDefinitions"), m = Symbol("paletteBlocks"), h = Symbol("htmlBlockPreview"), g = Symbol("colors"), _ = Symbol("customBlockStylesheets"), v = Symbol("mergeTags"), y = Symbol("mergeTagSyntax"), b = Symbol("onRequestMergeTag"), x = Symbol("mergeTagAutocomplete"), S = Symbol("mergeTagSampleMode"), C = Symbol("useMergeTagSamples"), w = Symbol("resolvePreview"), T = Symbol("previewResolution"), E = Symbol("mergeTagPicker"), D = Symbol("logicTags"), O = Symbol("logicPairs"), k = Symbol("logicPicker"), A = Symbol("onRequestLogic"), j = Symbol("onRequestMedia"), M = Symbol("imageUrlResolver"), N = Symbol("displayConditions"), P = Symbol("allowCustomConditions"), F = Symbol("capabilities"), I = Symbol("keyboardReorder"), L = Symbol("templateLint"), R = Symbol("editorRoot"), z = Symbol("popoverRoot"), B = Symbol("savedBlocks"), V = Symbol("authManager"), H = Symbol("aiConfig"), U = Symbol("scoring"), W = Symbol("cloudTranslations");
|
|
4
|
-
function G(t, n) {
|
|
5
|
-
let r = e(t, null);
|
|
6
|
-
if (r == null) throw Error(`${n} requires a provider for ${t.description ?? "unknown key"}. Ensure it renders inside the editor, below Editor.vue.`);
|
|
7
|
-
return r;
|
|
8
|
-
}
|
|
9
|
-
//#endregion
|
|
10
|
-
export { A, c as B, D as C, E as D, x as E, T as F, G, u as H, w as I, B as L, b as M, m as N, S as O, z as P, U as R, O as S, v as T, l as U, t as V, C as W, s as _, i as a, M as b, F as c, a as d, p as f, R as g, n as h, V as i, j, y as k, W as l, N as m, P as n, d as o, _ as p, o as r, f as s, H as t, g as u, r as v, k as w, I as x, h as y, L as z };
|
|
11
|
-
|
|
12
|
-
//# sourceMappingURL=keys-BOn5i9jV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"keys-BOn5i9jV.js","names":[],"sources":["../../../src/keys.ts"],"sourcesContent":["import { inject, type InjectionKey, type ComputedRef, type Ref } from \"vue\";\nimport type {\n UseHistoryReturn,\n UseBlockActionsReturn,\n UseConditionPreviewReturn,\n} from \"@templatical/core\";\nimport type {\n BlockDefaults,\n CustomBlockDefinition,\n DisplayCondition,\n LogicPair,\n LogicTag,\n MergeTag,\n ResolvePreview,\n SyntaxPreset,\n} from \"@templatical/types\";\nimport type { Translations, CloudTranslations } from \"./i18n\";\nimport type {\n AuthManager,\n UseAiConfigReturn,\n UseTemplateScoringReturn,\n} from \"@templatical/core/cloud\";\nimport type { UseSavedBlocksReturn } from \"@templatical/core\";\nimport type { BaseEditorReturn } from \"./composables/useEditorCore\";\nimport type { ImageUrlResolver } from \"./composables/useImageUrlResolver\";\nimport type { UseFontsReturn } from \"./composables/useFonts\";\nimport type { UseBlockRegistryReturn } from \"./composables/useBlockRegistry\";\nimport type { UseKeyboardReorderReturn } from \"./composables/useKeyboardReorder\";\nimport type { EditorCapabilities } from \"./types/editor-capabilities\";\nimport type { OnRequestMedia } from \"./index\";\n\n// ---------------------------------------------------------------------------\n// Shared keys (provided by useEditorCore, consumed by all components)\n// ---------------------------------------------------------------------------\n\nexport const TRANSLATIONS_KEY: InjectionKey<Translations> =\n Symbol(\"translations\");\n\nexport const EDITOR_KEY: InjectionKey<BaseEditorReturn> = Symbol(\"editor\");\n\nexport const HISTORY_KEY: InjectionKey<UseHistoryReturn> = Symbol(\"history\");\n\nexport const BLOCK_ACTIONS_KEY: InjectionKey<UseBlockActionsReturn> =\n Symbol(\"blockActions\");\n\nexport const CONDITION_PREVIEW_KEY: InjectionKey<UseConditionPreviewReturn> =\n Symbol(\"conditionPreview\");\n\n/**\n * Whether the hand-toggled display-condition filter applies on this surface —\n * provided per-surface, exactly like `USE_MERGE_TAG_SAMPLES_KEY`, and for the\n * same reason: the rule folds in both `previewMode` and whether a resolver owns\n * the preview, so a component that re-derived it from `CONDITION_PREVIEW_KEY`\n * plus the editor's `previewMode` could get one half wrong on its own.\n *\n * Absent means \"applies\" — a surface with no provider filters as it always has.\n */\nexport const APPLIES_CONDITION_FILTER_KEY: InjectionKey<ComputedRef<boolean>> =\n Symbol(\"appliesConditionFilter\");\n\nexport const FONTS_MANAGER_KEY: InjectionKey<UseFontsReturn> =\n Symbol(\"fontsManager\");\n\nexport const THEME_STYLES_KEY: InjectionKey<\n ComputedRef<Record<string, string>>\n> = Symbol(\"themeStyles\");\n\nexport const UI_THEME_KEY: InjectionKey<ComputedRef<string>> =\n Symbol(\"tplUiTheme\");\n\n/**\n * The editor's UI locale, exactly as the consumer passed it to\n * `init({ locale })` — unresolved, so it may be unsupported or malformed.\n *\n * For `Intl` formatting only. Translated *strings* come from\n * `TRANSLATIONS_KEY`, which is already resolved to a supported bundle; this is\n * for the labels `Intl` builds itself (dates), where the browser's own locale\n * would otherwise win and disagree with the surrounding chrome. Always format\n * through `formatAbsoluteDateTime`, which guards the malformed case.\n *\n * Not the template's `settings.locale` — that is the *email's* language and\n * belongs to content, not chrome.\n */\nexport const UI_LOCALE_KEY: InjectionKey<string | undefined> =\n Symbol(\"tplUiLocale\");\n\n// A ref, not a plain object: the recipient-facing half of these defaults\n// (video alt, countdown labels) tracks the template's own `settings.locale`,\n// which the author can change while the editor is open. Read it at insert\n// time — a value destructured at setup goes stale.\nexport const BLOCK_DEFAULTS_KEY: InjectionKey<ComputedRef<BlockDefaults>> =\n Symbol(\"blockDefaults\");\n\nexport const BLOCK_REGISTRY_KEY: InjectionKey<UseBlockRegistryReturn> =\n Symbol(\"blockRegistry\");\n\nexport const CUSTOM_BLOCK_DEFINITIONS_KEY: InjectionKey<\n CustomBlockDefinition[]\n> = Symbol(\"customBlockDefinitions\");\n\n/**\n * Consumer-supplied block-palette allowlist + order (`config.paletteBlocks`).\n * `undefined` means the default full palette. Consumed by `Sidebar.vue`.\n */\nexport const PALETTE_BLOCKS_KEY: InjectionKey<string[] | undefined> =\n Symbol(\"paletteBlocks\");\n\n/**\n * Whether HTML blocks render a live sandboxed-iframe preview in the canvas\n * (`config.htmlBlockPreview`), normalized to a boolean. `false` (the default)\n * keeps the static placeholder card. Consumed by `HtmlBlock.vue`.\n */\nexport const HTML_BLOCK_PREVIEW_KEY: InjectionKey<boolean> =\n Symbol(\"htmlBlockPreview\");\n\n/**\n * Consumer-supplied color-picker palette (`config.colors`), normalized to\n * `{ presets, allowCustom, allowCustomIgnored }` by `resolveColorsConfig`.\n * Provided by `useEditorCore`, consumed by every `ColorPicker`. The inject\n * default (`DEFAULT_RESOLVED_COLORS` = `{ presets: [], allowCustom: true,\n * allowCustomIgnored: false }`) makes an unconfigured picker render exactly\n * as before.\n */\nexport const COLORS_KEY: InjectionKey<\n import(\"./utils/resolveColorsConfig\").ResolvedColors\n> = Symbol(\"colors\");\n\nexport const CUSTOM_BLOCK_STYLESHEETS_KEY: InjectionKey<ComputedRef<string[]>> =\n Symbol(\"customBlockStylesheets\");\n\nexport const MERGE_TAGS_KEY: InjectionKey<MergeTag[]> = Symbol(\"mergeTags\");\n\nexport const MERGE_TAG_SYNTAX_KEY: InjectionKey<SyntaxPreset> =\n Symbol(\"mergeTagSyntax\");\n\nexport const ON_REQUEST_MERGE_TAG_KEY: InjectionKey<\n (() => Promise<MergeTag | null>) | null\n> = Symbol(\"onRequestMergeTag\");\n\nexport const MERGE_TAG_AUTOCOMPLETE_KEY: InjectionKey<boolean> = Symbol(\n \"mergeTagAutocomplete\",\n);\n\n/**\n * The user's choice between the previews' two merge-tag views: `true` for\n * Sample (tags replaced by their `MergeTag.sample`, rendered as ordinary text)\n * and `false` for Label (tags shown as their label with the usual cue).\n *\n * Session state owned by `useEditorCore` and driven by a toggle that exists\n * only on preview surfaces. Defaults to Sample.\n */\nexport const MERGE_TAG_SAMPLE_MODE_KEY: InjectionKey<Ref<boolean>> =\n Symbol(\"mergeTagSampleMode\");\n\n/**\n * Whether **the current render surface** substitutes samples.\n *\n * Provided per surface rather than globally, and that is the whole point:\n * substitution must never happen while editing, so `Canvas.vue` folds in its\n * `previewMode` flag and provides `false` whenever the canvas is editable, no\n * matter what the mode ref says. Preview surfaces provide the mode directly.\n *\n * Block components inject **this** key. They must never read\n * `MERGE_TAG_SAMPLE_MODE_KEY`, which would bypass the editing guard.\n */\nexport const USE_MERGE_TAG_SAMPLES_KEY: InjectionKey<ComputedRef<boolean>> =\n Symbol(\"useMergeTagSamples\");\n\n/**\n * The `resolvePreview` seam — resolved content plus its loading and failure\n * state. Provided by `useEditorCore` so every preview surface shares one\n * lifecycle; `null` when the consumer configured no hook.\n *\n * Surfaces read `content` from here instead of `editor.content`, and gate the\n * Sample/Label toggle on `supersedesSamples`.\n */\n/**\n * The raw `config.resolvePreview` hook.\n *\n * Provided alongside PREVIEW_RESOLUTION_KEY because the test-email dialog needs\n * its **own** resolution instance — it resolves for the selected recipient,\n * which the editor's canvas has no notion of — and so cannot reuse the shared\n * one. `undefined` when the consumer configured no hook.\n */\nexport const RESOLVE_PREVIEW_KEY: InjectionKey<ResolvePreview | undefined> =\n Symbol(\"resolvePreview\");\n\nexport const PREVIEW_RESOLUTION_KEY: InjectionKey<\n import(\"./composables/usePreviewResolution\").UsePreviewResolutionReturn | null\n> = Symbol(\"previewResolution\");\n\n/**\n * Singleton state for the built-in merge tag picker modal. Provided by\n * `useEditorCore`, consumed by `useMergeTag.requestMergeTag()` (to open\n * the modal as a fall-through when only `mergeTags.tags` is configured)\n * and by `MergeTagPickerModal.vue` (to render and resolve).\n */\nexport const MERGE_TAG_PICKER_KEY: InjectionKey<\n import(\"./composables/useMergeTagPicker\").UseMergeTagPickerReturn\n> = Symbol(\"mergeTagPicker\");\n\n// ---------------------------------------------------------------------------\n// Logic tags — a standalone feature, separate from merge tags. Native\n// highlighting (LogicMergeTagNode) is always on; these drive the dedicated\n// logic picker + insertion.\n// ---------------------------------------------------------------------------\n\nexport const LOGIC_TAGS_KEY: InjectionKey<LogicTag[]> = Symbol(\"logicTags\");\n\nexport const LOGIC_PAIRS_KEY: InjectionKey<LogicPair[]> = Symbol(\"logicPairs\");\n\n/**\n * Singleton state for the built-in logic picker modal. Provided by\n * `useEditorCore`, consumed by `useLogicTag.requestLogicTag()` (to open the modal)\n * and by `LogicTagPickerModal.vue` (to render and resolve).\n */\nexport const LOGIC_TAG_PICKER_KEY: InjectionKey<\n import(\"./composables/useLogicTagPicker\").UseLogicTagPickerReturn\n> = Symbol(\"logicPicker\");\n\nexport const ON_REQUEST_LOGIC_TAG_KEY: InjectionKey<\n (() => Promise<LogicTag | LogicPair | null>) | null\n> = Symbol(\"onRequestLogic\");\n\nexport const ON_REQUEST_MEDIA_KEY: InjectionKey<OnRequestMedia | null> =\n Symbol(\"onRequestMedia\");\n\n/**\n * Per-editor display-only image URL resolver (`config.resolveImageUrl`),\n * wrapped with a per-src cache by `createImageUrlResolver`. `null` when the\n * host doesn't resolve — the canvas then displays canonical src values\n * verbatim. Consumed via `useResolvedImageSrc` in image-displaying blocks.\n */\nexport const IMAGE_URL_RESOLVER_KEY: InjectionKey<ImageUrlResolver | null> =\n Symbol(\"imageUrlResolver\");\n\nexport const DISPLAY_CONDITIONS_KEY: InjectionKey<DisplayCondition[]> =\n Symbol(\"displayConditions\");\n\nexport const ALLOW_CUSTOM_CONDITIONS_KEY: InjectionKey<boolean> = Symbol(\n \"allowCustomConditions\",\n);\n\nexport const CAPABILITIES_KEY: InjectionKey<EditorCapabilities> =\n Symbol(\"capabilities\");\n\nexport const KEYBOARD_REORDER_KEY: InjectionKey<UseKeyboardReorderReturn> =\n Symbol(\"keyboardReorder\");\n\nexport const TEMPLATE_LINT_KEY: InjectionKey<\n import(\"./composables/useTemplateLint\").UseTemplateLintReturn | null\n> = Symbol(\"templateLint\");\n\n/**\n * The editor's effective DOM root — `Document` in light-DOM mode, `ShadowRoot`\n * when `shadowDom: true`. Composables that read `document.activeElement`,\n * popup mount targets, etc. should inject this and use the root-aware API\n * (both `Document` and `ShadowRoot` expose `activeElement` etc.).\n */\nexport const EDITOR_ROOT_KEY: InjectionKey<Document | ShadowRoot> =\n Symbol(\"editorRoot\");\n\n/**\n * Mount target for popovers, toolbars, and modal dialogs — never\n * `document.body`. Provided by `useEditorCore` as a ref bound\n * to a `<div class=\"tpl-popover-root\" />` rendered at the top level of the\n * editor template. Teleports use `:to=\"popoverRoot\"` so popups land inside\n * the editor's effective root — `document` in light-DOM mode, `ShadowRoot`\n * when `shadowDom: true` — instead of escaping the shadow boundary.\n *\n * Null until the editor's template mounts; consumers must guard with\n * `v-if=\"popoverRoot\"` before passing to `<Teleport>`.\n */\nexport const POPOVER_ROOT_KEY: InjectionKey<Ref<HTMLElement | null>> =\n Symbol(\"popoverRoot\");\n\n/**\n * Reactive saved-blocks state, provided by `useSavedBlocksFeature` when a\n * `SavedBlocksProvider` is configured. Shared by OSS and Cloud — the storage\n * transport lives behind the provider, so this key is not cloud-specific.\n */\nexport const SAVED_BLOCKS_KEY: InjectionKey<UseSavedBlocksReturn> =\n Symbol(\"savedBlocks\");\n\n// ---------------------------------------------------------------------------\n// Cloud-only keys (provided by createCloudRuntime, consumed by cloud components)\n// ---------------------------------------------------------------------------\n\nexport const AUTH_MANAGER_KEY: InjectionKey<AuthManager> =\n Symbol(\"authManager\");\n\nexport const AI_CONFIG_KEY: InjectionKey<UseAiConfigReturn> =\n Symbol(\"aiConfig\");\n\n// Comments are deliberately not injected: the panel takes `useCommentsFeature`'s\n// return as a **prop** the way `TestEmailPanel` and `SavedBlocksPanels` do, and the\n// per-block indicators read the comments entry on `CAPABILITIES_KEY`. Nothing\n// injects the composable itself.\n\nexport const SCORING_KEY: InjectionKey<UseTemplateScoringReturn> =\n Symbol(\"scoring\");\n\nexport const CLOUD_TRANSLATIONS_KEY: InjectionKey<CloudTranslations> =\n Symbol(\"cloudTranslations\");\n\n// ---------------------------------------------------------------------------\n// Helper for required injections with explicit null default + throw\n// ---------------------------------------------------------------------------\n\nexport function requireInject<T>(\n key: InjectionKey<T>,\n componentName: string,\n): T {\n const value = inject(key, null) as T | null;\n if (value === null || value === undefined) {\n throw new Error(\n `${componentName} requires a provider for ${key.description ?? \"unknown key\"}. Ensure it renders inside the editor, below Editor.vue.`,\n );\n }\n return value;\n}\n"],"mappings":";;AAmCA,IAAa,IACX,OAAO,cAAc,GAEV,IAA6C,OAAO,QAAQ,GAE5D,IAA8C,OAAO,SAAS,GAE9D,IACX,OAAO,cAAc,GAEV,IACX,OAAO,kBAAkB,GAWd,IACX,OAAO,wBAAwB,GAEpB,IACX,OAAO,cAAc,GAEV,IAET,OAAO,aAAa,GAEX,IACX,OAAO,YAAY,GAeR,IACX,OAAO,aAAa,GAMT,IACX,OAAO,eAAe,GAEX,IACX,OAAO,eAAe,GAEX,IAET,OAAO,wBAAwB,GAMtB,IACX,OAAO,eAAe,GAOX,IACX,OAAO,kBAAkB,GAUd,IAET,OAAO,QAAQ,GAEN,IACX,OAAO,wBAAwB,GAEpB,IAA2C,OAAO,WAAW,GAE7D,IACX,OAAO,gBAAgB,GAEZ,IAET,OAAO,mBAAmB,GAEjB,IAAoD,OAC/D,sBACF,GAUa,IACX,OAAO,oBAAoB,GAahB,IACX,OAAO,oBAAoB,GAkBhB,IACX,OAAO,gBAAgB,GAEZ,IAET,OAAO,mBAAmB,GAQjB,IAET,OAAO,gBAAgB,GAQd,IAA2C,OAAO,WAAW,GAE7D,IAA6C,OAAO,YAAY,GAOhE,IAET,OAAO,aAAa,GAEX,IAET,OAAO,gBAAgB,GAEd,IACX,OAAO,gBAAgB,GAQZ,IACX,OAAO,kBAAkB,GAEd,IACX,OAAO,mBAAmB,GAEf,IAAqD,OAChE,uBACF,GAEa,IACX,OAAO,cAAc,GAEV,IACX,OAAO,iBAAiB,GAEb,IAET,OAAO,cAAc,GAQZ,IACX,OAAO,YAAY,GAaR,IACX,OAAO,aAAa,GAOT,IACX,OAAO,aAAa,GAMT,IACX,OAAO,aAAa,GAET,IACX,OAAO,UAAU,GAON,IACX,OAAO,SAAS,GAEL,IACX,OAAO,mBAAmB;AAM5B,SAAgB,EACd,GACA,GACG;CACH,IAAM,IAAQ,EAAO,GAAK,IAAI;CAC9B,IAAI,KAAU,MACZ,MAAU,MACR,GAAG,EAAc,2BAA2B,EAAI,eAAe,cAAc,yDAC/E;CAEF,OAAO;AACT"}
|