agentic-ui-libs 1.0.0-beta.6 → 1.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1482,6 +1482,16 @@ const Minimize2 = createLucideIcon("Minimize2", [
1482
1482
  * See the LICENSE file in the root directory of this source tree.
1483
1483
  */
1484
1484
  const Minus = createLucideIcon("Minus", [["path", { d: "M5 12h14", key: "1ays0h" }]]);
1485
+ /**
1486
+ * @license lucide-react v0.294.0 - ISC
1487
+ *
1488
+ * This source code is licensed under the ISC license.
1489
+ * See the LICENSE file in the root directory of this source tree.
1490
+ */
1491
+ const Pencil = createLucideIcon("Pencil", [
1492
+ ["path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z", key: "5qss01" }],
1493
+ ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
1494
+ ]);
1485
1495
  /**
1486
1496
  * @license lucide-react v0.294.0 - ISC
1487
1497
  *
@@ -68357,6 +68367,8 @@ const buildVariableSyntax = (variableType, path) => {
68357
68367
  const VariableChipComponent = ({
68358
68368
  node,
68359
68369
  deleteNode: deleteNode2,
68370
+ editor,
68371
+ getPos,
68360
68372
  selected
68361
68373
  }) => {
68362
68374
  const { variableType, path, displayName } = node.attrs;
@@ -68367,6 +68379,24 @@ const VariableChipComponent = ({
68367
68379
  e3.stopPropagation();
68368
68380
  deleteNode2();
68369
68381
  };
68382
+ const handleEdit = (e3) => {
68383
+ e3.preventDefault();
68384
+ e3.stopPropagation();
68385
+ const pos = typeof getPos === "function" ? getPos() : null;
68386
+ if (pos !== null && editor) {
68387
+ const event = new CustomEvent("variable-chip-edit", {
68388
+ bubbles: true,
68389
+ detail: {
68390
+ variableType,
68391
+ path,
68392
+ displayName,
68393
+ position: pos,
68394
+ nodeSize: node.nodeSize
68395
+ }
68396
+ });
68397
+ editor.view.dom.dispatchEvent(event);
68398
+ }
68399
+ };
68370
68400
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
68371
68401
  NodeViewWrapper,
68372
68402
  {
@@ -68401,7 +68431,19 @@ const VariableChipComponent = ({
68401
68431
  "button",
68402
68432
  {
68403
68433
  type: "button",
68404
- className: "k-md-editor-variable-chip__remove inline-flex items-center justify-center w-3.5 h-3.5 p-0 border-0 bg-transparent cursor-pointer rounded-sm opacity-70 transition-opacity ml-0.5 shrink-0 hover:opacity-100",
68434
+ className: "k-md-editor-variable-chip__edit inline-flex items-center justify-center w-3.5 h-3.5 p-0 border-0 bg-transparent cursor-pointer rounded-sm opacity-70 transition-opacity shrink-0 hover:opacity-100",
68435
+ onClick: handleEdit,
68436
+ onMouseDown: (e3) => e3.preventDefault(),
68437
+ style: { color: config2.color },
68438
+ "aria-label": "Edit variable",
68439
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { size: 10 })
68440
+ }
68441
+ ),
68442
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
68443
+ "button",
68444
+ {
68445
+ type: "button",
68446
+ className: "k-md-editor-variable-chip__remove inline-flex items-center justify-center w-3.5 h-3.5 p-0 border-0 bg-transparent cursor-pointer rounded-sm opacity-70 transition-opacity shrink-0 hover:opacity-100",
68405
68447
  onClick: handleRemove,
68406
68448
  onMouseDown: (e3) => e3.preventDefault(),
68407
68449
  style: { color: config2.color },
@@ -69826,18 +69868,51 @@ const VariableMenu = ({
69826
69868
  query,
69827
69869
  onQueryChange,
69828
69870
  onSelect,
69871
+ onCustomVariable,
69829
69872
  onClose,
69830
69873
  envVariables: envVariables2 = [],
69831
69874
  memoryVariables = [],
69832
69875
  systemVariables: systemVariables2 = [],
69833
- contentVariables = []
69876
+ contentVariables = [],
69877
+ allowCustomVariables = false,
69878
+ editorControlled = false,
69879
+ customInputMode = false,
69880
+ isEditMode = false
69834
69881
  }) => {
69882
+ const [customVariableInput, setCustomVariableInput] = useState("");
69883
+ const customInputRef = useRef(null);
69835
69884
  const [activeCategory, setActiveCategory] = useState(null);
69836
69885
  const [selectedIndex, setSelectedIndex] = useState(0);
69837
69886
  const [currentPath, setCurrentPath] = useState([]);
69838
69887
  const [adjustedPosition, setAdjustedPosition] = useState(position);
69839
69888
  const menuRef = useRef(null);
69840
69889
  const inputRef = useRef(null);
69890
+ const parsedQuery = useMemo(() => {
69891
+ const parts = query.split(".");
69892
+ if (parts.length > 1) {
69893
+ const category = parts[0].toLowerCase();
69894
+ if (["env", "memory", "system", "content"].includes(category)) {
69895
+ return {
69896
+ category,
69897
+ path: parts.slice(1, -1),
69898
+ searchTerm: parts[parts.length - 1],
69899
+ fullPath: parts.slice(0, -1).join(".")
69900
+ };
69901
+ }
69902
+ }
69903
+ return {
69904
+ category: null,
69905
+ path: [],
69906
+ searchTerm: query,
69907
+ fullPath: ""
69908
+ };
69909
+ }, [query]);
69910
+ useEffect(() => {
69911
+ if (parsedQuery.category && parsedQuery.category !== activeCategory) {
69912
+ setActiveCategory(parsedQuery.category);
69913
+ setCurrentPath(parsedQuery.path);
69914
+ }
69915
+ }, [parsedQuery.category, parsedQuery.path, activeCategory]);
69841
69916
  useEffect(() => {
69842
69917
  if (!menuRef.current) return;
69843
69918
  const menuRect = menuRef.current.getBoundingClientRect();
@@ -69867,10 +69942,11 @@ const VariableMenu = ({
69867
69942
  { id: "content", label: "Content Variables", icon: FileText, variables: contentVariables }
69868
69943
  ].filter((cat) => cat.variables.length > 0);
69869
69944
  const getCurrentItems = useCallback(() => {
69945
+ const searchTerm = parsedQuery.searchTerm.toLowerCase();
69870
69946
  if (!activeCategory) {
69871
- if (query) {
69947
+ if (searchTerm) {
69872
69948
  return categories.filter(
69873
- (cat) => cat.label.toLowerCase().includes(query.toLowerCase())
69949
+ (cat) => cat.label.toLowerCase().includes(searchTerm) || cat.id.toLowerCase().includes(searchTerm)
69874
69950
  );
69875
69951
  }
69876
69952
  return categories;
@@ -69878,29 +69954,99 @@ const VariableMenu = ({
69878
69954
  const category = categories.find((c3) => c3.id === activeCategory);
69879
69955
  if (!category) return [];
69880
69956
  let variables = category.variables;
69881
- for (const segment of currentPath) {
69882
- const parent = variables.find((v) => v.name === segment);
69957
+ const pathToFollow = parsedQuery.path.length > 0 ? parsedQuery.path : currentPath;
69958
+ for (const segment of pathToFollow) {
69959
+ const parent = variables.find((v) => v.name.toLowerCase() === segment.toLowerCase());
69883
69960
  if (parent == null ? void 0 : parent.children) {
69884
69961
  variables = parent.children;
69885
69962
  } else {
69886
69963
  break;
69887
69964
  }
69888
69965
  }
69889
- if (query) {
69966
+ if (searchTerm) {
69890
69967
  variables = variables.filter(
69891
69968
  (v) => {
69892
69969
  var _a;
69893
- return v.name.toLowerCase().includes(query.toLowerCase()) || ((_a = v.description) == null ? void 0 : _a.toLowerCase().includes(query.toLowerCase()));
69970
+ return v.name.toLowerCase().includes(searchTerm) || ((_a = v.description) == null ? void 0 : _a.toLowerCase().includes(searchTerm));
69894
69971
  }
69895
69972
  );
69896
69973
  }
69897
69974
  return variables;
69898
- }, [activeCategory, categories, currentPath, query]);
69975
+ }, [activeCategory, categories, currentPath, parsedQuery]);
69976
+ const shouldShowCustomOption = useMemo(() => {
69977
+ if (!allowCustomVariables || !query.trim()) return false;
69978
+ const items2 = getCurrentItems();
69979
+ const hasExactMatch = items2.some((item) => {
69980
+ if ("variables" in item) return false;
69981
+ return item.name.toLowerCase() === parsedQuery.searchTerm.toLowerCase();
69982
+ });
69983
+ return !hasExactMatch && query.length > 0;
69984
+ }, [allowCustomVariables, query, getCurrentItems, parsedQuery.searchTerm]);
69985
+ const getCustomVariablePath = useCallback(() => {
69986
+ if (query.includes(".")) {
69987
+ return query;
69988
+ }
69989
+ if (activeCategory) {
69990
+ const pathParts = [activeCategory, ...currentPath, query].filter(Boolean);
69991
+ return pathParts.join(".");
69992
+ }
69993
+ return query;
69994
+ }, [query, activeCategory, currentPath]);
69899
69995
  const items = getCurrentItems();
69996
+ const totalItems = items.length + (shouldShowCustomOption ? 1 : 0);
69997
+ const handleBack = useCallback(() => {
69998
+ if (currentPath.length > 0) {
69999
+ setCurrentPath((prev) => prev.slice(0, -1));
70000
+ } else {
70001
+ setActiveCategory(null);
70002
+ }
70003
+ onQueryChange("");
70004
+ }, [currentPath.length, onQueryChange]);
70005
+ const handleItemClick = useCallback((item) => {
70006
+ if (item === "custom") {
70007
+ if (onCustomVariable) {
70008
+ onCustomVariable(getCustomVariablePath());
70009
+ }
70010
+ return;
70011
+ }
70012
+ if ("variables" in item) {
70013
+ setActiveCategory(item.id);
70014
+ setCurrentPath([]);
70015
+ onQueryChange(item.id + ".");
70016
+ } else {
70017
+ if (item.children && item.children.length > 0) {
70018
+ setCurrentPath((prev) => [...prev, item.name]);
70019
+ const newPath = activeCategory ? `${activeCategory}.${[...currentPath, item.name].join(".")}.` : `${item.name}.`;
70020
+ onQueryChange(newPath);
70021
+ } else {
70022
+ const fullPath = activeCategory ? [...currentPath, item.name].join(".") : item.path;
70023
+ onSelect({
70024
+ ...item,
70025
+ path: fullPath
70026
+ });
70027
+ }
70028
+ }
70029
+ }, [onCustomVariable, getCustomVariablePath, onQueryChange, activeCategory, currentPath, onSelect]);
69900
70030
  useEffect(() => {
69901
70031
  var _a;
69902
- (_a = inputRef.current) == null ? void 0 : _a.focus();
69903
- }, []);
70032
+ if (!editorControlled && !customInputMode) {
70033
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
70034
+ }
70035
+ }, [editorControlled, customInputMode]);
70036
+ useEffect(() => {
70037
+ if (customInputMode) {
70038
+ setTimeout(() => {
70039
+ var _a;
70040
+ (_a = customInputRef.current) == null ? void 0 : _a.focus();
70041
+ }, 50);
70042
+ }
70043
+ }, [customInputMode]);
70044
+ const handleCustomVariableSubmit = useCallback(() => {
70045
+ if (customVariableInput.trim() && onCustomVariable) {
70046
+ onCustomVariable(customVariableInput.trim());
70047
+ setCustomVariableInput("");
70048
+ }
70049
+ }, [customVariableInput, onCustomVariable]);
69904
70050
  useEffect(() => {
69905
70051
  const handleClickOutside = (e3) => {
69906
70052
  if (menuRef.current && !menuRef.current.contains(e3.target)) {
@@ -69912,65 +70058,61 @@ const VariableMenu = ({
69912
70058
  }, [onClose]);
69913
70059
  useEffect(() => {
69914
70060
  const handleKeyDown2 = (e3) => {
70061
+ if (customInputMode) return;
69915
70062
  switch (e3.key) {
69916
70063
  case "ArrowDown":
69917
70064
  e3.preventDefault();
69918
- setSelectedIndex((prev) => Math.min(prev + 1, items.length - 1));
70065
+ e3.stopPropagation();
70066
+ setSelectedIndex((prev) => Math.min(prev + 1, totalItems - 1));
69919
70067
  break;
69920
70068
  case "ArrowUp":
69921
70069
  e3.preventDefault();
70070
+ e3.stopPropagation();
69922
70071
  setSelectedIndex((prev) => Math.max(prev - 1, 0));
69923
70072
  break;
69924
70073
  case "Enter":
69925
70074
  e3.preventDefault();
69926
- if (items[selectedIndex]) {
70075
+ e3.stopPropagation();
70076
+ if (shouldShowCustomOption && selectedIndex === items.length) {
70077
+ handleItemClick("custom");
70078
+ } else if (items[selectedIndex]) {
69927
70079
  handleItemClick(items[selectedIndex]);
70080
+ } else if (items.length > 0) {
70081
+ handleItemClick(items[0]);
70082
+ } else if (shouldShowCustomOption) {
70083
+ handleItemClick("custom");
70084
+ }
70085
+ if (items.length === 0 && !shouldShowCustomOption) {
70086
+ onClose();
69928
70087
  }
69929
70088
  break;
69930
70089
  case "Escape":
69931
70090
  e3.preventDefault();
69932
- if (activeCategory) {
70091
+ e3.stopPropagation();
70092
+ if (activeCategory && !parsedQuery.category) {
69933
70093
  handleBack();
69934
70094
  } else {
69935
70095
  onClose();
69936
70096
  }
69937
70097
  break;
69938
- case "Backspace":
69939
- if (!query && activeCategory) {
69940
- e3.preventDefault();
69941
- handleBack();
70098
+ case "Tab":
70099
+ if (items.length > 0 && !("variables" in items[0])) {
70100
+ const firstItem = items[0];
70101
+ if (firstItem.children && firstItem.children.length > 0) {
70102
+ e3.preventDefault();
70103
+ e3.stopPropagation();
70104
+ handleItemClick(firstItem);
70105
+ }
69942
70106
  }
69943
70107
  break;
69944
70108
  }
69945
70109
  };
69946
- document.addEventListener("keydown", handleKeyDown2);
69947
- return () => document.removeEventListener("keydown", handleKeyDown2);
69948
- }, [items, selectedIndex, activeCategory, query, onClose]);
70110
+ document.addEventListener("keydown", handleKeyDown2, true);
70111
+ return () => document.removeEventListener("keydown", handleKeyDown2, true);
70112
+ }, [customInputMode, items, selectedIndex, activeCategory, onClose, shouldShowCustomOption, totalItems, parsedQuery.category, handleItemClick, handleBack]);
69949
70113
  useEffect(() => {
69950
70114
  setSelectedIndex(0);
69951
- }, [items.length, activeCategory, query]);
69952
- const handleItemClick = (item) => {
69953
- if ("variables" in item) {
69954
- setActiveCategory(item.id);
69955
- setCurrentPath([]);
69956
- onQueryChange("");
69957
- } else {
69958
- if (item.children && item.children.length > 0) {
69959
- setCurrentPath((prev) => [...prev, item.name]);
69960
- onQueryChange("");
69961
- } else {
69962
- onSelect(item);
69963
- }
69964
- }
69965
- };
69966
- const handleBack = () => {
69967
- if (currentPath.length > 0) {
69968
- setCurrentPath((prev) => prev.slice(0, -1));
69969
- } else {
69970
- setActiveCategory(null);
69971
- }
69972
- onQueryChange("");
69973
- };
70115
+ }, [totalItems, activeCategory, query]);
69974
70116
  const getIconForType = (type) => {
69975
70117
  switch (type) {
69976
70118
  case "env":
@@ -69986,10 +70128,12 @@ const VariableMenu = ({
69986
70128
  }
69987
70129
  };
69988
70130
  const getCurrentTitle = () => {
69989
- if (!activeCategory) return "Insert Variable";
70131
+ const prefix2 = isEditMode ? "Edit Variable" : "Insert Variable";
70132
+ if (!activeCategory) return prefix2;
69990
70133
  const category = categories.find((c3) => c3.id === activeCategory);
69991
- if (currentPath.length > 0) {
69992
- return currentPath.join(".");
70134
+ const pathToShow = parsedQuery.path.length > 0 ? parsedQuery.path : currentPath;
70135
+ if (pathToShow.length > 0) {
70136
+ return `${activeCategory}.${pathToShow.join(".")}`;
69993
70137
  }
69994
70138
  return (category == null ? void 0 : category.label) || "Variables";
69995
70139
  };
@@ -70015,51 +70159,142 @@ const VariableMenu = ({
70015
70159
  ),
70016
70160
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[13px] font-medium text-gray-700 flex-1", children: getCurrentTitle() })
70017
70161
  ] }),
70018
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-2 border-b border-gray-200", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-2.5 py-1.5 bg-gray-50 rounded-md border border-gray-200", children: [
70019
- /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { size: 14, className: "text-gray-400" }),
70020
- /* @__PURE__ */ jsxRuntimeExports.jsx(
70021
- "input",
70022
- {
70023
- ref: inputRef,
70024
- type: "text",
70025
- value: query,
70026
- onChange: (e3) => onQueryChange(e3.target.value),
70027
- placeholder: "Search...",
70028
- className: "flex-1 border-0 bg-transparent outline-none text-[13px] text-gray-700",
70029
- "data-id": "md-editor-variable-search"
70030
- }
70031
- )
70032
- ] }) }),
70033
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto p-1", children: items.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-center text-gray-400 text-[13px]", children: "No items found" }) : items.map((item, index) => {
70034
- var _a;
70035
- const isCategory = "variables" in item;
70036
- const Icon = isCategory ? item.icon : getIconForType(item.type);
70037
- const hasChildren = !isCategory && ((_a = item.children) == null ? void 0 : _a.length);
70038
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
70162
+ customInputMode ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-3 border-b border-gray-200 bg-blue-50", children: [
70163
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[12px] text-blue-600 mb-2 font-medium", children: "Type your custom variable:" }),
70164
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
70165
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[14px] font-mono text-gray-500", children: "{{" }),
70166
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
70167
+ "input",
70168
+ {
70169
+ ref: customInputRef,
70170
+ type: "text",
70171
+ value: customVariableInput,
70172
+ onChange: (e3) => setCustomVariableInput(e3.target.value),
70173
+ onKeyDown: (e3) => {
70174
+ if (e3.key === "Enter" && customVariableInput.trim()) {
70175
+ e3.preventDefault();
70176
+ handleCustomVariableSubmit();
70177
+ } else if (e3.key === "Escape") {
70178
+ e3.preventDefault();
70179
+ onClose();
70180
+ }
70181
+ },
70182
+ placeholder: "memory.store.field",
70183
+ className: "flex-1 border border-blue-300 bg-white rounded px-2 py-1.5 outline-none text-[13px] text-gray-700 font-mono focus:border-blue-500 focus:ring-1 focus:ring-blue-500",
70184
+ "data-id": "md-editor-custom-variable-input"
70185
+ }
70186
+ ),
70187
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[14px] font-mono text-gray-500", children: "}}" })
70188
+ ] }),
70189
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 flex gap-2", children: [
70190
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
70191
+ "button",
70192
+ {
70193
+ type: "button",
70194
+ onClick: handleCustomVariableSubmit,
70195
+ disabled: !customVariableInput.trim(),
70196
+ className: "px-3 py-1 text-[12px] bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed",
70197
+ children: "Insert"
70198
+ }
70199
+ ),
70200
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
70201
+ "button",
70202
+ {
70203
+ type: "button",
70204
+ onClick: onClose,
70205
+ className: "px-3 py-1 text-[12px] bg-gray-200 text-gray-700 rounded hover:bg-gray-300",
70206
+ children: "Cancel"
70207
+ }
70208
+ )
70209
+ ] })
70210
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
70211
+ !editorControlled && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-2 border-b border-gray-200", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-2.5 py-1.5 bg-gray-50 rounded-md border border-gray-200", children: [
70212
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { size: 14, className: "text-gray-400" }),
70213
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
70214
+ "input",
70215
+ {
70216
+ ref: inputRef,
70217
+ type: "text",
70218
+ value: query,
70219
+ onChange: (e3) => onQueryChange(e3.target.value),
70220
+ placeholder: "Search...",
70221
+ className: "flex-1 border-0 bg-transparent outline-none text-[13px] text-gray-700",
70222
+ "data-id": "md-editor-variable-search"
70223
+ }
70224
+ )
70225
+ ] }) }),
70226
+ editorControlled && query && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1.5 border-b border-gray-200 bg-gray-50", children: [
70227
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] text-gray-500", children: "Typing: " }),
70228
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] font-mono text-gray-700", children: `{{${query}` })
70229
+ ] })
70230
+ ] }),
70231
+ !customInputMode && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto p-1", children: items.length === 0 && !shouldShowCustomOption ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-center text-gray-400 text-[13px]", children: "No items found" }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
70232
+ items.map((item, index) => {
70233
+ var _a;
70234
+ const isCategory = "variables" in item;
70235
+ const Icon = isCategory ? item.icon : getIconForType(item.type);
70236
+ const hasChildren = !isCategory && ((_a = item.children) == null ? void 0 : _a.length);
70237
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
70238
+ "button",
70239
+ {
70240
+ type: "button",
70241
+ onClick: () => handleItemClick(item),
70242
+ className: `flex items-center gap-2.5 w-full py-2 px-2.5 border-0 rounded-md text-left cursor-pointer transition-colors duration-100 ${index === selectedIndex ? "bg-gray-100" : "bg-transparent hover:bg-gray-100"}`,
70243
+ onMouseEnter: () => setSelectedIndex(index),
70244
+ "data-id": `md-editor-variable-item-${isCategory ? item.id : item.id}`,
70245
+ children: [
70246
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center justify-center w-7 h-7 rounded-md bg-gray-100 text-gray-500 shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { size: 16 }) }),
70247
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
70248
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[13px] font-medium text-gray-800 truncate", children: isCategory ? item.label : item.name }),
70249
+ !isCategory && item.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-400 truncate", children: item.description })
70250
+ ] }),
70251
+ (isCategory || hasChildren) && /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 14, className: "text-gray-400 shrink-0" })
70252
+ ]
70253
+ },
70254
+ isCategory ? item.id : item.id
70255
+ );
70256
+ }),
70257
+ shouldShowCustomOption && /* @__PURE__ */ jsxRuntimeExports.jsxs(
70039
70258
  "button",
70040
70259
  {
70041
70260
  type: "button",
70042
- onClick: () => handleItemClick(item),
70043
- className: `flex items-center gap-2.5 w-full py-2 px-2.5 border-0 rounded-md text-left cursor-pointer transition-colors duration-100 ${index === selectedIndex ? "bg-gray-100" : "bg-transparent hover:bg-gray-100"}`,
70044
- onMouseEnter: () => setSelectedIndex(index),
70045
- "data-id": `md-editor-variable-item-${isCategory ? item.id : item.id}`,
70261
+ onClick: () => handleItemClick("custom"),
70262
+ className: `flex items-center gap-2.5 w-full py-2 px-2.5 border-0 rounded-md text-left cursor-pointer transition-colors duration-100 border-t border-gray-100 mt-1 pt-2 ${selectedIndex === items.length ? "bg-blue-50" : "bg-transparent hover:bg-blue-50"}`,
70263
+ onMouseEnter: () => setSelectedIndex(items.length),
70264
+ "data-id": "md-editor-variable-custom",
70046
70265
  children: [
70047
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center justify-center w-7 h-7 rounded-md bg-gray-100 text-gray-500 shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { size: 16 }) }),
70266
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center justify-center w-7 h-7 rounded-md bg-blue-100 text-blue-600 shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { size: 16 }) }),
70048
70267
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
70049
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[13px] font-medium text-gray-800 truncate", children: isCategory ? item.label : item.name }),
70050
- !isCategory && item.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-400 truncate", children: item.description })
70051
- ] }),
70052
- (isCategory || hasChildren) && /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 14, className: "text-gray-400 shrink-0" })
70268
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[13px] font-medium text-blue-700 truncate", children: [
70269
+ 'Use "',
70270
+ getCustomVariablePath(),
70271
+ '"'
70272
+ ] }),
70273
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-blue-500 truncate", children: "Insert as custom variable" })
70274
+ ] })
70053
70275
  ]
