@qoretechnologies/reqraft 0.10.53 → 0.10.54-pr.115.g9bc96ed

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/.claude/CLAUDE.md +25 -0
  2. package/.tasks/INDEX.md +1 -0
  3. package/.tasks/STORY_NETWORK_ISOLATION.md +98 -0
  4. package/README.md +1 -1
  5. package/design/FORM_ENGINE_EXPRESSIONS.md +110 -0
  6. package/design/FORM_ENGINE_FIELD_MIGRATION.md +56 -1
  7. package/design/RENDER_EXPRESSION_TRANSPORT.md +76 -10
  8. package/design/SMART_EDITOR_UX.md +21 -0
  9. package/dist/components/dpqlEditor/DpqlEditor.d.ts.map +1 -1
  10. package/dist/components/dpqlEditor/DpqlEditor.js +3 -3
  11. package/dist/components/dpqlEditor/DpqlEditor.js.map +1 -1
  12. package/dist/components/dpqlEditor/dpqlHelpers.d.ts +6 -0
  13. package/dist/components/dpqlEditor/dpqlHelpers.d.ts.map +1 -1
  14. package/dist/components/dpqlEditor/dpqlHelpers.js +21 -2
  15. package/dist/components/dpqlEditor/dpqlHelpers.js.map +1 -1
  16. package/dist/components/dpqlEditor/dpqlProbe.d.ts +37 -0
  17. package/dist/components/dpqlEditor/dpqlProbe.d.ts.map +1 -0
  18. package/dist/components/dpqlEditor/dpqlProbe.js +203 -0
  19. package/dist/components/dpqlEditor/dpqlProbe.js.map +1 -0
  20. package/dist/components/dpqlEditor/dpqlTags.d.ts +8 -0
  21. package/dist/components/dpqlEditor/dpqlTags.d.ts.map +1 -1
  22. package/dist/components/dpqlEditor/dpqlTags.js +5 -1
  23. package/dist/components/dpqlEditor/dpqlTags.js.map +1 -1
  24. package/dist/components/dpqlEditor/index.d.ts +4 -0
  25. package/dist/components/dpqlEditor/index.d.ts.map +1 -1
  26. package/dist/components/dpqlEditor/index.js +5 -1
  27. package/dist/components/dpqlEditor/index.js.map +1 -1
  28. package/dist/components/dpqlEditor/types.d.ts +42 -2
  29. package/dist/components/dpqlEditor/types.d.ts.map +1 -1
  30. package/dist/components/dpqlEditor/types.js +0 -4
  31. package/dist/components/dpqlEditor/types.js.map +1 -1
  32. package/dist/components/dpqlEditor/useDpqlProbe.d.ts +4 -0
  33. package/dist/components/dpqlEditor/useDpqlProbe.d.ts.map +1 -0
  34. package/dist/components/dpqlEditor/useDpqlProbe.js +29 -0
  35. package/dist/components/dpqlEditor/useDpqlProbe.js.map +1 -0
  36. package/dist/components/dpqlEditor/useDpqlSession.d.ts +5 -2
  37. package/dist/components/dpqlEditor/useDpqlSession.d.ts.map +1 -1
  38. package/dist/components/dpqlEditor/useDpqlSession.js +8 -2
  39. package/dist/components/dpqlEditor/useDpqlSession.js.map +1 -1
  40. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  41. package/dist/components/form/engine/CompactRow.js +192 -45
  42. package/dist/components/form/engine/CompactRow.js.map +1 -1
  43. package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
  44. package/dist/components/form/engine/CompactToolbar.js +5 -2
  45. package/dist/components/form/engine/CompactToolbar.js.map +1 -1
  46. package/dist/components/form/engine/FormEngine.d.ts +160 -12
  47. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  48. package/dist/components/form/engine/FormEngine.js +376 -75
  49. package/dist/components/form/engine/FormEngine.js.map +1 -1
  50. package/dist/components/form/engine/FormFieldsSkeleton.d.ts +48 -0
  51. package/dist/components/form/engine/FormFieldsSkeleton.d.ts.map +1 -0
  52. package/dist/components/form/engine/FormFieldsSkeleton.js +38 -0
  53. package/dist/components/form/engine/FormFieldsSkeleton.js.map +1 -0
  54. package/dist/components/form/engine/OptionFieldMessages.d.ts +17 -2
  55. package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
  56. package/dist/components/form/engine/OptionFieldMessages.js +61 -11
  57. package/dist/components/form/engine/OptionFieldMessages.js.map +1 -1
  58. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
  59. package/dist/components/form/engine/_structuredData/SchemaDataView.js +7 -1
  60. package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
  61. package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
  62. package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
  63. package/dist/components/form/engine/readFirst.d.ts +42 -1
  64. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  65. package/dist/components/form/engine/readFirst.js +74 -7
  66. package/dist/components/form/engine/readFirst.js.map +1 -1
  67. package/dist/components/form/engine/rendererTypes.d.ts +13 -0
  68. package/dist/components/form/engine/rendererTypes.d.ts.map +1 -1
  69. package/dist/components/form/engine/rendererTypes.js.map +1 -1
  70. package/dist/components/form/engine/rowMenuContext.d.ts +78 -0
  71. package/dist/components/form/engine/rowMenuContext.d.ts.map +1 -0
  72. package/dist/components/form/engine/rowMenuContext.js +103 -0
  73. package/dist/components/form/engine/rowMenuContext.js.map +1 -0
  74. package/dist/components/form/engine/typeChoices.d.ts +37 -0
  75. package/dist/components/form/engine/typeChoices.d.ts.map +1 -0
  76. package/dist/components/form/engine/typeChoices.js +25 -0
  77. package/dist/components/form/engine/typeChoices.js.map +1 -0
  78. package/dist/components/form/expressions/DpqlRendering.d.ts +26 -0
  79. package/dist/components/form/expressions/DpqlRendering.d.ts.map +1 -0
  80. package/dist/components/form/expressions/DpqlRendering.js +53 -0
  81. package/dist/components/form/expressions/DpqlRendering.js.map +1 -0
  82. package/dist/components/form/expressions/ExpressionField.d.ts +7 -1
  83. package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
  84. package/dist/components/form/expressions/ExpressionField.js +202 -45
  85. package/dist/components/form/expressions/ExpressionField.js.map +1 -1
  86. package/dist/components/form/expressions/argumentPresence.d.ts +97 -0
  87. package/dist/components/form/expressions/argumentPresence.d.ts.map +1 -0
  88. package/dist/components/form/expressions/argumentPresence.js +203 -0
  89. package/dist/components/form/expressions/argumentPresence.js.map +1 -0
  90. package/dist/components/form/expressions/builder/argumentLabel.d.ts.map +1 -1
  91. package/dist/components/form/expressions/builder/argumentLabel.js +9 -4
  92. package/dist/components/form/expressions/builder/argumentLabel.js.map +1 -1
  93. package/dist/components/form/expressions/builder/index.d.ts +15 -2
  94. package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
  95. package/dist/components/form/expressions/builder/index.js +20 -58
  96. package/dist/components/form/expressions/builder/index.js.map +1 -1
  97. package/dist/components/form/expressions/builder/renderTemplate.d.ts +4 -1
  98. package/dist/components/form/expressions/builder/renderTemplate.d.ts.map +1 -1
  99. package/dist/components/form/expressions/builder/renderTemplate.js +10 -67
  100. package/dist/components/form/expressions/builder/renderTemplate.js.map +1 -1
  101. package/dist/components/form/expressions/dpqlMockLanguage.d.ts +76 -0
  102. package/dist/components/form/expressions/dpqlMockLanguage.d.ts.map +1 -0
  103. package/dist/components/form/expressions/dpqlMockLanguage.js +525 -0
  104. package/dist/components/form/expressions/dpqlMockLanguage.js.map +1 -0
  105. package/dist/components/form/expressions/dpqlMockLsp.d.ts +31 -2
  106. package/dist/components/form/expressions/dpqlMockLsp.d.ts.map +1 -1
  107. package/dist/components/form/expressions/dpqlMockLsp.js +86 -80
  108. package/dist/components/form/expressions/dpqlMockLsp.js.map +1 -1
  109. package/dist/components/form/expressions/mockExpressions.d.ts.map +1 -1
  110. package/dist/components/form/expressions/mockExpressions.js +8 -4
  111. package/dist/components/form/expressions/mockExpressions.js.map +1 -1
  112. package/dist/components/form/expressions/renderExpressionToText.d.ts +1 -1
  113. package/dist/components/form/expressions/renderExpressionToText.d.ts.map +1 -1
  114. package/dist/components/form/expressions/renderExpressionToText.js +95 -19
  115. package/dist/components/form/expressions/renderExpressionToText.js.map +1 -1
  116. package/dist/components/form/expressions/types.d.ts +7 -0
  117. package/dist/components/form/expressions/types.d.ts.map +1 -1
  118. package/dist/components/form/expressions/useRenderExpression.d.ts +7 -16
  119. package/dist/components/form/expressions/useRenderExpression.d.ts.map +1 -1
  120. package/dist/components/form/expressions/useRenderExpression.js +50 -126
  121. package/dist/components/form/expressions/useRenderExpression.js.map +1 -1
  122. package/dist/components/form/fields/Field.d.ts.map +1 -1
  123. package/dist/components/form/fields/Field.js +3 -1
  124. package/dist/components/form/fields/Field.js.map +1 -1
  125. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +11 -1
  126. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
  127. package/dist/components/form/fields/allowed-values/AllowedValues.js +14 -2
  128. package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
  129. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  130. package/dist/components/form/fields/auto/AutoFormField.js +32 -8
  131. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  132. package/dist/components/form/fields/date/Date.d.ts +1 -1
  133. package/dist/components/form/fields/date/Date.d.ts.map +1 -1
  134. package/dist/components/form/fields/date/Date.js +16 -2
  135. package/dist/components/form/fields/date/Date.js.map +1 -1
  136. package/dist/components/form/fields/rich-text/RichText.d.ts +21 -1
  137. package/dist/components/form/fields/rich-text/RichText.d.ts.map +1 -1
  138. package/dist/components/form/fields/rich-text/RichText.js +140 -8
  139. package/dist/components/form/fields/rich-text/RichText.js.map +1 -1
  140. package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts +2 -1
  141. package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts.map +1 -1
  142. package/dist/components/form/fields/template/ReadOnlyTemplateTag.js +3 -2
  143. package/dist/components/form/fields/template/ReadOnlyTemplateTag.js.map +1 -1
  144. package/dist/components/form/fields/template/TemplateField.d.ts +31 -1
  145. package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
  146. package/dist/components/form/fields/template/TemplateField.js +528 -50
  147. package/dist/components/form/fields/template/TemplateField.js.map +1 -1
  148. package/dist/components/form/index.d.ts +1 -0
  149. package/dist/components/form/index.d.ts.map +1 -1
  150. package/dist/components/form/index.js +1 -0
  151. package/dist/components/form/index.js.map +1 -1
  152. package/dist/components/smartEditor/SmartEditor.d.ts.map +1 -1
  153. package/dist/components/smartEditor/SmartEditor.js +29 -8
  154. package/dist/components/smartEditor/SmartEditor.js.map +1 -1
  155. package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts +8 -0
  156. package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts.map +1 -1
  157. package/dist/components/smartEditor/__fixtures__/mockLspServer.js +53 -10
  158. package/dist/components/smartEditor/__fixtures__/mockLspServer.js.map +1 -1
  159. package/dist/components/smartEditor/useLspSession.d.ts +5 -1
  160. package/dist/components/smartEditor/useLspSession.d.ts.map +1 -1
  161. package/dist/components/smartEditor/useLspSession.js +16 -2
  162. package/dist/components/smartEditor/useLspSession.js.map +1 -1
  163. package/dist/helpers/dpqlDetection.d.ts +58 -0
  164. package/dist/helpers/dpqlDetection.d.ts.map +1 -0
  165. package/dist/helpers/dpqlDetection.js +164 -0
  166. package/dist/helpers/dpqlDetection.js.map +1 -0
  167. package/dist/helpers/optionUiTypes.d.ts +3 -3
  168. package/dist/helpers/options.d.ts +37 -0
  169. package/dist/helpers/options.d.ts.map +1 -1
  170. package/dist/helpers/options.js +78 -1
  171. package/dist/helpers/options.js.map +1 -1
  172. package/dist/helpers/templateItems.d.ts +47 -0
  173. package/dist/helpers/templateItems.d.ts.map +1 -0
  174. package/dist/helpers/templateItems.js +88 -0
  175. package/dist/helpers/templateItems.js.map +1 -0
  176. package/dist/helpers/templateText.d.ts +37 -0
  177. package/dist/helpers/templateText.d.ts.map +1 -0
  178. package/dist/helpers/templateText.js +64 -0
  179. package/dist/helpers/templateText.js.map +1 -0
  180. package/dist/helpers/templates.d.ts +19 -11
  181. package/dist/helpers/templates.d.ts.map +1 -1
  182. package/dist/helpers/templates.js +46 -29
  183. package/dist/helpers/templates.js.map +1 -1
  184. package/dist/helpers/validations.d.ts.map +1 -1
  185. package/dist/helpers/validations.js +56 -9
  186. package/dist/helpers/validations.js.map +1 -1
  187. package/dist/hooks/useArgSchema.d.ts +2 -1
  188. package/dist/hooks/useArgSchema.d.ts.map +1 -1
  189. package/dist/hooks/useFetch/useFetch.d.ts +3 -1
  190. package/dist/hooks/useFetch/useFetch.d.ts.map +1 -1
  191. package/dist/hooks/useFetch/useFetch.js +47 -9
  192. package/dist/hooks/useFetch/useFetch.js.map +1 -1
  193. package/dist/hooks/useTemplates.d.ts +20 -0
  194. package/dist/hooks/useTemplates.d.ts.map +1 -1
  195. package/dist/hooks/useTemplates.js +34 -2
  196. package/dist/hooks/useTemplates.js.map +1 -1
  197. package/dist/index.d.ts +2 -1
  198. package/dist/index.d.ts.map +1 -1
  199. package/dist/index.js +5 -1
  200. package/dist/index.js.map +1 -1
  201. package/dist/stories/storyNetwork.d.ts +36 -0
  202. package/dist/stories/storyNetwork.d.ts.map +1 -0
  203. package/dist/stories/storyNetwork.js +82 -0
  204. package/dist/stories/storyNetwork.js.map +1 -0
  205. package/dist/utils/fetch.d.ts +151 -1
  206. package/dist/utils/fetch.d.ts.map +1 -1
  207. package/dist/utils/fetch.js +256 -44
  208. package/dist/utils/fetch.js.map +1 -1
  209. package/dist/utils/lspClient.d.ts +6 -0
  210. package/dist/utils/lspClient.d.ts.map +1 -1
  211. package/dist/utils/lspClient.js +62 -11
  212. package/dist/utils/lspClient.js.map +1 -1
  213. package/dist/utils/websocket.d.ts +6 -0
  214. package/dist/utils/websocket.d.ts.map +1 -1
  215. package/dist/utils/websocket.js +15 -7
  216. package/dist/utils/websocket.js.map +1 -1
  217. package/package.json +2 -2
  218. package/src/components/dpqlEditor/DpqlEditor.stories.tsx +3 -119
  219. package/src/components/dpqlEditor/DpqlEditor.tsx +5 -2
  220. package/src/components/dpqlEditor/dpqlHelpers.ts +20 -1
  221. package/src/components/dpqlEditor/dpqlProbe.ts +165 -0
  222. package/src/components/dpqlEditor/dpqlTags.ts +13 -0
  223. package/src/components/dpqlEditor/index.ts +4 -0
  224. package/src/components/dpqlEditor/types.ts +38 -2
  225. package/src/components/dpqlEditor/useDpqlProbe.ts +33 -0
  226. package/src/components/dpqlEditor/useDpqlSession.ts +20 -4
  227. package/src/components/form/engine/CompactRow.tsx +240 -51
  228. package/src/components/form/engine/CompactToolbar.tsx +10 -3
  229. package/src/components/form/engine/FormEngine.stories.tsx +423 -120
  230. package/src/components/form/engine/FormEngine.tsx +504 -87
  231. package/src/components/form/engine/FormFieldsSkeleton.tsx +76 -0
  232. package/src/components/form/engine/OptionFieldMessages.tsx +89 -11
  233. package/src/components/form/engine/_structuredData/SchemaDataView.tsx +11 -0
  234. package/src/components/form/engine/compactToolbarContext.ts +1 -1
  235. package/src/components/form/engine/readFirst.ts +86 -7
  236. package/src/components/form/engine/rendererTypes.ts +12 -0
  237. package/src/components/form/engine/rowMenuContext.ts +159 -0
  238. package/src/components/form/engine/typeChoices.ts +55 -0
  239. package/src/components/form/expressions/DpqlRendering.tsx +85 -0
  240. package/src/components/form/expressions/ExpressionField.stories.tsx +826 -48
  241. package/src/components/form/expressions/ExpressionField.tsx +265 -54
  242. package/src/components/form/expressions/argumentPresence.ts +200 -0
  243. package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +20 -4
  244. package/src/components/form/expressions/builder/argumentLabel.tsx +10 -4
  245. package/src/components/form/expressions/builder/index.tsx +39 -77
  246. package/src/components/form/expressions/builder/renderTemplate.tsx +23 -56
  247. package/src/components/form/expressions/dpqlMockLanguage.ts +565 -0
  248. package/src/components/form/expressions/dpqlMockLsp.ts +109 -83
  249. package/src/components/form/expressions/mockExpressions.ts +8 -4
  250. package/src/components/form/expressions/renderExpressionToText.ts +112 -22
  251. package/src/components/form/expressions/types.ts +7 -0
  252. package/src/components/form/expressions/useRenderExpression.ts +43 -127
  253. package/src/components/form/fields/Field.tsx +3 -2
  254. package/src/components/form/fields/allowed-values/AllowedValues.tsx +13 -2
  255. package/src/components/form/fields/auto/AutoFormField.stories.tsx +27 -20
  256. package/src/components/form/fields/auto/AutoFormField.tsx +33 -9
  257. package/src/components/form/fields/date/Date.tsx +17 -1
  258. package/src/components/form/fields/rich-text/RichText.tsx +199 -22
  259. package/src/components/form/fields/template/ReadOnlyTemplateTag.tsx +4 -2
  260. package/src/components/form/fields/template/TemplateField.stories.tsx +31 -9
  261. package/src/components/form/fields/template/TemplateField.tsx +714 -122
  262. package/src/components/form/index.tsx +1 -0
  263. package/src/components/log/Log.stories.tsx +2 -1
  264. package/src/components/smartEditor/SmartEditor.tsx +41 -9
  265. package/src/components/smartEditor/__fixtures__/mockLspServer.ts +52 -3
  266. package/src/components/smartEditor/useLspSession.ts +21 -3
  267. package/src/helpers/dpqlDetection.ts +209 -0
  268. package/src/helpers/options.ts +70 -0
  269. package/src/helpers/templateItems.ts +81 -0
  270. package/src/helpers/templateText.ts +92 -0
  271. package/src/helpers/templates.ts +47 -37
  272. package/src/helpers/validations.ts +59 -9
  273. package/src/hooks/useFetch/useFetch.stories.tsx +6 -5
  274. package/src/hooks/useFetch/useFetch.tsx +53 -7
  275. package/src/hooks/useStorage/useStorage.stories.tsx +2 -1
  276. package/src/hooks/useTemplates.ts +41 -0
  277. package/src/hooks/useWebSocket/useWebsocket.stories.tsx +2 -1
  278. package/src/index.tsx +14 -1
  279. package/src/stores/currentUser/currentUser.stories.tsx +2 -1
  280. package/src/stories/storyNetwork.ts +92 -0
  281. package/src/utils/fetch.ts +311 -21
  282. package/src/utils/lspClient.ts +68 -11
  283. package/src/utils/websocket.ts +20 -9
