@verbb/plugin-kit-tiptap-core 2.0.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +36 -0
  4. package/dist/extensions/create-extensions.d.ts +13 -0
  5. package/dist/extensions/create-extensions.d.ts.map +1 -0
  6. package/dist/extensions/create-extensions.js +92 -0
  7. package/dist/extensions/create-extensions.js.map +1 -0
  8. package/dist/extensions/index.d.ts +6 -0
  9. package/dist/extensions/index.d.ts.map +1 -0
  10. package/dist/extensions/index.js +4 -0
  11. package/dist/extensions/one-liner-document.d.ts +2 -0
  12. package/dist/extensions/one-liner-document.d.ts.map +1 -0
  13. package/dist/extensions/one-liner-document.js +7 -0
  14. package/dist/extensions/one-liner-document.js.map +1 -0
  15. package/dist/extensions/variable-tag.d.ts +7 -0
  16. package/dist/extensions/variable-tag.d.ts.map +1 -0
  17. package/dist/extensions/variable-tag.js +156 -0
  18. package/dist/extensions/variable-tag.js.map +1 -0
  19. package/dist/index.d.ts +12 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +13 -0
  22. package/dist/links/commands.d.ts +9 -0
  23. package/dist/links/commands.d.ts.map +1 -0
  24. package/dist/links/commands.js +63 -0
  25. package/dist/links/commands.js.map +1 -0
  26. package/dist/links/craft-element.d.ts +28 -0
  27. package/dist/links/craft-element.d.ts.map +1 -0
  28. package/dist/links/craft-element.js +80 -0
  29. package/dist/links/craft-element.js.map +1 -0
  30. package/dist/links/extension.d.ts +3 -0
  31. package/dist/links/extension.d.ts.map +1 -0
  32. package/dist/links/extension.js +17 -0
  33. package/dist/links/extension.js.map +1 -0
  34. package/dist/links/index.d.ts +5 -0
  35. package/dist/links/index.d.ts.map +1 -0
  36. package/dist/links/index.js +4 -0
  37. package/dist/links/types.d.ts +62 -0
  38. package/dist/links/types.d.ts.map +1 -0
  39. package/dist/links/types.js +0 -0
  40. package/dist/serialization/editor.d.ts +9 -0
  41. package/dist/serialization/editor.d.ts.map +1 -0
  42. package/dist/serialization/editor.js +112 -0
  43. package/dist/serialization/editor.js.map +1 -0
  44. package/dist/serialization/input.d.ts +55 -0
  45. package/dist/serialization/input.d.ts.map +1 -0
  46. package/dist/serialization/input.js +293 -0
  47. package/dist/serialization/input.js.map +1 -0
  48. package/dist/toolbar/button-registry.d.ts +14 -0
  49. package/dist/toolbar/button-registry.d.ts.map +1 -0
  50. package/dist/toolbar/button-registry.js +114 -0
  51. package/dist/toolbar/button-registry.js.map +1 -0
  52. package/dist/toolbar/index.d.ts +3 -0
  53. package/dist/toolbar/index.d.ts.map +1 -0
  54. package/dist/toolbar/index.js +3 -0
  55. package/dist/toolbar/toolbar-schema.d.ts +66 -0
  56. package/dist/toolbar/toolbar-schema.d.ts.map +1 -0
  57. package/dist/toolbar/toolbar-schema.js +340 -0
  58. package/dist/toolbar/toolbar-schema.js.map +1 -0
  59. package/dist/types/variable-option.d.ts +10 -0
  60. package/dist/types/variable-option.d.ts.map +1 -0
  61. package/dist/types/variable-option.js +0 -0
  62. package/package.json +99 -0
