@xlsft/grammy-reactive 0.7.34

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 (187) hide show
  1. package/LICENSE +7 -0
  2. package/dist/jsx/index.d.ts +3 -0
  3. package/dist/jsx/index.d.ts.map +1 -0
  4. package/dist/jsx/index.js +2 -0
  5. package/dist/jsx/index.js.map +1 -0
  6. package/dist/jsx/jsx-dev-runtime.d.ts +2 -0
  7. package/dist/jsx/jsx-dev-runtime.d.ts.map +1 -0
  8. package/dist/jsx/jsx-dev-runtime.js +2 -0
  9. package/dist/jsx/jsx-dev-runtime.js.map +1 -0
  10. package/dist/jsx/jsx-runtime.d.ts +2 -0
  11. package/dist/jsx/jsx-runtime.d.ts.map +1 -0
  12. package/dist/jsx/jsx-runtime.js +2 -0
  13. package/dist/jsx/jsx-runtime.js.map +1 -0
  14. package/dist/jsx/runtime/jsx.d.ts +10 -0
  15. package/dist/jsx/runtime/jsx.d.ts.map +1 -0
  16. package/dist/jsx/runtime/jsx.errors.d.ts +4 -0
  17. package/dist/jsx/runtime/jsx.errors.d.ts.map +1 -0
  18. package/dist/jsx/runtime/jsx.errors.js +7 -0
  19. package/dist/jsx/runtime/jsx.errors.js.map +1 -0
  20. package/dist/jsx/runtime/jsx.js +209 -0
  21. package/dist/jsx/runtime/jsx.js.map +1 -0
  22. package/dist/jsx/runtime/jsx.runtime.d.ts +18 -0
  23. package/dist/jsx/runtime/jsx.runtime.d.ts.map +1 -0
  24. package/dist/jsx/runtime/jsx.runtime.js +3 -0
  25. package/dist/jsx/runtime/jsx.runtime.js.map +1 -0
  26. package/dist/lib/helpers/context.helper.d.ts +3 -0
  27. package/dist/lib/helpers/context.helper.d.ts.map +1 -0
  28. package/dist/lib/helpers/index.d.ts +2 -0
  29. package/dist/lib/helpers/index.d.ts.map +1 -0
  30. package/dist/lib/index.d.ts +12 -0
  31. package/dist/lib/index.d.ts.map +1 -0
  32. package/dist/lib/index.js +45 -0
  33. package/dist/lib/index.js.map +1 -0
  34. package/dist/lib/jsx-runtime.d.ts +2 -0
  35. package/dist/lib/jsx-runtime.d.ts.map +1 -0
  36. package/dist/lib/plugin/index.d.ts +4 -0
  37. package/dist/lib/plugin/index.d.ts.map +1 -0
  38. package/dist/lib/plugin/index.js +40 -0
  39. package/dist/lib/plugin/index.js.map +1 -0
  40. package/dist/lib/render/components/Error.d.ts +26 -0
  41. package/dist/lib/render/components/Error.d.ts.map +1 -0
  42. package/dist/lib/render/components/Error.js +25 -0
  43. package/dist/lib/render/components/Error.js.map +1 -0
  44. package/dist/lib/render/message.render.d.ts +40 -0
  45. package/dist/lib/render/message.render.d.ts.map +1 -0
  46. package/dist/lib/render/message.render.js +60 -0
  47. package/dist/lib/render/message.render.js.map +1 -0
  48. package/dist/lib/render/node/fragmemt.render.d.ts +34 -0
  49. package/dist/lib/render/node/fragmemt.render.d.ts.map +1 -0
  50. package/dist/lib/render/node/fragmemt.render.js +56 -0
  51. package/dist/lib/render/node/fragmemt.render.js.map +1 -0
  52. package/dist/lib/render/node/intrinsic.render.d.ts +37 -0
  53. package/dist/lib/render/node/intrinsic.render.d.ts.map +1 -0
  54. package/dist/lib/render/node/intrinsic.render.js +167 -0
  55. package/dist/lib/render/node/intrinsic.render.js.map +1 -0
  56. package/dist/lib/render/node/plain.render.d.ts +27 -0
  57. package/dist/lib/render/node/plain.render.d.ts.map +1 -0
  58. package/dist/lib/render/node/plain.render.js +32 -0
  59. package/dist/lib/render/node/plain.render.js.map +1 -0
  60. package/dist/lib/render/tag.render.d.ts +24 -0
  61. package/dist/lib/render/tag.render.d.ts.map +1 -0
  62. package/dist/lib/render/tag.render.js +27 -0
  63. package/dist/lib/render/tag.render.js.map +1 -0
  64. package/dist/lib/state/create.state.d.ts +8 -0
  65. package/dist/lib/state/create.state.d.ts.map +1 -0
  66. package/dist/lib/state/create.state.js +61 -0
  67. package/dist/lib/state/create.state.js.map +1 -0
  68. package/dist/lib/state/events/onclick.event.d.ts +21 -0
  69. package/dist/lib/state/events/onclick.event.d.ts.map +1 -0
  70. package/dist/lib/state/events/onclick.event.js +36 -0
  71. package/dist/lib/state/events/onclick.event.js.map +1 -0
  72. package/dist/lib/state/hooks/callback.hooks.d.ts +2 -0
  73. package/dist/lib/state/hooks/callback.hooks.d.ts.map +1 -0
  74. package/dist/lib/state/hooks/create.d.ts +7 -0
  75. package/dist/lib/state/hooks/create.d.ts.map +1 -0
  76. package/dist/lib/state/hooks/create.hooks.d.ts +29 -0
  77. package/dist/lib/state/hooks/create.hooks.d.ts.map +1 -0
  78. package/dist/lib/state/hooks/create.hooks.js +38 -0
  79. package/dist/lib/state/hooks/create.hooks.js.map +1 -0
  80. package/dist/lib/state/hooks/effect.hooks.d.ts +5 -0
  81. package/dist/lib/state/hooks/effect.hooks.d.ts.map +1 -0
  82. package/dist/lib/state/hooks/get.hooks.d.ts +25 -0
  83. package/dist/lib/state/hooks/get.hooks.d.ts.map +1 -0
  84. package/dist/lib/state/hooks/get.hooks.js +33 -0
  85. package/dist/lib/state/hooks/get.hooks.js.map +1 -0
  86. package/dist/lib/state/hooks/index.d.ts +7 -0
  87. package/dist/lib/state/hooks/index.d.ts.map +1 -0
  88. package/dist/lib/state/hooks/memo.hooks.d.ts +2 -0
  89. package/dist/lib/state/hooks/memo.hooks.d.ts.map +1 -0
  90. package/dist/lib/state/hooks/reducer.hooks.d.ts +3 -0
  91. package/dist/lib/state/hooks/reducer.hooks.d.ts.map +1 -0
  92. package/dist/lib/state/hooks/ref.hooks.d.ts +4 -0
  93. package/dist/lib/state/hooks/ref.hooks.d.ts.map +1 -0
  94. package/dist/lib/state/hooks/reset.hooks.d.ts +16 -0
  95. package/dist/lib/state/hooks/reset.hooks.d.ts.map +1 -0
  96. package/dist/lib/state/hooks/reset.hooks.js +19 -0
  97. package/dist/lib/state/hooks/reset.hooks.js.map +1 -0
  98. package/dist/lib/state/hooks/set.hooks.d.ts +23 -0
  99. package/dist/lib/state/hooks/set.hooks.d.ts.map +1 -0
  100. package/dist/lib/state/hooks/set.hooks.js +28 -0
  101. package/dist/lib/state/hooks/set.hooks.js.map +1 -0
  102. package/dist/lib/state/hooks/state.hooks.d.ts +50 -0
  103. package/dist/lib/state/hooks/state.hooks.d.ts.map +1 -0
  104. package/dist/lib/state/lifecycle/error.state.d.ts +7 -0
  105. package/dist/lib/state/lifecycle/error.state.d.ts.map +1 -0
  106. package/dist/lib/state/lifecycle/error.state.js +55 -0
  107. package/dist/lib/state/lifecycle/error.state.js.map +1 -0
  108. package/dist/lib/state/lifecycle/mount.state.d.ts +10 -0
  109. package/dist/lib/state/lifecycle/mount.state.d.ts.map +1 -0
  110. package/dist/lib/state/lifecycle/mount.state.js +84 -0
  111. package/dist/lib/state/lifecycle/mount.state.js.map +1 -0
  112. package/dist/lib/state/lifecycle/rerender.state.d.ts +10 -0
  113. package/dist/lib/state/lifecycle/rerender.state.d.ts.map +1 -0
  114. package/dist/lib/state/lifecycle/rerender.state.js +86 -0
  115. package/dist/lib/state/lifecycle/rerender.state.js.map +1 -0
  116. package/dist/lib/state/lifecycle/unmount.state.d.ts +9 -0
  117. package/dist/lib/state/lifecycle/unmount.state.d.ts.map +1 -0
  118. package/dist/lib/state/lifecycle/unmount.state.js +33 -0
  119. package/dist/lib/state/lifecycle/unmount.state.js.map +1 -0
  120. package/dist/types/grammy.types.d.ts +29 -0
  121. package/dist/types/grammy.types.d.ts.map +1 -0
  122. package/dist/types/grammy.types.js +3 -0
  123. package/dist/types/grammy.types.js.map +1 -0
  124. package/dist/types/hooks.types.d.ts +27 -0
  125. package/dist/types/hooks.types.d.ts.map +1 -0
  126. package/dist/types/jsx.types.d.ts +240 -0
  127. package/dist/types/jsx.types.d.ts.map +1 -0
  128. package/dist/types/jsx.types.js +29 -0
  129. package/dist/types/jsx.types.js.map +1 -0
  130. package/dist/types/lib.types.d.ts +80 -0
  131. package/dist/types/lib.types.d.ts.map +1 -0
  132. package/dist/types/lib.types.js +1 -0
  133. package/dist/types/lib.types.js.map +1 -0
  134. package/dist/types/plugin.types.d.ts +81 -0
  135. package/dist/types/plugin.types.d.ts.map +1 -0
  136. package/dist/types/plugin.types.js +1 -0
  137. package/dist/types/plugin.types.js.map +1 -0
  138. package/dist/utils/generateUniqueId.d.ts +29 -0
  139. package/dist/utils/generateUniqueId.d.ts.map +1 -0
  140. package/dist/utils/generateUniqueId.js +41 -0
  141. package/dist/utils/generateUniqueId.js.map +1 -0
  142. package/dist/utils/getEmoji.d.ts +26 -0
  143. package/dist/utils/getEmoji.d.ts.map +1 -0
  144. package/dist/utils/getEmoji.js +33 -0
  145. package/dist/utils/getEmoji.js.map +1 -0
  146. package/dist/utils/getPlainText.d.ts +23 -0
  147. package/dist/utils/getPlainText.d.ts.map +1 -0
  148. package/dist/utils/getPlainText.js +30 -0
  149. package/dist/utils/getPlainText.js.map +1 -0
  150. package/dist/utils/global.d.ts +13 -0
  151. package/dist/utils/global.d.ts.map +1 -0
  152. package/dist/utils/global.js +7 -0
  153. package/dist/utils/global.js.map +1 -0
  154. package/dist/utils/index.d.ts +9 -0
  155. package/dist/utils/index.d.ts.map +1 -0
  156. package/dist/utils/index.js +10 -0
  157. package/dist/utils/index.js.map +1 -0
  158. package/dist/utils/isAbortError.d.ts +2 -0
  159. package/dist/utils/isAbortError.d.ts.map +1 -0
  160. package/dist/utils/isEmoji.d.ts +25 -0
  161. package/dist/utils/isEmoji.d.ts.map +1 -0
  162. package/dist/utils/isEmoji.js +27 -0
  163. package/dist/utils/isEmoji.js.map +1 -0
  164. package/dist/utils/isEqual.d.ts +42 -0
  165. package/dist/utils/isEqual.d.ts.map +1 -0
  166. package/dist/utils/isEqual.js +142 -0
  167. package/dist/utils/isEqual.js.map +1 -0
  168. package/dist/utils/isIntrinsicElement.d.ts +23 -0
  169. package/dist/utils/isIntrinsicElement.d.ts.map +1 -0
  170. package/dist/utils/isIntrinsicElement.js +25 -0
  171. package/dist/utils/isIntrinsicElement.js.map +1 -0
  172. package/dist/utils/isMessageNotFount.d.ts +2 -0
  173. package/dist/utils/isMessageNotFount.d.ts.map +1 -0
  174. package/dist/utils/isUnixTime.d.ts +32 -0
  175. package/dist/utils/isUnixTime.d.ts.map +1 -0
  176. package/dist/utils/isUnixTime.js +38 -0
  177. package/dist/utils/isUnixTime.js.map +1 -0
  178. package/dist/utils/sanitizeHtmlString.d.ts +24 -0
  179. package/dist/utils/sanitizeHtmlString.d.ts.map +1 -0
  180. package/dist/utils/sanitizeHtmlString.js +29 -0
  181. package/dist/utils/sanitizeHtmlString.js.map +1 -0
  182. package/dist/utils/withComponentScope.d.ts +2 -0
  183. package/dist/utils/withComponentScope.d.ts.map +1 -0
  184. package/dist/utils/withRuntime.d.ts +4 -0
  185. package/dist/utils/withRuntime.d.ts.map +1 -0
  186. package/package.json +62 -0
  187. package/readme.md +373 -0