@@ -44,11 +44,20 @@ var __rest = (this && this.__rest) || function (s, e) {
44
44
  }
45
45
  return t;
46
46
  };
47
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
48
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
49
+ if (ar || !(i in from)) {
50
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
51
+ ar[i] = from[i];
52
+ }
53
+ }
54
+ return to.concat(ar || Array.prototype.slice.call(from));
55
+ };
47
56
  var __importDefault = (this && this.__importDefault) || function (mod) {
48
57
  return (mod && mod.__esModule) ? mod : { "default": mod };
49
58
  };
50
59
  Object.defineProperty(exports, "__esModule", { value: true });
51
- exports.TemplateField = exports.TemplateDropdownSelector = exports.CustomMenuItems = exports.ComponentMap = exports.TemplatesListProps = exports.isValueTemplate = exports.getTemplateValue = exports.getTemplateKey = void 0;
60
+ exports.TemplateField = exports.isTemplateAwareUiType = exports.BuiltInTemplateAwareUiTypes = exports.TemplateDropdownSelector = exports.CustomMenuItems = exports.ComponentMap = exports.TemplatesListProps = exports.isValueTemplate = exports.getTemplateValue = exports.getTemplateKey = void 0;
52
61
  var react_1 = require("react");
53
62
  var jsx_runtime_1 = require("react/jsx-runtime");
