kindy-editor 3.2.1 → 3.2.2

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.
@@ -1,4 +1,4 @@
1
- import { a as j, j as _, A as F, t as k, D as L } from "./toc-DSwkNKls.js";
1
+ import { a as j, j as _, A as F, t as k, D as L } from "./toc-C6XLbDEA.js";
2
2
  const s = (e) => Math.round(e * 100) / 100;
3
3
  function A(e) {
4
4
  const o = { font: e.fontFamily, sizePx: e.fontSizePx };
@@ -332,7 +332,7 @@ function H(e, o = {}, r = {}) {
332
332
  if (i && e.search(i).total === 0)
333
333
  return e.searchClear(), f(`text not found: ${i}`);
334
334
  if (!e.getSelection()) return f("no selection (pass 'find' or select_range first)");
335
- const { insertText: d } = await import("./editorApp-7-JzxxVn.js").then((m) => m.c);
335
+ const { insertText: d } = await import("./editorApp-N20nk5uQ.js").then((m) => m.c);
336
336
  return e.dispatch(d(t)), i && e.searchClear(), g("inserted");
337
337
  }
338
338
  }), a({
@@ -6,6 +6,7 @@ export default defineConfig({
6
6
  themeConfig: {
7
7
  nav: [
8
8
  { text: 'Home', link: '/' },
9
+ { text: 'Template Variables', link: '/template-variables' },
9
10
  { text: 'Fonts & CDN', link: '/fonts' },
10
11
  { text: 'Table editing', link: '/table-editing' },
11
12
  { text: 'Public Events', link: '/public-events' },
@@ -16,6 +17,7 @@ export default defineConfig({
16
17
  text: 'Integration & Events',
17
18
  items: [
18
19
  { text: 'Overview', link: '/' },
20
+ { text: 'Template Variables & Metadata', link: '/template-variables' },
19
21
  { text: 'Fonts & CDN', link: '/fonts' },
20
22
  { text: 'Table editing', link: '/table-editing' },
21
23
  { text: 'Public Events API', link: '/public-events' },
@@ -98,6 +98,7 @@ general-purpose analytics services.
98
98
  | Export | `document.export.*` |
99
99
  | Changes | `document.change.applied`, `document.change.committed`, `document.change.rejected`, `document.remoteChange.applied` |
100
100
  | Review | `review.operation.applied`, `review.suggestion.*`, `review.thread.*`, `review.comment.*` |
101
+ | Template & Metadata | `template.variable.clicked`, `template.variable.changed`, `template.displayMode.changed` |
101
102
  | Collaboration | `collaboration.connecting`, `collaboration.connected`, `collaboration.disconnected`, `collaboration.user.*`, `collaboration.presence.changed` |
102
103
  | Other | `document.shared`, `selection.changed`, `custom` |
103
104
 
@@ -0,0 +1,310 @@
1
+ # Template Variables & Contract Metadata API
2
+
3
+ Kindy Editor hỗ trợ quản lý các **biến mẫu (Template Variables)** và **Metadata Hợp đồng** trực tiếp trong mô hình tài liệu (AST level).
4
+
5
+ Các biến mẫu được liên kết chặt chẽ với văn bản thông qua thuộc tính `CharStyle.variableKey`, đảm bảo tính toàn vẹn (atomic tokens), hỗ trợ định dạng tự động theo kiểu dữ liệu (`TEXT`, `NUMBER`, `DATE`, `CURRENCY`, `SELECT`), và cung cấp hệ thống event phong phú để host application (React, Vue, Angular, v.v.) tự do dựng giao diện popover/drawer theo design system riêng.
6
+
7
+ ---
8
+
9
+ ## 1. Khởi tạo & Cấu hình (Options)
10
+
11
+ Khi khởi tạo `KindyEditor`, bạn có thể cấu hình các tùy chọn liên quan đến biến mẫu:
12
+
13
+ ```ts
14
+ import { KindyEditor } from "kindy-editor";
15
+ import type { VariableClickInfo } from "kindy-editor";
16
+
17
+ const editor = new KindyEditor({
18
+ container: document.getElementById("editor-container")!,
19
+
20
+ // Callback khi người dùng click vào một biến mẫu trong văn bản
21
+ onVariableClick: (info: VariableClickInfo) => {
22
+ console.log("Clicked variable:", info.key, info.def);
23
+ // info.clientRect chứa tọa độ viewport { top, left, width, height }
24
+ // để host app hiển thị Popover / Drawer / Modal tùy biến
25
+ },
26
+
27
+ // Có hiển thị Popover mặc định của editor không (mặc định: false)
28
+ // Nếu đặt là false, host app toàn quyền hiển thị UI qua onVariableClick
29
+ showVariablePopover: false,
30
+ });
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 2. Các phương thức của Editor API (`EditorHandle` / `KindyEditor`)
36
+
37
+ Tất cả các phương thức sau có thể gọi thông qua instance của `KindyEditor` hoặc thông qua `handle` nhận được từ `onReady` / `editor.ready`:
38
+
39
+ ### 2.1. `setTemplateVariables(values, options?)`
40
+ Cập nhật giá trị hàng loạt biến mà không cần reload tài liệu. Trạng thái con trỏ, lịch sử undo/redo và vị trí scroll đều được bảo toàn.
41
+
42
+ ```ts
43
+ await editor.setTemplateVariables(
44
+ {
45
+ contract_code: "HD-2026/001",
46
+ contract_value: 25000000,
47
+ signing_date: "2026-10-04",
48
+ customer_name: "Công ty Cổ phần Công nghệ ABC",
49
+ },
50
+ {
51
+ author: { id: "user-1", firstName: "Hùng", lastName: "Ngô" },
52
+ source: "sidebar", // "api" | "editor" | "sidebar" | "inline" | "import" | "palette"
53
+ }
54
+ );
55
+ ```
56
+
57
+ ### 2.2. `insertTemplateVariable(item, author?)`
58
+ Chèn một token biến mẫu atomic tại vị trí con trỏ hiện tại (hoặc thay thế vùng chọn hiện tại).
59
+
60
+ ```ts
61
+ await editor.insertTemplateVariable(
62
+ {
63
+ key: "contract_value",
64
+ label: "Giá trị hợp đồng",
65
+ dataType: "CURRENCY",
66
+ value: 50000000,
67
+ defaultValue: "{{contract_value}}",
68
+ group: "TAI_CHINH",
69
+ metadataId: 102,
70
+ },
71
+ { id: "user-1", firstName: "Hùng", lastName: "Ngô" }
72
+ );
73
+ ```
74
+
75
+ ### 2.3. `setVariableDisplayMode(mode)` & `getVariableDisplayMode()`
76
+ Thay đổi chế độ hiển thị biến trên toàn bộ văn bản:
77
+ * `'code'` / `'placeholder'`: Hiển thị mã placeholder, ví dụ `{{contract_code}}`. Thích hợp khi soạn thảo mẫu hợp đồng (Template Editor).
78
+ * `'value'`: Hiển thị giá trị thực tế sau khi đã format theo `dataType`, ví dụ `HD-2026/001` hoặc `25.000.000 VNĐ`. Nếu biến chưa có giá trị, tự động fallback về mã placeholder.
79
+ * `'label'`: Hiển thị nhãn tiếng Việt của biến.
80
+
81
+ ```ts
82
+ // Chuyển sang hiển thị giá trị thực tế
83
+ await editor.setVariableDisplayMode("value");
84
+
85
+ // Đọc chế độ hiện tại
86
+ const currentMode = await editor.getVariableDisplayMode(); // "value" | "code"
87
+ ```
88
+
89
+ ### 2.4. `getTemplateVariables()` & `getTemplateVariable(key)`
90
+ Truy vấn danh sách hoặc chi tiết các biến đã đăng ký trong tài liệu.
91
+
92
+ ```ts
93
+ // Lấy toàn bộ biến đã đăng ký
94
+ const allVariables = await editor.getTemplateVariables();
95
+ console.log(allVariables["contract_code"]);
96
+
97
+ // Lấy 1 biến cụ thể
98
+ const codeVar = await editor.getTemplateVariable("contract_code");
99
+ ```
100
+
101
+ ### 2.5. `getUsedMetadataIds()`
102
+ Trả về danh sách các `metadataId` (ID số định danh từ cơ sở dữ liệu backend) hiện đang thực sự được nhúng trong tài liệu. Rất hữu ích cho backend khi cần kiểm tra những metadata nào đang được văn bản sử dụng.
103
+
104
+ ```ts
105
+ const usedIds = await editor.getUsedMetadataIds();
106
+ // Ví dụ: [101, 102, 105]
107
+ ```
108
+
109
+ ### 2.6. `setMetadataCatalog(catalog)` & `openMetadataPalette()`
110
+ Cung cấp danh mục các biến từ backend cho tính năng gợi ý autocomplete (`@`), hoặc chủ động mở thanh tìm kiếm biến tại vị trí con trỏ.
111
+
112
+ ```ts
113
+ // Cung cấp danh mục biến cho autocomplete
114
+ await editor.setMetadataCatalog([
115
+ {
116
+ key: "contract_code",
117
+ label: "Mã hợp đồng",
118
+ dataType: "TEXT",
119
+ group: "THONG_TIN_CHUNG",
120
+ metadataId: 1,
121
+ },
122
+ {
123
+ key: "contract_value",
124
+ label: "Giá trị hợp đồng",
125
+ dataType: "CURRENCY",
126
+ group: "TAI_CHINH",
127
+ metadataId: 2,
128
+ },
129
+ {
130
+ key: "effective_date",
131
+ label: "Ngày hiệu lực",
132
+ dataType: "DATE",
133
+ dateFormat: "dd/MM/yyyy",
134
+ group: "THOI_HAN",
135
+ metadataId: 3,
136
+ },
137
+ ]);
138
+
139
+ // Chủ động mở bảng chọn @ tại vị trí con trỏ
140
+ await editor.openMetadataPalette();
141
+ ```
142
+
143
+ ---
144
+
145
+ ## 3. Public Events API
146
+
147
+ Lắng nghe các sự kiện liên quan đến Template Variables thông qua `editor.on(...)`:
148
+
149
+ ### 3.1. `template.variable.clicked`
150
+ Kích hoạt khi người dùng click vào một biến mẫu trong văn bản:
151
+
152
+ ```ts
153
+ editor.on("template.variable.clicked", (event) => {
154
+ const { key, def, position, rect, clientRect } = event.data;
155
+
156
+ console.log(`Clicked variable: ${key}`);
157
+ console.log(`Current value:`, def.value);
158
+ console.log(`Bounding Box trên màn hình:`, clientRect);
159
+ // clientRect: { left, top, right, bottom, width, height }
160
+ // Dùng để định vị floating popover/tooltip cạnh biến vừa click
161
+ });
162
+ ```
163
+
164
+ ### 3.2. `template.variable.changed`
165
+ Kích hoạt khi một biến được tạo mới, cập nhật giá trị hoặc hoàn tác:
166
+
167
+ ```ts
168
+ editor.on("template.variable.changed", (event) => {
169
+ const { key, newValue, previousValue, action, source, def } = event.data;
170
+ console.log(`Variable ${key} was ${action} from source ${source}`);
171
+ console.log(`Old: ${previousValue} -> New: ${newValue}`);
172
+ });
173
+ ```
174
+
175
+ ### 3.3. `template.displayMode.changed`
176
+ Kích hoạt khi chế độ hiển thị biến thay đổi:
177
+
178
+ ```ts
179
+ editor.on("template.displayMode.changed", (event) => {
180
+ const { mode, previousMode } = event.data;
181
+ console.log(`Display mode changed from ${previousMode} to ${mode}`);
182
+ });
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 4. Định dạng tự động theo Kiểu dữ liệu (`MetadataDataType`)
188
+
189
+ Khi ở chế độ `value`, hàm định dạng tự động chuyển đổi giá trị dựa vào trường `dataType`:
190
+
191
+ | `dataType` | Ví dụ đầu vào | Kết quả hiển thị |
192
+ | :--- | :--- | :--- |
193
+ | `TEXT` | `"Hà Nội"` | `Hà Nội` |
194
+ | `NUMBER` | `1500000` | `1.500.000` (định dạng theo locale vi-VN) |
195
+ | `CURRENCY` | `25000000` | `25.000.000 VNĐ` |
196
+ | `DATE` | `"2026-10-04"` | `04/10/2026` (hỗ trợ `dateFormat: "dd/MM/yyyy"` hoặc `"yyyy-MM-dd"`) |
197
+ | `SELECT` | `"Đã ký"` | `Đã ký` |
198
+
199
+ ---
200
+
201
+ ## 5. Tương tác Người dùng (UX & Hành vi gõ phím)
202
+
203
+ 1. **Kích hoạt Autocomplete qua `@`**:
204
+ - Khi gõ ký tự `@` ở đầu dòng hoặc sau một khoảng trắng, bảng **Metadata Palette** sẽ tự động mở ra.
205
+ - Người dùng có thể dùng các phím mũi tên `↑` `↓` để duyệt, `Enter` hoặc `Tab` để chèn, và `Escape` để đóng.
206
+ - Gõ email (ví dụ: `sales@gmail.com`) sẽ **không** bị kích hoạt bảng chọn vì trước `@` không phải là khoảng trắng.
207
+
208
+ 2. **Tính chất Atomic Token**:
209
+ - Khi bấm phím `Backspace` hoặc `Delete` tại biên của biến, toàn bộ token biến sẽ được xóa sạch trong một thao tác (thay vì xóa từng ký tự placeholder).
210
+ - Khi gõ phím tiếp theo ngay sau một biến, văn bản mới sẽ tự động nhận style thông thường và không bị dính thuộc tính `variableKey`.
211
+ - Khi click vào biến, văn bản của biến sẽ tự động được chọn toàn bộ.
212
+
213
+ ---
214
+
215
+ ## 6. Ví dụ Tích hợp với React
216
+
217
+ ```tsx
218
+ import React, { useEffect, useRef, useState } from "react";
219
+ import { KindyEditor, type VariableClickInfo } from "kindy-editor";
220
+ import "kindy-editor/style";
221
+
222
+ export function ContractEditor() {
223
+ const containerRef = useRef<HTMLDivElement>(null);
224
+ const editorRef = useRef<KindyEditor | null>(null);
225
+ const [selectedVar, setSelectedVar] = useState<VariableClickInfo | null>(null);
226
+
227
+ useEffect(() => {
228
+ if (!containerRef.current) return;
229
+
230
+ const editor = new KindyEditor({
231
+ container: containerRef.current,
232
+ showVariablePopover: false, // tắt popup mặc định để dùng React Popover
233
+ onVariableClick: (info) => {
234
+ setSelectedVar(info);
235
+ },
236
+ });
237
+
238
+ editorRef.current = editor;
239
+
240
+ // Lắng nghe sự kiện click ra ngoài để đóng popover
241
+ const handleMouseDown = (e: MouseEvent) => {
242
+ if (!(e.target as HTMLElement).closest(".custom-variable-popover")) {
243
+ setSelectedVar(null);
244
+ }
245
+ };
246
+ window.addEventListener("mousedown", handleMouseDown);
247
+
248
+ return () => {
249
+ window.removeEventListener("mousedown", handleMouseDown);
250
+ editor.destroy();
251
+ };
252
+ }, []);
253
+
254
+ return (
255
+ <div style={{ position: "relative", width: "100%", height: "100vh" }}>
256
+ {/* Editor Canvas Container */}
257
+ <div ref={containerRef} style={{ width: "100%", height: "100%" }} />
258
+
259
+ {/* Custom React Floating Popover */}
260
+ {selectedVar && selectedVar.clientRect && (
261
+ <div
262
+ className="custom-variable-popover"
263
+ style={{
264
+ position: "fixed",
265
+ left: `${selectedVar.clientRect.left}px`,
266
+ top: `${selectedVar.clientRect.bottom + 8}px`,
267
+ background: "#ffffff",
268
+ border: "1px solid #e2e8f0",
269
+ borderRadius: "8px",
270
+ boxShadow: "0 10px 15px -3px rgba(0,0,0,0.1)",
271
+ padding: "12px 16px",
272
+ zIndex: 1000,
273
+ minWidth: "260px",
274
+ }}
275
+ >
276
+ <div style={{ fontWeight: "bold", color: "#0284c7" }}>
277
+ {selectedVar.def.label} ({`{{${selectedVar.key}}}`})
278
+ </div>
279
+ <div style={{ fontSize: "12px", color: "#64748b", marginTop: "4px" }}>
280
+ Loại: {selectedVar.def.dataType}
281
+ </div>
282
+ <div style={{ fontSize: "14px", marginTop: "6px" }}>
283
+ Giá trị: <strong>{String(selectedVar.def.value ?? "Chưa có")}</strong>
284
+ </div>
285
+ <button
286
+ onClick={() => {
287
+ const nextVal = prompt("Nhập giá trị mới:", String(selectedVar.def.value ?? ""));
288
+ if (nextVal !== null) {
289
+ editorRef.current?.setTemplateVariables({ [selectedVar.key]: nextVal });
290
+ setSelectedVar(null);
291
+ }
292
+ }}
293
+ style={{
294
+ marginTop: "8px",
295
+ padding: "4px 8px",
296
+ background: "#0284c7",
297
+ color: "#fff",
298
+ border: "none",
299
+ borderRadius: "4px",
300
+ cursor: "pointer",
301
+ }}
302
+ >
303
+ Chỉnh sửa giá trị
304
+ </button>
305
+ </div>
306
+ )}
307
+ </div>
308
+ );
309
+ }
310
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kindy-editor",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "type": "module",
5
5
  "description": "Trình soạn thảo tài liệu Word chính xác, vẽ bằng canvas",
6
6
  "license": "MIT",
@@ -54,7 +54,71 @@ export interface RevealRangeOptions {
54
54
  align?: "center" | "nearest" | "top" | "bottom";
55
55
  }
56
56
 
57
- export type TemplateVariableValues = Record<string, string | number | null | undefined>;
57
+ export type TemplateVariableValues = Record<string, string | number | boolean | null | undefined>;
58
+
59
+ export type MetadataDataType = "TEXT" | "NUMBER" | "DATE" | "CURRENCY" | "SELECT";
60
+ export type VariableDisplayMode = "code" | "value" | "placeholder" | "label";
61
+
62
+ export interface VariableBoundingBox {
63
+ left: number;
64
+ top: number;
65
+ right: number;
66
+ bottom: number;
67
+ width: number;
68
+ height: number;
69
+ }
70
+
71
+ export interface VariableClickInfo {
72
+ key: string;
73
+ def: TemplateVariableDef;
74
+ position: DocPosition;
75
+ rect: VariableBoundingBox;
76
+ clientRect?: VariableBoundingBox;
77
+ }
78
+
79
+ export interface MetadataAuditEntry {
80
+ id: string;
81
+ author: UserInfo;
82
+ timestamp: number;
83
+ previousValue: unknown;
84
+ newValue: unknown;
85
+ action: "created" | "updated" | "reverted";
86
+ source?: "api" | "editor" | "sidebar" | "palette" | "inline" | "import";
87
+ }
88
+
89
+ export interface TemplateVariableDef {
90
+ key: string;
91
+ label: string;
92
+ dataType: MetadataDataType;
93
+ dateFormat?: string;
94
+ value?: unknown;
95
+ defaultValue?: string;
96
+ metadataId?: number | string;
97
+ group?: string;
98
+ createdBy?: UserInfo;
99
+ createdAt?: number;
100
+ lastModifiedBy?: UserInfo;
101
+ lastModifiedAt?: number;
102
+ history?: MetadataAuditEntry[];
103
+ }
104
+
105
+ export interface SetTemplateVariablesOptions {
106
+ author?: UserInfo;
107
+ source?: "api" | "editor" | "sidebar" | "inline" | "import" | "palette";
108
+ trackInReview?: boolean;
109
+ metadata?: Record<string, Partial<TemplateVariableDef>>;
110
+ }
111
+
112
+ export interface InsertTemplateVariableItem {
113
+ key: string;
114
+ label: string;
115
+ dataType?: MetadataDataType;
116
+ dateFormat?: string;
117
+ value?: unknown;
118
+ defaultValue?: string;
119
+ metadataId?: number | string;
120
+ group?: string;
121
+ }
58
122
 
59
123
  export interface EditorPermissions {
60
124
  editContent: boolean;
@@ -547,6 +611,13 @@ export interface KindyEditorOptions {
547
611
  onLoadProgress?: (progress: LoadProgress) => void;
548
612
  /** Granular capabilities governing content edits, annotations, and selection. */
549
613
  permissions?: Partial<EditorPermissions>;
614
+ /** Callback fired when a template variable token is clicked in the editor.
615
+ * Provides variable key, definition, doc position, and bounding rects (container & client viewport).
616
+ * Allows host application (React/Vue/etc.) to render custom modals, drawers, or popovers. */
617
+ onVariableClick?: (info: VariableClickInfo) => void;
618
+ /** Whether to show the built-in variable audit popover UI on click. Defaults to false.
619
+ * When false, the built-in popover does not appear, leaving UI rendering to the host via onVariableClick / event. */
620
+ showVariablePopover?: boolean;
550
621
  }
551
622
 
552
623
  /** Initial view-chrome state (see KindyEditorOptions.view). Every field is
@@ -805,7 +876,31 @@ export interface EditorHandle {
805
876
  revealRange(range: ExternalRange, options?: RevealRangeOptions): void;
806
877
  /** Live-update {{KEY}} template placeholders in the document without full reload,
807
878
  * preserving zoom, scroll position, and selection. */
808
- setTemplateVariables(values: TemplateVariableValues): void;
879
+ setTemplateVariables(values: TemplateVariableValues, options?: SetTemplateVariablesOptions): void;
880
+ /** Revert a template variable to an earlier value recorded in its audit history. */
881
+ revertTemplateVariable(key: string, historyId: string, actor?: UserInfo): boolean;
882
+ /** Insert an atomic template variable token at current caret/selection. */
883
+ insertTemplateVariable(item: InsertTemplateVariableItem, author?: UserInfo): boolean;
884
+ /** Open the contract metadata palette autocomplete at current caret position. */
885
+ openMetadataPalette(): void;
886
+ /** Set template variable display mode ('code' | 'value' | 'placeholder'). */
887
+ setVariableDisplayMode(mode: VariableDisplayMode): void;
888
+ /** Get current template variable display mode. */
889
+ getVariableDisplayMode(): VariableDisplayMode;
890
+ /** Get all registered template variables in the document. */
891
+ getTemplateVariables(): Record<string, TemplateVariableDef>;
892
+ /** Get a single registered template variable definition by key. */
893
+ getTemplateVariable(key: string): TemplateVariableDef | null;
894
+ /** Get audit trail history for a template variable. */
895
+ getVariableHistory(key: string): MetadataAuditEntry[];
896
+ /** Open built-in variable popover explicitly. */
897
+ openVariablePopover(key: string, pos?: DocPosition): void;
898
+ /** Close built-in variable popover. */
899
+ closeVariablePopover(): void;
900
+ /** Get all metadata IDs (numbers) currently used by template variables in the document. */
901
+ getUsedMetadataIds(): number[];
902
+ /** Set custom metadata catalog for autocomplete palette. */
903
+ setMetadataCatalog(catalog: TemplateVariableDef[]): void;
809
904
  /** Update fine-grained capabilities (e.g. allow comments/selection in view mode). */
810
905
  setPermissions(permissions: Partial<EditorPermissions>): void;
811
906
  /** Current effective permissions. */
@@ -894,7 +989,31 @@ export declare class KindyEditor {
894
989
  revealRange(range: ExternalRange, options?: RevealRangeOptions): Promise<void>;
895
990
  /** Live-update {{KEY}} template placeholders in the document without full reload,
896
991
  * preserving zoom, scroll position, and selection. */
897
- setTemplateVariables(values: TemplateVariableValues): Promise<void>;
992
+ setTemplateVariables(values: TemplateVariableValues, options?: SetTemplateVariablesOptions): Promise<void>;
993
+ /** Revert a template variable to an earlier value recorded in its audit history. */
994
+ revertTemplateVariable(key: string, historyId: string, actor?: UserInfo): Promise<boolean>;
995
+ /** Insert an atomic template variable token at current caret/selection. */
996
+ insertTemplateVariable(item: InsertTemplateVariableItem, author?: UserInfo): Promise<boolean>;
997
+ /** Open the contract metadata palette autocomplete at current caret position. */
998
+ openMetadataPalette(): Promise<void>;
999
+ /** Set template variable display mode ('code' | 'value' | 'placeholder'). */
1000
+ setVariableDisplayMode(mode: VariableDisplayMode): Promise<void>;
1001
+ /** Get current template variable display mode. */
1002
+ getVariableDisplayMode(): Promise<VariableDisplayMode>;
1003
+ /** Get all registered template variables in the document. */
1004
+ getTemplateVariables(): Promise<Record<string, TemplateVariableDef>>;
1005
+ /** Get a single registered template variable definition by key. */
1006
+ getTemplateVariable(key: string): Promise<TemplateVariableDef | null>;
1007
+ /** Get audit trail history for a template variable. */
1008
+ getVariableHistory(key: string): Promise<MetadataAuditEntry[]>;
1009
+ /** Open built-in variable popover explicitly. */
1010
+ openVariablePopover(key: string, pos?: DocPosition): Promise<void>;
1011
+ /** Close built-in variable popover. */
1012
+ closeVariablePopover(): Promise<void>;
1013
+ /** Get all metadata IDs (numbers) currently used by template variables in the document. */
1014
+ getUsedMetadataIds(): Promise<number[]>;
1015
+ /** Set custom metadata catalog for autocomplete palette. */
1016
+ setMetadataCatalog(catalog: TemplateVariableDef[]): Promise<void>;
898
1017
  /** Update fine-grained capabilities (e.g. allow comments/selection in view mode). */
899
1018
  setPermissions(permissions: Partial<EditorPermissions>): Promise<void>;
900
1019
  /** Current effective permissions. */