70054
- },
70055
- isCategory ? item.id : item.id
70056
- );
70057
- }) }),
70058
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1.5 border-t border-gray-200 text-[11px] text-gray-400 flex gap-3", children: [
70276
+ }
70277
+ )
70278
+ ] }) }),
70279
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-1.5 border-t border-gray-200 text-[11px] text-gray-400 flex gap-3 flex-wrap", children: customInputMode ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
70280
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: " Insert" }),
70281
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Esc Cancel" })
70282
+ ] }) : editorControlled ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
70283
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Click to select" }),
70284
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-500 font-medium", children: [
70285
+ "{{{",
70286
+ " Custom input"
70287
+ ] }),
70288
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
70289
+ "Type ",
70290
+ "}}",
70291
+ " to close"
70292
+ ] })
70293
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
70059
70294
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "↑↓ Navigate" }),
70060
70295
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "↵ Select" }),
70061
70296
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Esc Close" })
70062
- ] })
70297
+ ] }) })
70063
70298
  ]
70064
70299
  }
70065
70300
  );
@@ -71925,6 +72160,8 @@ const MDEditor = forwardRef(
71925
72160
  const [variableMenuOpen, setVariableMenuOpen] = useState(false);
71926
72161
  const [variableMenuPosition, setVariableMenuPosition] = useState({ top: 0, left: 0 });
71927
72162
  const [variableMenuQuery, setVariableMenuQuery] = useState("");
72163
+ const [customInputMode, setCustomInputMode] = useState(false);
72164
+ const [editingVariableChip, setEditingVariableChip] = useState(null);
71928
72165
  const [aiPanelOpen, setAIPanelOpen] = useState(mergedAIConfig.alwaysShowPanel ?? false);
71929
72166
  const [aiRefineContext, setAIRefineContext] = useState(null);
71930
72167
  const variableTriggerPosRef = useRef(null);
@@ -71994,6 +72231,21 @@ const MDEditor = forwardRef(
71994
72231
  (variable, triggerPos) => {
71995
72232
  if (!editorRef.current) return;
71996
72233
  const editor2 = editorRef.current;
72234
+ if (editingVariableChip) {
72235
+ const { position, nodeSize: nodeSize2 } = editingVariableChip;
72236
+ editor2.chain().focus().deleteRange({ from: position, to: position + nodeSize2 }).insertContentAt(position, {
72237
+ type: "variableChip",
72238
+ attrs: {
72239
+ variableType: variable.type,
72240
+ path: variable.path,
72241
+ displayName: variable.name
72242
+ }
72243
+ }).run();
72244
+ setEditingVariableChip(null);
72245
+ setVariableMenuOpen(false);
72246
+ setVariableMenuQuery("");
72247
+ return;
72248
+ }
71997
72249
  const deleteFrom = triggerPos ?? variableTriggerPosRef.current;
71998
72250
  if (deleteFrom !== null) {
71999
72251
  const { from: from2 } = editor2.state.selection;
@@ -72017,9 +72269,63 @@ const MDEditor = forwardRef(
72017
72269
  }).insertContent(" ").run();
72018
72270
  }
72019
72271
  setVariableMenuOpen(false);
72272
+ setVariableMenuQuery("");
72020
72273
  variableTriggerPosRef.current = null;
72021
72274
  },
72022
- []
72275
+ [editingVariableChip]
72276
+ );
72277
+ const insertCustomVariable = useCallback(
72278
+ (variablePath) => {
72279
+ if (!editorRef.current) return;
72280
+ const editor2 = editorRef.current;
72281
+ let variableType = "custom";
72282
+ let displayPath = variablePath;
72283
+ if (variablePath.startsWith("env.")) {
72284
+ variableType = "env";
72285
+ displayPath = variablePath.substring(4);
72286
+ } else if (variablePath.startsWith("memory.")) {
72287
+ variableType = "memory";
72288
+ displayPath = variablePath.substring(7);
72289
+ } else if (variablePath.startsWith("content.")) {
72290
+ variableType = "content";
72291
+ displayPath = variablePath.substring(8);
72292
+ } else if (variablePath.startsWith("system.")) {
72293
+ variableType = "system";
72294
+ displayPath = variablePath.substring(7);
72295
+ }
72296
+ if (editingVariableChip) {
72297
+ const { position, nodeSize: nodeSize2 } = editingVariableChip;
72298
+ editor2.chain().focus().deleteRange({ from: position, to: position + nodeSize2 }).insertContentAt(position, {
72299
+ type: "variableChip",
72300
+ attrs: {
72301
+ variableType,
72302
+ path: displayPath,
72303
+ displayName: displayPath.split(".").pop() || displayPath
72304
+ }
72305
+ }).run();
72306
+ setEditingVariableChip(null);
72307
+ setVariableMenuOpen(false);
72308
+ setVariableMenuQuery("");
72309
+ return;
72310
+ }
72311
+ const deleteFrom = variableTriggerPosRef.current;
72312
+ if (deleteFrom !== null) {
72313
+ const { from: from2 } = editor2.state.selection;
72314
+ const deleteRange2 = { from: deleteFrom, to: from2 };
72315
+ editor2.chain().focus().deleteRange(deleteRange2).insertContent({
72316
+ type: "variableChip",
72317
+ attrs: {
72318
+ variableType,
72319
+ path: displayPath,
72320
+ displayName: displayPath.split(".").pop() || displayPath
72321
+ }
72322
+ }).insertContent(" ").run();
72323
+ }
72324
+ setVariableMenuOpen(false);
72325
+ setVariableMenuQuery("");
72326
+ variableTriggerPosRef.current = null;
72327
+ },
72328
+ [editingVariableChip]
72023
72329
  );