54
63
  // Verbatim port of qorus-ide `src/components/Field/template.tsx` (774 LOC,
@@ -65,7 +74,11 @@ var templates_1 = require("../../../../helpers/templates");
65
74
  Object.defineProperty(exports, "getTemplateKey", { enumerable: true, get: function () { return templates_1.getTemplateKey; } });
66
75
  Object.defineProperty(exports, "getTemplateValue", { enumerable: true, get: function () { return templates_1.getTemplateValue; } });
67
76
  Object.defineProperty(exports, "isValueTemplate", { enumerable: true, get: function () { return templates_1.isValueTemplate; } });
77
+ var dpqlDetection_1 = require("../../../../helpers/dpqlDetection");
78
+ var templateItems_1 = require("../../../../helpers/templateItems");
79
+ var markdownRendererContext_1 = require("../../../Description/markdownRendererContext");
68
80
  var validations_1 = require("../../../../helpers/validations");
81
+ var useDpqlProbe_1 = require("../../../dpqlEditor/useDpqlProbe");
69
82
  var useQorusTypes_1 = require("../../../../hooks/useQorusTypes");
70
83
  var useWhyDidYouUpdate_1 = require("../../../../hooks/useWhyDidYouUpdate");
71
84
  var builder_1 = require("../../expressions/builder");
@@ -81,6 +94,16 @@ var LongString_1 = __importDefault(require("../long-string/LongString"));
81
94
  var Number_1 = __importDefault(require("../number/Number"));
82
95
  var ReadOnlyTemplateTag_1 = require("./ReadOnlyTemplateTag");
83
96
  var RichText_1 = require("../rich-text/RichText");
97
+ var common_1 = require("../../../../helpers/common");
98
+ var singleLineString_1 = require("../../../../helpers/singleLineString");
99
+ var rowMenuContext_1 = require("../../engine/rowMenuContext");
100
+ /**
101
+ * How long the author must pause before typed text is sent to the DPQL
102
+ * probe. Long enough that a probe is not sent for every prefix of what is
103
+ * being typed, short enough that the offer appears while they are still
104
+ * looking at the field.
105
+ */
106
+ var DPQL_DETECT_DEBOUNCE_MS = 400;
84
107
  exports.TemplatesListProps = {
85
108
  useTargetWidth: true,
86
109
  handler: 'focus',
@@ -165,18 +188,25 @@ var MenuActionsSection = (0, react_2.memo)(function (_a) {
165
188
  exports.CustomMenuItems = (0, react_2.memo)(function (_a) {
166
189
  var items = _a.items, closePopover = _a.closePopover, setIsTemplate = _a.setIsTemplate, setTemplateValue = _a.setTemplateValue, rest = __rest(_a, ["items", "closePopover", "setIsTemplate", "setTemplateValue"]);
167
190
  return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreMenuSection, __assign({ label: 'Set Custom Value', isCollapsed: true, transparent: true, icon: 'Text' }, rest, { children: items.map(function (menuItem, index) {
168
- return 'isDivider' in menuItem ? ((0, jsx_runtime_1.jsx)(divider_1.default, __assign({}, menuItem), index)) : ((0, react_1.createElement)(reqore_1.ReqoreButton, __assign({}, rest, menuItem, { key: index, onClick: function (e) {
169
- var _a, _b;
170
- (_b = (_a = menuItem).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e, function () {
171
- setIsTemplate(false);
172
- setTemplateValue(null);
173
- closePopover === null || closePopover === void 0 ? void 0 : closePopover();
174
- });
175
- } })));
191
+ return 'isDivider' in menuItem ?
192
+ (0, jsx_runtime_1.jsx)(divider_1.default, __assign({}, menuItem), index)
193
+ : (0, react_1.createElement)(reqore_1.ReqoreButton, __assign({}, rest, menuItem, { key: index, onClick: function (e) {
194
+ var _a, _b;
195
+ (_b = (_a = menuItem).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e, function () {
196
+ setIsTemplate(false);
197
+ setTemplateValue(null);
198
+ closePopover === null || closePopover === void 0 ? void 0 : closePopover();
199
+ });
200
+ } }));
176
201
  }) })));
177
202
  });
178
203
  exports.TemplateDropdownSelector = (0, react_2.memo)(function (_a) {
179
204
  var onItemSelect = _a.onItemSelect, onRemoveClick = _a.onRemoveClick, items = _a.items, templates = _a.templates, allowCustomValues = _a.allowCustomValues, hasOnlyAllowedValues = _a.hasOnlyAllowedValues, value = _a.value, size = _a.size, rest = __rest(_a, ["onItemSelect", "onRemoveClick", "items", "templates", "allowCustomValues", "hasOnlyAllowedValues", "value", "size"]);
205
+ /* The LAST hop before Reqore, which is the only place a drawn description
206
+ may be made: `filteredTemplates` upstream is a `JSON.stringify` memo key,
207
+ and an element in it throws on its own circular owner. */
208
+ var renderMarkdown = (0, markdownRendererContext_1.useMarkdownRenderer)();
209
+ var shownItems = (0, react_2.useMemo)(function () { return (0, templateItems_1.renderTemplateItemDescriptions)((0, templateItems_1.templateItemsToShow)(items), renderMarkdown); }, [items, renderMarkdown]);
180
210
  // One resolver for every surface that names a reference — the picker chip
181
211
  // here, the read-only tag, and the compact row's expression summary. The
182
212
  // row and this editor must agree: a reference that reads as its path when
@@ -194,13 +224,33 @@ exports.TemplateDropdownSelector = (0, react_2.memo)(function (_a) {
194
224
  // SEAM (reqraft): the IDE resolves the template's app/action via
195
225
  // `useGetAppActionData` and renders the action's display name as a badge
196
226
  // here — the app catalogue is IDE-only, so the badge is dropped.
197
- return ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { vertical: true, fluid: true, children: [hasOnlyAllowedValues && ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { intent: 'warning', size: 'small', opaque: false, children: "This field has pre-defined allowed values, make sure the template you select is compatible with those" })), (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { stack: true, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreDropdown, __assign({ className: 'template-selector', customTheme: exports.TemplatesListProps.listCustomTheme, minimal: true, compact: true, onItemSelect: onItemSelect, items: items, label: label, leftIconProps: leftIconProps, caretPosition: 'right', filterable: true, size: size }, exports.TemplatesListProps)), allowCustomValues || value ? ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { customTheme: exports.TemplatesListProps.listCustomTheme, fixed: true, icon: 'CloseLine', tooltip: 'Remove template value', minimal: true, className: 'template-remove', compact: true, size: size, onClick: onRemoveClick })) : null] })] }));
227
+ return ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { vertical: true, fluid: true, children: [hasOnlyAllowedValues && ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { intent: 'warning', size: 'small', opaque: false, children: "This field has pre-defined allowed values, make sure the template you select is compatible with those" })), (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { stack: true, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreDropdown, __assign({ className: 'template-selector', customTheme: exports.TemplatesListProps.listCustomTheme, minimal: true, compact: true, onItemSelect: onItemSelect, items: shownItems, label: label, leftIconProps: leftIconProps, caretPosition: 'right', filterable: true, size: size }, exports.TemplatesListProps)), allowCustomValues || value ?
228
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { customTheme: exports.TemplatesListProps.listCustomTheme, fixed: true, icon: 'CloseLine', tooltip: 'Remove template value', minimal: true, className: 'template-remove', compact: true, size: size, onClick: onRemoveClick })
229
+ : null] })] }));
198
230
  });
