triggerix-editor-preset-war3 0.0.0 → 0.0.5

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 imba97 <https://github.com/imba97>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs ADDED
@@ -0,0 +1,412 @@
1
+ 'use strict';
2
+
3
+ const editor = require('@triggerix/editor');
4
+
5
+ function parseTemplate(template, slots, slotValues) {
6
+ const segments = [];
7
+ const regex = /\$\{(\w+)\}/g;
8
+ let lastIndex = 0;
9
+ let match;
10
+ while ((match = regex.exec(template)) !== null) {
11
+ if (match.index > lastIndex) {
12
+ segments.push({ type: "text", content: template.slice(lastIndex, match.index) });
13
+ }
14
+ const key = match[1];
15
+ const slotDef = slots?.[key];
16
+ if (slotDef) {
17
+ const entry = slotValues?.[key];
18
+ segments.push({
19
+ type: "slot",
20
+ key,
21
+ label: slotDef.label,
22
+ tools: slotDef.tools,
23
+ value: entry?.value ?? null,
24
+ entry: entry ?? void 0
25
+ });
26
+ } else {
27
+ segments.push({ type: "text", content: match[0] });
28
+ }
29
+ lastIndex = regex.lastIndex;
30
+ }
31
+ if (lastIndex < template.length) {
32
+ segments.push({ type: "text", content: template.slice(lastIndex) });
33
+ }
34
+ return segments;
35
+ }
36
+
37
+ function buildDescriptor(def, slotValues) {
38
+ return {
39
+ id: def.id,
40
+ segments: parseTemplate(def.template, def.slots, slotValues)
41
+ };
42
+ }
43
+ function getEventDescriptor(registry, id, slotValues) {
44
+ const def = registry.getEvent(id);
45
+ return def ? buildDescriptor(def, slotValues) : null;
46
+ }
47
+ function getActionDescriptor(registry, id, slotValues) {
48
+ const def = registry.getAction(id);
49
+ return def ? buildDescriptor(def, slotValues) : null;
50
+ }
51
+ function getConditionDescriptor(registry, id, slotValues) {
52
+ const def = registry.getCondition(id);
53
+ return def ? buildDescriptor(def, slotValues) : null;
54
+ }
55
+ function getToolDescriptor(registry, toolName, slotValues) {
56
+ const def = registry.getTool(toolName);
57
+ if (!def)
58
+ return null;
59
+ if (def.kind === "leaf") {
60
+ return {
61
+ kind: "leaf",
62
+ name: toolName,
63
+ label: def.label,
64
+ input: def.input
65
+ };
66
+ }
67
+ return {
68
+ kind: "composite",
69
+ name: toolName,
70
+ label: def.label,
71
+ segments: parseTemplate(def.template, def.slots, slotValues)
72
+ };
73
+ }
74
+ function getSlotToolDescriptors(registry, slotDef) {
75
+ return slotDef.tools.map((name) => getToolDescriptor(registry, name)).filter((d) => d !== null);
76
+ }
77
+
78
+ class War3Registry extends editor.BaseRegistry {
79
+ tools = /* @__PURE__ */ new Map();
80
+ registerTool(name, def) {
81
+ this.tools.set(name, def);
82
+ }
83
+ getTool(name) {
84
+ return this.tools.get(name);
85
+ }
86
+ getTools() {
87
+ return new Map(this.tools);
88
+ }
89
+ getValueSources(valueType) {
90
+ let conditions = this.getConditions();
91
+ let tools = this.getTools();
92
+ if (valueType) {
93
+ conditions = conditions.filter((c) => c.type === valueType);
94
+ tools = new Map([...tools.entries()].filter(([_, t]) => t.type === valueType));
95
+ }
96
+ return { conditions, tools };
97
+ }
98
+ }
99
+
100
+ function resolveSlotValue(entry, registry) {
101
+ if (!entry.tool)
102
+ return void 0;
103
+ const toolDef = registry.getTool(entry.tool);
104
+ if (!toolDef)
105
+ return void 0;
106
+ if (toolDef.kind === "leaf") {
107
+ return toolDef.resolve(entry.value);
108
+ }
109
+ const resolvedSubSlots = {};
110
+ if (entry.subSlots) {
111
+ for (const [key, subEntry] of Object.entries(entry.subSlots)) {
112
+ resolvedSubSlots[key] = resolveSlotValue(subEntry, registry);
113
+ }
114
+ }
115
+ return toolDef.resolve(resolvedSubSlots);
116
+ }
117
+ function resolveItemParams(slotValues, registry) {
118
+ const params = {};
119
+ let hasParams = false;
120
+ for (const [key, entry] of Object.entries(slotValues)) {
121
+ const resolved = resolveSlotValue(entry, registry);
122
+ if (resolved !== void 0) {
123
+ params[key] = resolved;
124
+ hasParams = true;
125
+ }
126
+ }
127
+ return hasParams ? params : void 0;
128
+ }
129
+ function serializeItems(items, registry) {
130
+ return items.map((item) => {
131
+ const params = resolveItemParams(item.slotValues, registry);
132
+ const action = { type: item.id };
133
+ if (params) {
134
+ action.params = params;
135
+ }
136
+ return action;
137
+ });
138
+ }
139
+ function generateRuleId() {
140
+ if (typeof globalThis.crypto?.randomUUID === "function") {
141
+ return globalThis.crypto.randomUUID();
142
+ }
143
+ return `rule-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
144
+ }
145
+ function toRule(state, registry, ruleId) {
146
+ const eventParams = state.event ? resolveItemParams(state.event.slotValues, registry) : void 0;
147
+ const event = {
148
+ type: state.event?.id ?? "",
149
+ ...eventParams ? { payload: eventParams } : {}
150
+ };
151
+ const actions = serializeItems(state.actions, registry);
152
+ const rule = {
153
+ id: ruleId ?? generateRuleId(),
154
+ event,
155
+ actions
156
+ };
157
+ if (state.conditions.length > 0) {
158
+ rule.conditions = {
159
+ type: "and",
160
+ conditions: serializeItems(state.conditions, registry)
161
+ };
162
+ }
163
+ return rule;
164
+ }
165
+
166
+ const INITIAL_STATE = {
167
+ event: null,
168
+ conditions: [],
169
+ actions: []
170
+ };
171
+ class War3EditorStateManager extends editor.ObservableState {
172
+ constructor() {
173
+ super({ ...INITIAL_STATE });
174
+ }
175
+ // --- Event ---
176
+ setEvent(id) {
177
+ this.setState((s) => ({ ...s, event: { id, slotValues: {} } }));
178
+ }
179
+ clearEvent() {
180
+ this.setState((s) => ({ ...s, event: null }));
181
+ }
182
+ setEventSlot(key, entry) {
183
+ this.setState((s) => {
184
+ if (!s.event)
185
+ return s;
186
+ return {
187
+ ...s,
188
+ event: {
189
+ ...s.event,
190
+ slotValues: { ...s.event.slotValues, [key]: entry }
191
+ }
192
+ };
193
+ });
194
+ }
195
+ // --- Actions ---
196
+ addAction(id) {
197
+ this.setState((s) => ({
198
+ ...s,
199
+ actions: [...s.actions, { id, slotValues: {} }]
200
+ }));
201
+ }
202
+ removeAction(index) {
203
+ this.setState((s) => ({
204
+ ...s,
205
+ actions: s.actions.filter((_, i) => i !== index)
206
+ }));
207
+ }
208
+ moveAction(from, to) {
209
+ this.setState((s) => {
210
+ const actions = [...s.actions];
211
+ const [moved] = actions.splice(from, 1);
212
+ actions.splice(to, 0, moved);
213
+ return { ...s, actions };
214
+ });
215
+ }
216
+ setActionSlot(actionIndex, key, entry) {
217
+ this.setItemSlot("actions", actionIndex, key, entry);
218
+ }
219
+ // --- Conditions ---
220
+ addCondition(id) {
221
+ this.setState((s) => ({
222
+ ...s,
223
+ conditions: [...s.conditions, { id, slotValues: {} }]
224
+ }));
225
+ }
226
+ removeCondition(index) {
227
+ this.setState((s) => ({
228
+ ...s,
229
+ conditions: s.conditions.filter((_, i) => i !== index)
230
+ }));
231
+ }
232
+ setConditionSlot(conditionIndex, key, entry) {
233
+ this.setItemSlot("conditions", conditionIndex, key, entry);
234
+ }
235
+ // --- Reset ---
236
+ reset() {
237
+ this.setState(() => ({ ...INITIAL_STATE }));
238
+ }
239
+ // --- Helpers ---
240
+ setItemSlot(field, index, key, entry) {
241
+ this.setState((s) => {
242
+ const items = [...s[field]];
243
+ const item = items[index];
244
+ if (!item)
245
+ return s;
246
+ items[index] = { ...item, slotValues: { ...item.slotValues, [key]: entry } };
247
+ return { ...s, [field]: items };
248
+ });
249
+ }
250
+ }
251
+
252
+ function createWar3Editor() {
253
+ const registry = new War3Registry();
254
+ const stateManager = new War3EditorStateManager();
255
+ const editor = {
256
+ // --- Editor 接口 ---
257
+ getState: () => stateManager.getState(),
258
+ onChange: (listener) => stateManager.onChange(listener),
259
+ toRule: (ruleId) => toRule(stateManager.getState(), registry, ruleId),
260
+ reset: () => stateManager.reset(),
261
+ dispose: () => stateManager.dispose(),
262
+ // --- 注册 ---
263
+ registerEvent: (def) => registry.registerEvent(def),
264
+ registerAction: (def) => registry.registerAction(def),
265
+ registerCondition: (def) => registry.registerCondition(def),
266
+ registerTool: (name, def) => registry.registerTool(name, def),
267
+ // --- 注册表访问 ---
268
+ getRegistry: () => registry,
269
+ // --- 查询 ---
270
+ getAvailableEvents: () => registry.getEvents(),
271
+ getAvailableActions: () => registry.getActions(),
272
+ getAvailableConditions: () => registry.getConditions(),
273
+ // --- 描述符 ---
274
+ getEventDescriptor: () => {
275
+ const state = stateManager.getState();
276
+ if (!state.event)
277
+ return null;
278
+ return getEventDescriptor(registry, state.event.id, state.event.slotValues);
279
+ },
280
+ getActionDescriptor: (index) => {
281
+ const state = stateManager.getState();
282
+ const action = state.actions[index];
283
+ if (!action)
284
+ return null;
285
+ return getActionDescriptor(registry, action.id, action.slotValues);
286
+ },
287
+ getConditionDescriptor: (index) => {
288
+ const state = stateManager.getState();
289
+ const condition = state.conditions[index];
290
+ if (!condition)
291
+ return null;
292
+ return getConditionDescriptor(registry, condition.id, condition.slotValues);
293
+ },
294
+ getToolDescriptor: (toolName, slotValues) => getToolDescriptor(registry, toolName, slotValues),
295
+ getSlotTools: (slotDef) => getSlotToolDescriptors(registry, slotDef),
296
+ // --- 状态操作 ---
297
+ setEvent: (id) => stateManager.setEvent(id),
298
+ clearEvent: () => stateManager.clearEvent(),
299
+ setEventSlot: (key, entry) => stateManager.setEventSlot(key, entry),
300
+ addAction: (id) => stateManager.addAction(id),
301
+ removeAction: (index) => stateManager.removeAction(index),
302
+ moveAction: (from, to) => stateManager.moveAction(from, to),
303
+ setActionSlot: (actionIndex, key, entry) => stateManager.setActionSlot(actionIndex, key, entry),
304
+ addCondition: (id) => stateManager.addCondition(id),
305
+ removeCondition: (index) => stateManager.removeCondition(index),
306
+ setConditionSlot: (conditionIndex, key, entry) => stateManager.setConditionSlot(conditionIndex, key, entry),
307
+ // --- 值来源查询 ---
308
+ getValueSources: (valueType) => registry.getValueSources(valueType),
309
+ // --- Preset ---
310
+ applyPreset: (preset) => {
311
+ preset.setup(editor);
312
+ },
313
+ // --- 序列化工具 ---
314
+ resolveSlotValue: (entry) => resolveSlotValue(entry, registry)
315
+ };
316
+ return editor;
317
+ }
318
+
319
+ function valueEquals(a, b) {
320
+ if (a === b)
321
+ return true;
322
+ if (a == null || b == null)
323
+ return false;
324
+ if (typeof a !== "object" || typeof b !== "object")
325
+ return false;
326
+ try {
327
+ return JSON.stringify(a) === JSON.stringify(b);
328
+ } catch {
329
+ return false;
330
+ }
331
+ }
332
+ function stringifyValue(v) {
333
+ if (v == null)
334
+ return "";
335
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean")
336
+ return String(v);
337
+ try {
338
+ return JSON.stringify(v);
339
+ } catch {
340
+ return String(v);
341
+ }
342
+ }
343
+ function resolveSlotDisplayText(entry, registry, fallbackLabel) {
344
+ if (!entry?.tool)
345
+ return fallbackLabel;
346
+ const toolDef = registry.getTool(entry.tool);
347
+ if (!toolDef)
348
+ return fallbackLabel;
349
+ if (toolDef.kind === "leaf") {
350
+ if (entry.value == null || entry.value === "")
351
+ return fallbackLabel;
352
+ if (toolDef.input.type === "select") {
353
+ const opt = toolDef.input.options?.find((o) => valueEquals(o.value, entry.value));
354
+ if (opt)
355
+ return opt.label;
356
+ }
357
+ return stringifyValue(entry.value);
358
+ }
359
+ const segments = parseTemplate(toolDef.template, toolDef.slots, entry.subSlots ?? {});
360
+ return segments.map((seg) => {
361
+ if (seg.type === "text")
362
+ return seg.content;
363
+ if (seg.type === "slot") {
364
+ const subEntry = entry.subSlots?.[seg.key];
365
+ return resolveSlotDisplayText(subEntry ?? null, registry, seg.label);
366
+ }
367
+ return "";
368
+ }).join("");
369
+ }
370
+
371
+ function defineLeafTool(def) {
372
+ return { ...def, kind: "leaf" };
373
+ }
374
+ function defineCompositeTool(def) {
375
+ return { ...def, kind: "composite" };
376
+ }
377
+ function defineCondition(def) {
378
+ return def;
379
+ }
380
+
381
+ function defineWar3Preset(options) {
382
+ return {
383
+ name: options.name,
384
+ setup(editor) {
385
+ options.events?.forEach((def) => editor.registerEvent(def));
386
+ options.actions?.forEach((def) => editor.registerAction(def));
387
+ options.conditions?.forEach((def) => editor.registerCondition(def));
388
+ if (options.tools) {
389
+ for (const [name, def] of Object.entries(options.tools)) {
390
+ editor.registerTool(name, def);
391
+ }
392
+ }
393
+ }
394
+ };
395
+ }
396
+
397
+ exports.War3EditorStateManager = War3EditorStateManager;
398
+ exports.War3Registry = War3Registry;
399
+ exports.createWar3Editor = createWar3Editor;
400
+ exports.defineCompositeTool = defineCompositeTool;
401
+ exports.defineCondition = defineCondition;
402
+ exports.defineLeafTool = defineLeafTool;
403
+ exports.defineWar3Preset = defineWar3Preset;
404
+ exports.getActionDescriptor = getActionDescriptor;
405
+ exports.getConditionDescriptor = getConditionDescriptor;
406
+ exports.getEventDescriptor = getEventDescriptor;
407
+ exports.getSlotToolDescriptors = getSlotToolDescriptors;
408
+ exports.getToolDescriptor = getToolDescriptor;
409
+ exports.parseTemplate = parseTemplate;
410
+ exports.resolveSlotDisplayText = resolveSlotDisplayText;
411
+ exports.resolveSlotValue = resolveSlotValue;
412
+ exports.toRule = toRule;
@@ -0,0 +1,239 @@
1
+ import { BaseItemDef, BaseRegistry, Editor, Preset, ObservableState } from '@triggerix/editor';
2
+ export { BaseItemDef, Preset } from '@triggerix/editor';
3
+ import { Value, Rule } from '@triggerix/core';
4
+
5
+ interface SlotDef {
6
+ label: string;
7
+ tools: string[];
8
+ }
9
+ interface SlotValueEntry {
10
+ tool: string | null;
11
+ value: unknown;
12
+ subSlots?: Record<string, SlotValueEntry>;
13
+ }
14
+ interface LeafToolInput<TValue = unknown> {
15
+ type: 'text' | 'number' | 'select';
16
+ placeholder?: string;
17
+ options?: Array<{
18
+ value: TValue;
19
+ label: string;
20
+ }>;
21
+ }
22
+ interface LeafToolDef<TInput = unknown, TOutput = unknown> {
23
+ kind: 'leaf';
24
+ type?: string;
25
+ label: string;
26
+ input: LeafToolInput<TInput>;
27
+ resolve: (input: TInput) => TOutput;
28
+ }
29
+ interface CompositeToolDef<TSlotValues extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown> {
30
+ kind: 'composite';
31
+ type?: string;
32
+ label: string;
33
+ template: string;
34
+ slots: Record<keyof TSlotValues & string, SlotDef>;
35
+ resolve: (slotValues: TSlotValues) => TOutput;
36
+ }
37
+ type ToolDef = LeafToolDef<any, any> | CompositeToolDef<any, any>;
38
+ interface War3EventDef extends BaseItemDef {
39
+ template: string;
40
+ slots?: Record<string, SlotDef>;
41
+ }
42
+ interface War3ActionDef extends BaseItemDef {
43
+ template: string;
44
+ slots?: Record<string, SlotDef>;
45
+ }
46
+ interface War3ConditionDef<TSlotValues extends Record<string, unknown> = Record<string, unknown>> extends BaseItemDef {
47
+ template: string;
48
+ slots?: Record<string, SlotDef>;
49
+ resolve?: (slotValues: TSlotValues) => unknown;
50
+ }
51
+ type Segment = {
52
+ type: 'text';
53
+ content: string;
54
+ } | {
55
+ type: 'slot';
56
+ key: string;
57
+ label: string;
58
+ tools: string[];
59
+ value: unknown;
60
+ entry?: SlotValueEntry;
61
+ };
62
+ interface ItemDescriptor {
63
+ id: string;
64
+ segments: Segment[];
65
+ }
66
+ interface LeafToolDescriptor {
67
+ kind: 'leaf';
68
+ name: string;
69
+ label: string;
70
+ input: LeafToolInput;
71
+ }
72
+ interface CompositeToolDescriptor {
73
+ kind: 'composite';
74
+ name: string;
75
+ label: string;
76
+ segments: Segment[];
77
+ }
78
+ type ToolDescriptor = LeafToolDescriptor | CompositeToolDescriptor;
79
+ interface ItemState {
80
+ id: string;
81
+ slotValues: Record<string, SlotValueEntry>;
82
+ }
83
+ interface War3EditorState {
84
+ event: ItemState | null;
85
+ conditions: ItemState[];
86
+ actions: ItemState[];
87
+ }
88
+ interface War3PresetOptions {
89
+ name: string;
90
+ events?: War3EventDef[];
91
+ actions?: War3ActionDef[];
92
+ conditions?: War3ConditionDef[];
93
+ tools?: Record<string, ToolDef>;
94
+ }
95
+
96
+ /**
97
+ * War3 注册表 - 继承 BaseRegistry,增加 Tool 注册能力
98
+ */
99
+ declare class War3Registry extends BaseRegistry<War3EventDef, War3ActionDef, War3ConditionDef> {
100
+ private tools;
101
+ registerTool(name: string, def: ToolDef): void;
102
+ getTool(name: string): ToolDef | undefined;
103
+ getTools(): Map<string, ToolDef>;
104
+ getValueSources(valueType?: string): {
105
+ conditions: War3ConditionDef[];
106
+ tools: Map<string, ToolDef>;
107
+ };
108
+ }
109
+
110
+ interface War3Editor extends Editor<War3EditorState> {
111
+ registerEvent: (def: War3EventDef) => void;
112
+ registerAction: (def: War3ActionDef) => void;
113
+ registerCondition: (def: War3ConditionDef) => void;
114
+ registerTool: (name: string, def: ToolDef) => void;
115
+ getRegistry: () => War3Registry;
116
+ getAvailableEvents: () => War3EventDef[];
117
+ getAvailableActions: () => War3ActionDef[];
118
+ getAvailableConditions: () => War3ConditionDef[];
119
+ getEventDescriptor: () => ItemDescriptor | null;
120
+ getActionDescriptor: (actionIndex: number) => ItemDescriptor | null;
121
+ getConditionDescriptor: (conditionIndex: number) => ItemDescriptor | null;
122
+ getToolDescriptor: (toolName: string, slotValues?: Record<string, SlotValueEntry>) => ToolDescriptor | null;
123
+ getSlotTools: (slotDef: SlotDef) => ToolDescriptor[];
124
+ setEvent: (id: string) => void;
125
+ clearEvent: () => void;
126
+ setEventSlot: (key: string, entry: SlotValueEntry) => void;
127
+ addAction: (id: string) => void;
128
+ removeAction: (index: number) => void;
129
+ moveAction: (from: number, to: number) => void;
130
+ setActionSlot: (actionIndex: number, key: string, entry: SlotValueEntry) => void;
131
+ addCondition: (id: string) => void;
132
+ removeCondition: (index: number) => void;
133
+ setConditionSlot: (conditionIndex: number, key: string, entry: SlotValueEntry) => void;
134
+ getValueSources: (valueType?: string) => {
135
+ conditions: War3ConditionDef[];
136
+ tools: Map<string, ToolDef>;
137
+ };
138
+ applyPreset: (preset: Preset<War3Editor>) => void;
139
+ resolveSlotValue: (entry: SlotValueEntry) => unknown;
140
+ }
141
+ declare function createWar3Editor(): War3Editor;
142
+
143
+ declare function getEventDescriptor(registry: War3Registry, id: string, slotValues?: Record<string, SlotValueEntry>): ItemDescriptor | null;
144
+ declare function getActionDescriptor(registry: War3Registry, id: string, slotValues?: Record<string, SlotValueEntry>): ItemDescriptor | null;
145
+ declare function getConditionDescriptor(registry: War3Registry, id: string, slotValues?: Record<string, SlotValueEntry>): ItemDescriptor | null;
146
+ declare function getToolDescriptor(registry: War3Registry, toolName: string, slotValues?: Record<string, SlotValueEntry>): ToolDescriptor | null;
147
+ declare function getSlotToolDescriptors(registry: War3Registry, slotDef: SlotDef): ToolDescriptor[];
148
+
149
+ /**
150
+ * 递归解析 SlotValueEntry 为人类可读的展示文本
151
+ *
152
+ * - 如果 entry 为 null/undefined 或未选择 tool,返回 fallbackLabel(slot 占位文案)
153
+ * - 如果 tool 为 leaf:
154
+ * - select 类型:尝试匹配 options 找到对应 label(支持对象值的深比较)
155
+ * - 其它类型:返回 value 的字符串形式
156
+ * - 若 value 为空:返回 fallbackLabel
157
+ * - 如果 tool 为 composite:使用 tool 的 template 递归展开
158
+ */
159
+ declare function resolveSlotDisplayText(entry: SlotValueEntry | null | undefined, registry: War3Registry, fallbackLabel: string): string;
160
+
161
+ /**
162
+ * Type-safe LeafTool definition.
163
+ * Input type comes from the resolve callback annotation; output is inferred.
164
+ */
165
+ declare function defineLeafTool<TInput, TOutput>(def: {
166
+ type?: string;
167
+ label: string;
168
+ input: LeafToolInput<TInput>;
169
+ resolve: (input: TInput) => TOutput;
170
+ }): {
171
+ kind: "leaf";
172
+ type?: string;
173
+ label: string;
174
+ input: LeafToolInput<TInput>;
175
+ resolve: (input: TInput) => TOutput;
176
+ };
177
+ /**
178
+ * Type-safe CompositeTool definition.
179
+ * Slot value types come from the resolve callback; slot keys are validated against it.
180
+ */
181
+ declare function defineCompositeTool<TSlotValues extends Record<string, unknown>, TOutput>(def: {
182
+ type?: string;
183
+ label: string;
184
+ template: string;
185
+ slots: Record<keyof TSlotValues & string, SlotDef>;
186
+ resolve: (slotValues: TSlotValues) => TOutput;
187
+ }): CompositeToolDef<TSlotValues, TOutput>;
188
+ /**
189
+ * Type-safe Condition definition.
190
+ */
191
+ declare function defineCondition<TSlotValues extends Record<string, unknown> = Record<string, unknown>>(def: Omit<War3ConditionDef<TSlotValues>, 'resolve'> & {
192
+ resolve?: (slotValues: TSlotValues) => unknown;
193
+ }): War3ConditionDef;
194
+
195
+ /**
196
+ * 解析模板字符串为 Segment 数组
197
+ * 模板格式: "普通文本${slotKey}更多文本"
198
+ */
199
+ declare function parseTemplate(template: string, slots?: Record<string, SlotDef>, slotValues?: Record<string, SlotValueEntry>): Segment[];
200
+
201
+ declare function defineWar3Preset(options: War3PresetOptions): Preset<War3Editor>;
202
+
203
+ /**
204
+ * Recursively resolve a single slot value.
205
+ */
206
+ declare function resolveSlotValue(entry: SlotValueEntry, registry: War3Registry): Value | undefined;
207
+ /**
208
+ * Serialize editor state into a standard Rule JSON.
209
+ *
210
+ * Output shape (compatible with @triggerix/core):
211
+ * {
212
+ * id, event: { type, payload? }, conditions?: { type:'and', conditions:[...] },
213
+ * actions: [{ type, params? }]
214
+ * }
215
+ */
216
+ declare function toRule(state: War3EditorState, registry: War3Registry, ruleId?: string): Rule;
217
+
218
+ /**
219
+ * War3 编辑器状态管理
220
+ * 继承 ObservableState,提供模板模式特有的状态操作
221
+ */
222
+ declare class War3EditorStateManager extends ObservableState<War3EditorState> {
223
+ constructor();
224
+ setEvent(id: string): void;
225
+ clearEvent(): void;
226
+ setEventSlot(key: string, entry: SlotValueEntry): void;
227
+ addAction(id: string): void;
228
+ removeAction(index: number): void;
229
+ moveAction(from: number, to: number): void;
230
+ setActionSlot(actionIndex: number, key: string, entry: SlotValueEntry): void;
231
+ addCondition(id: string): void;
232
+ removeCondition(index: number): void;
233
+ setConditionSlot(conditionIndex: number, key: string, entry: SlotValueEntry): void;
234
+ reset(): void;
235
+ private setItemSlot;
236
+ }
237
+
238
+ export { War3EditorStateManager, War3Registry, createWar3Editor, defineCompositeTool, defineCondition, defineLeafTool, defineWar3Preset, getActionDescriptor, getConditionDescriptor, getEventDescriptor, getSlotToolDescriptors, getToolDescriptor, parseTemplate, resolveSlotDisplayText, resolveSlotValue, toRule };
239
+ export type { CompositeToolDef, CompositeToolDescriptor, ItemDescriptor, ItemState, LeafToolDef, LeafToolDescriptor, LeafToolInput, Segment, SlotDef, SlotValueEntry, ToolDef, ToolDescriptor, War3ActionDef, War3ConditionDef, War3Editor, War3EditorState, War3EventDef, War3PresetOptions };