@verbb/plugin-kit-react 1.0.0 → 1.0.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.
- package/CHANGELOG.md +15 -0
- package/dist/components/SelectInput.js +1 -1
- package/dist/components/SelectInput.js.map +1 -1
- package/dist/components/TiptapEditor.d.ts +4 -2
- package/dist/components/TiptapEditor.d.ts.map +1 -1
- package/dist/components/TiptapEditor.js +27 -9
- package/dist/components/TiptapEditor.js.map +1 -1
- package/dist/components/TiptapInput.d.ts +18 -13
- package/dist/components/TiptapInput.d.ts.map +1 -1
- package/dist/components/TiptapInput.js +3 -1
- package/dist/components/TiptapInput.js.map +1 -1
- package/dist/components/tiptap/VariableDropdown.d.ts +7 -0
- package/dist/components/tiptap/VariableDropdown.d.ts.map +1 -1
- package/dist/components/tiptap/VariableDropdown.js.map +1 -1
- package/dist/components/tiptap/VariablePickerContext.d.ts +22 -2
- package/dist/components/tiptap/VariablePickerContext.d.ts.map +1 -1
- package/dist/components/tiptap/VariablePickerContext.js +7 -3
- package/dist/components/tiptap/VariablePickerContext.js.map +1 -1
- package/dist/components/tiptap/VariableTagView.d.ts.map +1 -1
- package/dist/components/tiptap/VariableTagView.js +160 -21
- package/dist/components/tiptap/VariableTagView.js.map +1 -1
- package/dist/components/tiptap/variableSerialization.d.ts +4 -0
- package/dist/components/tiptap/variableSerialization.d.ts.map +1 -1
- package/dist/components/tiptap/variableSerialization.js +71 -30
- package/dist/components/tiptap/variableSerialization.js.map +1 -1
- package/dist/forms/contexts/VariableCategoriesContext.d.ts +3 -1
- package/dist/forms/contexts/VariableCategoriesContext.d.ts.map +1 -1
- package/dist/forms/contexts/VariableCategoriesContext.js +3 -1
- package/dist/forms/contexts/VariableCategoriesContext.js.map +1 -1
- package/dist/forms/fields/RichTextField.d.ts.map +1 -1
- package/dist/forms/fields/RichTextField.js +3 -1
- package/dist/forms/fields/RichTextField.js.map +1 -1
- package/dist/forms/fields/SelectField.js +1 -1
- package/dist/forms/fields/SelectField.js.map +1 -1
- package/dist/forms/fields/VariablePickerField.d.ts.map +1 -1
- package/dist/forms/fields/VariablePickerField.js +3 -1
- package/dist/forms/fields/VariablePickerField.js.map +1 -1
- package/package.json +5 -4
|
@@ -21,18 +21,26 @@ function parseTokenMetadata(tokenValue) {
|
|
|
21
21
|
const cleanSegments = [];
|
|
22
22
|
let transformerId;
|
|
23
23
|
let transformerParams;
|
|
24
|
+
const referenceParams = {};
|
|
25
|
+
let isTransformerParam = false;
|
|
24
26
|
segments.forEach((segment) => {
|
|
25
27
|
if (segment.startsWith(TRANSFORMER_ID_PREFIX)) {
|
|
26
28
|
transformerId = decodeURIComponent(segment.slice(10)).trim() || void 0;
|
|
29
|
+
isTransformerParam = true;
|
|
27
30
|
return;
|
|
28
31
|
}
|
|
29
32
|
if (segment.includes("=")) {
|
|
30
33
|
const [keyRaw, ...valueParts] = segment.split("=");
|
|
31
|
-
const key = (keyRaw ?? "").trim();
|
|
34
|
+
const key = (keyRaw ?? "").trim().toLowerCase();
|
|
32
35
|
if (!key) return;
|
|
33
36
|
const value = decodeURIComponent(valueParts.join("=").trim());
|
|
34
|
-
if (
|
|
35
|
-
|
|
37
|
+
if (isTransformerParam) {
|
|
38
|
+
if (!transformerParams) transformerParams = {};
|
|
39
|
+
transformerParams[key] = value;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
referenceParams[key] = value;
|
|
43
|
+
cleanSegments.push(`${key}=${encodeURIComponent(value)}`);
|
|
36
44
|
return;
|
|
37
45
|
}
|
|
38
46
|
cleanSegments.push(segment);
|
|
@@ -41,7 +49,8 @@ function parseTokenMetadata(tokenValue) {
|
|
|
41
49
|
tokenWithoutDefault: `{${cleanSegments.join(";")}}`,
|
|
42
50
|
defaultIfEmpty,
|
|
43
51
|
transformerId,
|
|
44
|
-
transformerParams
|
|
52
|
+
transformerParams,
|
|
53
|
+
referenceParams
|
|
45
54
|
};
|
|
46
55
|
}
|
|
47
56
|
function isVariableLikeToken(tokenValue) {
|
|
@@ -53,9 +62,15 @@ function toTitleWords(value) {
|
|
|
53
62
|
});
|
|
54
63
|
}
|
|
55
64
|
function buildFallbackLabelForUnknownToken(tokenWithoutDefault) {
|
|
65
|
+
const fieldMatch = tokenWithoutDefault.match(/^\{field:([^}]+)\}$/);
|
|
66
|
+
if (fieldMatch) {
|
|
67
|
+
const segments = (fieldMatch[1].split(";")[0]?.trim() ?? "").split(":").filter(Boolean);
|
|
68
|
+
if (segments.length >= 2) return toTitleWords(segments[segments.length - 1] ?? "") || "Field";
|
|
69
|
+
if (segments.length === 1) return toTitleWords(segments[0] ?? "") || "Field";
|
|
70
|
+
return "Field";
|
|
71
|
+
}
|
|
56
72
|
const [target = "", identifier = "", selector = ""] = tokenWithoutDefault.replace(/^\{|\}$/g, "").split(":");
|
|
57
|
-
if (target
|
|
58
|
-
if (target) return toTitleWords(selector || identifier || target) || tokenWithoutDefault;
|
|
73
|
+
if (target) return toTitleWords(String(selector || identifier || target).split(";")[0]?.trim() ?? "") || tokenWithoutDefault;
|
|
59
74
|
return tokenWithoutDefault;
|
|
60
75
|
}
|
|
61
76
|
function serializeTokenMetadata(baseToken, metadata) {
|
|
@@ -63,9 +78,10 @@ function serializeTokenMetadata(baseToken, metadata) {
|
|
|
63
78
|
if (!baseMatch) return baseToken;
|
|
64
79
|
const parts = [baseMatch[1]];
|
|
65
80
|
const transformerId = metadata.transformerId?.trim();
|
|
81
|
+
const params = metadata.transformerParams && typeof metadata.transformerParams === "object" ? Object.entries(metadata.transformerParams) : [];
|
|
66
82
|
if (transformerId) {
|
|
67
83
|
parts.push(`${TRANSFORMER_ID_PREFIX}${encodeURIComponent(transformerId)}`);
|
|
68
|
-
|
|
84
|
+
params.forEach(([key, value]) => {
|
|
69
85
|
const normalizedKey = String(key ?? "").trim();
|
|
70
86
|
if (!normalizedKey || normalizedKey === "transform") return;
|
|
71
87
|
const normalizedValue = value == null ? "" : String(value);
|
|
@@ -103,8 +119,8 @@ function flattenVariableOptions(items) {
|
|
|
103
119
|
* Optional defaultIfEmpty is used when the resolved value is empty (e.g. "Guest" for {user:firstName|Guest}).
|
|
104
120
|
*/
|
|
105
121
|
function buildVariableTagAttrs(baseVariable, selectedVariable = baseVariable, options = {}) {
|
|
106
|
-
const selectedLabel = selectedVariable?.label ?? baseVariable?.label ?? "";
|
|
107
|
-
const value = selectedVariable?.value ?? baseVariable?.value ?? "";
|
|
122
|
+
const selectedLabel = options.label ?? selectedVariable?.label ?? baseVariable?.label ?? "";
|
|
123
|
+
const value = options.value ?? selectedVariable?.value ?? baseVariable?.value ?? "";
|
|
108
124
|
const defaultIfEmpty = options.defaultIfEmpty?.trim();
|
|
109
125
|
const attrs = {
|
|
110
126
|
label: selectedLabel,
|
|
@@ -124,39 +140,64 @@ function parseTokenWithDefault(tokenValue) {
|
|
|
124
140
|
const parsed = parseTokenMetadata(tokenValue);
|
|
125
141
|
return [parsed.tokenWithoutDefault, parsed.defaultIfEmpty];
|
|
126
142
|
}
|
|
143
|
+
function getReferenceBaseToken(tokenValue) {
|
|
144
|
+
const [tokenWithoutDefault] = parseTokenWithDefault(tokenValue);
|
|
145
|
+
const match = tokenWithoutDefault.match(/^\{([^}]*)\}$/);
|
|
146
|
+
if (!match) return tokenWithoutDefault;
|
|
147
|
+
const body = match[1].split(";")[0]?.trim() ?? "";
|
|
148
|
+
return body ? `{${body}}` : tokenWithoutDefault;
|
|
149
|
+
}
|
|
150
|
+
function variableValuesMatchReference(tokenValue, optionValue) {
|
|
151
|
+
if (!tokenValue || !optionValue) return false;
|
|
152
|
+
if (tokenValue === optionValue) return true;
|
|
153
|
+
return getReferenceBaseToken(tokenValue) === getReferenceBaseToken(optionValue);
|
|
154
|
+
}
|
|
155
|
+
function resolveVariableTagLabel(tokenValue, option) {
|
|
156
|
+
const { tokenWithoutDefault } = parseTokenMetadata(String(tokenValue || ""));
|
|
157
|
+
if (option?.label) return option.label;
|
|
158
|
+
return buildFallbackLabelForUnknownToken(tokenWithoutDefault);
|
|
159
|
+
}
|
|
160
|
+
function findMatchingVariableOption(items, tokenWithoutDefault) {
|
|
161
|
+
let fallbackMatch = null;
|
|
162
|
+
for (const item of items) {
|
|
163
|
+
const children = Array.isArray(item.children) ? item.children : [];
|
|
164
|
+
const itemValue = String(item.value ?? "");
|
|
165
|
+
if (itemValue === tokenWithoutDefault) return item;
|
|
166
|
+
if (children.length) {
|
|
167
|
+
const childMatch = findMatchingVariableOption(children, tokenWithoutDefault);
|
|
168
|
+
if (childMatch?.value === tokenWithoutDefault) return childMatch;
|
|
169
|
+
if (childMatch && !fallbackMatch) fallbackMatch = childMatch;
|
|
170
|
+
}
|
|
171
|
+
if (variableValuesMatchReference(tokenWithoutDefault, itemValue)) {
|
|
172
|
+
if (!fallbackMatch) fallbackMatch = item;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return fallbackMatch;
|
|
176
|
+
}
|
|
127
177
|
/**
|
|
128
178
|
* Resolve variable tag attrs from a token string (e.g. '{form:name}' or '{user:firstName|Guest}').
|
|
129
179
|
*/
|
|
130
180
|
function resolveVariableTagByValue(tokenValue, topLevelVariables, allVariables) {
|
|
131
181
|
const { tokenWithoutDefault, defaultIfEmpty, transformerId, transformerParams } = parseTokenMetadata(tokenValue);
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (exactTopLevel) return buildVariableTagAttrs(exactTopLevel, exactTopLevel, {
|
|
182
|
+
const resolvedValue = tokenWithoutDefault;
|
|
183
|
+
const topLevelMatch = findMatchingVariableOption(topLevelVariables, tokenWithoutDefault);
|
|
184
|
+
if (topLevelMatch) return buildVariableTagAttrs(topLevelMatch, topLevelMatch, {
|
|
136
185
|
defaultIfEmpty,
|
|
137
186
|
transformerId,
|
|
138
|
-
transformerParams
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const matchedChild = (Array.isArray(variable.children) ? variable.children : []).find((c) => {
|
|
142
|
-
return c.value === tokenWithoutDefault;
|
|
143
|
-
});
|
|
144
|
-
if (matchedChild) return buildVariableTagAttrs(variable, matchedChild, {
|
|
145
|
-
defaultIfEmpty,
|
|
146
|
-
transformerId,
|
|
147
|
-
transformerParams
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
const fallback = allVariables.find((v) => {
|
|
151
|
-
return v.value === tokenWithoutDefault;
|
|
187
|
+
transformerParams,
|
|
188
|
+
label: resolveVariableTagLabel(resolvedValue, topLevelMatch),
|
|
189
|
+
value: resolvedValue
|
|
152
190
|
});
|
|
191
|
+
const fallback = findMatchingVariableOption(allVariables, tokenWithoutDefault);
|
|
153
192
|
if (fallback) return buildVariableTagAttrs(fallback, fallback, {
|
|
154
193
|
defaultIfEmpty,
|
|
155
194
|
transformerId,
|
|
156
|
-
transformerParams
|
|
195
|
+
transformerParams,
|
|
196
|
+
label: resolveVariableTagLabel(resolvedValue, fallback),
|
|
197
|
+
value: resolvedValue
|
|
157
198
|
});
|
|
158
199
|
if (isVariableLikeToken(tokenWithoutDefault)) return {
|
|
159
|
-
label:
|
|
200
|
+
label: resolveVariableTagLabel(tokenWithoutDefault, null),
|
|
160
201
|
value: tokenWithoutDefault,
|
|
161
202
|
openOnInsert: false,
|
|
162
203
|
...defaultIfEmpty ? { default: defaultIfEmpty } : {},
|
|
@@ -245,6 +286,6 @@ function replaceTokenWithVariable(editor, attrs, from, to) {
|
|
|
245
286
|
editor.view.dispatch(tr);
|
|
246
287
|
}
|
|
247
288
|
//#endregion
|
|
248
|
-
export { buildVariableTagAttrs, contentToValue, dedupeVariableOptions, flattenVariableOptions, parseTokenWithDefault, replaceTokenWithVariable, resolveVariableTagByValue, valueToContent };
|
|
289
|
+
export { buildVariableTagAttrs, contentToValue, dedupeVariableOptions, flattenVariableOptions, getReferenceBaseToken, parseTokenWithDefault, replaceTokenWithVariable, resolveVariableTagByValue, resolveVariableTagLabel, valueToContent };
|
|
249
290
|
|
|
250
291
|
//# sourceMappingURL=variableSerialization.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"variableSerialization.js","names":[],"sources":["../../../src/components/tiptap/variableSerialization.ts"],"sourcesContent":["/**\n * Shared serialization and variable-tag helpers for Tiptap variable input.\n * Used by TiptapInput and InlineVariableSuggestion.\n */\n\nimport { TextSelection } from '@tiptap/pm/state';\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport type { VariableOption } from './VariableDropdown';\n\nexport type VariableTagAttrs = {\n label: string;\n value: string;\n openOnInsert: 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};\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\n segments.forEach((segment) => {\n if (segment.startsWith(TRANSFORMER_ID_PREFIX)) {\n transformerId = decodeURIComponent(segment.slice(TRANSFORMER_ID_PREFIX.length)).trim() || undefined;\n return;\n }\n\n if (segment.includes('=')) {\n const [keyRaw, ...valueParts] = segment.split('=');\n const key = (keyRaw ?? '').trim();\n if (!key) {\n return;\n }\n\n const value = decodeURIComponent(valueParts.join('=').trim());\n if (!transformerParams) {\n transformerParams = {};\n }\n transformerParams[key] = 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 };\n}\n\nfunction isVariableLikeToken(tokenValue: string): boolean {\n return /^\\{[a-zA-Z][a-zA-Z0-9_]*(?::[^}]*)?\\}$/.test(tokenValue);\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\nfunction buildFallbackLabelForUnknownToken(tokenWithoutDefault: string): string {\n const inner = tokenWithoutDefault.replace(/^\\{|\\}$/g, '');\n const [target = '', identifier = '', selector = ''] = inner.split(':');\n\n if (target === 'field') {\n return 'Field';\n }\n\n if (target) {\n const reference = selector || identifier || target;\n return toTitleWords(reference) || tokenWithoutDefault;\n }\n\n return tokenWithoutDefault;\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 if (transformerId) {\n parts.push(`${TRANSFORMER_ID_PREFIX}${encodeURIComponent(transformerId)}`);\n\n const params = metadata.transformerParams && typeof metadata.transformerParams === 'object'\n ? Object.entries(metadata.transformerParams)\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 } = {},\n): VariableTagAttrs {\n const selectedLabel = selectedVariable?.label ?? baseVariable?.label ?? '';\n const 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\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\n const exactTopLevel = topLevelVariables.find(v => {\n return v.value === tokenWithoutDefault;\n });\n if (exactTopLevel) {\n return buildVariableTagAttrs(exactTopLevel, exactTopLevel, {\n defaultIfEmpty,\n transformerId,\n transformerParams,\n });\n }\n\n for (const variable of topLevelVariables) {\n const children = Array.isArray(variable.children) ? variable.children : [];\n const matchedChild = children.find(c => {\n return c.value === tokenWithoutDefault;\n });\n if (matchedChild) {\n return buildVariableTagAttrs(variable, matchedChild, {\n defaultIfEmpty,\n transformerId,\n transformerParams,\n });\n }\n }\n\n const fallback = allVariables.find(v => {\n return v.value === tokenWithoutDefault;\n });\n if (fallback) {\n return buildVariableTagAttrs(fallback, fallback, {\n defaultIfEmpty,\n transformerId,\n transformerParams,\n });\n }\n\n // For dev/HMR, cross-form, and read-only contexts, unresolved variable tokens\n // should still render as variable tags instead of disappearing while categories load.\n if (isVariableLikeToken(tokenWithoutDefault)) {\n return {\n label: buildFallbackLabelForUnknownToken(tokenWithoutDefault),\n value: tokenWithoutDefault,\n openOnInsert: false,\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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"}
|
|
1
|
+
{"version":3,"file":"variableSerialization.js","names":[],"sources":["../../../src/components/tiptap/variableSerialization.ts"],"sourcesContent":["/**\n * Shared serialization and variable-tag helpers for Tiptap variable input.\n * Used by TiptapInput and InlineVariableSuggestion.\n */\n\nimport { TextSelection } from '@tiptap/pm/state';\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport type { VariableOption } from './VariableDropdown';\n\nexport type VariableTagAttrs = {\n label: string;\n value: string;\n openOnInsert: 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\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\nfunction buildFallbackLabelForUnknownToken(tokenWithoutDefault: string): string {\n const fieldMatch = tokenWithoutDefault.match(/^\\{field:([^}]+)\\}$/);\n if (fieldMatch) {\n const fieldBody = fieldMatch[1].split(';')[0]?.trim() ?? '';\n const segments = fieldBody.split(':').filter(Boolean);\n\n if (segments.length >= 2) {\n return toTitleWords(segments[segments.length - 1] ?? '') || 'Field';\n }\n\n if (segments.length === 1) {\n return toTitleWords(segments[0] ?? '') || 'Field';\n }\n\n return 'Field';\n }\n\n const inner = tokenWithoutDefault.replace(/^\\{|\\}$/g, '');\n const [target = '', identifier = '', selector = ''] = inner.split(':');\n\n if (target) {\n const reference = String(selector || identifier || target).split(';')[0]?.trim() ?? '';\n return toTitleWords(reference) || tokenWithoutDefault;\n }\n\n return tokenWithoutDefault;\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 dev/HMR, cross-form, and read-only contexts, unresolved variable tokens\n // should still render as variable tags instead of disappearing while categories load.\n if (isVariableLikeToken(tokenWithoutDefault)) {\n return {\n label: resolveVariableTagLabel(tokenWithoutDefault, null),\n value: tokenWithoutDefault,\n openOnInsert: false,\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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VariableTransformerRegistry } from '../../components/tiptap/VariablePickerContext';
|
|
1
|
+
import { VariableTransformerRegistry, VariableConfigureSectionProps, VariableTagLabelResolver } from '../../components/tiptap/VariablePickerContext';
|
|
2
2
|
export type VariableConfig = Record<string, unknown>;
|
|
3
3
|
export type VariableCategoriesGetter = (variableConfig: VariableConfig, options?: {
|
|
4
4
|
form?: unknown;
|
|
@@ -11,6 +11,8 @@ export type VariableCategoriesContextValue = {
|
|
|
11
11
|
variableCategoryLabels?: Record<string, string>;
|
|
12
12
|
variableCategoryOrder?: string[];
|
|
13
13
|
variableTransformerRegistry?: VariableTransformerRegistry;
|
|
14
|
+
renderVariableConfigureSection?: (props: VariableConfigureSectionProps) => React.ReactNode;
|
|
15
|
+
resolveVariableTagLabel?: VariableTagLabelResolver;
|
|
14
16
|
};
|
|
15
17
|
export declare const VariableCategoriesProvider: import('react').Provider<VariableCategoriesContextValue | null>;
|
|
16
18
|
export declare const useVariableCategoriesContext: () => VariableCategoriesContextValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariableCategoriesContext.d.ts","sourceRoot":"","sources":["../../../src/forms/contexts/VariableCategoriesContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iEAAiE,CAAC;
|
|
1
|
+
{"version":3,"file":"VariableCategoriesContext.d.ts","sourceRoot":"","sources":["../../../src/forms/contexts/VariableCategoriesContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,wBAAwB,EAAE,MAAM,iEAAiE,CAAC;AAE5K,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAErD,MAAM,MAAM,wBAAwB,GAAG,CACnC,cAAc,EAAE,cAAc,EAC9B,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,KAC3B,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAE7D,MAAM,MAAM,8BAA8B,GAAG;IACzC,qBAAqB,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACvD,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;IAC1D,8BAA8B,CAAC,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3F,uBAAuB,CAAC,EAAE,wBAAwB,CAAC;CACtD,CAAC;AAIF,eAAO,MAAM,0BAA0B,iEAAqC,CAAC;AAE7E,eAAO,MAAM,4BAA4B,QAAO,8BAc/C,CAAC"}
|
|
@@ -9,7 +9,9 @@ var useVariableCategoriesContext = () => {
|
|
|
9
9
|
getVariableCategories: value.getVariableCategories ?? null,
|
|
10
10
|
variableCategoryLabels: value.variableCategoryLabels,
|
|
11
11
|
variableCategoryOrder: value.variableCategoryOrder,
|
|
12
|
-
variableTransformerRegistry: value.variableTransformerRegistry
|
|
12
|
+
variableTransformerRegistry: value.variableTransformerRegistry,
|
|
13
|
+
renderVariableConfigureSection: value.renderVariableConfigureSection,
|
|
14
|
+
resolveVariableTagLabel: value.resolveVariableTagLabel
|
|
13
15
|
};
|
|
14
16
|
};
|
|
15
17
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariableCategoriesContext.js","names":[],"sources":["../../../src/forms/contexts/VariableCategoriesContext.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\nimport type { VariableTransformerRegistry } from '@verbb/plugin-kit-react/components/tiptap/VariablePickerContext';\n\nexport type VariableConfig = Record<string, unknown>;\n\nexport type VariableCategoriesGetter = (\n variableConfig: VariableConfig,\n options?: { form?: unknown },\n) => Record<string, Array<{ label: string; value: string }>>;\n\nexport type VariableCategoriesContextValue = {\n getVariableCategories: VariableCategoriesGetter | null;\n variableCategoryLabels?: Record<string, string>;\n variableCategoryOrder?: string[];\n variableTransformerRegistry?: VariableTransformerRegistry;\n};\n\nconst VariableCategoriesContext = createContext<VariableCategoriesContextValue | null>(null);\n\nexport const VariableCategoriesProvider = VariableCategoriesContext.Provider;\n\nexport const useVariableCategoriesContext = (): VariableCategoriesContextValue => {\n const value = useContext(VariableCategoriesContext);\n if (value == null) {\n return { getVariableCategories: null };\n }\n\n return {\n getVariableCategories: value.getVariableCategories ?? null,\n variableCategoryLabels: value.variableCategoryLabels,\n variableCategoryOrder: value.variableCategoryOrder,\n variableTransformerRegistry: value.variableTransformerRegistry,\n };\n};\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"VariableCategoriesContext.js","names":[],"sources":["../../../src/forms/contexts/VariableCategoriesContext.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\nimport type { VariableTransformerRegistry, VariableConfigureSectionProps, VariableTagLabelResolver } from '@verbb/plugin-kit-react/components/tiptap/VariablePickerContext';\n\nexport type VariableConfig = Record<string, unknown>;\n\nexport type VariableCategoriesGetter = (\n variableConfig: VariableConfig,\n options?: { form?: unknown },\n) => Record<string, Array<{ label: string; value: string }>>;\n\nexport type VariableCategoriesContextValue = {\n getVariableCategories: VariableCategoriesGetter | null;\n variableCategoryLabels?: Record<string, string>;\n variableCategoryOrder?: string[];\n variableTransformerRegistry?: VariableTransformerRegistry;\n renderVariableConfigureSection?: (props: VariableConfigureSectionProps) => React.ReactNode;\n resolveVariableTagLabel?: VariableTagLabelResolver;\n};\n\nconst VariableCategoriesContext = createContext<VariableCategoriesContextValue | null>(null);\n\nexport const VariableCategoriesProvider = VariableCategoriesContext.Provider;\n\nexport const useVariableCategoriesContext = (): VariableCategoriesContextValue => {\n const value = useContext(VariableCategoriesContext);\n if (value == null) {\n return { getVariableCategories: null };\n }\n\n return {\n getVariableCategories: value.getVariableCategories ?? null,\n variableCategoryLabels: value.variableCategoryLabels,\n variableCategoryOrder: value.variableCategoryOrder,\n variableTransformerRegistry: value.variableTransformerRegistry,\n renderVariableConfigureSection: value.renderVariableConfigureSection,\n resolveVariableTagLabel: value.resolveVariableTagLabel,\n };\n};\n"],"mappings":";;AAmBA,IAAM,4BAA4B,cAAqD,KAAK;AAE5F,IAAa,6BAA6B,0BAA0B;AAEpE,IAAa,qCAAqE;CAC9E,MAAM,QAAQ,WAAW,0BAA0B;AACnD,KAAI,SAAS,KACT,QAAO,EAAE,uBAAuB,MAAM;AAG1C,QAAO;EACH,uBAAuB,MAAM,yBAAyB;EACtD,wBAAwB,MAAM;EAC9B,uBAAuB,MAAM;EAC7B,6BAA6B,MAAM;EACnC,gCAAgC,MAAM;EACtC,yBAAyB,MAAM;EAClC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextField.d.ts","sourceRoot":"","sources":["../../../src/forms/fields/RichTextField.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAgB,MAAM,oCAAoC,CAAC;AAEpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAI5E,KAAK,kBAAkB,GAAG;IACtB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,gBAAgB,CAAC;QAC/B,4BAA4B,CAAC,EAAE,MAAM,CAAC;KACzC,CAAC;CACL,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,iBAAiB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"RichTextField.d.ts","sourceRoot":"","sources":["../../../src/forms/fields/RichTextField.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAgB,MAAM,oCAAoC,CAAC;AAEpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAI5E,KAAK,kBAAkB,GAAG;IACtB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,gBAAgB,CAAC;QAC/B,4BAA4B,CAAC,EAAE,MAAM,CAAC;KACzC,CAAC;CACL,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,iBAAiB,kBAAkB,4CAiDhE,CAAC"}
|
|
@@ -9,7 +9,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
9
9
|
var RichTextField = ({ form, field }) => {
|
|
10
10
|
const { value, setValue, errors } = useEngineField(form, field.name);
|
|
11
11
|
const buttons = field.buttons ?? ["bold", "italic"];
|
|
12
|
-
const { getVariableCategories, variableCategoryLabels, variableCategoryOrder, variableTransformerRegistry } = useVariableCategoriesContext();
|
|
12
|
+
const { getVariableCategories, variableCategoryLabels, variableCategoryOrder, variableTransformerRegistry, renderVariableConfigureSection, resolveVariableTagLabel } = useVariableCategoriesContext();
|
|
13
13
|
const { variableConfig } = field;
|
|
14
14
|
const variableCategories = useMemo(() => {
|
|
15
15
|
if (!variableConfig || !getVariableCategories) return;
|
|
@@ -37,6 +37,8 @@ var RichTextField = ({ form, field }) => {
|
|
|
37
37
|
...variableCategoryLabels && { variableCategoryLabels },
|
|
38
38
|
...variableCategoryOrder && { variableCategoryOrder },
|
|
39
39
|
...variableTransformerRegistry && { variableTransformerRegistry },
|
|
40
|
+
...renderVariableConfigureSection && { renderVariableConfigureSection },
|
|
41
|
+
...resolveVariableTagLabel && { resolveVariableTagLabel },
|
|
40
42
|
...field.linkOptions && { linkOptions: field.linkOptions },
|
|
41
43
|
...field.linkSelectorStorageKeyPrefix && { linkSelectorStorageKeyPrefix: field.linkSelectorStorageKeyPrefix },
|
|
42
44
|
disabled: field.disabled,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextField.js","names":[],"sources":["../../../src/forms/fields/RichTextField.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { LinkOptionsInput, TiptapEditor } from '@verbb/plugin-kit-react/components';\nimport { FieldLayout } from '../Field';\nimport type { SchemaFormEngineApi } from '../engine/context';\nimport type { VariableConfig } from '../contexts/VariableCategoriesContext';\nimport { useEngineField } from '../useEngineField';\nimport { useVariableCategoriesContext } from '../contexts/VariableCategoriesContext';\n\ntype RichTextFieldProps = {\n form: SchemaFormEngineApi;\n field: {\n name: string;\n label?: string;\n instructions?: string;\n warning?: string;\n placeholder?: string;\n buttons?: string[];\n variableConfig?: VariableConfig;\n required?: boolean;\n disabled?: boolean;\n rows?: number;\n linkOptions?: LinkOptionsInput;\n linkSelectorStorageKeyPrefix?: string;\n };\n};\n\nexport const RichTextField = ({ form, field }: RichTextFieldProps) => {\n const { value, setValue, errors } = useEngineField(form, field.name);\n const buttons = field.buttons ?? ['bold', 'italic'];\n const {\n getVariableCategories,\n variableCategoryLabels,\n variableCategoryOrder,\n variableTransformerRegistry,\n } = useVariableCategoriesContext();\n const { variableConfig } = field;\n\n const variableCategories = useMemo(() => {\n if (!variableConfig || !getVariableCategories) {\n return undefined;\n }\n return getVariableCategories(variableConfig, { form });\n }, [variableConfig, form, getVariableCategories]);\n\n return (\n <FieldLayout\n name={field.name}\n label={field.label}\n instructions={field.instructions}\n warning={field.warning}\n required={field.required}\n errors={errors}\n withControl={false}\n >\n <TiptapEditor\n value={value ?? ''}\n onChange={setValue}\n placeholder={field.placeholder}\n rows={field.rows}\n buttons={buttons}\n {...(variableCategories && { variableCategories })}\n {...(variableCategoryLabels && { variableCategoryLabels })}\n {...(variableCategoryOrder && { variableCategoryOrder })}\n {...(variableTransformerRegistry && { variableTransformerRegistry })}\n {...(field.linkOptions && { linkOptions: field.linkOptions })}\n {...(field.linkSelectorStorageKeyPrefix && { linkSelectorStorageKeyPrefix: field.linkSelectorStorageKeyPrefix })}\n disabled={field.disabled}\n isInvalid={errors.length > 0}\n />\n </FieldLayout>\n );\n};\n"],"mappings":";;;;;;;;AA0BA,IAAa,iBAAiB,EAAE,MAAM,YAAgC;CAClE,MAAM,EAAE,OAAO,UAAU,WAAW,eAAe,MAAM,MAAM,KAAK;CACpE,MAAM,UAAU,MAAM,WAAW,CAAC,QAAQ,SAAS;CACnD,MAAM,EACF,uBACA,wBACA,uBACA,gCACA,8BAA8B;CAClC,MAAM,EAAE,mBAAmB;CAE3B,MAAM,qBAAqB,cAAc;AACrC,MAAI,CAAC,kBAAkB,CAAC,sBACpB;AAEJ,SAAO,sBAAsB,gBAAgB,EAAE,MAAM,CAAC;IACvD;EAAC;EAAgB;EAAM;EAAsB,CAAC;AAEjD,QACI,oBAAC,aAAD;EACI,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,SAAS,MAAM;EACf,UAAU,MAAM;EACR;EACR,aAAa;YAEb,oBAAC,cAAD;GACI,OAAO,SAAS;GAChB,UAAU;GACV,aAAa,MAAM;GACnB,MAAM,MAAM;GACH;GACT,GAAK,sBAAsB,EAAE,oBAAoB;GACjD,GAAK,0BAA0B,EAAE,wBAAwB;GACzD,GAAK,yBAAyB,EAAE,uBAAuB;GACvD,GAAK,+BAA+B,EAAE,6BAA6B;GACnE,GAAK,MAAM,eAAe,EAAE,aAAa,MAAM,aAAa;GAC5D,GAAK,MAAM,gCAAgC,EAAE,8BAA8B,MAAM,8BAA8B;GAC/G,UAAU,MAAM;GAChB,WAAW,OAAO,SAAS;GAC7B,CAAA;EACQ,CAAA"}
|
|
1
|
+
{"version":3,"file":"RichTextField.js","names":[],"sources":["../../../src/forms/fields/RichTextField.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { LinkOptionsInput, TiptapEditor } from '@verbb/plugin-kit-react/components';\nimport { FieldLayout } from '../Field';\nimport type { SchemaFormEngineApi } from '../engine/context';\nimport type { VariableConfig } from '../contexts/VariableCategoriesContext';\nimport { useEngineField } from '../useEngineField';\nimport { useVariableCategoriesContext } from '../contexts/VariableCategoriesContext';\n\ntype RichTextFieldProps = {\n form: SchemaFormEngineApi;\n field: {\n name: string;\n label?: string;\n instructions?: string;\n warning?: string;\n placeholder?: string;\n buttons?: string[];\n variableConfig?: VariableConfig;\n required?: boolean;\n disabled?: boolean;\n rows?: number;\n linkOptions?: LinkOptionsInput;\n linkSelectorStorageKeyPrefix?: string;\n };\n};\n\nexport const RichTextField = ({ form, field }: RichTextFieldProps) => {\n const { value, setValue, errors } = useEngineField(form, field.name);\n const buttons = field.buttons ?? ['bold', 'italic'];\n const {\n getVariableCategories,\n variableCategoryLabels,\n variableCategoryOrder,\n variableTransformerRegistry,\n renderVariableConfigureSection,\n resolveVariableTagLabel,\n } = useVariableCategoriesContext();\n const { variableConfig } = field;\n\n const variableCategories = useMemo(() => {\n if (!variableConfig || !getVariableCategories) {\n return undefined;\n }\n return getVariableCategories(variableConfig, { form });\n }, [variableConfig, form, getVariableCategories]);\n\n return (\n <FieldLayout\n name={field.name}\n label={field.label}\n instructions={field.instructions}\n warning={field.warning}\n required={field.required}\n errors={errors}\n withControl={false}\n >\n <TiptapEditor\n value={value ?? ''}\n onChange={setValue}\n placeholder={field.placeholder}\n rows={field.rows}\n buttons={buttons}\n {...(variableCategories && { variableCategories })}\n {...(variableCategoryLabels && { variableCategoryLabels })}\n {...(variableCategoryOrder && { variableCategoryOrder })}\n {...(variableTransformerRegistry && { variableTransformerRegistry })}\n {...(renderVariableConfigureSection && { renderVariableConfigureSection })}\n {...(resolveVariableTagLabel && { resolveVariableTagLabel })}\n {...(field.linkOptions && { linkOptions: field.linkOptions })}\n {...(field.linkSelectorStorageKeyPrefix && { linkSelectorStorageKeyPrefix: field.linkSelectorStorageKeyPrefix })}\n disabled={field.disabled}\n isInvalid={errors.length > 0}\n />\n </FieldLayout>\n );\n};\n"],"mappings":";;;;;;;;AA0BA,IAAa,iBAAiB,EAAE,MAAM,YAAgC;CAClE,MAAM,EAAE,OAAO,UAAU,WAAW,eAAe,MAAM,MAAM,KAAK;CACpE,MAAM,UAAU,MAAM,WAAW,CAAC,QAAQ,SAAS;CACnD,MAAM,EACF,uBACA,wBACA,uBACA,6BACA,gCACA,4BACA,8BAA8B;CAClC,MAAM,EAAE,mBAAmB;CAE3B,MAAM,qBAAqB,cAAc;AACrC,MAAI,CAAC,kBAAkB,CAAC,sBACpB;AAEJ,SAAO,sBAAsB,gBAAgB,EAAE,MAAM,CAAC;IACvD;EAAC;EAAgB;EAAM;EAAsB,CAAC;AAEjD,QACI,oBAAC,aAAD;EACI,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,SAAS,MAAM;EACf,UAAU,MAAM;EACR;EACR,aAAa;YAEb,oBAAC,cAAD;GACI,OAAO,SAAS;GAChB,UAAU;GACV,aAAa,MAAM;GACnB,MAAM,MAAM;GACH;GACT,GAAK,sBAAsB,EAAE,oBAAoB;GACjD,GAAK,0BAA0B,EAAE,wBAAwB;GACzD,GAAK,yBAAyB,EAAE,uBAAuB;GACvD,GAAK,+BAA+B,EAAE,6BAA6B;GACnE,GAAK,kCAAkC,EAAE,gCAAgC;GACzE,GAAK,2BAA2B,EAAE,yBAAyB;GAC3D,GAAK,MAAM,eAAe,EAAE,aAAa,MAAM,aAAa;GAC5D,GAAK,MAAM,gCAAgC,EAAE,8BAA8B,MAAM,8BAA8B;GAC/G,UAAU,MAAM;GAChB,WAAW,OAAO,SAAS;GAC7B,CAAA;EACQ,CAAA"}
|
|
@@ -37,7 +37,7 @@ var SelectField = ({ form, field }) => {
|
|
|
37
37
|
useEffect(() => {
|
|
38
38
|
if (value === void 0 || value === null || value === "") return;
|
|
39
39
|
if (filteredOptions.some((option) => {
|
|
40
|
-
return option?.value === value;
|
|
40
|
+
return String(option?.value) === String(value);
|
|
41
41
|
})) return;
|
|
42
42
|
const fallback = filteredOptions.find((option) => {
|
|
43
43
|
return option?.value !== void 0 && option?.disabled !== true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectField.js","names":[],"sources":["../../../src/forms/fields/SelectField.tsx"],"sourcesContent":["import type React from 'react';\nimport { SelectInput } from '@verbb/plugin-kit-react/components';\nimport { evaluateCondition } from '@verbb/plugin-kit-react/utils/schema';\nimport { useEffect, useMemo, useSyncExternalStore } from 'react';\nimport { FieldLayout } from '../Field';\nimport type { SchemaFormEngineApi } from '../engine/context';\nimport type { SchemaNode } from '../engine/SchemaIndex';\nimport { useEngineField } from '../useEngineField';\n\ntype SelectFieldOption = {\n value: unknown;\n label: string;\n disabled?: boolean;\n if?: string;\n [key: string]: unknown;\n};\n\ntype SelectFieldProps = {\n form: SchemaFormEngineApi;\n field: SchemaNode & {\n name: string;\n label?: string;\n instructions?: string;\n warning?: string;\n placeholder?: string;\n options?: SelectFieldOption[];\n required?: boolean;\n disabled?: boolean;\n };\n};\n\ntype SelectInputProps = React.ComponentProps<typeof SelectInput>;\n\nexport const SelectField = ({ form, field }: SelectFieldProps) => {\n const {\n value, setValue, setTouched, errors, isInvalid,\n } = useEngineField(form, field.name);\n const values = useSyncExternalStore(\n form.store.subscribe.bind(form.store),\n () => { return form.store.state.values; },\n () => { return form.store.state.values; },\n );\n\n const conditionData = useMemo(() => {\n const scopePath = typeof field._scopePath === 'string' ? field._scopePath : '';\n const scopedValues = scopePath ? form?.getFieldValue?.(scopePath) : null;\n const scopedObject = scopedValues && typeof scopedValues === 'object' ? scopedValues : {};\n const fieldData = (field._data && typeof field._data === 'object') ? field._data : {};\n\n return {\n ...(values || {}),\n ...scopedObject,\n ...fieldData,\n };\n }, [field, form, values]);\n\n const filteredOptions = useMemo(() => {\n const options = Array.isArray(field.options) ? field.options : [];\n\n return options.filter((option) => {\n if (!option?.if) {\n return true;\n }\n\n return evaluateCondition(option.if, conditionData);\n });\n }, [conditionData, field.options]);\n\n useEffect(() => {\n if (value === undefined || value === null || value === '') {\n return;\n }\n\n const hasCurrentValue = filteredOptions.some((option) => {\n return option?.value === value;\n });\n\n if (hasCurrentValue) {\n return;\n }\n\n const fallback = filteredOptions.find((option) => {\n return option?.value !== undefined && option?.disabled !== true;\n });\n\n setValue(fallback ? fallback.value : '');\n }, [filteredOptions, setValue, value]);\n\n return (\n <FieldLayout\n name={field.name}\n label={field.label}\n instructions={field.instructions}\n warning={field.warning}\n required={field.required}\n errors={errors}\n >\n <SelectInput\n options={filteredOptions}\n placeholder={field.placeholder}\n value={value ?? ''}\n onChange={(nextValue) => { return setValue(nextValue); }}\n isInvalid={isInvalid}\n onBlur={setTouched as SelectInputProps['onBlur']}\n />\n </FieldLayout>\n );\n};\n"],"mappings":";;;;;;;;AAiCA,IAAa,eAAe,EAAE,MAAM,YAA8B;CAC9D,MAAM,EACF,OAAO,UAAU,YAAY,QAAQ,cACrC,eAAe,MAAM,MAAM,KAAK;CACpC,MAAM,SAAS,qBACX,KAAK,MAAM,UAAU,KAAK,KAAK,MAAM,QAC/B;AAAE,SAAO,KAAK,MAAM,MAAM;UAC1B;AAAE,SAAO,KAAK,MAAM,MAAM;GACnC;CAED,MAAM,gBAAgB,cAAc;EAChC,MAAM,YAAY,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;EAC5E,MAAM,eAAe,YAAY,MAAM,gBAAgB,UAAU,GAAG;EACpE,MAAM,eAAe,gBAAgB,OAAO,iBAAiB,WAAW,eAAe,EAAE;EACzF,MAAM,YAAa,MAAM,SAAS,OAAO,MAAM,UAAU,WAAY,MAAM,QAAQ,EAAE;AAErF,SAAO;GACH,GAAI,UAAU,EAAE;GAChB,GAAG;GACH,GAAG;GACN;IACF;EAAC;EAAO;EAAM;EAAO,CAAC;CAEzB,MAAM,kBAAkB,cAAc;AAGlC,UAFgB,MAAM,QAAQ,MAAM,QAAQ,GAAG,MAAM,UAAU,EAAE,EAElD,QAAQ,WAAW;AAC9B,OAAI,CAAC,QAAQ,GACT,QAAO;AAGX,UAAO,kBAAkB,OAAO,IAAI,cAAc;IACpD;IACH,CAAC,eAAe,MAAM,QAAQ,CAAC;AAElC,iBAAgB;AACZ,MAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,GACnD;AAOJ,MAJwB,gBAAgB,MAAM,WAAW;AACrD,UAAO,QAAQ,
|
|
1
|
+
{"version":3,"file":"SelectField.js","names":[],"sources":["../../../src/forms/fields/SelectField.tsx"],"sourcesContent":["import type React from 'react';\nimport { SelectInput } from '@verbb/plugin-kit-react/components';\nimport { evaluateCondition } from '@verbb/plugin-kit-react/utils/schema';\nimport { useEffect, useMemo, useSyncExternalStore } from 'react';\nimport { FieldLayout } from '../Field';\nimport type { SchemaFormEngineApi } from '../engine/context';\nimport type { SchemaNode } from '../engine/SchemaIndex';\nimport { useEngineField } from '../useEngineField';\n\ntype SelectFieldOption = {\n value: unknown;\n label: string;\n disabled?: boolean;\n if?: string;\n [key: string]: unknown;\n};\n\ntype SelectFieldProps = {\n form: SchemaFormEngineApi;\n field: SchemaNode & {\n name: string;\n label?: string;\n instructions?: string;\n warning?: string;\n placeholder?: string;\n options?: SelectFieldOption[];\n required?: boolean;\n disabled?: boolean;\n };\n};\n\ntype SelectInputProps = React.ComponentProps<typeof SelectInput>;\n\nexport const SelectField = ({ form, field }: SelectFieldProps) => {\n const {\n value, setValue, setTouched, errors, isInvalid,\n } = useEngineField(form, field.name);\n const values = useSyncExternalStore(\n form.store.subscribe.bind(form.store),\n () => { return form.store.state.values; },\n () => { return form.store.state.values; },\n );\n\n const conditionData = useMemo(() => {\n const scopePath = typeof field._scopePath === 'string' ? field._scopePath : '';\n const scopedValues = scopePath ? form?.getFieldValue?.(scopePath) : null;\n const scopedObject = scopedValues && typeof scopedValues === 'object' ? scopedValues : {};\n const fieldData = (field._data && typeof field._data === 'object') ? field._data : {};\n\n return {\n ...(values || {}),\n ...scopedObject,\n ...fieldData,\n };\n }, [field, form, values]);\n\n const filteredOptions = useMemo(() => {\n const options = Array.isArray(field.options) ? field.options : [];\n\n return options.filter((option) => {\n if (!option?.if) {\n return true;\n }\n\n return evaluateCondition(option.if, conditionData);\n });\n }, [conditionData, field.options]);\n\n useEffect(() => {\n if (value === undefined || value === null || value === '') {\n return;\n }\n\n const hasCurrentValue = filteredOptions.some((option) => {\n return String(option?.value) === String(value);\n });\n\n if (hasCurrentValue) {\n return;\n }\n\n const fallback = filteredOptions.find((option) => {\n return option?.value !== undefined && option?.disabled !== true;\n });\n\n setValue(fallback ? fallback.value : '');\n }, [filteredOptions, setValue, value]);\n\n return (\n <FieldLayout\n name={field.name}\n label={field.label}\n instructions={field.instructions}\n warning={field.warning}\n required={field.required}\n errors={errors}\n >\n <SelectInput\n options={filteredOptions}\n placeholder={field.placeholder}\n value={value ?? ''}\n onChange={(nextValue) => { return setValue(nextValue); }}\n isInvalid={isInvalid}\n onBlur={setTouched as SelectInputProps['onBlur']}\n />\n </FieldLayout>\n );\n};\n"],"mappings":";;;;;;;;AAiCA,IAAa,eAAe,EAAE,MAAM,YAA8B;CAC9D,MAAM,EACF,OAAO,UAAU,YAAY,QAAQ,cACrC,eAAe,MAAM,MAAM,KAAK;CACpC,MAAM,SAAS,qBACX,KAAK,MAAM,UAAU,KAAK,KAAK,MAAM,QAC/B;AAAE,SAAO,KAAK,MAAM,MAAM;UAC1B;AAAE,SAAO,KAAK,MAAM,MAAM;GACnC;CAED,MAAM,gBAAgB,cAAc;EAChC,MAAM,YAAY,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;EAC5E,MAAM,eAAe,YAAY,MAAM,gBAAgB,UAAU,GAAG;EACpE,MAAM,eAAe,gBAAgB,OAAO,iBAAiB,WAAW,eAAe,EAAE;EACzF,MAAM,YAAa,MAAM,SAAS,OAAO,MAAM,UAAU,WAAY,MAAM,QAAQ,EAAE;AAErF,SAAO;GACH,GAAI,UAAU,EAAE;GAChB,GAAG;GACH,GAAG;GACN;IACF;EAAC;EAAO;EAAM;EAAO,CAAC;CAEzB,MAAM,kBAAkB,cAAc;AAGlC,UAFgB,MAAM,QAAQ,MAAM,QAAQ,GAAG,MAAM,UAAU,EAAE,EAElD,QAAQ,WAAW;AAC9B,OAAI,CAAC,QAAQ,GACT,QAAO;AAGX,UAAO,kBAAkB,OAAO,IAAI,cAAc;IACpD;IACH,CAAC,eAAe,MAAM,QAAQ,CAAC;AAElC,iBAAgB;AACZ,MAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,GACnD;AAOJ,MAJwB,gBAAgB,MAAM,WAAW;AACrD,UAAO,OAAO,QAAQ,MAAM,KAAK,OAAO,MAAM;IAG9C,CACA;EAGJ,MAAM,WAAW,gBAAgB,MAAM,WAAW;AAC9C,UAAO,QAAQ,UAAU,KAAA,KAAa,QAAQ,aAAa;IAC7D;AAEF,WAAS,WAAW,SAAS,QAAQ,GAAG;IACzC;EAAC;EAAiB;EAAU;EAAM,CAAC;AAEtC,QACI,oBAAC,aAAD;EACI,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,SAAS,MAAM;EACf,UAAU,MAAM;EACR;YAER,oBAAC,aAAD;GACI,SAAS;GACT,aAAa,MAAM;GACnB,OAAO,SAAS;GAChB,WAAW,cAAc;AAAE,WAAO,SAAS,UAAU;;GAC1C;GACX,QAAQ;GACV,CAAA;EACQ,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariablePickerField.d.ts","sourceRoot":"","sources":["../../../src/forms/fields/VariablePickerField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAGrG,KAAK,wBAAwB,GAAG;IAC5B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;QACxC,+BAA+B,CAAC,EAAE,MAAM,EAAE,CAAC;KAC9C,CAAC;CACL,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,iBAAiB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"VariablePickerField.d.ts","sourceRoot":"","sources":["../../../src/forms/fields/VariablePickerField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAGrG,KAAK,wBAAwB,GAAG;IAC5B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;QACxC,+BAA+B,CAAC,EAAE,MAAM,EAAE,CAAC;KAC9C,CAAC;CACL,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,iBAAiB,wBAAwB,4CAmD5E,CAAC"}
|
|
@@ -8,7 +8,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
8
8
|
//#region src/forms/fields/VariablePickerField.tsx
|
|
9
9
|
var VariablePickerField = ({ form, field }) => {
|
|
10
10
|
const { value, setValue, errors } = useEngineField(form, field.name);
|
|
11
|
-
const { getVariableCategories, variableCategoryLabels, variableCategoryOrder, variableTransformerRegistry } = useVariableCategoriesContext();
|
|
11
|
+
const { getVariableCategories, variableCategoryLabels, variableCategoryOrder, variableTransformerRegistry, renderVariableConfigureSection, resolveVariableTagLabel } = useVariableCategoriesContext();
|
|
12
12
|
const { variableCategories, variableConfig } = field;
|
|
13
13
|
const resolvedVariableCategories = useMemo(() => {
|
|
14
14
|
if (variableCategories) return variableCategories;
|
|
@@ -39,6 +39,8 @@ var VariablePickerField = ({ form, field }) => {
|
|
|
39
39
|
variableCategoryLabels,
|
|
40
40
|
variableCategoryOrder,
|
|
41
41
|
variableTransformerRegistry,
|
|
42
|
+
renderVariableConfigureSection,
|
|
43
|
+
resolveVariableTagLabel,
|
|
42
44
|
variablePickerTriggerCharacters: field.variablePickerTriggerCharacters
|
|
43
45
|
})
|
|
44
46
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariablePickerField.js","names":[],"sources":["../../../src/forms/fields/VariablePickerField.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { TiptapInput } from '@verbb/plugin-kit-react/components';\nimport { FieldLayout } from '../Field';\nimport type { SchemaFormEngineApi } from '../engine/context';\nimport type { VariableConfig } from '../contexts/VariableCategoriesContext';\nimport { useEngineField } from '../useEngineField';\nimport type { VariableCategories } from '@verbb/plugin-kit-react/components/tiptap/VariableDropdown';\nimport { useVariableCategoriesContext } from '../contexts/VariableCategoriesContext';\n\ntype VariablePickerFieldProps = {\n form: SchemaFormEngineApi;\n field: {\n name: string;\n label?: string;\n instructions?: string;\n warning?: string;\n placeholder?: string;\n required?: boolean;\n disabled?: boolean;\n variableConfig?: VariableConfig;\n variableCategories?: VariableCategories;\n variablePickerTriggerCharacters?: string[];\n };\n};\n\nexport const VariablePickerField = ({ form, field }: VariablePickerFieldProps) => {\n const { value, setValue, errors } = useEngineField(form, field.name);\n const {\n getVariableCategories,\n variableCategoryLabels,\n variableCategoryOrder,\n variableTransformerRegistry,\n } = useVariableCategoriesContext();\n const { variableCategories, variableConfig } = field;\n\n const resolvedVariableCategories = useMemo(() => {\n if (variableCategories) {\n return variableCategories;\n }\n\n if (!variableConfig || !getVariableCategories) {\n return undefined;\n }\n\n return getVariableCategories(variableConfig, { form });\n }, [variableCategories, variableConfig, form, getVariableCategories]);\n\n return (\n <FieldLayout\n name={field.name}\n label={field.label}\n instructions={field.instructions}\n warning={field.warning}\n required={field.required}\n errors={errors}\n withControl={false}\n >\n <TiptapInput\n value={String(value ?? '')}\n onChange={setValue}\n placeholder={field.placeholder}\n className=\"\"\n disabled={field.disabled}\n isInvalid={errors.length > 0}\n variableCategories={resolvedVariableCategories}\n variableCategoryLabels={variableCategoryLabels}\n variableCategoryOrder={variableCategoryOrder}\n variableTransformerRegistry={variableTransformerRegistry}\n variablePickerTriggerCharacters={field.variablePickerTriggerCharacters}\n />\n </FieldLayout>\n );\n};\n"],"mappings":";;;;;;;;AAyBA,IAAa,uBAAuB,EAAE,MAAM,YAAsC;CAC9E,MAAM,EAAE,OAAO,UAAU,WAAW,eAAe,MAAM,MAAM,KAAK;CACpE,MAAM,EACF,uBACA,wBACA,uBACA,gCACA,8BAA8B;CAClC,MAAM,EAAE,oBAAoB,mBAAmB;CAE/C,MAAM,6BAA6B,cAAc;AAC7C,MAAI,mBACA,QAAO;AAGX,MAAI,CAAC,kBAAkB,CAAC,sBACpB;AAGJ,SAAO,sBAAsB,gBAAgB,EAAE,MAAM,CAAC;IACvD;EAAC;EAAoB;EAAgB;EAAM;EAAsB,CAAC;AAErE,QACI,oBAAC,aAAD;EACI,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,SAAS,MAAM;EACf,UAAU,MAAM;EACR;EACR,aAAa;YAEb,oBAAC,aAAD;GACI,OAAO,OAAO,SAAS,GAAG;GAC1B,UAAU;GACV,aAAa,MAAM;GACnB,WAAU;GACV,UAAU,MAAM;GAChB,WAAW,OAAO,SAAS;GAC3B,oBAAoB;GACI;GACD;GACM;
|
|
1
|
+
{"version":3,"file":"VariablePickerField.js","names":[],"sources":["../../../src/forms/fields/VariablePickerField.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { TiptapInput } from '@verbb/plugin-kit-react/components';\nimport { FieldLayout } from '../Field';\nimport type { SchemaFormEngineApi } from '../engine/context';\nimport type { VariableConfig } from '../contexts/VariableCategoriesContext';\nimport { useEngineField } from '../useEngineField';\nimport type { VariableCategories } from '@verbb/plugin-kit-react/components/tiptap/VariableDropdown';\nimport { useVariableCategoriesContext } from '../contexts/VariableCategoriesContext';\n\ntype VariablePickerFieldProps = {\n form: SchemaFormEngineApi;\n field: {\n name: string;\n label?: string;\n instructions?: string;\n warning?: string;\n placeholder?: string;\n required?: boolean;\n disabled?: boolean;\n variableConfig?: VariableConfig;\n variableCategories?: VariableCategories;\n variablePickerTriggerCharacters?: string[];\n };\n};\n\nexport const VariablePickerField = ({ form, field }: VariablePickerFieldProps) => {\n const { value, setValue, errors } = useEngineField(form, field.name);\n const {\n getVariableCategories,\n variableCategoryLabels,\n variableCategoryOrder,\n variableTransformerRegistry,\n renderVariableConfigureSection,\n resolveVariableTagLabel,\n } = useVariableCategoriesContext();\n const { variableCategories, variableConfig } = field;\n\n const resolvedVariableCategories = useMemo(() => {\n if (variableCategories) {\n return variableCategories;\n }\n\n if (!variableConfig || !getVariableCategories) {\n return undefined;\n }\n\n return getVariableCategories(variableConfig, { form });\n }, [variableCategories, variableConfig, form, getVariableCategories]);\n\n return (\n <FieldLayout\n name={field.name}\n label={field.label}\n instructions={field.instructions}\n warning={field.warning}\n required={field.required}\n errors={errors}\n withControl={false}\n >\n <TiptapInput\n value={String(value ?? '')}\n onChange={setValue}\n placeholder={field.placeholder}\n className=\"\"\n disabled={field.disabled}\n isInvalid={errors.length > 0}\n variableCategories={resolvedVariableCategories}\n variableCategoryLabels={variableCategoryLabels}\n variableCategoryOrder={variableCategoryOrder}\n variableTransformerRegistry={variableTransformerRegistry}\n renderVariableConfigureSection={renderVariableConfigureSection}\n resolveVariableTagLabel={resolveVariableTagLabel}\n variablePickerTriggerCharacters={field.variablePickerTriggerCharacters}\n />\n </FieldLayout>\n );\n};\n"],"mappings":";;;;;;;;AAyBA,IAAa,uBAAuB,EAAE,MAAM,YAAsC;CAC9E,MAAM,EAAE,OAAO,UAAU,WAAW,eAAe,MAAM,MAAM,KAAK;CACpE,MAAM,EACF,uBACA,wBACA,uBACA,6BACA,gCACA,4BACA,8BAA8B;CAClC,MAAM,EAAE,oBAAoB,mBAAmB;CAE/C,MAAM,6BAA6B,cAAc;AAC7C,MAAI,mBACA,QAAO;AAGX,MAAI,CAAC,kBAAkB,CAAC,sBACpB;AAGJ,SAAO,sBAAsB,gBAAgB,EAAE,MAAM,CAAC;IACvD;EAAC;EAAoB;EAAgB;EAAM;EAAsB,CAAC;AAErE,QACI,oBAAC,aAAD;EACI,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,SAAS,MAAM;EACf,UAAU,MAAM;EACR;EACR,aAAa;YAEb,oBAAC,aAAD;GACI,OAAO,OAAO,SAAS,GAAG;GAC1B,UAAU;GACV,aAAa,MAAM;GACnB,WAAU;GACV,UAAU,MAAM;GAChB,WAAW,OAAO,SAAS;GAC3B,oBAAoB;GACI;GACD;GACM;GACG;GACP;GACzB,iCAAiC,MAAM;GACzC,CAAA;EACQ,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verbb/plugin-kit-react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
],
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/verbb/plugin-kit
|
|
16
|
+
"url": "git+https://github.com/verbb/plugin-kit.git",
|
|
17
|
+
"directory": "plugin-kit-react"
|
|
17
18
|
},
|
|
18
19
|
"bugs": {
|
|
19
|
-
"url": "https://github.com/verbb/plugin-kit
|
|
20
|
+
"url": "https://github.com/verbb/plugin-kit/issues"
|
|
20
21
|
},
|
|
21
|
-
"homepage": "https://docs.verbb.io/plugin-kit
|
|
22
|
+
"homepage": "https://docs.verbb.io/plugin-kit",
|
|
22
23
|
"engines": {
|
|
23
24
|
"node": ">=20.0.0"
|
|
24
25
|
},
|