199
- exports.TemplateField = (0, react_2.memo)(function (_a) {
231
+ /**
232
+ * `ui_type`s whose OWN editor renders templates as chips inline.
233
+ *
234
+ * For these the template SELECTOR must not take over: it replaces a control the
235
+ * author can type in with one they can only pick from. A Qorus test assertion's
236
+ * `Value` is the case this was written for — the IDE's own `auto.tsx` already
237
+ * renders it as template rich text (type freely, references become chips), and
238
+ * the same field reached through this form engine offered a dropdown and no way
239
+ * to type at all.
240
+ *
241
+ * `richtext` is reqraft's own; a consumer adds its types through the
242
+ * `templateAwareUiTypes` prop, exactly as it adds `rendererOnlyUiTypes`.
243
+ */
244
+ exports.BuiltInTemplateAwareUiTypes = ['richtext'];
245
+ var isTemplateAwareUiType = function (uiType, extra) {
246
+ return !!uiType && __spreadArray(__spreadArray([], exports.BuiltInTemplateAwareUiTypes, true), (extra !== null && extra !== void 0 ? extra : []), true).includes(uiType);
247
+ };
248
+ exports.isTemplateAwareUiType = isTemplateAwareUiType;
249
+ var TemplateFieldImpl = (0, react_2.memo)(function (_a) {
200
250
  var _b, _c, _d;
201
- var value = _a.value, name = _a.name, onChange = _a.onChange, _e = _a.component, Comp = _e === void 0 ? AutoFormField_1.AutoFormField : _e, templates = _a.templates, interfaceContext = _a.interfaceContext, // eslint-disable-line @typescript-eslint/no-unused-vars
251
+ var rowMenu = _a.rowMenu, value = _a.value, name = _a.name, onChange = _a.onChange, _e = _a.component, Comp = _e === void 0 ? AutoFormField_1.AutoFormField : _e, templates = _a.templates, interfaceContext = _a.interfaceContext, // eslint-disable-line @typescript-eslint/no-unused-vars
202
252
  _f = _a.allowTemplates, // eslint-disable-line @typescript-eslint/no-unused-vars
203
- allowTemplates = _f === void 0 ? true : _f, allowFunctions = _a.allowFunctions, allowTextExpressions = _a.allowTextExpressions, extraActions = _a.extraActions, _g = _a.allowCustomValues, allowCustomValues = _g === void 0 ? true : _g, _h = _a.filterTemplatesByType, filterTemplatesByType = _h === void 0 ? true : _h, filterTemplatesFunc = _a.filterTemplatesFunc, componentFromType = _a.componentFromType, isFunction = _a.isFunction, isDefaultFunction = _a.isDefaultFunction, isDefaultTemplate = _a.isDefaultTemplate, returnType = _a.returnType, level = _a.level, className = _a.className, menuItems = _a.menuItems, menuActions = _a.menuActions, reorder = _a.reorder, label = _a.label, rest = __rest(_a, ["value", "name", "onChange", "component", "templates", "interfaceContext", "allowTemplates", "allowFunctions", "allowTextExpressions", "extraActions", "allowCustomValues", "filterTemplatesByType", "filterTemplatesFunc", "componentFromType", "isFunction", "isDefaultFunction", "isDefaultTemplate", "returnType", "level", "className", "menuItems", "menuActions", "reorder", "label"]);
253
+ allowTemplates = _f === void 0 ? true : _f, allowFunctions = _a.allowFunctions, allowTextExpressions = _a.allowTextExpressions, extraActions = _a.extraActions, componentOverrides = _a.componentOverrides, _g = _a.allowCustomValues, allowCustomValues = _g === void 0 ? true : _g, _h = _a.filterTemplatesByType, filterTemplatesByType = _h === void 0 ? true : _h, filterTemplatesFunc = _a.filterTemplatesFunc, componentFromType = _a.componentFromType, isFunction = _a.isFunction, isDefaultFunction = _a.isDefaultFunction, isDefaultTemplate = _a.isDefaultTemplate, returnType = _a.returnType, level = _a.level, className = _a.className, menuItems = _a.menuItems, menuActions = _a.menuActions, reorder = _a.reorder, label = _a.label, rest = __rest(_a, ["rowMenu", "value", "name", "onChange", "component", "templates", "interfaceContext", "allowTemplates", "allowFunctions", "allowTextExpressions", "extraActions", "componentOverrides", "allowCustomValues", "filterTemplatesByType", "filterTemplatesFunc", "componentFromType", "isFunction", "isDefaultFunction", "isDefaultTemplate", "returnType", "level", "className", "menuItems", "menuActions", "reorder", "label"]);
204
254
  var qorusTypes = (0, useQorusTypes_1.useQorusTypes)();
205
255
  var functions = (0, useExpressions_1.useExpressions)({
206
256
  allow: !!allowFunctions,
@@ -208,6 +258,19 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
208
258
  extraExpressions: rest.expressions,
209
259
  });
210
260
  var type = rest.ui_type || rest.type || rest.defaultType;
261
+ /* The type an EXPRESSION must return, and is stored with, is a DATA type.
262
+ `type` above deliberately prefers `ui_type`, because that is what decides
263
+ which editor to render — but a ui_type says how a value is EDITED, not
264
+ what it is. The IDE's reference fields carry `ui_type: 'test-reference'`
265
+ (a rich-text editor that turns `$.` paths into chips), and feeding that
266
+ to the expression builder asked it for an expression RETURNING
267
+ `test-reference`: no expression returns one, so every choice was refused
268
+ with *"the expected return type is test-reference"*, and the ui_type was
269
+ then stored on the saved expression as its declared type.
270
+
271
+ The declared data type is the constraint; the ui_type is only a fallback
272
+ for a field that declares no type at all. */
273
+ var expressionDataType = rest.type || rest.defaultType || rest.ui_type;
211
274
  var filteredTemplates = (0, react_2.useMemo)(function () {
212
275
  if (!allowTemplates) {
213
276
  return undefined;
@@ -219,7 +282,20 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
219
282
  if (filterTemplatesFunc) {
220
283
  result = filterTemplatesFunc(result);
221
284
  }
222
- return result;
285
+ /* A lone category is opened, once, HERE — where this control resolves the
286
+ templates every one of its pickers then reads: the "Select Template"
287
+ dropdown, the in-editor `$` list, the numeric field's focus dropdown and
288
+ the expression builder's argument picker. Applying it per picker meant
289
+ each new one had to remember, and the ones that forgot made the author
290
+ click through a header naming the only category on offer to reach the
291
+ only values on offer.
292
+
293
+ LAST, after both filters. `filterTemplatesFunc` is given the grouped
294
+ shape on purpose — the Qog expression builder filters top-level items by
295
+ `metadata.dataRole`, which is a property of the CATEGORY — so flattening
296
+ before it would hand it values and quietly change what it keeps. This
297
+ only changes what is finally shown. */
298
+ return __assign(__assign({}, result), { items: (0, templateItems_1.templateItemsToShow)(result === null || result === void 0 ? void 0 : result.items) });
223
299
  }, [
224
300
  JSON.stringify(templates),
225
301
  type,
@@ -243,19 +319,59 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
243
319
  // Only while the field is EMPTY. A field already holding a literal must
244
320
  // open showing that literal — flipping to the template view would hide a
245
321
  // value the author put there and make it look lost.
246
- // ...and only when there is actually something to pick. A field with no
247
- // templates on offer would otherwise open on an EMPTY picker, which is a
248
- // worse place to start than the type picker it replaced.
322
+ //
323
+ // A field that may hold a custom value opens there whether or not templates
324
+ // are on offer, and whether or not they have ARRIVED: template mode gives it
325
+ // a typable editor, which offers the list once there is one. Waiting for the
326
+ // list decided the landing from data that is async — on a cold load the
327
+ // type-filtered list did not exist at mount, so the field fell to the type
328
+ // picker and stayed there. A pick-only field (no custom values) is in
329
+ // template mode regardless, by the `!allowCustomValues` term.
249
330
  var typeIsAnyLike = type === 'any' || type === 'auto';
250
- var isEmptyValue = value === undefined || value === null || value === '';
331
+ /* An EMPTY field, for the purpose of offering the template selector.
332
+
333
+ `null` is deliberately not empty. It is the DPQL null literal — a value
334
+ an author writes to say "this is nothing", and the only way to assert
335
+ that a call returned no value. Counted as emptiness here, an argument
336
+ holding it was treated as a field the author had just cleared: with a
337
+ type of `any` and templates on offer, the selector-restore effect below
338
+ flipped the field into template mode with a null template value, and
339
+ that reported the field as cleared — so writing `null` in the Text tab
340
+ and switching to Visual silently erased it, leaving `{type: "any"}` in
341
+ the draft and the message "Value for argument 1 ("any") is invalid:
342
+ Value is empty".
343
+
344
+ `undefined` is the cleared state; `null` is a value. Same rule as
345
+ `expressions/argumentPresence`, which states it canonically. */
346
+ var isEmptyValue = value === undefined || value === '';
251
347
  var hasTemplatesOnOffer = !!(0, lodash_1.size)(filteredTemplates === null || filteredTemplates === void 0 ? void 0 : filteredTemplates.items);
252
- var _j = (0, react_2.useState)((isDefaultTemplate ||
253
- (0, templates_1.isValueTemplate)(value) ||
254
- !allowCustomValues ||
255
- (typeIsAnyLike && isEmptyValue && hasTemplatesOnOffer)) &&
256
- allowTemplates), isTemplate = _j[0], setIsTemplate = _j[1];
348
+ /* The field's own editor already renders templates inline, so the selector
349
+ is not merely unnecessary here — it is a downgrade, swapping a typable
350
+ control for a pick-only one. Derived rather than folded into the state
351
+ below so every `setIsTemplate` path keeps working untouched; they simply
352
+ stop having anything to say for these fields. */
353
+ var editorHandlesTemplates = !!allowTemplates && (0, exports.isTemplateAwareUiType)(type, rest.templateAwareUiTypes);
354
+ var hasOnlyAllowedValues = (0, react_2.useMemo)(function () { return !!(0, lodash_1.size)(rest.allowed_values) && !rest.allowed_values_creatable; }, [rest.allowed_values, rest.allowed_values_creatable]);
355
+ /** Where this field lands when it is empty: an untyped one in template mode — see above. */
356
+ var emptyLandsOnTemplates = typeIsAnyLike && (hasTemplatesOnOffer || (!!allowCustomValues && !hasOnlyAllowedValues));
357
+ var opensOnTemplates = isEmptyValue && emptyLandsOnTemplates;
358
+ var _j = (0, react_2.useState)((isDefaultTemplate || (0, templates_1.isValueTemplate)(value) || !allowCustomValues || opensOnTemplates) &&
359
+ allowTemplates), isTemplateState = _j[0], setIsTemplate = _j[1];
360
+ var isTemplate = editorHandlesTemplates ? false : isTemplateState;
257
361
  var _k = (0, react_2.useState)(!!isDefaultFunction && !!allowFunctions), internalIsFunction = _k[0], setInternalIsFunction = _k[1];
258
362
  var _l = (0, react_2.useState)(value), templateValue = _l[0], setTemplateValue = _l[1];
363
+ // Typed text that turned out to be an expression the author may accept.
364
+ var _m = (0, react_2.useState)(null), dpqlOffer = _m[0], setDpqlOffer = _m[1];
365
+ // The literal this field held before typed text switched it into
366
+ // expression mode — kept so the switch is undoable, and so the editor
367
+ // opens on the Text view the author was already writing in.
368
+ var _o = (0, react_2.useState)(null), expressionFromText = _o[0], setExpressionFromText = _o[1];
369
+ // Texts the author has said no to. Without this, dismissing an offer (or
370
+ // undoing a switch) would re-detect the same text on the next render and
371
+ // ask again forever.
372
+ var declinedTexts = (0, react_2.useRef)(new Set());
373
+ var detectTimer = (0, react_2.useRef)(null);
374
+ var probeDpql = (0, useDpqlProbe_1.useDpqlProbe)();
259
375
  var effectiveIsFunction = isFunction || internalIsFunction;
260
376
  (0, useWhyDidYouUpdate_1.useWhyDidYouUpdate)("Template field ".concat(name), __assign({ name: name, onChange: onChange, value: value }, rest));
261
377
  (0, react_2.useEffect)(function () {
@@ -263,6 +379,58 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
263
379
  setTemplateValue(value);
264
380
  }
265
381
  }, [JSON.stringify(value)]);
382
+ /* Clearing an untyped field returns it to the template selector, which is
383
+ where mounting it empty already lands.
384
+
385
+ The rule above that opens an `any`-like field on the template selector is
386
+ a `useState` INITIALISER, so it only ever ran on mount. Clearing a value
387
+ in place does not remount anything, so the field fell through to the TYPE
388
+ picker and demanded `string`/`int`/`hash` before it would let the author
389
+ name a value they had already captured -- the very question that rule
390
+ exists to stop asking. Reloading the page fixed it, which is the tell:
391
+ same field, same empty value, different landing, because only one of the
392
+ two paths ran the rule.
393
+
394
+ Watched as a TRANSITION from a value to no value, not as "the value is
395
+ empty": an author who picks `Set Custom Value` on an empty field is
396
+ asking for the type picker, and re-asserting the template view on every
397
+ render while the field sat empty would take it away again immediately. */
398
+ var hadValue = (0, react_2.useRef)(!isEmptyValue);
399
+ /* A clear is REMEMBERED rather than acted on in the same render.
400
+
401
+ While the field holds a value its resolved type is that VALUE's type — a
402
+ reference reads as `test-reference`, not `auto` — and clearing reverts it
403
+ to the schema's `auto` one render LATER than the value empties. Acting
404
+ only on the transition therefore ran while `typeIsAnyLike` was still
405
+ false and did nothing, and by the time the type settled the transition
406
+ had passed. Measured in the live IDE at the moment of the clear:
407
+ `{ wasCleared: true, typeIsAnyLike: false, type: "test-reference",
408
+ hasTemplatesOnOffer: true }`, then `typeIsAnyLike: true` on the very next
409
+ render with `wasCleared` already false. */
410
+ var restoreSelectorWhenSettled = (0, react_2.useRef)(false);
411
+ /** Set by the template control's own `×`, which is an author saying "not a
412
+ * template" — that clear must not be answered with the selector again. */
413
+ var suppressSelectorRestore = (0, react_2.useRef)(false);
414
+ (0, react_2.useEffect)(function () {
415
+ if (hadValue.current && isEmptyValue) {
416
+ restoreSelectorWhenSettled.current = !suppressSelectorRestore.current;
417
+ suppressSelectorRestore.current = false;
418
+ }
419
+ if (!isEmptyValue) {
420
+ // A value arrived: whatever the author did, they are not sitting on an
421
+ // empty field waiting to be offered the list.
422
+ restoreSelectorWhenSettled.current = false;
423
+ }
424
+ hadValue.current = !isEmptyValue;
425
+ if (restoreSelectorWhenSettled.current &&
426
+ opensOnTemplates &&
427
+ allowTemplates &&
428
+ !effectiveIsFunction) {
429
+ restoreSelectorWhenSettled.current = false;
430
+ setTemplateValue(null);
431
+ setIsTemplate(true);
432
+ }
433
+ }, [isEmptyValue, opensOnTemplates, allowTemplates, effectiveIsFunction]);
266
434
  (0, react_2.useEffect)(function () {
267
435
  if (allowCustomValues && isTemplate && value && !(0, templates_1.isValueTemplate)(value)) {
268
436
  setIsTemplate(false);
@@ -279,6 +447,16 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
279
447
  !(0, templates_1.isCompleteTemplateToken)(value)) {
280
448
  return;
281
449
  }
450
+ // A template reference with an OPERATOR on it (`$local:count + 1`) is
451
+ // an expression, not a template. The loose check above passes it —
452
+ // it starts with `$` and has a colon — so without this every such
453
+ // string was swallowed into template mode, where the arithmetic is
454
+ // dead text and no affordance can reach it. A token standing alone
455
+ // (`$local:count`, `$data:{1.field}`) has no operator and still
456
+ // flips, which is the case template mode is for.
457
+ if (!(0, templates_1.isCompleteTemplateToken)(value) && (0, dpqlDetection_1.mightBeDpqlExpression)(value)) {
458
+ return;
459
+ }
282
460
  setIsTemplate(true);
283
461
  setTemplateValue(value);
284
462
  }
@@ -289,7 +467,6 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
289
467
  onChange === null || onChange === void 0 ? void 0 : onChange(name, templateValue, type, effectiveIsFunction);
290
468
  }
291
469
  }, [JSON.stringify(templateValue)]);
292
- var hasOnlyAllowedValues = (0, react_2.useMemo)(function () { return !!(0, lodash_1.size)(rest.allowed_values) && !rest.allowed_values_creatable; }, [rest.allowed_values, rest.allowed_values_creatable]);
293
470
  var showTemplateToggle = allowCustomValues && allowTemplates && !rest.arg_schema;
294
471
  // Only a BRACED context ref (`$data:{…}` — machine-written, nobody types
295
472
  // one) renders as the picker chip (named via `resolveTemplateLabel`)
@@ -299,7 +476,22 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
299
476
  // keep the string editor too; the chip-in-editor treatment arrives with
300
477
  // the rich-text string mode.
301
478
  var templateValueIsBracedToken = (0, templates_1.isBracedTemplateToken)(templateValue);
302
- var templateSupportsCustomValues = allowCustomValues && type === 'string' && !hasOnlyAllowedValues;
479
+ /* An UNTYPED field can be typed into as well as picked from.
480
+
481
+ Template mode has a typable editor whenever the field's type can hold
482
+ arbitrary text, and `any`/`auto` can — it is the type that has not been
483
+ narrowed yet, not a type that excludes text. Restricting this to
484
+ `string` meant an empty untyped field opened on template mode with no
485
+ editor to offer, so it fell through to the pick-only "Select Template"
486
+ dropdown: a control that can only choose from a list, on exactly the
487
+ fields where an author most often needs to write something the list
488
+ cannot hold — a deeper walk, a literal, or an expression.
489
+
490
+ Reported against a Qorus assertion's Expected Value, and it was never
491
+ specific to that field: every empty untyped field with templates on
492
+ offer got the same downgrade. The editor still offers the same templates
493
+ on focus, so nothing is lost by being able to type as well. */
494
+ var templateSupportsCustomValues = allowCustomValues && (type === 'string' || typeIsAnyLike) && !hasOnlyAllowedValues;
303
495
  var showTemplatesDropdown = allowTemplates && (!allowCustomValues || (isTemplate && !templateSupportsCustomValues));
304
496
  var hasOnlyExpressions = !allowCustomValues && !allowTemplates && allowFunctions;
305
497
  // True when some input control renders besides the ⋮ menu. When nothing
@@ -318,23 +510,39 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
318
510
  var fieldAriaLabel = (_d = (_c = (_b = rest['aria-label']) !== null && _b !== void 0 ? _b : label) !== null && _c !== void 0 ? _c : rest.display_name) !== null && _d !== void 0 ? _d : name;
319
511
  var handleTemplateFieldChange = (0, react_2.useCallback)(function (_name, val) {
320
512
  if (!val) {
321
- setIsTemplate(false);
513
+ /* Emptying the text leaves the field where an empty field lands. For
514
+ an untyped field that is THIS editor: switching to custom mode here
515
+ mounted a different editor in its place, so deleting the last
516
+ character lost the cursor. */
517
+ if (!(emptyLandsOnTemplates && allowTemplates)) {
518
+ setIsTemplate(false);
519
+ }
322
520
  setTemplateValue(null);
323
521
  onChange(name, undefined);
324
522
  }
325
523
  else {
326
524
  setTemplateValue(val);
327
525
  }
328
- }, [name, onChange]);
526
+ }, [name, onChange, emptyLandsOnTemplates, allowTemplates]);
527
+ var handleTemplateTextChange = (0, react_2.useCallback)(function (val) { return handleTemplateFieldChange(name, typeof val === 'string' ? val : ''); }, [handleTemplateFieldChange, name]);
329
528
  var handleSelectTemplateFromList = (0, react_2.useCallback)(
330
529
  // If the field has allowed values and supports templates, we do not want to overwrite the field type with the template type
331
530
  function (item) {
332
531
  // If the template type is richtext, we need to wrap the template value in the richtext template format
333
- var value = item.badge === 'richtext'
334
- ? [
532
+ var value = item.badge === 'richtext' ?
533
+ [
335
534
  {
336
535
  type: 'paragraph',
536
+ /* The empty text nodes on either side are load-bearing. A
537
+ chip is an inline VOID: it holds no text of its own, so the
538
+ only places a cursor can go are the text nodes AROUND it.
539
+ Slate treats that as an invariant and repairs it during
540
+ normalisation, which runs on edits but NOT on a document
541
+ handed in whole as a controlled value — which is what this
542
+ is. Without them the picked template renders as a chip that
543
+ cannot be typed after, so it can never be extended by hand. */
337
544
  children: [
545
+ { text: '' },
338
546
  {
339
547
  children: [{ text: '' }],
340
548
  label: item.label,
@@ -342,6 +550,7 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
342
550
  value: item.value,
343
551
  metadata: item.metadata,
344
552
  },
553
+ { text: '' },
345
554
  ],
346
555
  },
347
556
  ]
@@ -352,7 +561,15 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
352
561
  // `SaveValueButton` in the controls menu — the saved-values storage is
353
562
  // IDE-only, so the menu item is dropped (`allowSaving` is inert).
354
563
  var handleRemoveTemplateClick = (0, react_2.useCallback)(function () {
564
+ /* This is the `×` ON the template control, and it means "I do not want a
565
+ template here" — on a field whose menu offers no `Set Custom Value` it
566
+ is the ONLY way to reach a literal. So it still drops to the custom
567
+ value editor, and it tells the empty-field rule below to keep its hands
568
+ off this particular clear: that rule watches the value going away, and
569
+ this handler clears the value too, so without the flag it would send
570
+ the author straight back to the selector they just dismissed. */
355
571
  if (allowCustomValues) {
572
+ suppressSelectorRestore.current = true;
356
573
  setIsTemplate(false);
357
574
  }
358
575
  setTemplateValue(null);
@@ -389,22 +606,229 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
389
606
  var handleExpressionChange = (0, react_2.useCallback)(function (expressionValue, remove) {
390
607
  if (remove) {
391
608
  setInternalIsFunction(false);
609
+ // The expression is gone, so there is no longer a switch to undo.
610
+ setExpressionFromText(null);
611
+ }
612
+ onChange(name, expressionValue === null || expressionValue === void 0 ? void 0 : expressionValue.value, expressionDataType, !remove);
613
+ }, [name, onChange, expressionDataType, value]);
614
+ // ─── Text typed into a plain field that is really a DPQL expression ───
615
+ //
616
+ // A field that accepts expressions still gets DPQL TYPED into it, in the
617
+ // ordinary editor, by an author who never opened the expression view.
618
+ // What happens then depends on the field's own type, and the asymmetry is
619
+ // deliberate: text that could stand as a literal here is only ever
620
+ // OFFERED, because silently rewriting the string `a + b` into a
621
+ // concatenation would destroy a value the author meant. Text that could
622
+ // NOT be a literal here was already an error the moment it was typed, so
623
+ // switching costs nothing and explains the error.
624
+ //
625
+ // The server decides whether the text is an expression at all — see
626
+ // `helpers/dpqlDetection` for why a successful parse alone means nothing.
627
+ var validationField = (0, react_2.useMemo)(function () { return ({
628
+ validation_regex: rest.validation_regex,
629
+ has_to_be_valid_identifier: rest.has_to_be_valid_identifier,
630
+ has_to_have_value: rest.has_to_have_value,
631
+ rules: rest.rules,
632
+ arg_schema: rest.arg_schema,
633
+ }); }, [
634
+ rest.validation_regex,
635
+ rest.has_to_be_valid_identifier,
636
+ rest.has_to_have_value,
637
+ JSON.stringify(rest.rules),
638
+ JSON.stringify(rest.arg_schema),
639
+ ]);
640
+ var enterExpressionFromText = (0, react_2.useCallback)(function (text, expression) {
641
+ var _a;
642
+ setDpqlOffer(null);
643
+ setExpressionFromText(text);
644
+ setInternalIsFunction(true);
645
+ setIsTemplate(false);
646
+ setTemplateValue(null);
647
+ // `dpql/parse` answers with the field-ready envelope
648
+ // (`{is_expression, value}`); this field stores the inner AST and
649
+ // signals the flag through `onChange`'s fourth argument, exactly as
650
+ // `handleExpressionChange` does.
651
+ onChange === null || onChange === void 0 ? void 0 : onChange(name, (_a = expression === null || expression === void 0 ? void 0 : expression.value) !== null && _a !== void 0 ? _a : expression, expressionDataType, true);
652
+ }, [name, onChange, expressionDataType]);
653
+ var undoExpressionFromText = (0, react_2.useCallback)(function () {
654
+ if (expressionFromText === null) {
655
+ return;
392
656
  }
393
- onChange(name, expressionValue === null || expressionValue === void 0 ? void 0 : expressionValue.value, type, !remove);
394
- }, [name, onChange, type, value]);
657
+ declinedTexts.current.add(expressionFromText);
658
+ setInternalIsFunction(false);
659
+ setExpressionFromText(null);
660
+ onChange === null || onChange === void 0 ? void 0 : onChange(name, expressionFromText, type, false);
661
+ }, [expressionFromText, name, onChange, type]);
662
+ var declineDpqlOffer = (0, react_2.useCallback)(function () {
663
+ if (dpqlOffer) {
664
+ declinedTexts.current.add(dpqlOffer.text);
665
+ }
666
+ setDpqlOffer(null);
667
+ }, [dpqlOffer]);
668
+ var acceptDpqlOffer = (0, react_2.useCallback)(function () {
669
+ if (dpqlOffer) {
670
+ enterExpressionFromText(dpqlOffer.text, dpqlOffer.expression);
671
+ }
672
+ }, [dpqlOffer, enterExpressionFromText]);
673
+ // Held in a ref so the debounce below does not depend on it. `onChange`
674
+ // comes from the host form and can be a fresh function on any render;
675
+ // with the callback in the effect's deps, a re-render caused by a
676
+ // DIFFERENT field would restart this field's timer, and a form the
677
+ // author is typing in re-renders constantly.
678
+ var enterExpressionRef = (0, react_2.useRef)(enterExpressionFromText);
679
+ (0, react_2.useEffect)(function () {
680
+ enterExpressionRef.current = enterExpressionFromText;
681
+ }, [enterExpressionFromText]);
682
+ // Detection only runs on a field that could hold an expression and is
683
+ // currently showing a plain editor — never on a read-only field, a
684
+ // fixed-value list, or one already in template or expression mode.
685
+ var canDetectDpql = !!allowFunctions &&
686
+ !!allowTextExpressions &&
687
+ !effectiveIsFunction &&
688
+ !isTemplate &&
689
+ !hasOnlyAllowedValues &&
690
+ !rest.readonly &&
691
+ !rest.readOnly &&
692
+ !rest.disabled;
693
+ (0, react_2.useEffect)(function () {
694
+ if (detectTimer.current) {
695
+ clearTimeout(detectTimer.current);
696
+ detectTimer.current = null;
697
+ }
698
+ /* A richtext field is still text. It hands its value back as a Slate
699
+ DOCUMENT rather than a flattened string — deliberately, so a chosen
700
+ reference cannot fuse with text typed beside it — and reading only
701
+ `typeof value === 'string'` here silently switched detection off for
702
+ every one of them the moment the field changed shape. A test
703
+ assertion's Value is exactly that field, and `1 + 2` typed into it
704
+ stopped being offered as an expression.
705
+
706
+ `richtextToString` flattens a tag to its raw value, so a document
707
+ holding only a chosen reference reads as `$.result` — no operator, so
708
+ `mightBeDpqlExpression` rejects it below and the server is never
709
+ asked. */
710
+ var text = typeof value === 'string' ? value
711
+ : Array.isArray(value) ? (0, common_1.richtextToString)(value)
712
+ : undefined;
713
+ if (!canDetectDpql ||
714
+ !text ||
715
+ declinedTexts.current.has(text) ||
716
+ !(0, dpqlDetection_1.mightBeDpqlExpression)(text)) {
717
+ setDpqlOffer(null);
718
+ return undefined;
719
+ }
720
+ var cancelled = false;
721
+ detectTimer.current = setTimeout(function () {
722
+ detectTimer.current = null;
723
+ void probeDpql(text)
724
+ .then(function (parsed) {
725
+ if (cancelled) {
726
+ return;
727
+ }
728
+ var outcome = (0, dpqlDetection_1.classifyTypedText)({ text: text, type: type, field: validationField, parsed: parsed });
729
+ if (outcome === 'switch') {
730
+ enterExpressionRef.current(text, parsed.expression);
731
+ }
732
+ else if (outcome === 'offer') {
733
+ setDpqlOffer({ text: text, expression: parsed.expression });
734
+ }
735
+ else {
736
+ setDpqlOffer(null);
737
+ }
738
+ })
739
+ .catch(function () {
740
+ // Detection is an offer of help, never a reason for a field to
741
+ // break: an unreachable instance or a classifier that threw leaves
742
+ // the author's text exactly where they put it.
743
+ if (!cancelled) {
744
+ setDpqlOffer(null);
745
+ }
746
+ });
747
+ }, DPQL_DETECT_DEBOUNCE_MS);
748
+ return function () {
749
+ cancelled = true;
750
+ if (detectTimer.current) {
751
+ clearTimeout(detectTimer.current);
752
+ detectTimer.current = null;
753
+ }
754
+ };
755
+ }, [value, canDetectDpql, type, validationField, probeDpql]);
756
+ var canOfferExpression = allowFunctions && !hasOnlyAllowedValues && !rest.readonly && !internalIsFunction;
757
+ var canOfferTemplate = showTemplateToggle && !isTemplate;
758
+ var publishedItems = (0, react_2.useMemo)(function () { return __spreadArray(__spreadArray(__spreadArray([], (canOfferExpression && !functions.loading
759
+ ? [
760
+ {
761
+ label: 'Use Expression',
762
+ icon: 'Functions',
763
+ tooltip: 'Run a function on this value',
764
+ onClick: handleSelectFunctionChange,
765
+ },
766
+ ]
767
+ : []), true), (canOfferTemplate
768
+ ? [
769
+ {
770
+ label: 'Use Template',
771
+ icon: 'MoneyDollarCircleLine',
772
+ tooltip: 'Use a template',
773
+ onClick: handleTemplateToggleClick,
774
+ },
775
+ ]
776
+ : []), true), (menuItems !== null && menuItems !== void 0 ? menuItems : [])
777
+ .filter(function (item) { return !('isDivider' in item); })
778
+ .map(function (item) { return ({
779
+ label: item.label,
780
+ description: item.description,
781
+ onClick: function () {
782
+ var _a;
783
+ return (_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, undefined, function () {
784
+ setIsTemplate(false);
785
+ setTemplateValue(null);
786
+ });
787
+ },
788
+ }); }), true); }, [
789
+ canOfferExpression,
790
+ functions.loading,
791
+ canOfferTemplate,
792
+ menuItems,
793
+ handleSelectFunctionChange,
794
+ handleTemplateToggleClick,
795
+ ]);
796
+ /* Keyed on WHICH items are offered, never on the items: they carry
797
+ handlers, so they are a new array every render and a row comparing them
798
+ by value would loop. */
799
+ var publishedKey = [
800
+ canOfferExpression && !functions.loading ? 'expression' : '',
801
+ canOfferTemplate ? 'template' : '',
802
+ "custom:".concat((menuItems !== null && menuItems !== void 0 ? menuItems : []).map(function (item) { var _a; return String((_a = item.label) !== null && _a !== void 0 ? _a : ''); }).join('|')),
803
+ ].join(',');
804
+ (0, rowMenuContext_1.useRowMenuPublisher)(rowMenu, publishedKey, publishedItems);
395
805
  var renderControls = (0, react_2.useCallback)(function () {
396
806
  var showFunctionsDropdown = allowFunctions && !hasOnlyAllowedValues && !rest.readonly && !internalIsFunction;
397
807
  var showTemplatesButton = showTemplateToggle && !isTemplate;
398
808
  // The "Set value" label promises a way to set one — reorder rows alone don't.
399
809
  var hasValueRows = showFunctionsDropdown || showTemplatesButton || (0, lodash_1.size)(menuItems) > 0;
810
+ /* ONE menu per control. Where this field sits in a form ROW, the row
811
+ already renders a ⋮ of its own, and drawing a second one beside it
812
+ put two menus of slightly different widths on the same control —
813
+ with the type choices an `any` field offers hidden in the narrower
814
+ one. The items are published to the row instead (see
815
+ `rowMenuContext`); outside a row there is nothing to publish into,
816
+ so the field goes on drawing its own. */
817
+ if (rowMenu) {
818
+ return null;
819
+ }
400
820
  if (hasOnlyExpressions) {
401
- return showFunctionsDropdown ? (functions.loading ? ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreSkeleton, { size: rest.size })) : ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { compact: true, minimal: true, label: 'Create New Expression', className: 'function-selector', icon: 'Functions', tooltip: 'This field only accepts expressions', onClick: function () {
402
- setIsTemplate(false);
403
- setTemplateValue(null);
404
- onChange === null || onChange === void 0 ? void 0 : onChange(name, {
405
- args: [],
406
- }, undefined, true);
407
- } }))) : null;
821
+ return (showFunctionsDropdown ?
822
+ functions.loading ?
823
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreSkeleton, { size: rest.size })
824
+ : (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { compact: true, minimal: true, label: 'Create New Expression', className: 'function-selector', icon: 'Functions', tooltip: 'This field only accepts expressions', onClick: function () {
825
+ setIsTemplate(false);
826
+ setTemplateValue(null);
827
+ onChange === null || onChange === void 0 ? void 0 : onChange(name, {
828
+ args: [],
829
+ }, undefined, true);
830
+ } })
831
+ : null);
408
832
  }
409
833
  if (hasValueRows || (0, lodash_1.size)(menuActions === null || menuActions === void 0 ? void 0 : menuActions.items) > 0) {
410
834
  return ((0, jsx_runtime_1.jsx)(reqore_1.ReqorePopover, { component: reqore_1.ReqoreButton, closeOnTargetClick: true, closeOnInsideClick: false, isReqoreComponent: true, noWrapper: true, noArrow: true, placement: 'bottom-end', componentProps: {
@@ -414,10 +838,18 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
414
838
  transparent: true,
415
839
  size: rest.size,
416
840
  fixed: true,
417
- // Centre the trailing menu in its flex line so it lines up with
418
- // sibling action buttons (reqore alignSelf; replaces a reqraft
419
- // `align-self !important` override of this button).
420
- alignSelf: 'center',
841
+ /* Centre the trailing menu in its flex line so it lines up
842
+ with sibling action buttons (reqore alignSelf; replaces a
843
+ reqraft `align-self !important` override of this button).
844
+
845
+ Centring is only right beside a ONE-LINE editor. The
846
+ expression shell is a toolbar with an editor, a type message
847
+ and a preview stacked under it, so centring put this menu
848
+ somewhere down the side of that block — level with nothing,
849
+ over the editor, and a long way from the Undo it belongs
850
+ beside. There it goes to the top, which is where the shell's
851
+ own toolbar is. */
852
+ alignSelf: effectiveIsFunction ? 'flex-start' : 'center',
421
853
  label: hasInputAffordance || !hasValueRows ? undefined : 'Set value',
422
854
  style: hasInputAffordance ?
423
855
  {
@@ -437,7 +869,17 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
437
869
  },
438
870
  },
439
871
  },
440
- }, handler: 'click', content: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreMenu, { size: rest.size, maxHeight: '400px', style: { overflow: 'auto' }, children: [showFunctionsDropdown ? (functions.loading ? ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreSkeleton, { size: rest.size })) : ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { compact: true, transparent: true, label: 'Use Expression', className: 'function-selector', icon: 'Functions', tooltip: 'Run a function on this value', onClick: handleSelectFunctionChange }))) : null, showTemplatesButton ? ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreButton, { transparent: true, icon: 'MoneyDollarCircleLine', className: 'template-toggle', tooltip: 'Use a template', compact: true, size: rest.size, onClick: handleTemplateToggleClick, children: [' ', "Use Template", ' '] })) : null, (0, lodash_1.size)(menuActions === null || menuActions === void 0 ? void 0 : menuActions.items) > 0 ? ((0, jsx_runtime_1.jsx)(MenuActionsSection, { actions: menuActions, size: rest.size })) : null, (0, lodash_1.size)(menuItems) > 0 ? ((0, jsx_runtime_1.jsx)(exports.CustomMenuItems, { items: menuItems, setIsTemplate: setIsTemplate, setTemplateValue: setTemplateValue })) : null] }) }));
872
+ }, handler: 'click', content: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreMenu, { size: rest.size, maxHeight: '400px', style: { overflow: 'auto' }, children: [showFunctionsDropdown ?
873
+ functions.loading ?
874
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreSkeleton, { size: rest.size })
875
+ : (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { compact: true, transparent: true, label: 'Use Expression', className: 'function-selector', icon: 'Functions', tooltip: 'Run a function on this value', onClick: handleSelectFunctionChange })
876
+ : null, showTemplatesButton ?
877
+ (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreButton, { transparent: true, icon: 'MoneyDollarCircleLine', className: 'template-toggle', tooltip: 'Use a template', compact: true, size: rest.size, onClick: handleTemplateToggleClick, children: [' ', "Use Template", ' '] })
878
+ : null, (0, lodash_1.size)(menuActions === null || menuActions === void 0 ? void 0 : menuActions.items) > 0 ?
879
+ (0, jsx_runtime_1.jsx)(MenuActionsSection, { actions: menuActions, size: rest.size })
880
+ : null, (0, lodash_1.size)(menuItems) > 0 ?
881
+ (0, jsx_runtime_1.jsx)(exports.CustomMenuItems, { items: menuItems, setIsTemplate: setIsTemplate, setTemplateValue: setTemplateValue })
882
+ : null] }) }));
441
883
  }