@@ -0,0 +1,293 @@
1
+ import { TextSelection } from "@tiptap/pm/state";
2
+ //#region src/serialization/input.ts
3
+ var TRANSFORMER_ID_PREFIX = "transform=";
4
+ function parseTokenMetadata(tokenValue) {
5
+ const match = tokenValue.match(/^\{([^}]*)\}$/);
6
+ if (!match) return { tokenWithoutDefault: tokenValue };
7
+ let body = match[1] ?? "";
8
+ let defaultIfEmpty;
9
+ if (body.includes("|")) {
10
+ const split = body.split("|");
11
+ body = split.shift() ?? "";
12
+ defaultIfEmpty = split.join("|").trim() || void 0;
13
+ }
14
+ const segments = body.split(";").map((part) => {
15
+ return part.trim();
16
+ }).filter(Boolean);
17
+ const cleanSegments = [];
18
+ let transformerId;
19
+ let transformerParams;
20
+ const referenceParams = {};
21
+ let isTransformerParam = false;
22
+ segments.forEach((segment) => {
23
+ if (segment.startsWith(TRANSFORMER_ID_PREFIX)) {
24
+ transformerId = decodeURIComponent(segment.slice(10)).trim() || void 0;
25
+ isTransformerParam = true;
26
+ return;
27
+ }
28
+ if (segment.includes("=")) {
29
+ const [keyRaw, ...valueParts] = segment.split("=");
30
+ const key = (keyRaw ?? "").trim().toLowerCase();
31
+ if (!key) return;
32
+ const value = decodeURIComponent(valueParts.join("=").trim());
33
+ if (isTransformerParam) {
34
+ if (!transformerParams) transformerParams = {};
35
+ transformerParams[key] = value;
36
+ return;
37
+ }
38
+ referenceParams[key] = value;
39
+ cleanSegments.push(`${key}=${encodeURIComponent(value)}`);
40
+ return;
41
+ }
42
+ cleanSegments.push(segment);
43
+ });
44
+ return {
45
+ tokenWithoutDefault: `{${cleanSegments.join(";")}}`,
46
+ defaultIfEmpty,
47
+ transformerId,
48
+ transformerParams,
49
+ referenceParams
50
+ };
51
+ }
52
+ function isVariableLikeToken(tokenValue) {
53
+ return /^\{[a-zA-Z][a-zA-Z0-9_]*(?::[^}]*)?\}$/.test(tokenValue);
54
+ }
55
+ /** Craft field UIDs — never surface these as chip labels. */
56
+ var FIELD_UID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
57
+ function isLikelyFieldUid(value) {
58
+ return FIELD_UID_PATTERN.test(String(value || "").trim());
59
+ }
60
+ function toTitleWords(value) {
61
+ return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim().replace(/\s+/g, " ").replace(/\b\w/g, (char) => {
62
+ return char.toUpperCase();
63
+ });
64
+ }
65
+ /**
66
+ * Label when no variable option matched. Prefer a clear "unknown" prompt over
67
+ * title-casing UIDs (e.g. "7aff44ed Bca7…"), which looks broken rather than fixable.
68
+ */
69
+ function buildFallbackLabelForUnknownToken(tokenWithoutDefault) {
70
+ if (tokenWithoutDefault.match(/^\{field:([^}]+)\}$/)) return "Unknown field";
71
+ const [target = "", identifier = "", selector = ""] = tokenWithoutDefault.replace(/^\{|\}$/g, "").split(":");
72
+ const reference = String(selector || identifier || target).split(";")[0]?.trim() ?? "";
73
+ if (isLikelyFieldUid(reference) || isLikelyFieldUid(identifier)) return "Unknown variable";
74
+ if (target) return toTitleWords(reference) || "Unknown variable";
75
+ return "Unknown variable";
76
+ }
77
+ function serializeTokenMetadata(baseToken, metadata) {
78
+ const baseMatch = baseToken.match(/^\{([^}]*)\}$/);
79
+ if (!baseMatch) return baseToken;
80
+ const parts = [baseMatch[1]];
81
+ const transformerId = metadata.transformerId?.trim();
82
+ const params = metadata.transformerParams && typeof metadata.transformerParams === "object" ? Object.entries(metadata.transformerParams) : [];
83
+ if (transformerId) {
84
+ parts.push(`${TRANSFORMER_ID_PREFIX}${encodeURIComponent(transformerId)}`);
85
+ params.forEach(([key, value]) => {
86
+ const normalizedKey = String(key ?? "").trim();
87
+ if (!normalizedKey || normalizedKey === "transform") return;
88
+ const normalizedValue = value == null ? "" : String(value);
89
+ parts.push(`${normalizedKey}=${encodeURIComponent(normalizedValue)}`);
90
+ });
91
+ }
92
+ const tokenBody = parts.filter(Boolean).join(";");
93
+ const defaultIfEmpty = metadata.defaultIfEmpty?.trim();
94
+ return defaultIfEmpty ? `{${tokenBody}|${defaultIfEmpty}}` : `{${tokenBody}}`;
95
+ }
96
+ function dedupeVariableOptions(items) {
97
+ const deduped = [];
98
+ const seen = /* @__PURE__ */ new Set();
99
+ items.forEach((item) => {
100
+ const key = String(item?.value ?? "") || `__label:${String(item?.label ?? "")}`;
101
+ if (seen.has(key)) return;
102
+ seen.add(key);
103
+ deduped.push(item);
104
+ });
105
+ return deduped;
106
+ }
107
+ function flattenVariableOptions(items) {
108
+ const flat = [];
109
+ const visit = (nodes) => {
110
+ nodes.forEach((node) => {
111
+ flat.push(node);
112
+ if (Array.isArray(node.children) && node.children.length > 0) visit(node.children);
113
+ });
114
+ };
115
+ visit(items);
116
+ return flat;
117
+ }
118
+ /**
119
+ * Build VariableTag attributes from base and selected variable options.
120
+ * Optional defaultIfEmpty is used when the resolved value is empty (e.g. "Guest" for {user:firstName|Guest}).
121
+ */
122
+ function buildVariableTagAttrs(baseVariable, selectedVariable = baseVariable, options = {}) {
123
+ const selectedLabel = options.label ?? selectedVariable?.label ?? baseVariable?.label ?? "";
124
+ const value = options.value ?? selectedVariable?.value ?? baseVariable?.value ?? "";
125
+ const defaultIfEmpty = options.defaultIfEmpty?.trim();
126
+ const attrs = {
127
+ label: selectedLabel,
128
+ value,
129
+ openOnInsert: options.openOnInsert ?? false
130
+ };
131
+ if (defaultIfEmpty) attrs.default = defaultIfEmpty;
132
+ if (options.transformerId?.trim()) attrs.transformerId = options.transformerId.trim();
133
+ if (options.transformerParams && typeof options.transformerParams === "object") attrs.transformerParams = options.transformerParams;
134
+ return attrs;
135
+ }
136
+ /**
137
+ * Strip optional inline default from token for lookup: {user:firstName|Guest} -> {user:firstName}.
138
+ * Returns [tokenWithoutDefault, defaultText].
139
+ */
140
+ function parseTokenWithDefault(tokenValue) {
141
+ const parsed = parseTokenMetadata(tokenValue);
142
+ return [parsed.tokenWithoutDefault, parsed.defaultIfEmpty];
143
+ }
144
+ function getReferenceBaseToken(tokenValue) {
145
+ const [tokenWithoutDefault] = parseTokenWithDefault(tokenValue);
146
+ const match = tokenWithoutDefault.match(/^\{([^}]*)\}$/);
147
+ if (!match) return tokenWithoutDefault;
148
+ const body = match[1].split(";")[0]?.trim() ?? "";
149
+ return body ? `{${body}}` : tokenWithoutDefault;
150
+ }
151
+ function variableValuesMatchReference(tokenValue, optionValue) {
152
+ if (!tokenValue || !optionValue) return false;
153
+ if (tokenValue === optionValue) return true;
154
+ return getReferenceBaseToken(tokenValue) === getReferenceBaseToken(optionValue);
155
+ }
156
+ function resolveVariableTagLabel(tokenValue, option) {
157
+ const { tokenWithoutDefault } = parseTokenMetadata(String(tokenValue || ""));
158
+ if (option?.label) return option.label;
159
+ return buildFallbackLabelForUnknownToken(tokenWithoutDefault);
160
+ }
161
+ function findMatchingVariableOption(items, tokenWithoutDefault) {
162
+ let fallbackMatch = null;
163
+ for (const item of items) {
164
+ const children = Array.isArray(item.children) ? item.children : [];
165
+ const itemValue = String(item.value ?? "");
166
+ if (itemValue === tokenWithoutDefault) return item;
167
+ if (children.length) {
168
+ const childMatch = findMatchingVariableOption(children, tokenWithoutDefault);
169
+ if (childMatch?.value === tokenWithoutDefault) return childMatch;
170
+ if (childMatch && !fallbackMatch) fallbackMatch = childMatch;
171
+ }
172
+ if (variableValuesMatchReference(tokenWithoutDefault, itemValue)) {
173
+ if (!fallbackMatch) fallbackMatch = item;
174
+ }
175
+ }
176
+ return fallbackMatch;
177
+ }
178
+ /**
179
+ * Resolve variable tag attrs from a token string (e.g. '{form:name}' or '{user:firstName|Guest}').
180
+ */
181
+ function resolveVariableTagByValue(tokenValue, topLevelVariables, allVariables) {
182
+ const { tokenWithoutDefault, defaultIfEmpty, transformerId, transformerParams } = parseTokenMetadata(tokenValue);
183
+ const resolvedValue = tokenWithoutDefault;
184
+ const topLevelMatch = findMatchingVariableOption(topLevelVariables, tokenWithoutDefault);
185
+ if (topLevelMatch) return buildVariableTagAttrs(topLevelMatch, topLevelMatch, {
186
+ defaultIfEmpty,
187
+ transformerId,
188
+ transformerParams,
189
+ label: resolveVariableTagLabel(resolvedValue, topLevelMatch),
190
+ value: resolvedValue
191
+ });
192
+ const fallback = findMatchingVariableOption(allVariables, tokenWithoutDefault);
193
+ if (fallback) return buildVariableTagAttrs(fallback, fallback, {
194
+ defaultIfEmpty,
195
+ transformerId,
196
+ transformerParams,
197
+ label: resolveVariableTagLabel(resolvedValue, fallback),
198
+ value: resolvedValue
199
+ });
200
+ if (isVariableLikeToken(tokenWithoutDefault)) return {
201
+ label: resolveVariableTagLabel(tokenWithoutDefault, null),
202
+ value: tokenWithoutDefault,
203
+ openOnInsert: false,
204
+ unresolved: true,
205
+ ...defaultIfEmpty ? { default: defaultIfEmpty } : {},
206
+ ...transformerId ? { transformerId } : {},
207
+ ...transformerParams ? { transformerParams } : {}
208
+ };
209
+ return null;
210
+ }
211
+ /**
212
+ * Convert string value with {token} placeholders to Tiptap doc content.
213
+ */
214
+ function valueToContent(value, topLevelVariables, allVariables, trailingCursorText = "​") {
215
+ if (!value) return null;
216
+ const content = value.split(/({.*?})/).flatMap((param) => {
217
+ if (param.includes("{")) {
218
+ const variable = resolveVariableTagByValue(param, topLevelVariables, allVariables);
219
+ if (variable) return [{
220
+ type: "variableTag",
221
+ attrs: variable
222
+ }];
223
+ }
224
+ if (!param) return [];
225
+ return [{
226
+ type: "text",
227
+ text: param
228
+ }];
229
+ });
230
+ if (trailingCursorText && content.length && content[content.length - 1].type === "variableTag") content.push({
231
+ type: "text",
232
+ text: trailingCursorText
233
+ });
234
+ return {
235
+ type: "doc",
236
+ content
237
+ };
238
+ }
239
+ /**
240
+ * Convert Tiptap content to string value.
241
+ * Content is typically editor.getJSON().content (array of block/inline nodes).
242
+ */
243
+ function contentToValue(content) {
244
+ if (!content) return "";
245
+ const items = Array.isArray(content) ? content : [];
246
+ let result = "";
247
+ const visit = (nodes) => {
248
+ nodes.forEach((node) => {
249
+ if (!node || typeof node !== "object") return;
250
+ const n = node;
251
+ if (n.type === "paragraph" && Array.isArray(n.content)) visit(n.content);
252
+ else if (n.type === "text") result += (n.text ?? "").replace(/[\u200B\u2060]/g, "");
253
+ else if (n.type === "variableTag") {
254
+ const val = n.attrs?.value ?? "";
255
+ const def = n.attrs?.default?.trim();
256
+ const transformerId = n.attrs?.transformerId?.trim();
257
+ const transformerParams = n.attrs?.transformerParams;
258
+ result += serializeTokenMetadata(val, {
259
+ defaultIfEmpty: def,
260
+ transformerId,
261
+ transformerParams
262
+ });
263
+ }
264
+ });
265
+ };
266
+ visit(items);
267
+ return result.replace(/[\r\n]+/g, " ");
268
+ }
269
+ /**
270
+ * Replace a range in the editor with a variable tag node.
271
+ * @param editor - Tiptap editor instance
272
+ */
273
+ function replaceTokenWithVariable(editor, attrs, from, to) {
274
+ const { state } = editor;
275
+ const { schema } = state;
276
+ const variableNode = schema.nodes.variableTag?.create(attrs);
277
+ if (!variableNode) return;
278
+ const variableTagExtension = editor.extensionManager.extensions.find((extension) => {
279
+ return extension.name === "variableTag";
280
+ });
281
+ const trailingCursorText = String(variableTagExtension?.options?.trailingCursorText ?? "​");
282
+ const tr = state.tr.deleteRange(from, to);
283
+ tr.insert(from, variableNode);
284
+ if (trailingCursorText) {
285
+ tr.insert(from + variableNode.nodeSize, schema.text(trailingCursorText));
286
+ tr.setSelection(TextSelection.create(tr.doc, from + variableNode.nodeSize + trailingCursorText.length));
287
+ } else tr.setSelection(TextSelection.create(tr.doc, from + variableNode.nodeSize));
288
+ editor.view.dispatch(tr);
289
+ }
290
+ //#endregion
291
+ export { buildVariableTagAttrs, contentToValue, dedupeVariableOptions, flattenVariableOptions, getReferenceBaseToken, parseTokenWithDefault, replaceTokenWithVariable, resolveVariableTagByValue, resolveVariableTagLabel, valueToContent };
292
+
293
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","names":[],"sources":["../../src/serialization/input.ts"],"sourcesContent":["import { TextSelection } from '@tiptap/pm/state';\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport type { VariableOption } from '../types/variable-option.js';\n\nexport type VariableTagAttrs = {\n label: string;\n value: string;\n openOnInsert: boolean;\n /** True when the token did not match a known variable option (display-only). */\n unresolved?: boolean;\n /** Inline default when value is empty (e.g. {user:firstName|Guest}) */\n default?: string;\n /** Optional transform id (e.g. \"round\", \"format\"). */\n transformerId?: string;\n /** Optional transform params payload. */\n transformerParams?: Record<string, unknown>;\n};\n\ntype ParsedTokenMetadata = {\n tokenWithoutDefault: string;\n defaultIfEmpty?: string;\n transformerId?: string;\n transformerParams?: Record<string, unknown>;\n referenceParams?: Record<string, unknown>;\n};\n\nconst TRANSFORMER_ID_PREFIX = 'transform=';\n\nfunction parseTokenMetadata(tokenValue: string): ParsedTokenMetadata {\n const match = tokenValue.match(/^\\{([^}]*)\\}$/);\n if (!match) {\n return { tokenWithoutDefault: tokenValue };\n }\n\n let body = match[1] ?? '';\n let defaultIfEmpty: string | undefined;\n\n if (body.includes('|')) {\n const split = body.split('|');\n body = split.shift() ?? '';\n defaultIfEmpty = split.join('|').trim() || undefined;\n }\n\n const segments = body\n .split(';')\n .map(part => {\n return part.trim();\n })\n .filter(Boolean);\n\n const cleanSegments: string[] = [];\n let transformerId: string | undefined;\n let transformerParams: Record<string, unknown> | undefined;\n const referenceParams: Record<string, unknown> = {};\n let isTransformerParam = false;\n\n segments.forEach((segment) => {\n if (segment.startsWith(TRANSFORMER_ID_PREFIX)) {\n transformerId = decodeURIComponent(segment.slice(TRANSFORMER_ID_PREFIX.length)).trim() || undefined;\n isTransformerParam = true;\n return;\n }\n\n if (segment.includes('=')) {\n const [keyRaw, ...valueParts] = segment.split('=');\n const key = (keyRaw ?? '').trim().toLowerCase();\n if (!key) {\n return;\n }\n\n const value = decodeURIComponent(valueParts.join('=').trim());\n\n if (isTransformerParam) {\n if (!transformerParams) {\n transformerParams = {};\n }\n transformerParams[key] = value;\n return;\n }\n\n referenceParams[key] = value;\n cleanSegments.push(`${key}=${encodeURIComponent(value)}`);\n return;\n }\n\n cleanSegments.push(segment);\n });\n\n const tokenWithoutDefault = `{${cleanSegments.join(';')}}`;\n\n return {\n tokenWithoutDefault,\n defaultIfEmpty,\n transformerId,\n transformerParams,\n referenceParams,\n };\n}\n\nfunction isVariableLikeToken(tokenValue: string): boolean {\n return /^\\{[a-zA-Z][a-zA-Z0-9_]*(?::[^}]*)?\\}$/.test(tokenValue);\n}\n\n/** Craft field UIDs — never surface these as chip labels. */\nconst FIELD_UID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction isLikelyFieldUid(value: string): boolean {\n return FIELD_UID_PATTERN.test(String(value || '').trim());\n}\n\nfunction toTitleWords(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .trim()\n .replace(/\\s+/g, ' ')\n .replace(/\\b\\w/g, char => {\n return char.toUpperCase();\n });\n}\n\n/**\n * Label when no variable option matched. Prefer a clear \"unknown\" prompt over\n * title-casing UIDs (e.g. \"7aff44ed Bca7…\"), which looks broken rather than fixable.\n */\nfunction buildFallbackLabelForUnknownToken(tokenWithoutDefault: string): string {\n const fieldMatch = tokenWithoutDefault.match(/^\\{field:([^}]+)\\}$/);\n if (fieldMatch) {\n return 'Unknown field';\n }\n\n const inner = tokenWithoutDefault.replace(/^\\{|\\}$/g, '');\n const [target = '', identifier = '', selector = ''] = inner.split(':');\n const reference = String(selector || identifier || target).split(';')[0]?.trim() ?? '';\n\n if (isLikelyFieldUid(reference) || isLikelyFieldUid(identifier)) {\n return 'Unknown variable';\n }\n\n if (target) {\n return toTitleWords(reference) || 'Unknown variable';\n }\n\n return 'Unknown variable';\n}\n\nfunction serializeTokenMetadata(\n baseToken: string,\n metadata: {\n defaultIfEmpty?: string;\n transformerId?: string;\n transformerParams?: Record<string, unknown>;\n },\n): string {\n const baseMatch = baseToken.match(/^\\{([^}]*)\\}$/);\n if (!baseMatch) {\n return baseToken;\n }\n\n const parts = [baseMatch[1]];\n const transformerId = metadata.transformerId?.trim();\n\n const params = metadata.transformerParams && typeof metadata.transformerParams === 'object'\n ? Object.entries(metadata.transformerParams)\n : [];\n\n if (transformerId) {\n parts.push(`${TRANSFORMER_ID_PREFIX}${encodeURIComponent(transformerId)}`);\n\n params.forEach(([key, value]) => {\n const normalizedKey = String(key ?? '').trim();\n if (!normalizedKey || normalizedKey === 'transform') {\n return;\n }\n\n const normalizedValue = value == null ? '' : String(value);\n parts.push(`${normalizedKey}=${encodeURIComponent(normalizedValue)}`);\n });\n }\n\n const tokenBody = parts.filter(Boolean).join(';');\n const defaultIfEmpty = metadata.defaultIfEmpty?.trim();\n\n return defaultIfEmpty ? `{${tokenBody}|${defaultIfEmpty}}` : `{${tokenBody}}`;\n}\n\nexport function dedupeVariableOptions(items: VariableOption[]): VariableOption[] {\n const deduped: VariableOption[] = [];\n const seen = new Set<string>();\n\n items.forEach((item) => {\n const key = String(item?.value ?? '') || `__label:${String(item?.label ?? '')}`;\n if (seen.has(key)) {\n return;\n }\n\n seen.add(key);\n deduped.push(item);\n });\n\n return deduped;\n}\n\nexport function flattenVariableOptions(items: VariableOption[]): VariableOption[] {\n const flat: VariableOption[] = [];\n\n const visit = (nodes: VariableOption[]) => {\n nodes.forEach((node) => {\n flat.push(node);\n\n if (Array.isArray(node.children) && node.children.length > 0) {\n visit(node.children);\n }\n });\n };\n\n visit(items);\n return flat;\n}\n\n/**\n * Build VariableTag attributes from base and selected variable options.\n * Optional defaultIfEmpty is used when the resolved value is empty (e.g. \"Guest\" for {user:firstName|Guest}).\n */\nexport function buildVariableTagAttrs(\n baseVariable: VariableOption,\n selectedVariable: VariableOption = baseVariable,\n options: {\n openOnInsert?: boolean;\n defaultIfEmpty?: string;\n transformerId?: string;\n transformerParams?: Record<string, unknown>;\n label?: string;\n value?: string;\n } = {},\n): VariableTagAttrs {\n const selectedLabel = options.label ?? selectedVariable?.label ?? baseVariable?.label ?? '';\n const value = options.value ?? selectedVariable?.value ?? baseVariable?.value ?? '';\n const defaultIfEmpty = options.defaultIfEmpty?.trim();\n\n const attrs: VariableTagAttrs = {\n label: selectedLabel,\n value,\n openOnInsert: options.openOnInsert ?? false,\n };\n if (defaultIfEmpty) {\n attrs.default = defaultIfEmpty;\n }\n if (options.transformerId?.trim()) {\n attrs.transformerId = options.transformerId.trim();\n }\n if (options.transformerParams && typeof options.transformerParams === 'object') {\n attrs.transformerParams = options.transformerParams;\n }\n return attrs;\n}\n\n/**\n * Strip optional inline default from token for lookup: {user:firstName|Guest} -> {user:firstName}.\n * Returns [tokenWithoutDefault, defaultText].\n */\nexport function parseTokenWithDefault(tokenValue: string): [string, string | undefined] {\n const parsed = parseTokenMetadata(tokenValue);\n return [parsed.tokenWithoutDefault, parsed.defaultIfEmpty];\n}\n\nexport function getReferenceBaseToken(tokenValue: string): string {\n const [tokenWithoutDefault] = parseTokenWithDefault(tokenValue);\n const match = tokenWithoutDefault.match(/^\\{([^}]*)\\}$/);\n\n if (!match) {\n return tokenWithoutDefault;\n }\n\n const body = match[1].split(';')[0]?.trim() ?? '';\n\n return body ? `{${body}}` : tokenWithoutDefault;\n}\n\nfunction variableValuesMatchReference(tokenValue: string, optionValue: string): boolean {\n if (!tokenValue || !optionValue) {\n return false;\n }\n\n if (tokenValue === optionValue) {\n return true;\n }\n\n return getReferenceBaseToken(tokenValue) === getReferenceBaseToken(optionValue);\n}\n\nexport function resolveVariableTagLabel(\n tokenValue: string,\n option: VariableOption | null,\n): string {\n const { tokenWithoutDefault } = parseTokenMetadata(String(tokenValue || ''));\n\n if (option?.label) {\n return option.label;\n }\n\n return buildFallbackLabelForUnknownToken(tokenWithoutDefault);\n}\n\nfunction findMatchingVariableOption(\n items: VariableOption[],\n tokenWithoutDefault: string,\n): VariableOption | null {\n let fallbackMatch: VariableOption | null = null;\n\n for (const item of items) {\n const children = Array.isArray(item.children) ? item.children : [];\n const itemValue = String(item.value ?? '');\n if (itemValue === tokenWithoutDefault) {\n return item;\n }\n\n if (children.length) {\n const childMatch = findMatchingVariableOption(children, tokenWithoutDefault);\n if (childMatch?.value === tokenWithoutDefault) {\n return childMatch;\n }\n\n if (childMatch && !fallbackMatch) {\n fallbackMatch = childMatch;\n }\n }\n\n if (variableValuesMatchReference(tokenWithoutDefault, itemValue)) {\n if (!fallbackMatch) {\n fallbackMatch = item;\n }\n }\n }\n\n return fallbackMatch;\n}\n\n/**\n * Resolve variable tag attrs from a token string (e.g. '{form:name}' or '{user:firstName|Guest}').\n */\nexport function resolveVariableTagByValue(\n tokenValue: string,\n topLevelVariables: VariableOption[],\n allVariables: VariableOption[],\n): VariableTagAttrs | null {\n const {\n tokenWithoutDefault,\n defaultIfEmpty,\n transformerId,\n transformerParams,\n } = parseTokenMetadata(tokenValue);\n const resolvedValue = tokenWithoutDefault;\n\n const topLevelMatch = findMatchingVariableOption(topLevelVariables, tokenWithoutDefault);\n if (topLevelMatch) {\n return buildVariableTagAttrs(topLevelMatch, topLevelMatch, {\n defaultIfEmpty,\n transformerId,\n transformerParams,\n label: resolveVariableTagLabel(resolvedValue, topLevelMatch),\n value: resolvedValue,\n });\n }\n\n const fallback = findMatchingVariableOption(allVariables, tokenWithoutDefault);\n if (fallback) {\n return buildVariableTagAttrs(fallback, fallback, {\n defaultIfEmpty,\n transformerId,\n transformerParams,\n label: resolveVariableTagLabel(resolvedValue, fallback),\n value: resolvedValue,\n });\n }\n\n // For cross-form / deleted-field / categories-not-ready contexts, unresolved\n // tokens still render as chips — with unresolved styling + a fixable label\n // (never a raw field UID title-cased into the chip).\n if (isVariableLikeToken(tokenWithoutDefault)) {\n return {\n label: resolveVariableTagLabel(tokenWithoutDefault, null),\n value: tokenWithoutDefault,\n openOnInsert: false,\n unresolved: true,\n ...(defaultIfEmpty ? { default: defaultIfEmpty } : {}),\n ...(transformerId ? { transformerId } : {}),\n ...(transformerParams ? { transformerParams } : {}),\n };\n }\n\n return null;\n}\n\n/**\n * Convert string value with {token} placeholders to Tiptap doc content.\n */\nexport function valueToContent(\n value: string,\n topLevelVariables: VariableOption[],\n allVariables: VariableOption[],\n trailingCursorText = '\\u200B',\n): JSONContent | null {\n if (!value) {\n return null;\n }\n\n const parts = value.split(/({.*?})/);\n type ContentNode = NonNullable<JSONContent['content']>[number];\n const content: ContentNode[] = parts.flatMap((param): ContentNode[] => {\n if (param.includes('{')) {\n const variable = resolveVariableTagByValue(param, topLevelVariables, allVariables);\n if (variable) {\n return [{ type: 'variableTag', attrs: variable }];\n }\n\n }\n if (!param) {\n return [];\n }\n return [{ type: 'text', text: param }];\n });\n\n if (trailingCursorText && content.length && (content[content.length - 1] as { type?: string }).type === 'variableTag') {\n content.push({ type: 'text', text: trailingCursorText });\n }\n\n return { type: 'doc', content };\n}\n\n/**\n * Convert Tiptap content to string value.\n * Content is typically editor.getJSON().content (array of block/inline nodes).\n */\nexport function contentToValue(content: unknown): string {\n if (!content) {\n return '';\n }\n\n const items = Array.isArray(content) ? content : [];\n let result = '';\n\n const visit = (nodes: unknown[]) => {\n nodes.forEach((node) => {\n if (!node || typeof node !== 'object') {\n return;\n }\n const n = node as {\n type?: string;\n content?: unknown[];\n text?: string;\n attrs?: {\n value?: string;\n default?: string;\n transformerId?: string;\n transformerParams?: Record<string, unknown>;\n };\n };\n if (n.type === 'paragraph' && Array.isArray(n.content)) {\n visit(n.content);\n } else if (n.type === 'text') {\n result += (n.text ?? '').replace(/[\\u200B\\u2060]/g, '');\n } else if (n.type === 'variableTag') {\n const val = n.attrs?.value ?? '';\n const def = n.attrs?.default?.trim();\n const transformerId = n.attrs?.transformerId?.trim();\n const transformerParams = n.attrs?.transformerParams;\n result += serializeTokenMetadata(val, {\n defaultIfEmpty: def,\n transformerId,\n transformerParams,\n });\n }\n });\n };\n\n visit(items);\n return result.replace(/[\\r\\n]+/g, ' ');\n}\n\n/**\n * Replace a range in the editor with a variable tag node.\n * @param editor - Tiptap editor instance\n */\nexport function replaceTokenWithVariable(\n editor: Editor,\n attrs: VariableTagAttrs,\n from: number,\n to: number,\n): void {\n const { state } = editor;\n const { schema } = state;\n const variableNode = schema.nodes.variableTag?.create(attrs);\n if (!variableNode) {\n return;\n }\n\n const variableTagExtension = editor.extensionManager.extensions.find((extension) => {\n return extension.name === 'variableTag';\n });\n const trailingCursorText = String(variableTagExtension?.options?.trailingCursorText ?? '\\u200B');\n const tr = state.tr.deleteRange(from, to);\n tr.insert(from, variableNode);\n if (trailingCursorText) {\n tr.insert(from + variableNode.nodeSize, schema.text(trailingCursorText));\n tr.setSelection(TextSelection.create(tr.doc, from + variableNode.nodeSize + trailingCursorText.length));\n } else {\n tr.setSelection(TextSelection.create(tr.doc, from + variableNode.nodeSize));\n }\n editor.view.dispatch(tr);\n}\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Editor } from '@tiptap/core';
2
+ export type TiptapButtonName = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'subscript' | 'superscript' | 'unordered-list' | 'ordered-list' | 'blockquote' | 'highlight' | 'code' | 'code-block' | 'hr' | 'line-break' | 'align-left' | 'align-center' | 'align-right' | 'align-justify' | 'clear-format' | 'undo' | 'redo' | 'link' | 'table' | 'variableTag' | `h${1 | 2 | 3 | 4 | 5 | 6}`;
3
+ export type TiptapTableInsertOptions = {
4
+ rows?: number;
5
+ cols?: number;
6
+ withHeaderRow?: boolean;
7
+ };
8
+ export type RunTiptapButtonOptions = {
9
+ tableOptions?: TiptapTableInsertOptions;
10
+ };
11
+ export declare function isTiptapButtonName(value: string): value is TiptapButtonName;
12
+ export declare function isTiptapButtonActive(editor: Editor, buttonName: string): boolean;
13
+ export declare function runTiptapButton(editor: Editor, buttonName: string, options?: RunTiptapButtonOptions): boolean;
14
+ //# sourceMappingURL=button-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-registry.d.ts","sourceRoot":"","sources":["../../src/toolbar/button-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,MAAM,gBAAgB,GACtB,MAAM,GACN,QAAQ,GACR,WAAW,GACX,eAAe,GACf,WAAW,GACX,aAAa,GACb,gBAAgB,GAChB,cAAc,GACd,YAAY,GACZ,WAAW,GACX,MAAM,GACN,YAAY,GACZ,IAAI,GACJ,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,aAAa,GACb,eAAe,GACf,cAAc,GACd,MAAM,GACN,MAAM,GACN,MAAM,GACN,OAAO,GACP,aAAa,GACb,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;AAElC,MAAM,MAAM,wBAAwB,GAAG;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,YAAY,CAAC,EAAE,wBAAwB,CAAC;CAC3C,CAAC;AAIF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,gBAAgB,CA+B3E;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAmDhF;AAED,wBAAgB,eAAe,CAC3B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACrC,OAAO,CAsET"}
@@ -0,0 +1,114 @@
1
+ //#region src/toolbar/button-registry.ts
2
+ var HEADING_LEVELS = [
3
+ 1,
4
+ 2,
5
+ 3,
6
+ 4,
7
+ 5,
8
+ 6
9
+ ];
10
+ function isTiptapButtonName(value) {
11
+ if (HEADING_LEVELS.some((level) => value === `h${level}`)) return true;
12
+ return [
13
+ "bold",
14
+ "italic",
15
+ "underline",
16
+ "strikethrough",
17
+ "subscript",
18
+ "superscript",
19
+ "unordered-list",
20
+ "ordered-list",
21
+ "blockquote",
22
+ "highlight",
23
+ "code",
24
+ "code-block",
25
+ "hr",
26
+ "line-break",
27
+ "align-left",
28
+ "align-center",
29
+ "align-right",
30
+ "align-justify",
31
+ "clear-format",
32
+ "undo",
33
+ "redo",
34
+ "link",
35
+ "table",
36
+ "variableTag"
37
+ ].includes(value);
38
+ }
39
+ function isTiptapButtonActive(editor, buttonName) {
40
+ if (!isTiptapButtonName(buttonName)) return false;
41
+ const headingMatch = buttonName.match(/^h([1-6])$/);
42
+ if (headingMatch) {
43
+ const level = Number(headingMatch[1]);
44
+ return editor.isActive("heading", { level });
45
+ }
46
+ switch (buttonName) {
47
+ case "bold": return editor.isActive("bold");
48
+ case "italic": return editor.isActive("italic");
49
+ case "underline": return editor.isActive("underline");
50
+ case "strikethrough": return editor.isActive("strike");
51
+ case "subscript": return editor.isActive("subscript");
52
+ case "superscript": return editor.isActive("superscript");
53
+ case "unordered-list": return editor.isActive("bulletList");
54
+ case "ordered-list": return editor.isActive("orderedList");
55
+ case "blockquote": return editor.isActive("blockquote");
56
+ case "highlight": return editor.isActive("highlight");
57
+ case "code": return editor.isActive("code");
58
+ case "code-block": return editor.isActive("codeBlock");
59
+ case "align-left": return editor.isActive({ textAlign: "left" });
60
+ case "align-center": return editor.isActive({ textAlign: "center" });
61
+ case "align-right": return editor.isActive({ textAlign: "right" });
62
+ case "align-justify": return editor.isActive({ textAlign: "justify" });
63
+ case "link": return editor.isActive("link");
64
+ case "variableTag": return editor.isActive("variableTag");
65
+ default: return false;
66
+ }
67
+ }
68
+ function runTiptapButton(editor, buttonName, options = {}) {
69
+ if (!isTiptapButtonName(buttonName)) return false;
70
+ const chain = editor.chain().focus();
71
+ const headingMatch = buttonName.match(/^h([1-6])$/);
72
+ if (headingMatch) {
73
+ const level = Number(headingMatch[1]);
74
+ return chain.toggleHeading({ level }).run();
75
+ }
76
+ switch (buttonName) {
77
+ case "bold": return chain.toggleBold().run();
78
+ case "italic": return chain.toggleItalic().run();
79
+ case "underline": return chain.toggleUnderline().run();
80
+ case "strikethrough": return chain.toggleStrike().run();
81
+ case "subscript": return chain.toggleSubscript().run();
82
+ case "superscript": return chain.toggleSuperscript().run();
83
+ case "unordered-list": return chain.toggleBulletList().run();
84
+ case "ordered-list": return chain.toggleOrderedList().run();
85
+ case "blockquote": return chain.toggleBlockquote().run();
86
+ case "highlight": return chain.toggleHighlight().run();
87
+ case "code": return chain.toggleCode().run();
88
+ case "code-block": return chain.toggleCodeBlock().run();
89
+ case "hr": return chain.setHorizontalRule().run();
90
+ case "line-break": return chain.setHardBreak().run();
91
+ case "align-left": return chain.setTextAlign("left").run();
92
+ case "align-center": return chain.setTextAlign("center").run();
93
+ case "align-right": return chain.setTextAlign("right").run();
94
+ case "align-justify": return chain.setTextAlign("justify").run();
95
+ case "clear-format": return chain.clearNodes().unsetAllMarks().run();
96
+ case "undo": return chain.undo().run();
97
+ case "redo": return chain.redo().run();
98
+ case "table": {
99
+ const tableOptions = options.tableOptions ?? {};
100
+ return chain.insertTable({
101
+ rows: tableOptions.rows ?? 3,
102
+ cols: tableOptions.cols ?? 3,
103
+ withHeaderRow: tableOptions.withHeaderRow ?? true
104
+ }).run();
105
+ }
106
+ case "link":
107
+ case "variableTag": return false;
108
+ default: return false;
109
+ }
110
+ }
111
+ //#endregion
112
+ export { isTiptapButtonActive, isTiptapButtonName, runTiptapButton };
113
+
114
+ //# sourceMappingURL=button-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-registry.js","names":[],"sources":["../../src/toolbar/button-registry.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core';\n\nexport type TiptapButtonName =\n | 'bold'\n | 'italic'\n | 'underline'\n | 'strikethrough'\n | 'subscript'\n | 'superscript'\n | 'unordered-list'\n | 'ordered-list'\n | 'blockquote'\n | 'highlight'\n | 'code'\n | 'code-block'\n | 'hr'\n | 'line-break'\n | 'align-left'\n | 'align-center'\n | 'align-right'\n | 'align-justify'\n | 'clear-format'\n | 'undo'\n | 'redo'\n | 'link'\n | 'table'\n | 'variableTag'\n | `h${1 | 2 | 3 | 4 | 5 | 6}`;\n\nexport type TiptapTableInsertOptions = {\n rows?: number;\n cols?: number;\n withHeaderRow?: boolean;\n};\n\nexport type RunTiptapButtonOptions = {\n tableOptions?: TiptapTableInsertOptions;\n};\n\nconst HEADING_LEVELS = [1, 2, 3, 4, 5, 6] as const;\n\nexport function isTiptapButtonName(value: string): value is TiptapButtonName {\n if (HEADING_LEVELS.some((level) => value === `h${level}`)) {\n return true;\n }\n\n return [\n 'bold',\n 'italic',\n 'underline',\n 'strikethrough',\n 'subscript',\n 'superscript',\n 'unordered-list',\n 'ordered-list',\n 'blockquote',\n 'highlight',\n 'code',\n 'code-block',\n 'hr',\n 'line-break',\n 'align-left',\n 'align-center',\n 'align-right',\n 'align-justify',\n 'clear-format',\n 'undo',\n 'redo',\n 'link',\n 'table',\n 'variableTag',\n ].includes(value);\n}\n\nexport function isTiptapButtonActive(editor: Editor, buttonName: string): boolean {\n if (!isTiptapButtonName(buttonName)) {\n return false;\n }\n\n const headingMatch = buttonName.match(/^h([1-6])$/);\n if (headingMatch) {\n const level = Number(headingMatch[1]) as 1 | 2 | 3 | 4 | 5 | 6;\n return editor.isActive('heading', { level });\n }\n\n switch (buttonName) {\n case 'bold':\n return editor.isActive('bold');\n case 'italic':\n return editor.isActive('italic');\n case 'underline':\n return editor.isActive('underline');\n case 'strikethrough':\n return editor.isActive('strike');\n case 'subscript':\n return editor.isActive('subscript');\n case 'superscript':\n return editor.isActive('superscript');\n case 'unordered-list':\n return editor.isActive('bulletList');\n case 'ordered-list':\n return editor.isActive('orderedList');\n case 'blockquote':\n return editor.isActive('blockquote');\n case 'highlight':\n return editor.isActive('highlight');\n case 'code':\n return editor.isActive('code');\n case 'code-block':\n return editor.isActive('codeBlock');\n case 'align-left':\n return editor.isActive({ textAlign: 'left' });\n case 'align-center':\n return editor.isActive({ textAlign: 'center' });\n case 'align-right':\n return editor.isActive({ textAlign: 'right' });\n case 'align-justify':\n return editor.isActive({ textAlign: 'justify' });\n case 'link':\n return editor.isActive('link');\n case 'variableTag':\n return editor.isActive('variableTag');\n default:\n return false;\n }\n}\n\nexport function runTiptapButton(\n editor: Editor,\n buttonName: string,\n options: RunTiptapButtonOptions = {},\n): boolean {\n if (!isTiptapButtonName(buttonName)) {\n return false;\n }\n\n const chain = editor.chain().focus();\n const headingMatch = buttonName.match(/^h([1-6])$/);\n\n if (headingMatch) {\n const level = Number(headingMatch[1]) as 1 | 2 | 3 | 4 | 5 | 6;\n return chain.toggleHeading({ level }).run();\n }\n\n switch (buttonName) {\n case 'bold':\n return chain.toggleBold().run();\n case 'italic':\n return chain.toggleItalic().run();\n case 'underline':\n return chain.toggleUnderline().run();\n case 'strikethrough':\n return chain.toggleStrike().run();\n case 'subscript':\n return chain.toggleSubscript().run();\n case 'superscript':\n return chain.toggleSuperscript().run();\n case 'unordered-list':\n return chain.toggleBulletList().run();\n case 'ordered-list':\n return chain.toggleOrderedList().run();\n case 'blockquote':\n return chain.toggleBlockquote().run();\n case 'highlight':\n return chain.toggleHighlight().run();\n case 'code':\n return chain.toggleCode().run();\n case 'code-block':\n return chain.toggleCodeBlock().run();\n case 'hr':\n return chain.setHorizontalRule().run();\n case 'line-break':\n return chain.setHardBreak().run();\n case 'align-left':\n return chain.setTextAlign('left').run();\n case 'align-center':\n return chain.setTextAlign('center').run();\n case 'align-right':\n return chain.setTextAlign('right').run();\n case 'align-justify':\n return chain.setTextAlign('justify').run();\n case 'clear-format':\n return chain.clearNodes().unsetAllMarks().run();\n case 'undo':\n return chain.undo().run();\n case 'redo':\n return chain.redo().run();\n case 'table': {\n const tableOptions = options.tableOptions ?? {};\n return chain.insertTable({\n rows: tableOptions.rows ?? 3,\n cols: tableOptions.cols ?? 3,\n withHeaderRow: tableOptions.withHeaderRow ?? true,\n }).run();\n }\n case 'link':\n case 'variableTag':\n return false;\n default:\n return false;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './button-registry.js';
2
+ export * from './toolbar-schema.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/toolbar/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { isTiptapButtonActive, isTiptapButtonName, runTiptapButton } from "./button-registry.js";
2
+ import { expandPresetItems, flattenToolbarButtonNames, getToolbarGroupDefaultIcon, getToolbarGroupItems, getToolbarGroupMenuItems, getToolbarGroupTriggerState, isFormattingToolbarPreset, isHeadingsOnlyToolbarPreset, isToolbarButtonActive, isToolbarSeparatorToken, normalizeToolbarNodes, parseToolbarConfig, runToolbarButton, toolbarIncludesButton } from "./toolbar-schema.js";
3
+ export { expandPresetItems, flattenToolbarButtonNames, getToolbarGroupDefaultIcon, getToolbarGroupItems, getToolbarGroupMenuItems, getToolbarGroupTriggerState, isFormattingToolbarPreset, isHeadingsOnlyToolbarPreset, isTiptapButtonActive, isTiptapButtonName, isToolbarButtonActive, isToolbarSeparatorToken, normalizeToolbarNodes, parseToolbarConfig, runTiptapButton, runToolbarButton, toolbarIncludesButton };
@@ -0,0 +1,66 @@
1
+ import { Editor } from '@tiptap/core';
2
+ import { RunTiptapButtonOptions, TiptapButtonName } from './button-registry.js';
3
+ /** Toolbar chrome icons that are not editor commands. */
4
+ export type ToolbarIconName = TiptapButtonName | 'paragraph' | 'heading';
5
+ export type ToolbarSeparatorToken = '|' | 'separator';
6
+ /** Paragraph, headings, blockquote, and code block. */
7
+ export type ToolbarFormattingPreset = 'formatting';
8
+ /** Heading levels only — TipTap-style trigger with icon menu items. */
9
+ export type ToolbarHeadingsPreset = 'headings';
10
+ export type ToolbarGroupPreset = ToolbarFormattingPreset | ToolbarHeadingsPreset | 'lists' | 'align';
11
+ export type ToolbarHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
12
+ export type ToolbarGroupMenuButton = TiptapButtonName | 'paragraph';
13
+ export type ToolbarGroupMenuEntry = {
14
+ type: 'item';
15
+ name: ToolbarGroupMenuButton;
16
+ } | {
17
+ type: 'separator';
18
+ };
19
+ /** Custom dropdown item — buttons, paragraph, or separators. */
20
+ export type ToolbarGroupItemDefinition = ToolbarGroupMenuButton | ToolbarSeparatorToken | {
21
+ type: 'separator';
22
+ };
23
+ export type ToolbarGroup = {
24
+ label?: string;
25
+ icon?: TiptapButtonName;
26
+ preset?: ToolbarGroupPreset;
27
+ items?: ToolbarGroupItemDefinition[];
28
+ headingLevels?: ToolbarHeadingLevel[];
29
+ };
30
+ export type ToolbarButtonNode = {
31
+ type: 'button';
32
+ name: TiptapButtonName;
33
+ };
34
+ export type ToolbarSeparatorNode = {
35
+ type: 'separator';
36
+ };
37
+ export type ToolbarGroupNode = {
38
+ type: 'group';
39
+ group: ToolbarGroup;
40
+ };
41
+ export type ToolbarNode = ToolbarButtonNode | ToolbarSeparatorNode | ToolbarGroupNode;
42
+ export type ToolbarGroupTriggerState = {
43
+ /** Active item inside the group, or `paragraph` for formatting presets when in body text. */
44
+ activeName: TiptapButtonName | 'paragraph' | null;
45
+ /** Short label for the trigger (e.g. `H2`, `Text`). */
46
+ label: string;
47
+ /** Whether any item in the group is currently active. */
48
+ isActive: boolean;
49
+ /** Icon to render on the trigger when no text label is preferred. */
50
+ icon: ToolbarIconName;
51
+ };
52
+ export declare function isFormattingToolbarPreset(preset?: ToolbarGroupPreset): preset is ToolbarFormattingPreset;
53
+ export declare function isHeadingsOnlyToolbarPreset(preset?: ToolbarGroupPreset): preset is ToolbarHeadingsPreset;
54
+ export declare function getToolbarGroupDefaultIcon(group: ToolbarGroup): ToolbarIconName;
55
+ export declare function isToolbarSeparatorToken(value: string): value is ToolbarSeparatorToken;
56
+ export declare function expandPresetItems(group: ToolbarGroup): TiptapButtonName[];
57
+ export declare function getToolbarGroupItems(group: ToolbarGroup): TiptapButtonName[];
58
+ export declare function flattenToolbarButtonNames(nodes: ToolbarNode[]): TiptapButtonName[];
59
+ export declare function toolbarIncludesButton(nodes: ToolbarNode[], buttonName: string): boolean;
60
+ export declare function normalizeToolbarNodes(raw: unknown[]): ToolbarNode[];
61
+ export declare function parseToolbarConfig(input: unknown): ToolbarNode[];
62
+ export declare function runToolbarButton(editor: Editor, buttonName: string, options?: RunTiptapButtonOptions): boolean;
63
+ export declare function isToolbarButtonActive(editor: Editor, buttonName: string): boolean;
64
+ export declare function getToolbarGroupTriggerState(editor: Editor, group: ToolbarGroup): ToolbarGroupTriggerState;
65
+ export declare function getToolbarGroupMenuItems(group: ToolbarGroup): ToolbarGroupMenuEntry[];
66
+ //# sourceMappingURL=toolbar-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar-schema.d.ts","sourceRoot":"","sources":["../../src/toolbar/toolbar-schema.ts"],"names":[],"mappings":"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"}