72024
72330
  const insertMention = useCallback(
72025
72331
  (mention) => {
@@ -72282,9 +72588,14 @@ const MDEditor = forwardRef(
72282
72588
  const handleKeyDown2 = (event) => {
72283
72589
  if (event.key === "{") {
72284
72590
  const { from: from2 } = editor.state.selection;
72285
- const textBefore = editor.state.doc.textBetween(Math.max(0, from2 - 1), from2);
72286
- if (textBefore === "{") {
72591
+ const textBefore = editor.state.doc.textBetween(Math.max(0, from2 - 2), from2);
72592
+ const charBefore = editor.state.doc.textBetween(Math.max(0, from2 - 1), from2);
72593
+ if (textBefore === "{{" && variableMenuOpen) {
72287
72594
  event.preventDefault();
72595
+ setCustomInputMode(true);
72596
+ return;
72597
+ }
72598
+ if (charBefore === "{") {
72288
72599
  variableTriggerPosRef.current = from2 - 1;
72289
72600
  const coords = editor.view.coordsAtPos(from2);
72290
72601
  setVariableMenuPosition({
@@ -72293,20 +72604,41 @@ const MDEditor = forwardRef(
72293
72604
  });
72294
72605
  setVariableMenuQuery("");
72295
72606
  setVariableMenuOpen(true);
72607
+ setCustomInputMode(false);
72296
72608
  }
72297
72609
  }
72298
72610
  };
72611
+ const handleInput = () => {
72612
+ if (!variableMenuOpen || variableTriggerPosRef.current === null || customInputMode) return;
72613
+ const { from: from2 } = editor.state.selection;
72614
+ const triggerPos = variableTriggerPosRef.current;
72615
+ const textAfterTrigger = editor.state.doc.textBetween(
72616
+ triggerPos + 2,
72617
+ // After {{
72618
+ from2
72619
+ );
72620
+ if (textAfterTrigger.includes("}}")) {
72621
+ setVariableMenuOpen(false);
72622
+ setCustomInputMode(false);
72623
+ variableTriggerPosRef.current = null;
72624
+ return;
72625
+ }
72626
+ setVariableMenuQuery(textAfterTrigger);
72627
+ };
72299
72628
  const editorElement = editor.view.dom;
72300
72629
  editorElement.addEventListener("keydown", handleKeyDown2);
72630
+ editorElement.addEventListener("input", handleInput);
72301
72631
  return () => {
72302
72632
  editorElement.removeEventListener("keydown", handleKeyDown2);
72633
+ editorElement.removeEventListener("input", handleInput);
72303
72634
  };
72304
- }, [editor, mergedFeatures.variableChips]);
72635
+ }, [editor, mergedFeatures.variableChips, variableMenuOpen, customInputMode]);
72305
72636
  useEffect(() => {
72306
72637
  if (!variableMenuOpen) return;
72307
72638
  const handleKeyDown2 = (event) => {
72308
72639
  if (event.key === "Escape") {
72309
72640
  setVariableMenuOpen(false);
72641
+ setEditingVariableChip(null);
72310
72642
  variableTriggerPosRef.current = null;
72311
72643
  editor == null ? void 0 : editor.chain().focus().run();
72312
72644
  }
@@ -72314,6 +72646,32 @@ const MDEditor = forwardRef(
72314
72646
  document.addEventListener("keydown", handleKeyDown2);
72315
72647
  return () => document.removeEventListener("keydown", handleKeyDown2);
72316
72648
  }, [variableMenuOpen, editor]);
72649
+ useEffect(() => {
72650
+ if (!editor) return;
72651
+ const handleVariableChipEdit = (event) => {
72652
+ const customEvent = event;
72653
+ const { variableType, path, position, nodeSize: nodeSize2 } = customEvent.detail;
72654
+ const coords = editor.view.coordsAtPos(position);
72655
+ setEditingVariableChip({
72656
+ position,
72657
+ nodeSize: nodeSize2,
72658
+ variableType,
72659
+ path
72660
+ });
72661
+ setVariableMenuPosition({
72662
+ top: coords.bottom + 8,
72663
+ left: coords.left
72664
+ });
72665
+ setVariableMenuQuery("");
72666
+ setCustomInputMode(false);
72667
+ setVariableMenuOpen(true);
72668
+ };
72669
+ const editorElement = editor.view.dom;
72670
+ editorElement.addEventListener("variable-chip-edit", handleVariableChipEdit);
72671
+ return () => {
72672
+ editorElement.removeEventListener("variable-chip-edit", handleVariableChipEdit);
72673
+ };
72674
+ }, [editor]);
72317
72675
  useEffect(() => {
72318
72676
  if (!editor || isInternalUpdateRef.current) {
72319
72677
  isInternalUpdateRef.current = false;
@@ -72570,14 +72928,22 @@ const MDEditor = forwardRef(
72570
72928
  query: variableMenuQuery,
72571
72929
  onQueryChange: setVariableMenuQuery,
72572
72930
  onSelect: (variable) => insertVariable(variable),
72931
+ onCustomVariable: insertCustomVariable,
72573
72932
  onClose: () => {
72574
72933
  setVariableMenuOpen(false);
72934
+ setVariableMenuQuery("");
72935
+ setCustomInputMode(false);
72936
+ setEditingVariableChip(null);
72575
72937
  variableTriggerPosRef.current = null;
72576
72938
  },
72577
72939
  envVariables: envVariables2,
72578
72940
  memoryVariables,
72579
72941
  systemVariables: systemVariables2,
72580
- contentVariables
72942
+ contentVariables,
72943
+ allowCustomVariables: true,
72944
+ editorControlled: !customInputMode && !editingVariableChip,
72945
+ customInputMode,
72946
+ isEditMode: !!editingVariableChip
72581
72947
  }
72582
72948
  ),
72583
72949
  isAIEnabled && mergedAIConfig.contextMenu && /* @__PURE__ */ jsxRuntimeExports.jsx(