442
884
  return null;
443
885
  }, [
@@ -456,15 +898,18 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
456
898
  menuItems,
457
899
  menuActions,
458
900
  internalIsFunction,
901
+ effectiveIsFunction,
459
902
  hasInputAffordance,
903
+ // the row decides whether this field draws a menu at all
904
+ rowMenu,
460
905
  ]);
461
906
  // When the type is a list, and it has an element type - that element type is different
462
907
  // from the field type, so we need to send down the full templates object
463
908
  // and the actual rendered field will filter it's own templates
464
909
  // This is a special case only for lists with element types
465
910
  var componentTemplates = (0, react_2.useMemo)(function () {
466
- return type === 'list' && (rest.ui_element_type || rest.element_type)
467
- ? templates
911
+ return type === 'list' && (rest.ui_element_type || rest.element_type) ?
912
+ templates
468
913
  : __assign(__assign({}, filteredTemplates), exports.TemplatesListProps);
469
914
  }, [JSON.stringify(filteredTemplates), rest.ui_element_type, rest.element_type, type]);
470
915
  if (effectiveIsFunction && !hasOnlyAllowedValues) {
@@ -476,12 +921,26 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
476
921
  return ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreErrorBoundary, { children: (0, jsx_runtime_1.jsx)(ExpressionField_1.ExpressionField, { value: {
477
922
  is_expression: true,
478
923
  value: value,
479
- }, localTemplates: templates, type: type, returnType: (returnType || type), onChange: handleExpressionChange, readOnly: rest.readOnly || rest.disabled, expressions: rest.expressions, expressionsUrl: rest.expressions_url, serverHandled: rest.server_expression_handling, extraActions: extraActions, size: rest.size, reorder: reorder }) }), renderControls()] }));
924
+ },
925
+ // The host's per-ui_type editors reach this field through the
926
+ // rest-spread; the expression shell needs them explicitly or the
927
+ // builder's operands render "Unknown type!" for any consumer
928
+ // ui_type (an assertion's `test-reference` Value, for one).
929
+ componentOverrides: componentOverrides, localTemplates: templates, type: type, returnType: (returnType || expressionDataType), onChange: handleExpressionChange, readOnly: rest.readOnly || rest.disabled, expressions: rest.expressions, expressionsUrl: rest.expressions_url, serverHandled: rest.server_expression_handling, extraActions: extraActions, size: rest.size,
930
+ // An author who typed the expression as text is already
931
+ // writing in that language — dropping them into the visual
932
+ // builder would make them find their own sentence again.
933
+ defaultMode: expressionFromText !== null ? 'text' : 'visual', reorder: reorder }) }), expressionFromText !== null ?
934
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { fixed: true, compact: true, minimal: true, icon: 'ArrowGoBackLine',
935
+ // No `intent` with `minimal`: a Reqore intent is a FILL, and
936
+ // `muted` as TEXT is 1.3:1 on the app surface.
937
+ size: rest.size, className: 'dpql-detected-undo', tooltip: "Keep \"".concat(expressionFromText, "\" as plain text instead"), onClick: undoExpressionFromText, children: "Undo" })
938
+ : null, renderControls()] }));
480
939
  }