@@ -0,0 +1,60 @@
1
+ import { createFragmentElementRender } from "./node/fragmemt.render";
2
+ import { InputMediaBuilder, InputFile } from "~/types/grammy.types";
3
+ /**
4
+ * Renders a JSX message tree into a Telegram-compatible payload.
5
+ *
6
+ * This is the root render pipeline entry responsible for converting
7
+ * a resolved JSX tree into:
8
+ * - HTML text
9
+ * - Telegram send options
10
+ * - optional media attachments
11
+ * - resolved render view mode
12
+ *
13
+ * The renderer automatically enforces `parse_mode: "HTML"` and
14
+ * converts collected image attachments into Telegram photo media.
15
+ *
16
+ * If at least one media attachment is present, the resulting
17
+ * render view is resolved as `"caption"`. Otherwise, it is
18
+ * rendered as a plain `"message"`.
19
+ *
20
+ * The final text output is automatically trimmed to Telegram's character message limit.
21
+ * If view is `"message"`, the text is trimmed to 4096 characters.
22
+ * If view is `"caption"`, the text is trimmed to 1024 characters.
23
+ *
24
+ * @template {ReactiveContext} C
25
+ * @template {OtherContexted<"sendMessage", "text" | "chat_id" | "parse_mode">} Other
26
+ * @param {RenderedMessageOptions<C, Other>} options - Root render options.
27
+ * @returns {RenderedMessage<Other>} The fully rendered Telegram payload.
28
+ *
29
+ * @example
30
+ * const result = await createMessageRender({
31
+ * id,
32
+ * method: "replyWithJSX",
33
+ * jsx: <b>Hello</b>,
34
+ * ctx,
35
+ * other: {},
36
+ * });
37
+ */
38
+ export async function createMessageRender(options) {
39
+ options.other ??= {};
40
+ options.other.parse_mode = "HTML";
41
+ const tree = await options.jsx;
42
+ let photo = undefined;
43
+ const media = [];
44
+ const [text, attachments] = await createFragmentElementRender(tree, options);
45
+ if (attachments?.length)
46
+ for (const item of attachments) {
47
+ media.push(InputMediaBuilder.photo(item.src, {
48
+ show_caption_above_media: item.position === 'top',
49
+ has_spoiler: item.spoiler
50
+ }));
51
+ photo = new InputFile(item.src);
52
+ }
53
+ return {
54
+ text: text.slice(0, media?.length ? 1024 : 4096),
55
+ other: options.other,
56
+ view: media?.length ? 'caption' : 'message',
57
+ media, photo
58
+ };
59
+ }
60
+ //# sourceMappingURL=message.render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.render.js","sourceRoot":"","sources":["../../../src/lib/render/message.render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAKpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,OAAyC;IAEzC,OAAO,CAAC,KAAK,KAAK,EAAW,CAAC;IAAE,OAAO,CAAC,KAAa,CAAC,UAAU,GAAG,MAAM,CAAA;IACzE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;IAC/B,IAAI,KAAK,GAA0B,SAAS,CAAC;IAAC,MAAM,KAAK,GAAsB,EAAE,CAAC;IAElF,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,MAAM,2BAA2B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE7E,IAAI,WAAW,EAAE,MAAM;QAAE,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACzC,wBAAwB,EAAE,IAAI,CAAC,QAAQ,KAAK,KAAK;gBACjD,WAAW,EAAE,IAAI,CAAC,OAAO;aAC5B,CAAC,CAAC,CAAA;YACH,KAAK,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACnC,CAAC;IACD,OAAO;QACH,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAChD,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC3C,KAAK,EAAE,KAAK;KACf,CAAC;AACN,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { RenderedMessageOptions } from "src/types/lib.types";
2
+ import type { JSX } from "src/types/jsx.types";
3
+ import type { MaybeArray, ReactiveContext } from "~/types/plugin.types";
4
+ import type { OtherContexted } from "~/types/grammy.types";
5
+ /**
6
+ * Recursively renders a JSX fragment tree into Telegram-compatible HTML string output.
7
+ *
8
+ * This renderer walks the provided JSX subtree, concatenates rendered
9
+ * text output, delegates intrinsic node rendering, and bubbles collected
10
+ * media attachments upward through the render pipeline.
11
+ *
12
+ * Supported node handling:
13
+ * - plain text nodes
14
+ * - fragment recursion
15
+ * - intrinsic host node rendering
16
+ *
17
+ * Media extraction can optionally be suppressed for nested render
18
+ * branches when only text output is required.
19
+ *
20
+ * @template {ReactiveContext} C
21
+ * @template {OtherContexted<"sendMessage", "text" | "chat_id" | "parse_mode">} Other
22
+ * @param {MaybeArray<JSX.Element>} elements - The JSX subtree to render.
23
+ * @param {RenderedMessageOptions<C, Other>} options - Active render context.
24
+ * @param {boolean} [noMedia]
25
+ * When `true`, extracted media is ignored for this render branch.
26
+ * @returns {Promise<[string, IntrinsicElements["img"][]] | [string]>}
27
+ * The rendered HTML text and optional bubbled media attachments.
28
+ */
29
+ export declare function createFragmentElementRender<C extends ReactiveContext, Other extends OtherContexted<"sendMessage", "text" | "chat_id" | "parse_mode">>(elements: MaybeArray<JSX.Element>, options: RenderedMessageOptions<C, Other>, noMedia?: boolean
30
+ /** TODO:
31
+ * Uncomment this when caption rerender is fixed
32
+ * */
33
+ ): Promise<[string, any[]] | [string]>;
34
+ //# sourceMappingURL=fragmemt.render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fragmemt.render.d.ts","sourceRoot":"","sources":["../../../../src/lib/render/node/fragmemt.render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAqB,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAGlE,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,2BAA2B,CAC7C,CAAC,SAAS,eAAe,EACzB,KAAK,SAAS,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC,EAE9E,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EACjC,OAAO,EAAE,sBAAsB,CAAC,CAAC,EAAE,KAAK,CAAC,EACzC,OAAO,CAAC,EAAE,OAAO;AACjB;;KAEK;GAEN,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CA2BrC"}
@@ -0,0 +1,56 @@
1
+ import { createIntrinsicElementRender } from "./intrinsic.render";
2
+ import { createPlainElementRender } from "./plain.render";
3
+ /**
4
+ * Recursively renders a JSX fragment tree into Telegram-compatible HTML string output.
5
+ *
6
+ * This renderer walks the provided JSX subtree, concatenates rendered
7
+ * text output, delegates intrinsic node rendering, and bubbles collected
8
+ * media attachments upward through the render pipeline.
9
+ *
10
+ * Supported node handling:
11
+ * - plain text nodes
12
+ * - fragment recursion
13
+ * - intrinsic host node rendering
14
+ *
15
+ * Media extraction can optionally be suppressed for nested render
16
+ * branches when only text output is required.
17
+ *
18
+ * @template {ReactiveContext} C
19
+ * @template {OtherContexted<"sendMessage", "text" | "chat_id" | "parse_mode">} Other
20
+ * @param {MaybeArray<JSX.Element>} elements - The JSX subtree to render.
21
+ * @param {RenderedMessageOptions<C, Other>} options - Active render context.
22
+ * @param {boolean} [noMedia]
23
+ * When `true`, extracted media is ignored for this render branch.
24
+ * @returns {Promise<[string, IntrinsicElements["img"][]] | [string]>}
25
+ * The rendered HTML text and optional bubbled media attachments.
26
+ */
27
+ export async function createFragmentElementRender(elements, options, noMedia) {
28
+ const array = Array.isArray(elements) ? elements : [elements];
29
+ let out = "";
30
+ const media = [];
31
+ for (let i = 0; i < array.length; i++) {
32
+ const current = array[i];
33
+ if (current == null)
34
+ continue;
35
+ const element = await current, type = element.type;
36
+ if (type === "plain") {
37
+ out += createPlainElementRender(element);
38
+ continue;
39
+ }
40
+ const rendered = type === "fragment"
41
+ ? await createFragmentElementRender(element.children, options)
42
+ : await createIntrinsicElementRender(element, options);
43
+ out += rendered[0];
44
+ if (noMedia)
45
+ continue;
46
+ const _media = rendered[1];
47
+ if (_media)
48
+ for (let j = 0; j < _media.length; j++) {
49
+ const item = _media[j];
50
+ if (item)
51
+ media.push(item);
52
+ }
53
+ }
54
+ return [out, media];
55
+ }
56
+ //# sourceMappingURL=fragmemt.render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fragmemt.render.js","sourceRoot":"","sources":["../../../../src/lib/render/node/fragmemt.render.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAI1D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAI7C,QAAiC,EACjC,OAAyC,EACzC,OAAiB;IAEjB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9D,IAAI,GAAG,GAAG,EAAE,CAAC;IAAC,MAAM,KAAK,GAA+B,EAAE,CAAC;IAE3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAAC,IAAI,OAAO,IAAI,IAAI;YAAE,SAAS;QACxD,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAEnD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YAAC,GAAG,IAAI,wBAAwB,CAAC,OAAO,CAAC,CAAC;YAAC,SAAQ;QAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,IAAI,KAAK,UAAU;YAChC,CAAC,CAAC,MAAM,2BAA2B,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC;YAC9D,CAAC,CAAC,MAAM,4BAA4B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAE3D,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAA;QAClB,IAAI,OAAO;YAAE,SAAQ;QACrB,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,MAAM;YAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBACvB,IAAI,IAAI;oBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { IntrinsicElement } from "src/types/jsx.types";
2
+ import type { ReactiveContext } from "~/types/plugin.types";
3
+ import type { RenderedMessageOptions } from "src/types/lib.types";
4
+ import type { OtherContexted } from "src/types/grammy.types";
5
+ /**
6
+ * Renders a single intrinsic JSX node into its Telegram-compatible HTML string output.
7
+ *
8
+ * This is the host renderer responsible for translating framework
9
+ * intrinsic elements into Telegram HTML, media attachments, preview
10
+ * metadata, and interactive reply markup mutations.
11
+ *
12
+ * Supported responsibilities include:
13
+ * - Telegram HTML tag rendering
14
+ * - media attachment extraction
15
+ * - link preview configuration
16
+ * - inline keyboard construction
17
+ * - callback button registration
18
+ * - intrinsic runtime validation
19
+ *
20
+ * Some intrinsic elements mutate the provided render options directly,
21
+ * such as:
22
+ * - `reply_markup`
23
+ * - `link_preview_options`
24
+ * - callback registry bindings
25
+ *
26
+ * Unsupported elements for the current render method are rejected
27
+ * through runtime JSX parse errors.
28
+ *
29
+ * @template {ReactiveContext} C
30
+ * @template {OtherContexted<"sendMessage", "text" | "chat_id" | "parse_mode">} Other
31
+ * @param {IntrinsicElement} element - The intrinsic node to render.
32
+ * @param {RenderedMessageOptions<C, Other>} options - Active render context.
33
+ * @returns {Promise<[string, IntrinsicElements["img"][]] | [string]>}
34
+ * The rendered HTML fragment and optional extracted media.
35
+ */
36
+ export declare function createIntrinsicElementRender<C extends ReactiveContext, Other extends OtherContexted<"sendMessage", "text" | "chat_id" | "parse_mode">>(element: IntrinsicElement, options: RenderedMessageOptions<C, Other>): Promise<[string, (any[])] | [string]>;
37
+ //# sourceMappingURL=intrinsic.render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intrinsic.render.d.ts","sourceRoot":"","sources":["../../../../src/lib/render/node/intrinsic.render.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA0B,gBAAgB,EAAmC,MAAM,qBAAqB,CAAC;AACrH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,4BAA4B,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,SAAS,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC,EACxJ,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,sBAAsB,CAAC,CAAC,EAAE,KAAK,CAAC,GAC1C,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAyHvC"}
@@ -0,0 +1,167 @@
1
+ import { InlineKeyboard, InputMediaBuilder, Keyboard } from "src/types/grammy.types";
2
+ import { createFragmentElementRender } from "./fragmemt.render";
3
+ import { generateUniqueId, isEmoji, isUnixTime } from "src/utils";
4
+ import { createTagRender as t } from "../tag.render";
5
+ import { getEmoji, getPlainText, globalButtonCallbacks } from "src/utils";
6
+ import { JSXParseError } from "src/jsx/runtime/jsx.errors";
7
+ /**
8
+ * Renders a single intrinsic JSX node into its Telegram-compatible HTML string output.
9
+ *
10
+ * This is the host renderer responsible for translating framework
11
+ * intrinsic elements into Telegram HTML, media attachments, preview
12
+ * metadata, and interactive reply markup mutations.
13
+ *
14
+ * Supported responsibilities include:
15
+ * - Telegram HTML tag rendering
16
+ * - media attachment extraction
17
+ * - link preview configuration
18
+ * - inline keyboard construction
19
+ * - callback button registration
20
+ * - intrinsic runtime validation
21
+ *
22
+ * Some intrinsic elements mutate the provided render options directly,
23
+ * such as:
24
+ * - `reply_markup`
25
+ * - `link_preview_options`
26
+ * - callback registry bindings
27
+ *
28
+ * Unsupported elements for the current render method are rejected
29
+ * through runtime JSX parse errors.
30
+ *
31
+ * @template {ReactiveContext} C
32
+ * @template {OtherContexted<"sendMessage", "text" | "chat_id" | "parse_mode">} Other
33
+ * @param {IntrinsicElement} element - The intrinsic node to render.
34
+ * @param {RenderedMessageOptions<C, Other>} options - Active render context.
35
+ * @returns {Promise<[string, IntrinsicElements["img"][]] | [string]>}
36
+ * The rendered HTML fragment and optional extracted media.
37
+ */
38
+ export async function createIntrinsicElementRender(element, options) {
39
+ const media = [];
40
+ if (options.unallowed && options.unallowed.includes(element.entity.type)) {
41
+ throw new JSXParseError(`Elements: ${options.unallowed.join(', ')} is not allowed in "${options.method}" method`);
42
+ }
43
+ switch (element.entity.type) {
44
+ case "br": return ['\n'];
45
+ case 'p': return [`${(await createFragmentElementRender(element.children, options, true))[0]}\n`];
46
+ case 'b': return [
47
+ t('b', (await createFragmentElementRender(element.children, options, true))[0])
48
+ ];
49
+ case 'i': return [
50
+ t('i', (await createFragmentElementRender(element.children, options, true))[0])
51
+ ];
52
+ case 'u': return [
53
+ t('u', (await createFragmentElementRender(element.children, options, true))[0])
54
+ ];
55
+ case 's': return [
56
+ t('s', (await createFragmentElementRender(element.children, options, true))[0])
57
+ ];
58
+ case 'h': return [
59
+ t('b', (await createFragmentElementRender(element.children, options, true))[0]) + '\n'
60
+ ];
61
+ case 'a': return [
62
+ t('a', (await createFragmentElementRender(element.children, options, true))[0], {
63
+ href: encodeURI(element.entity.href)
64
+ })
65
+ ];
66
+ case 'blockquote': return [
67
+ t('blockquote', (await createFragmentElementRender(element.children, options, true))[0])
68
+ ];
69
+ case 'code': return [
70
+ t('code', (await createFragmentElementRender(element.children, options, true))[0])
71
+ ];
72
+ case 'codeblock': return [element.entity.lang ?
73
+ t('pre', t('code', (await createFragmentElementRender(element.children, options, true))[0], {
74
+ class: `language-${element.entity.lang}`
75
+ })) : t('pre', (await createFragmentElementRender(element.children, options, true))[0])
76
+ ];
77
+ case 'spoiler': return [
78
+ t('tg-spoiler', (await createFragmentElementRender(element.children, options, true))[0])
79
+ ];
80
+ case 'emoji': {
81
+ const alt = element.children.find(v => v.type === 'plain').value || '👍';
82
+ if (!isEmoji(alt))
83
+ throw new JSXParseError(`Emoji alt property is not a valid emoji: ${alt}`);
84
+ return [
85
+ t('tg-emoji', alt, { "emoji-id": element.entity.id })
86
+ ];
87
+ }
88
+ case 'time': {
89
+ if (!isUnixTime(element.entity.unix))
90
+ throw new JSXParseError(`Time property is not a valid unix timestamp: ${element.entity.unix}`);
91
+ return [
92
+ t('tg-time', (await createFragmentElementRender(element.children, options, true))[0], {
93
+ unix: element.entity.unix,
94
+ format: element.entity.format
95
+ })
96
+ ];
97
+ }
98
+ case "img": {
99
+ media.push(element.entity);
100
+ return ['', media];
101
+ }
102
+ case "preview": {
103
+ if (options.other.link_preview_options)
104
+ throw new JSXParseError("Preview in this state are already set");
105
+ options.other.link_preview_options = {
106
+ is_disabled: false,
107
+ url: element.entity.src,
108
+ show_above_text: element.entity.position !== 'bottom',
109
+ ...(element.entity.size === 'small' ? { prefer_small_media: true } : { prefer_large_media: true }),
110
+ };
111
+ return [
112
+ t('a', '\u00A0', { href: encodeURI(element.entity.src) })
113
+ ];
114
+ }
115
+ case "button": {
116
+ if (options.other.reply_markup instanceof Keyboard)
117
+ throw new JSXParseError("Inline keyboard cannot be used with custom keyboards");
118
+ if (!options.other.reply_markup)
119
+ options.other.reply_markup = new InlineKeyboard();
120
+ const entity = element.entity;
121
+ const id = `::${options.id}::${entity.event || element.id || generateUniqueId()}`;
122
+ const keyboard = options.other.reply_markup;
123
+ const emoji = getEmoji(element);
124
+ if (emoji)
125
+ keyboard.icon(emoji.id);
126
+ const text = getPlainText(element);
127
+ if (!text)
128
+ throw new JSXParseError("Inline button must have a text child");
129
+ switch (entity.variant) {
130
+ case 'url':
131
+ keyboard.url(text, entity.url);
132
+ break;
133
+ case 'callback':
134
+ keyboard.text(text, id);
135
+ break;
136
+ case 'login':
137
+ keyboard.login(text, entity.data);
138
+ break;
139
+ case 'switch_inline':
140
+ keyboard.switchInline(text, entity.query);
141
+ break;
142
+ case 'switch_inline_chosen':
143
+ keyboard.switchInlineChosen(text, entity.data);
144
+ break;
145
+ case 'copy':
146
+ keyboard.copyText(text, entity.value.slice(0, 255));
147
+ break;
148
+ case 'game':
149
+ keyboard.game(text);
150
+ break;
151
+ case 'pay':
152
+ keyboard.pay(text);
153
+ break;
154
+ default: throw new Error(`Unknown button variant: ${entity.variant}`);
155
+ }
156
+ if (entity.color)
157
+ keyboard.style(entity.color);
158
+ if (entity.row)
159
+ keyboard.row();
160
+ if (entity.variant === 'callback' && entity.onClick)
161
+ globalButtonCallbacks[id] = entity.onClick;
162
+ return [''];
163
+ }
164
+ default: return ['', media];
165
+ }
166
+ }
167
+ //# sourceMappingURL=intrinsic.render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intrinsic.render.js","sourceRoot":"","sources":["../../../../src/lib/render/node/intrinsic.render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { PlainElement } from "~/types/jsx.types";
2
+ /**
3
+ * Renders a {@link PlainElement} into a sanitized HTML-safe string.
4
+ *
5
+ * This function serializes plain text render nodes during the final
6
+ * render phase of the message AST pipeline.
7
+ *
8
+ * Supported value handling:
9
+ * - `null`, `undefined`, and boolean values render as an empty string
10
+ * - `string` values are HTML-sanitized directly
11
+ * - numeric values are stringified before sanitization
12
+ *
13
+ * The resulting string is always safe to embed into Telegram HTML output.
14
+ *
15
+ * @param {PlainElement} element - The plain text node to render.
16
+ * @returns {string} The sanitized rendered string.
17
+ *
18
+ * @example
19
+ * plainElementRender({ type: "plain", value: "Hello <world>" });
20
+ * // "Hello &lt;world&gt;"
21
+ *
22
+ * @example
23
+ * plainElementRender({ type: "plain", value: 42 });
24
+ * // "42"
25
+ */
26
+ export declare function createPlainElementRender(element: PlainElement): string;
27
+ //# sourceMappingURL=plain.render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain.render.d.ts","sourceRoot":"","sources":["../../../../src/lib/render/node/plain.render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAItE"}
@@ -0,0 +1,32 @@
1
+ import { sanitizeHtmlString } from "~/utils";
2
+ /**
3
+ * Renders a {@link PlainElement} into a sanitized HTML-safe string.
4
+ *
5
+ * This function serializes plain text render nodes during the final
6
+ * render phase of the message AST pipeline.
7
+ *
8
+ * Supported value handling:
9
+ * - `null`, `undefined`, and boolean values render as an empty string
10
+ * - `string` values are HTML-sanitized directly
11
+ * - numeric values are stringified before sanitization
12
+ *
13
+ * The resulting string is always safe to embed into Telegram HTML output.
14
+ *
15
+ * @param {PlainElement} element - The plain text node to render.
16
+ * @returns {string} The sanitized rendered string.
17
+ *
18
+ * @example
19
+ * plainElementRender({ type: "plain", value: "Hello <world>" });
20
+ * // "Hello &lt;world&gt;"
21
+ *
22
+ * @example
23
+ * plainElementRender({ type: "plain", value: 42 });
24
+ * // "42"
25
+ */
26
+ export function createPlainElementRender(element) {
27
+ const value = element.value;
28
+ if (value == null || value === false || value === true)
29
+ return "";
30
+ return typeof value === "string" ? sanitizeHtmlString(value) : sanitizeHtmlString("" + value);
31
+ }
32
+ //# sourceMappingURL=plain.render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain.render.js","sourceRoot":"","sources":["../../../../src/lib/render/node/plain.render.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAqB;IAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAClE,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;AAClG,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Wraps pre-rendered child content in an intrinsic HTML tag pair.
3
+ *
4
+ * This is a low-level render helper used during the final serialization
5
+ * phase to convert intrinsic text entities into Telegram-compatible
6
+ * HTML markup.
7
+ *
8
+ * The function assumes that `children` has already been fully rendered
9
+ * and sanitized by the caller.
10
+ *
11
+ * @param {string} tag - The tag name to render.
12
+ * @param {string} children - Pre-rendered child HTML content.
13
+ * @returns {string} The serialized HTML tag string.
14
+ *
15
+ * @example
16
+ * createTagElementRender("b", "Hello");
17
+ * // "<b>Hello</b>"
18
+ *
19
+ * @example
20
+ * createTagElementRender("code", "&lt;div&gt;");
21
+ * // "<code>&lt;div&gt;</code>"
22
+ */
23
+ export declare function createTagRender(tag: string, children: string, attributes?: Record<string, any>): string;
24
+ //# sourceMappingURL=tag.render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.render.d.ts","sourceRoot":"","sources":["../../../src/lib/render/tag.render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,MAAM,CAG3G"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Wraps pre-rendered child content in an intrinsic HTML tag pair.
3
+ *
4
+ * This is a low-level render helper used during the final serialization
5
+ * phase to convert intrinsic text entities into Telegram-compatible
6
+ * HTML markup.
7
+ *
8
+ * The function assumes that `children` has already been fully rendered
9
+ * and sanitized by the caller.
10
+ *
11
+ * @param {string} tag - The tag name to render.
12
+ * @param {string} children - Pre-rendered child HTML content.
13
+ * @returns {string} The serialized HTML tag string.
14
+ *
15
+ * @example
16
+ * createTagElementRender("b", "Hello");
17
+ * // "<b>Hello</b>"
18
+ *
19
+ * @example
20
+ * createTagElementRender("code", "&lt;div&gt;");
21
+ * // "<code>&lt;div&gt;</code>"
22
+ */
23
+ export function createTagRender(tag, children, attributes = {}) {
24
+ const result = `<${tag}${Object.entries(attributes).filter(Boolean).map(([k, v]) => ` ${k}="${v}"`).join('')}>${children}</${tag}>`;
25
+ return result;
26
+ }
27
+ //# sourceMappingURL=tag.render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.render.js","sourceRoot":"","sources":["../../../src/lib/render/tag.render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,QAAgB,EAAE,aAAkC,EAAE;IAC/F,MAAM,MAAM,GAAG,IAAI,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,QAAQ,KAAK,GAAG,GAAG,CAAA;IACnI,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { BotHandlerLifecycleInstance, BotMessageHandler } from "~/types/lib.types";
2
+ import type { ReactiveContext } from "~/types/plugin.types";
3
+ export declare function createMessageState<C extends ReactiveContext>({ id, ctx, handler }: {
4
+ id: string;
5
+ ctx: C;
6
+ handler: BotMessageHandler<C>;
7
+ }): BotHandlerLifecycleInstance<C>;
8
+ //# sourceMappingURL=create.state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.state.d.ts","sourceRoot":"","sources":["../../../src/lib/state/create.state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAO5D,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,eAAe,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;IAChF,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,CAAC,CAAC;IACP,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;CACjC,GAAG,2BAA2B,CAAC,CAAC,CAAC,CA0FjC"}
@@ -0,0 +1,61 @@
1
+ import { createRerenderMessageState } from "./lifecycle/rerender.state";
2
+ import { createUnmountMessageState } from "./lifecycle/unmount.state";
3
+ import { globalAbortControllers } from "~/utils";
4
+ import { createMountMessageState } from "./lifecycle/mount.state";
5
+ import { createHooks } from "./hooks/create.hooks";
6
+ /**
7
+ * Creates a lifecycle state controller for a mounted message session.
8
+ *
9
+ * The returned lifecycle instance provides bound `rerender` and
10
+ * `unmount` controls for the specified message render session.
11
+ *
12
+ * Each lifecycle action recreates a fresh state controller instance
13
+ * before delegating to the corresponding lifecycle transition,
14
+ * ensuring isolated rerender and cleanup flows.
15
+ *
16
+ * Used as the core runtime state bridge for both static and
17
+ * reactive message handlers.
18
+ *
19
+ * @template {ReactiveContext} C
20
+ * @param {string} id - The unique lifecycle session identifier.
21
+ * @param {C} ctx - The bound reactive Telegram context.
22
+ * @param {BotStaticMessageHandler<C> | BotMessageHandler<C>} handler
23
+ * The original handler bound to the lifecycle session.
24
+ * @returns {BotHandlerLifecycleInstance<C>}
25
+ * A lifecycle controller with `rerender` and `unmount` methods.
26
+ *
27
+ * @example
28
+ * const state = createMessageState(id, ctx, handler);
29
+ * await state.rerender();
30
+ */
31
+ export function createMessageState({ id, ctx, handler }) {
32
+ return {
33
+ get controller() {
34
+ if (!globalAbortControllers.has(id))
35
+ globalAbortControllers.set(id, new AbortController());
36
+ return globalAbortControllers.get(id);
37
+ },
38
+ set controller(value) {
39
+ globalAbortControllers.set(id, value);
40
+ },
41
+ async mount() {
42
+ const state = createMessageState({ id, ctx, handler });
43
+ const hooks = createHooks({ id, ctx, handler, state, controller: this.controller });
44
+ await createMountMessageState({ id, ctx, handler, state, hooks });
45
+ },
46
+ async rerender() {
47
+ this.controller?.abort();
48
+ this.controller = new AbortController();
49
+ const state = createMessageState({ id, ctx, handler });
50
+ const hooks = createHooks({ id, ctx, handler, state, controller: this.controller });
51
+ await createRerenderMessageState({ id, ctx, handler, state, hooks, controller: this.controller });
52
+ },
53
+ async unmount() {
54
+ this.controller?.abort();
55
+ this.controller = new AbortController();
56
+ const state = createMessageState({ id, ctx, handler });
57
+ await createUnmountMessageState({ id, ctx, controller: this.controller });
58
+ }
59
+ };
60
+ }
61
+ //# sourceMappingURL=create.state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.state.js","sourceRoot":"","sources":["../../../src/lib/state/create.state.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,kBAAkB,CAA4B,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAI/E;IACG,OAAO;QACH,IAAI,UAAU;YACV,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,sBAAsB,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,eAAe,EAAE,CAAC,CAAC;YAC3F,OAAO,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;QAC3C,CAAC;QACD,IAAI,UAAU,CAAC,KAAsB;YACjC,sBAAsB,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,CAAC,KAAK;YACP,MAAM,KAAK,GAAG,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAA;YACtD,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAG,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;YACpF,MAAM,uBAAuB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;QACrE,CAAC;QACD,KAAK,CAAC,QAAQ;YACV,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;YACjE,MAAM,KAAK,GAAG,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAA;YACtD,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAG,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;YACpF,MAAM,0BAA0B,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;QACrG,CAAC;QACD,KAAK,CAAC,OAAO;YACT,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;YACjE,MAAM,KAAK,GAAG,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAA;YACtD,MAAM,yBAAyB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;QAC7E,CAAC;KACJ,CAAA;AACL,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ReactiveContext } from "~/types/plugin.types";
2
+ import type { NextFunction } from "~/types/grammy.types";
3
+ /**
4
+ * Dispatches registered reactive button callbacks for callback queries.
5
+ *
6
+ * This internal middleware resolves callback payloads against the
7
+ * button callback registry and executes the matching handler within
8
+ * its owning lifecycle session.
9
+ *
10
+ * If no registered callback exists, middleware control is delegated
11
+ * directly to the next handler.
12
+ *
13
+ * On handler failure, the owning lifecycle session is transitioned
14
+ * into its error fallback state.
15
+ *
16
+ * @param {ReactiveContext} ctx - The reactive Telegram context.
17
+ * @param {NextFunction} next - The next middleware in the pipeline.
18
+ * @returns {Promise<void>}
19
+ */
20
+ export declare function createOnClickEvent(ctx: ReactiveContext, next: NextFunction): Promise<void>;
21
+ //# sourceMappingURL=onclick.event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onclick.event.d.ts","sourceRoot":"","sources":["../../../../src/lib/state/events/onclick.event.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAehG"}