481
940
  return ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreErrorBoundary, { children: (0, jsx_runtime_1.jsx)(builder_1.ExpressionBuilder, { value: {
482
941
  is_expression: true,
483
942
  value: value,
484
- }, localTemplates: templates, level: level, type: type, returnType: (returnType || type), onChange: handleExpressionChange, readOnly: rest.readOnly || rest.disabled, expressions: rest.expressions, expressionsUrl: rest.expressions_url, serverHandled: rest.server_expression_handling, extraActions: extraActions, reorder: reorder }) }), renderControls()] }));
943
+ }, componentOverrides: componentOverrides, localTemplates: templates, level: level, type: type, returnType: (returnType || expressionDataType), onChange: handleExpressionChange, readOnly: rest.readOnly || rest.disabled, expressions: rest.expressions, expressionsUrl: rest.expressions_url, serverHandled: rest.server_expression_handling, extraActions: extraActions, reorder: reorder }) }), renderControls()] }));
485
944
  }
486
945
  if (rest.disabled) {
487
946
  if (isTemplate) {
@@ -491,9 +950,28 @@ exports.TemplateField = (0, react_2.memo)(function (_a) {
491
950
  // IDE's intent scheme. Shared with the compact read-first row.
492
951
  return (0, jsx_runtime_1.jsx)(ReadOnlyTemplateTag_1.ReadOnlyTemplateTag, { value: templateValue, templates: templates, size: rest.size });
493
952
  }
494
- return (0, jsx_runtime_1.jsx)(Comp, __assign({ value: value, onChange: onChange, name: name }, rest));
953
+ return ((0, jsx_runtime_1.jsx)(Comp, __assign({ value: value, onChange: onChange, name: name }, rest, { componentOverrides: componentOverrides })));
495
954
  }
496
- return ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, __assign({ fluid: rest.fluid, fixed: rest.fixed, size: rest.size }, rest, { stack: false, verticalAlign: 'flex-start', children: [!isTemplate && allowCustomValues ? ((0, jsx_runtime_1.jsx)(Component, __assign({ value: value, allowTemplates: allowTemplates, onChange: onChange, name: name, level: level }, rest, componentTypeProp, { "aria-label": fieldAriaLabel, className: "".concat(className, " template-selector"), templates: componentTemplates }))) : null, isTemplate && templateSupportsCustomValues && !templateValueIsBracedToken ? ((0, jsx_runtime_1.jsx)(LongStringField, __assign({ className: 'template-selector', type: 'string', name: 'templateVal', level: level, value: templateValue, templates: __assign(__assign({}, filteredTemplates), exports.TemplatesListProps), onChange: handleTemplateFieldChange }, rest, { "aria-label": fieldAriaLabel }))) : null, showTemplatesDropdown ||
497
- (isTemplate && templateSupportsCustomValues && templateValueIsBracedToken) ? ((0, jsx_runtime_1.jsx)(exports.TemplateDropdownSelector, { allowCustomValues: allowCustomValues, templates: templates, value: templateValue, items: filteredTemplates === null || filteredTemplates === void 0 ? void 0 : filteredTemplates.items, onItemSelect: handleSelectTemplateFromList, onRemoveClick: handleRemoveTemplateClick, size: rest.size, label: label, hasOnlyAllowedValues: hasOnlyAllowedValues })) : null, renderControls()] })));
955
+ return ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, __assign({ fluid: rest.fluid, fixed: rest.fixed, size: rest.size }, rest, { stack: false, verticalAlign: 'flex-start', children: [!isTemplate && allowCustomValues ?
956
+ (0, jsx_runtime_1.jsx)(Component, __assign({ value: value, allowTemplates: allowTemplates, onChange: onChange, name: name, level: level }, rest, { componentOverrides: componentOverrides }, componentTypeProp, { "aria-label": fieldAriaLabel, className: "".concat(className, " template-selector"), templates: componentTemplates }))
957
+ : null, isTemplate && templateSupportsCustomValues && !templateValueIsBracedToken ?
958
+ (0, jsx_runtime_1.jsx)(RichText_1.RichTextFormField, __assign({ className: 'template-selector', valueFormat: 'text', singleLine: (0, singleLineString_1.isSingleLineStringType)('string'), value: typeof templateValue === 'string' ? templateValue : '', templates: filteredTemplates, allowTemplates: true, onChange: handleTemplateTextChange }, (0, lodash_1.omit)(rest, 'tags'), { "aria-label": fieldAriaLabel }))
959
+ : null, dpqlOffer ?
960
+ (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { fixed: true, stack: true, size: rest.size, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { compact: true, icon: 'Functions', intent: 'info', className: 'dpql-detected-offer', tooltip: "\"".concat(dpqlOffer.text, "\" reads as an expression. It is also valid text here, so nothing has been changed \u2014 use it as an expression?"), onClick: acceptDpqlOffer, children: "Use as expression" }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { compact: true, icon: 'CloseLine', intent: 'info', className: 'dpql-detected-dismiss', tooltip: 'Keep it as plain text', onClick: declineDpqlOffer })] })
961
+ : null, (showTemplatesDropdown ||
962
+ (isTemplate && templateSupportsCustomValues && templateValueIsBracedToken)) ?
963
+ (0, jsx_runtime_1.jsx)(exports.TemplateDropdownSelector, { allowCustomValues: allowCustomValues, templates: templates, value: templateValue, items: filteredTemplates === null || filteredTemplates === void 0 ? void 0 : filteredTemplates.items, onItemSelect: handleSelectTemplateFromList, onRemoveClick: handleRemoveTemplateClick, size: rest.size, label: label, hasOnlyAllowedValues: hasOnlyAllowedValues })
964
+ : null, renderControls()] })));
965
+ });
966
+ /**
967
+ * The row channel belongs to the row's OWN editor: this field. It is read here
968
+ * and hidden from everything this field renders, so a field nested inside it —
969
+ * an expression operand, a list item — keeps drawing its own menu instead of
970
+ * publishing actions into a row menu that cannot say which value they act on.
971
+ * `undefined` outside a row, where this field draws its own menu too.
972
+ */
973
+ exports.TemplateField = (0, react_2.memo)(function (props) {
974
+ var rowMenu = (0, rowMenuContext_1.useRowMenu)();
975
+ return ((0, jsx_runtime_1.jsx)(rowMenuContext_1.RowMenuContext.Provider, { value: undefined, children: (0, jsx_runtime_1.jsx)(TemplateFieldImpl, __assign({}, props, { rowMenu: rowMenu })) }));
498
976
  });
499
977
  //# sourceMappingURL=TemplateField.js.map