@zaly/tui 0.0.4 → 0.0.6

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 (156) hide show
  1. package/dist/actions-CnVzKVID.d.mts +41 -0
  2. package/dist/actions-CnVzKVID.d.mts.map +1 -0
  3. package/dist/actions-DEIKF2ts.mjs +48 -0
  4. package/dist/actions-DEIKF2ts.mjs.map +1 -0
  5. package/dist/{box-DyaByEiG.mjs → box-DepqUtuo.mjs} +2 -2
  6. package/dist/{box-DyaByEiG.mjs.map → box-DepqUtuo.mjs.map} +1 -1
  7. package/dist/{builder-D49ECBEf.mjs → builder-DTz5mppV.mjs} +2 -2
  8. package/dist/{builder-D49ECBEf.mjs.map → builder-DTz5mppV.mjs.map} +1 -1
  9. package/dist/{callbacks-CNjGNxVw.mjs → callbacks-DcMBGQEO.mjs} +2 -2
  10. package/dist/{callbacks-CNjGNxVw.mjs.map → callbacks-DcMBGQEO.mjs.map} +1 -1
  11. package/dist/{client-D6C_uczF.mjs → client-BBdtbLp4.mjs} +5 -10
  12. package/dist/client-BBdtbLp4.mjs.map +1 -0
  13. package/dist/client-cIckDgAj.mjs +2 -0
  14. package/dist/clipboard-l_TWxxTf.mjs +404 -0
  15. package/dist/clipboard-l_TWxxTf.mjs.map +1 -0
  16. package/dist/clipboard.mjs +1 -403
  17. package/dist/ctx-Bt4VlRPg.mjs +2 -0
  18. package/dist/ctx-DjJ1zSbs.mjs +43 -0
  19. package/dist/ctx-DjJ1zSbs.mjs.map +1 -0
  20. package/dist/divider-cclEAdPx.mjs +9 -0
  21. package/dist/divider-cclEAdPx.mjs.map +1 -0
  22. package/dist/files-Aw3iWpXD.d.mts +29 -0
  23. package/dist/files-Aw3iWpXD.d.mts.map +1 -0
  24. package/dist/files-BvThQpOf.mjs +42 -0
  25. package/dist/files-BvThQpOf.mjs.map +1 -0
  26. package/dist/github-Cy2hfWJ7.mjs +137 -0
  27. package/dist/github-Cy2hfWJ7.mjs.map +1 -0
  28. package/dist/github-DS00VoOj.d.mts +64 -0
  29. package/dist/github-DS00VoOj.d.mts.map +1 -0
  30. package/dist/image-BTxDPPiT.d.mts +37 -0
  31. package/dist/image-BTxDPPiT.d.mts.map +1 -0
  32. package/dist/index.mjs +6 -202
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/input-CRBuTrsL.mjs +497 -0
  35. package/dist/input-CRBuTrsL.mjs.map +1 -0
  36. package/dist/{inspect-D1d9t-ni.mjs → inspect-DE5goDzB.mjs} +2 -2
  37. package/dist/{inspect-D1d9t-ni.mjs.map → inspect-DE5goDzB.mjs.map} +1 -1
  38. package/dist/log-Djvrxqk0.mjs +130 -0
  39. package/dist/log-Djvrxqk0.mjs.map +1 -0
  40. package/dist/logger-DDrt03So.mjs +71 -0
  41. package/dist/logger-DDrt03So.mjs.map +1 -0
  42. package/dist/markdown-CTlPe5ks.mjs +124 -0
  43. package/dist/markdown-CTlPe5ks.mjs.map +1 -0
  44. package/dist/markdown.mjs +1 -1
  45. package/dist/overlay-9xNgsuuy.mjs +18 -0
  46. package/dist/overlay-9xNgsuuy.mjs.map +1 -0
  47. package/dist/{picker-ndVVt6qF.mjs → picker-cH-rc7-X.mjs} +5 -5
  48. package/dist/{picker-ndVVt6qF.mjs.map → picker-cH-rc7-X.mjs.map} +1 -1
  49. package/dist/queries-B_lOwEiE.mjs +200 -0
  50. package/dist/queries-B_lOwEiE.mjs.map +1 -0
  51. package/dist/{registry-U654j61Y.mjs → registry-w_w7gZr_.mjs} +3 -5
  52. package/dist/registry-w_w7gZr_.mjs.map +1 -0
  53. package/dist/render-F8pVXN7h.mjs +33 -0
  54. package/dist/render-F8pVXN7h.mjs.map +1 -0
  55. package/dist/renderer-Dgj_qEOA.mjs +2 -0
  56. package/dist/{renderer-CdLCkJB-.mjs → renderer-qSMVeNSV.mjs} +3 -5
  57. package/dist/{renderer-CdLCkJB-.mjs.map → renderer-qSMVeNSV.mjs.map} +1 -1
  58. package/dist/{renderer-CxL4xbkl.mjs → renderer-uMeDzF9B.mjs} +8 -7
  59. package/dist/{renderer-CxL4xbkl.mjs.map → renderer-uMeDzF9B.mjs.map} +1 -1
  60. package/dist/select-m7NE6Rwa.mjs +195 -0
  61. package/dist/select-m7NE6Rwa.mjs.map +1 -0
  62. package/dist/services/logger.mjs +1 -70
  63. package/dist/services/notifier.mjs +2 -2
  64. package/dist/services/picker.d.mts +1 -1
  65. package/dist/services/picker.mjs +6 -6
  66. package/dist/services/prompt.d.mts +1 -1
  67. package/dist/services/prompt.mjs +5 -5
  68. package/dist/shiki/server.d.mts +1 -0
  69. package/dist/shiki/server.mjs +129 -0
  70. package/dist/shiki/server.mjs.map +1 -0
  71. package/dist/{shiki-BrjVUkeh.mjs → shiki-B5NwIiot.mjs} +5 -10
  72. package/dist/shiki-B5NwIiot.mjs.map +1 -0
  73. package/dist/shiki-BK-v9CtF.mjs +12 -0
  74. package/dist/shiki-BK-v9CtF.mjs.map +1 -0
  75. package/dist/show-DR2x1YFc.mjs +85 -0
  76. package/dist/show-DR2x1YFc.mjs.map +1 -0
  77. package/dist/style.mjs +2 -2
  78. package/dist/text-9lwQeqYr.d.mts +33 -0
  79. package/dist/text-9lwQeqYr.d.mts.map +1 -0
  80. package/dist/text-DILrol9j.mjs +32 -0
  81. package/dist/text-DILrol9j.mjs.map +1 -0
  82. package/dist/text-q26V6_Sc.mjs +111 -0
  83. package/dist/text-q26V6_Sc.mjs.map +1 -0
  84. package/dist/text.d.mts +2 -33
  85. package/dist/text.mjs +1 -110
  86. package/dist/{theme.config-CU3B50HN.mjs → theme.config-BptYUq4K.mjs} +4 -4
  87. package/dist/{theme.config-CU3B50HN.mjs.map → theme.config-BptYUq4K.mjs.map} +1 -1
  88. package/dist/themes.mjs +1 -1
  89. package/dist/tree-Bo1afYhe.mjs +73 -0
  90. package/dist/tree-Bo1afYhe.mjs.map +1 -0
  91. package/dist/widget-BkMwhY2p.mjs +40 -0
  92. package/dist/widget-BkMwhY2p.mjs.map +1 -0
  93. package/dist/widget-M7jD8Rgg.d.mts +49 -0
  94. package/dist/widget-M7jD8Rgg.d.mts.map +1 -0
  95. package/dist/widgets/autocomplete.mjs +2 -2
  96. package/dist/widgets/box.mjs +1 -1
  97. package/dist/widgets/code.mjs +7 -7
  98. package/dist/widgets/completions/actions.d.mts +2 -41
  99. package/dist/widgets/completions/actions.mjs +1 -47
  100. package/dist/widgets/completions/files.d.mts +2 -29
  101. package/dist/widgets/completions/files.mjs +1 -41
  102. package/dist/widgets/completions/github.d.mts +2 -64
  103. package/dist/widgets/completions/github.mjs +1 -136
  104. package/dist/widgets/completions/index.d.mts +3 -3
  105. package/dist/widgets/completions/index.mjs +3 -3
  106. package/dist/widgets/diff.d.mts +1 -1
  107. package/dist/widgets/diff.mjs +3 -3
  108. package/dist/widgets/divider.mjs +1 -8
  109. package/dist/widgets/image.d.mts +2 -37
  110. package/dist/widgets/image.mjs +1 -1
  111. package/dist/widgets/input.mjs +1 -496
  112. package/dist/widgets/log.mjs +1 -129
  113. package/dist/widgets/markdown.d.mts +2 -2
  114. package/dist/widgets/markdown.mjs +1 -123
  115. package/dist/widgets/overlay.mjs +1 -17
  116. package/dist/widgets/picker.mjs +1 -1
  117. package/dist/widgets/select.mjs +1 -194
  118. package/dist/widgets/show.mjs +1 -84
  119. package/dist/widgets/text.mjs +1 -31
  120. package/dist/widgets/tree.mjs +1 -72
  121. package/dist/widgets/widget.d.mts +2 -49
  122. package/dist/widgets/widget.mjs +1 -39
  123. package/dist/worker-BvRm4OsW.mjs +2 -0
  124. package/dist/worker-T6SdPzUH.mjs +52 -0
  125. package/dist/worker-T6SdPzUH.mjs.map +1 -0
  126. package/package.json +7 -3
  127. package/dist/client-D6C_uczF.mjs.map +0 -1
  128. package/dist/clipboard.mjs.map +0 -1
  129. package/dist/registry-U654j61Y.mjs.map +0 -1
  130. package/dist/render-DxVLqqB9.mjs +0 -74
  131. package/dist/render-DxVLqqB9.mjs.map +0 -1
  132. package/dist/rolldown-runtime-D7D4PA-g.mjs +0 -13
  133. package/dist/services/logger.mjs.map +0 -1
  134. package/dist/shiki-BrjVUkeh.mjs.map +0 -1
  135. package/dist/text.d.mts.map +0 -1
  136. package/dist/text.mjs.map +0 -1
  137. package/dist/widgets/completions/actions.d.mts.map +0 -1
  138. package/dist/widgets/completions/actions.mjs.map +0 -1
  139. package/dist/widgets/completions/files.d.mts.map +0 -1
  140. package/dist/widgets/completions/files.mjs.map +0 -1
  141. package/dist/widgets/completions/github.d.mts.map +0 -1
  142. package/dist/widgets/completions/github.mjs.map +0 -1
  143. package/dist/widgets/divider.mjs.map +0 -1
  144. package/dist/widgets/image.d.mts.map +0 -1
  145. package/dist/widgets/input.mjs.map +0 -1
  146. package/dist/widgets/log.mjs.map +0 -1
  147. package/dist/widgets/markdown.mjs.map +0 -1
  148. package/dist/widgets/overlay.mjs.map +0 -1
  149. package/dist/widgets/select.mjs.map +0 -1
  150. package/dist/widgets/show.mjs.map +0 -1
  151. package/dist/widgets/text.mjs.map +0 -1
  152. package/dist/widgets/tree.mjs.map +0 -1
  153. package/dist/widgets/widget.d.mts.map +0 -1
  154. package/dist/widgets/widget.mjs.map +0 -1
  155. package/dist/worker-DjHuQSbY.mjs +0 -27
  156. package/dist/worker-DjHuQSbY.mjs.map +0 -1
@@ -0,0 +1,130 @@
1
+ import { n as box } from "./box-DepqUtuo.mjs";
2
+ import { n as text } from "./text-DILrol9j.mjs";
3
+ import { n as markdown } from "./markdown-CTlPe5ks.mjs";
4
+ import { t as widget } from "./widget-BkMwhY2p.mjs";
5
+ import { stringWidth } from "@zaly/shared/ansi";
6
+ import { hasColors } from "@zaly/shared/env";
7
+ //#region src/widgets/log.ts
8
+ /** Per-level default prefix style + icon + color. Matches rekal's
9
+ * `defaultStyles` table, adapted to zaly's theme slots. */
10
+ const defaultLogStyles = {
11
+ cancel: {
12
+ color: "warn",
13
+ icon: "✖ ",
14
+ style: "icon"
15
+ },
16
+ debug: {
17
+ color: "info",
18
+ icon: "⚙ ",
19
+ style: "prompt"
20
+ },
21
+ error: {
22
+ color: "error",
23
+ icon: "✖ ",
24
+ style: "badge",
25
+ textColor: "error"
26
+ },
27
+ fatal: {
28
+ color: "error",
29
+ icon: "☢ ",
30
+ style: "badge"
31
+ },
32
+ info: {
33
+ color: "info",
34
+ icon: "ℹ ",
35
+ style: "icon"
36
+ },
37
+ log: {
38
+ color: "muted",
39
+ icon: "●",
40
+ style: "icon"
41
+ },
42
+ success: {
43
+ color: "success",
44
+ icon: "✔ ",
45
+ style: "icon"
46
+ },
47
+ trace: {
48
+ color: "muted",
49
+ icon: "⠿",
50
+ style: "icon",
51
+ textColor: "muted"
52
+ },
53
+ warn: {
54
+ color: "warn",
55
+ icon: "⚠",
56
+ style: "badge",
57
+ textColor: "warn"
58
+ }
59
+ };
60
+ const noColorStyles = {
61
+ badge: "title",
62
+ icon: "text",
63
+ notif: "text",
64
+ prompt: "text",
65
+ text: "text",
66
+ title: "text"
67
+ };
68
+ function renderPrefix(s, ctx) {
69
+ const style = ctx.style;
70
+ const base = defaultLogStyles[s.level];
71
+ let ls = s.style ?? base.style;
72
+ if (!hasColors) ls = noColorStyles[ls];
73
+ let icon = s.icon ?? base.icon ?? "";
74
+ icon = icon === "" ? "" : `${icon}${" ".repeat(2 - stringWidth(icon))}`;
75
+ const color = s.color ?? base.color ?? "inherit";
76
+ let styledPrefix = "";
77
+ if (ls === "badge") styledPrefix = style.bg(color).fg("black").bold(` ${s.level} `);
78
+ else if (ls === "icon") styledPrefix = style.fg(color)(icon);
79
+ else if (ls === "prompt") styledPrefix = style.fg(color).bold(`${icon} ${s.level}`);
80
+ else if (ls === "title") styledPrefix = style.fg(color).bold(`${s.level}:`);
81
+ else if (ls === "notif") styledPrefix = style.fg(color).bold(`${icon} ${s.title ?? s.level}`);
82
+ if (s.prefix) styledPrefix = s.prefix + styledPrefix;
83
+ if (s.title && ls !== "notif") styledPrefix += style.bold(` ${s.title}`);
84
+ return styledPrefix;
85
+ }
86
+ /**
87
+ * A single log entry — level-styled prefix (icon / badge / prompt / title /
88
+ * plain text) followed by the body content. The body can be any Node, so
89
+ * callers can stack markdown, code, images, etc. inside a log line.
90
+ *
91
+ * ```ts
92
+ * log({ level: "info", content: "hello" })
93
+ * log({ level: "error", content: markdown("**boom**") })
94
+ * ```
95
+ */
96
+ const log = widget((state, ...children) => {
97
+ const base = defaultLogStyles[state.level];
98
+ const color = state.color ?? base.color ?? "inherit";
99
+ const s = state;
100
+ const textColor = state.textColor ?? (s.style === "notif" ? "inherit" : base.textColor);
101
+ const style = {
102
+ style: textColor ? { fg: textColor } : void 0,
103
+ width: "fill"
104
+ };
105
+ if (state.content !== "") children = [state.markdown ?? true ? markdown(state.content, style) : text(state.content, style), ...children];
106
+ return box({
107
+ ...s.style === "notif" ? {
108
+ border: "single",
109
+ borderStyle: { fg: color },
110
+ borderTitle: (ctx) => renderPrefix(state, ctx),
111
+ borderTitleAlign: "center",
112
+ padding: [0, 1],
113
+ width: "fill"
114
+ } : void 0,
115
+ flexDirection: "row",
116
+ gap: 1,
117
+ visible: state.visible
118
+ }, s.style === "notif" ? void 0 : text((ctx) => renderPrefix(state, ctx), {
119
+ flexShrink: 0,
120
+ wrap: "none"
121
+ }), box({
122
+ flexDirection: "column",
123
+ flexGrow: 1,
124
+ gap: 1
125
+ }, ...children));
126
+ });
127
+ //#endregion
128
+ export { log as t };
129
+
130
+ //# sourceMappingURL=log-Djvrxqk0.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-Djvrxqk0.mjs","names":[],"sources":["../src/widgets/log.ts"],"sourcesContent":["import type { LogLevel } from \"@zaly/shared/logger\"\nimport type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Node } from \"../core/node.ts\"\nimport type { State } from \"../core/state.ts\"\nimport type { Color } from \"../style/types.ts\"\nimport type { TextContent } from \"./text.ts\"\n\nimport { stringWidth } from \"@zaly/shared/ansi\"\nimport { hasColors } from \"@zaly/shared/env\"\nimport { box } from \"./box.ts\"\nimport { markdown } from \"./markdown.ts\"\nimport { text } from \"./text.ts\"\nimport { widget } from \"./widget.ts\"\n\nexport type LogStyle = \"badge\" | \"icon\" | \"prompt\" | \"title\" | \"text\" | \"notif\"\n\nexport interface LogState {\n level: LogLevel\n content: TextContent\n title?: string\n /** Rendering of the per-level prefix chunk. Defaults by level. */\n style?: LogStyle\n /** Single-glyph icon for `icon` / `prompt` styles. */\n icon?: string\n /** Theme slot or color name used to tint the prefix. */\n color?: Color\n /** Extra plain text prepended to the auto prefix (unstyled). */\n prefix?: string\n /** Theme slot or color name for the body text. Defaults by level, except */\n textColor?: Color\n markdown?: boolean\n}\n\ninterface LevelDefaults {\n style: LogStyle\n icon?: string\n color?: Color\n textColor?: Color\n}\n\n/** Per-level default prefix style + icon + color. Matches rekal's\n * `defaultStyles` table, adapted to zaly's theme slots. */\nconst defaultLogStyles: Record<LogLevel, LevelDefaults> = {\n cancel: { color: \"warn\", icon: \"✖ \", style: \"icon\" },\n debug: { color: \"info\", icon: \"⚙ \", style: \"prompt\" },\n error: { color: \"error\", icon: \"✖ \", style: \"badge\", textColor: \"error\" },\n fatal: { color: \"error\", icon: \"☢ \", style: \"badge\" },\n info: { color: \"info\", icon: \"ℹ \", style: \"icon\" },\n log: { color: \"muted\", icon: \"●\", style: \"icon\" },\n success: { color: \"success\", icon: \"✔ \", style: \"icon\" },\n trace: { color: \"muted\", icon: \"⠿\", style: \"icon\", textColor: \"muted\" },\n warn: { color: \"warn\", icon: \"⚠\", style: \"badge\", textColor: \"warn\" },\n}\n\nconst noColorStyles: Record<LogStyle, LogStyle> = {\n badge: \"title\",\n icon: \"text\",\n notif: \"text\",\n prompt: \"text\",\n text: \"text\",\n title: \"text\",\n}\n\nfunction renderPrefix(s: LogState, ctx: RenderCtx): string {\n const style = ctx.style\n\n const base = defaultLogStyles[s.level]\n let ls: LogStyle = s.style ?? base.style\n if (!hasColors) ls = noColorStyles[ls]\n\n let icon = s.icon ?? base.icon ?? \"\"\n icon = icon === \"\" ? \"\" : `${icon}${\" \".repeat(2 - stringWidth(icon))}`\n const color: Color = s.color ?? base.color ?? \"inherit\"\n\n // text doesn't get a prefix\n let styledPrefix = \"\"\n if (ls === \"badge\") {\n styledPrefix = style.bg(color).fg(\"black\").bold(` ${s.level} `)\n } else if (ls === \"icon\") {\n styledPrefix = style.fg(color)(icon)\n } else if (ls === \"prompt\") {\n styledPrefix = style.fg(color).bold(`${icon} ${s.level}`)\n } else if (ls === \"title\") {\n styledPrefix = style.fg(color).bold(`${s.level}:`)\n } else if (ls === \"notif\") {\n styledPrefix = style.fg(color).bold(`${icon} ${s.title ?? s.level}`)\n }\n\n if (s.prefix) styledPrefix = s.prefix + styledPrefix\n if (s.title && ls !== \"notif\") styledPrefix += style.bold(` ${s.title}`)\n return styledPrefix\n}\n\n/**\n * A single log entry — level-styled prefix (icon / badge / prompt / title /\n * plain text) followed by the body content. The body can be any Node, so\n * callers can stack markdown, code, images, etc. inside a log line.\n *\n * ```ts\n * log({ level: \"info\", content: \"hello\" })\n * log({ level: \"error\", content: markdown(\"**boom**\") })\n * ```\n */\nexport const log = widget((state: State<LogState>, ...children: Node[]) => {\n const base = defaultLogStyles[state.level]\n const color: Color = state.color ?? base.color ?? \"inherit\"\n const s = state\n const textColor = state.textColor ?? (s.style === \"notif\" ? \"inherit\" : base.textColor)\n const style = {\n style: textColor\n ? {\n fg: textColor,\n }\n : undefined,\n width: \"fill\",\n } as const\n if (state.content !== \"\") {\n children = [\n (state.markdown ?? true) ? markdown(state.content, style) : text(state.content, style),\n ...children,\n ]\n }\n return box(\n {\n ...(s.style === \"notif\"\n ? {\n border: \"single\",\n borderStyle: { fg: color },\n borderTitle: (ctx) => renderPrefix(state, ctx),\n borderTitleAlign: \"center\",\n padding: [0, 1],\n //style: \"overlay\",\n width: \"fill\",\n }\n : undefined),\n flexDirection: \"row\",\n gap: 1,\n visible: state.visible,\n },\n s.style === \"notif\"\n ? undefined\n : text((ctx) => renderPrefix(state, ctx), { flexShrink: 0, wrap: \"none\" }),\n box({ flexDirection: \"column\", flexGrow: 1, gap: 1 }, ...children)\n )\n})\n"],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import { t as Node } from "./node-BZ7f6HzU.mjs";
2
+ import { n as inspectFormat, r as isMarkdown } from "./inspect-DE5goDzB.mjs";
3
+ import { t as log } from "./log-Djvrxqk0.mjs";
4
+ //#region src/services/logger.ts
5
+ const ERR_LEVELS = /* @__PURE__ */ new Set([
6
+ "error",
7
+ "fatal",
8
+ "warn"
9
+ ]);
10
+ function defaultWrite(text, kind) {
11
+ if (typeof process === "undefined") return;
12
+ (kind === "stderr" ? process.stderr : process.stdout).write(text);
13
+ }
14
+ var TuiReporter = class {
15
+ #stream;
16
+ #opts;
17
+ #factory;
18
+ constructor(opts = {}) {
19
+ this.#opts = opts;
20
+ this.#factory = opts.factory ?? ((level, msg) => this.#defaultFactory(level, msg));
21
+ }
22
+ attach(stream) {
23
+ this.#stream = stream;
24
+ return this;
25
+ }
26
+ detach() {
27
+ this.#stream = void 0;
28
+ return this;
29
+ }
30
+ $log({ level, msg }) {
31
+ if (this.#stream) {
32
+ this.#stream.append(() => {
33
+ const node = this.#factory(level, msg);
34
+ return this.#opts.wrap?.(node) ?? node;
35
+ });
36
+ return;
37
+ }
38
+ this.#writeFallback(level, msg);
39
+ }
40
+ #defaultFactory(level, msg) {
41
+ const nodes = msg.filter((m) => m instanceof Node);
42
+ msg = msg.filter((m) => !(m instanceof Node));
43
+ msg = this.#opts.stacktrace ? msg : msg.map((v) => v instanceof Error ? v.message : v);
44
+ if (msg.length && msg.every((m) => typeof m === "string")) msg = [msg.join(" ")];
45
+ let text = msg.length === 1 && typeof msg[0] === "string" ? msg[0] : void 0;
46
+ if (msg.length === 0) text = "";
47
+ const markdown = (this.#opts.markdown ?? true) && text !== void 0 && isMarkdown(text);
48
+ const overrides = this.#opts.styles?.[level] ?? {};
49
+ return log({
50
+ content: text ?? ((ctx) => inspectFormat(msg, {
51
+ ...this.#opts,
52
+ style: ctx.style
53
+ })),
54
+ level,
55
+ markdown,
56
+ ...overrides
57
+ }, ...nodes);
58
+ }
59
+ /** String path for the no-stream fallback — builds a plain inspected
60
+ * line (no prefix chrome) and writes it to stdout/stderr. Keeps the
61
+ * fallback synchronous and ordered. */
62
+ #writeFallback(level, msg) {
63
+ const str = inspectFormat(msg, this.#opts);
64
+ const kind = ERR_LEVELS.has(level) ? "stderr" : "stdout";
65
+ (this.#opts.write ?? defaultWrite)(`${str}\n`, kind);
66
+ }
67
+ };
68
+ //#endregion
69
+ export { TuiReporter as t };
70
+
71
+ //# sourceMappingURL=logger-DDrt03So.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger-DDrt03So.mjs","names":["#opts","#factory","#defaultFactory","#stream","#writeFallback"],"sources":["../src/services/logger.ts"],"sourcesContent":["import type { LogEntry, LogLevel, LogReporter } from \"@zaly/shared/logger\"\nimport type { InspectOpts } from \"../style/inspect.ts\"\nimport type { LogState } from \"../widgets/log.ts\"\n\nimport { Node } from \"../core/node.ts\"\nimport { inspectFormat, isMarkdown } from \"../style/inspect.ts\"\nimport { log } from \"../widgets/log.ts\"\n\n/** Minimal stream surface the logger needs. Stream satisfies this. */\nexport interface LoggerStream {\n append: (node: () => Node) => unknown\n}\n\nexport type LogEntryFactory = (level: LogLevel, msg: unknown[]) => Node\n\nexport type LogStyleOverride = Omit<LogState, \"level\" | \"content\">\n\nexport interface TuiReporterOpts extends InspectOpts {\n /** Render string messages as markdown when they look like it.\n * Default: `true`. */\n markdown?: boolean\n /** Per-level overrides for the default `log()` widget style fields. */\n styles?: Partial<Record<LogLevel, LogStyleOverride>>\n /** Override the node produced per entry. Default uses `log()`. */\n factory?: LogEntryFactory\n wrap?: (node: Node) => Node\n /** Fallback writer for when no stream is attached. Defaults to\n * `process.stdout/stderr`. Injectable for tests. */\n write?: (text: string, kind: \"stdout\" | \"stderr\") => void\n}\n\nconst ERR_LEVELS = new Set<LogLevel>([\"error\", \"fatal\", \"warn\"])\n\nfunction defaultWrite(text: string, kind: \"stdout\" | \"stderr\"): void {\n if (typeof process === \"undefined\") return\n const stream = kind === \"stderr\" ? process.stderr : process.stdout\n stream.write(text)\n}\n\nexport class TuiReporter implements LogReporter {\n #stream?: LoggerStream\n #opts: TuiReporterOpts\n #factory: LogEntryFactory\n\n constructor(opts: TuiReporterOpts = {}) {\n this.#opts = opts\n this.#factory = opts.factory ?? ((level, msg) => this.#defaultFactory(level, msg))\n }\n\n attach(stream: LoggerStream): this {\n this.#stream = stream\n return this\n }\n\n detach(): this {\n this.#stream = undefined\n return this\n }\n\n $log({ level, msg }: LogEntry): void {\n if (this.#stream) {\n this.#stream.append(() => {\n const node = this.#factory(level, msg)\n return this.#opts.wrap?.(node) ?? node\n })\n return\n }\n this.#writeFallback(level, msg)\n }\n\n #defaultFactory(level: LogLevel, msg: unknown[]): Node {\n const nodes = msg.filter((m): m is Node => m instanceof Node)\n msg = msg.filter((m) => !(m instanceof Node))\n\n // Convert Error objects to their message unless stacktrace is requested.\n msg = this.#opts.stacktrace ? msg : msg.map((v) => (v instanceof Error ? v.message : v))\n\n // If all remaining messages are strings, join them into one string for the log content.\n if (msg.length && msg.every((m) => typeof m === \"string\")) msg = [msg.join(\" \")]\n\n // If there's exactly one string message, use it as the log content;\n // otherwise, leave it undefined to be formatted with `inspect()`.\n // Text allow markdown if the message looks like markdown and the option is enabled.\n let text = msg.length === 1 && typeof msg[0] === \"string\" ? msg[0] : undefined\n if (msg.length === 0) text = \"\"\n const markdown = (this.#opts.markdown ?? true) && text !== undefined && isMarkdown(text)\n const overrides = this.#opts.styles?.[level] ?? {}\n return log(\n {\n content: text ?? ((ctx) => inspectFormat(msg, { ...this.#opts, style: ctx.style })),\n level,\n markdown,\n ...overrides,\n },\n ...nodes\n )\n }\n\n /** String path for the no-stream fallback — builds a plain inspected\n * line (no prefix chrome) and writes it to stdout/stderr. Keeps the\n * fallback synchronous and ordered. */\n #writeFallback(level: LogLevel, msg: unknown[]): void {\n const str = inspectFormat(msg, this.#opts)\n const kind: \"stdout\" | \"stderr\" = ERR_LEVELS.has(level) ? \"stderr\" : \"stdout\"\n const write = this.#opts.write ?? defaultWrite\n write(`${str}\\n`, kind)\n }\n}\n"],"mappings":";;;;AA+BA,MAAM,6BAAa,IAAI,IAAc;CAAC;CAAS;CAAS;AAAM,CAAC;AAE/D,SAAS,aAAa,MAAc,MAAiC;CACnE,IAAI,OAAO,YAAY,aAAa;CAEpC,CADe,SAAS,WAAW,QAAQ,SAAS,QAAQ,OAAA,CACrD,MAAM,IAAI;AACnB;AAEA,IAAa,cAAb,MAAgD;CAC9C;CACA;CACA;CAEA,YAAY,OAAwB,CAAC,GAAG;EACtC,KAAKA,QAAQ;EACb,KAAKC,WAAW,KAAK,aAAa,OAAO,QAAQ,KAAKC,gBAAgB,OAAO,GAAG;CAClF;CAEA,OAAO,QAA4B;EACjC,KAAKC,UAAU;EACf,OAAO;CACT;CAEA,SAAe;EACb,KAAKA,UAAU,KAAA;EACf,OAAO;CACT;CAEA,KAAK,EAAE,OAAO,OAAuB;EACnC,IAAI,KAAKA,SAAS;GAChB,KAAKA,QAAQ,aAAa;IACxB,MAAM,OAAO,KAAKF,SAAS,OAAO,GAAG;IACrC,OAAO,KAAKD,MAAM,OAAO,IAAI,KAAK;GACpC,CAAC;GACD;EACF;EACA,KAAKI,eAAe,OAAO,GAAG;CAChC;CAEA,gBAAgB,OAAiB,KAAsB;EACrD,MAAM,QAAQ,IAAI,QAAQ,MAAiB,aAAa,IAAI;EAC5D,MAAM,IAAI,QAAQ,MAAM,EAAE,aAAa,KAAK;EAG5C,MAAM,KAAKJ,MAAM,aAAa,MAAM,IAAI,KAAK,MAAO,aAAa,QAAQ,EAAE,UAAU,CAAE;EAGvF,IAAI,IAAI,UAAU,IAAI,OAAO,MAAM,OAAO,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,KAAK,GAAG,CAAC;EAK/E,IAAI,OAAO,IAAI,WAAW,KAAK,OAAO,IAAI,OAAO,WAAW,IAAI,KAAK,KAAA;EACrE,IAAI,IAAI,WAAW,GAAG,OAAO;EAC7B,MAAM,YAAY,KAAKA,MAAM,YAAY,SAAS,SAAS,KAAA,KAAa,WAAW,IAAI;EACvF,MAAM,YAAY,KAAKA,MAAM,SAAS,UAAU,CAAC;EACjD,OAAO,IACL;GACE,SAAS,UAAU,QAAQ,cAAc,KAAK;IAAE,GAAG,KAAKA;IAAO,OAAO,IAAI;GAAM,CAAC;GACjF;GACA;GACA,GAAG;EACL,GACA,GAAG,KACL;CACF;;;;CAKA,eAAe,OAAiB,KAAsB;EACpD,MAAM,MAAM,cAAc,KAAK,KAAKA,KAAK;EACzC,MAAM,OAA4B,WAAW,IAAI,KAAK,IAAI,WAAW;EAErE,CADc,KAAKA,MAAM,SAAS,aAAA,CAC5B,GAAG,IAAI,KAAK,IAAI;CACxB;AACF"}
@@ -0,0 +1,124 @@
1
+ import { S as unwrap, r as createAsync, w as useContext, y as signal } from "./reactive-f7NpAi69.mjs";
2
+ import { t as Node } from "./node-BZ7f6HzU.mjs";
3
+ import { i as expandTabs, o as formatText, t as calcLayout } from "./text-q26V6_Sc.mjs";
4
+ import { r as textContent } from "./text-DILrol9j.mjs";
5
+ import { t as RenderContext } from "./render-F8pVXN7h.mjs";
6
+ import { n as shikiWorker } from "./client-BBdtbLp4.mjs";
7
+ import { t as codeToAnsi } from "./shiki-BK-v9CtF.mjs";
8
+ import { hasColors } from "@zaly/shared/env";
9
+ //#region src/widgets/markdown.ts
10
+ var Markdown = class extends Node {
11
+ images = /* @__PURE__ */ new Map();
12
+ #renderer;
13
+ #code = /* @__PURE__ */ new Map();
14
+ #update = signal(0);
15
+ #gen = 0;
16
+ #worker;
17
+ #images;
18
+ constructor(state) {
19
+ super(state);
20
+ const context = useContext(RenderContext);
21
+ this.#images = context?.images;
22
+ this.#worker = createAsync(async () => {
23
+ const update = this.#update.get();
24
+ const todo = [...this.#code.values()].filter((c) => c.gen === this.#gen && !c.result);
25
+ if (!todo.length) return update;
26
+ await Promise.all(todo.map(async (req) => {
27
+ req.ac ??= new AbortController();
28
+ req.inflight ??= codeToAnsi(req.code, req.lang, {
29
+ signal: req.ac.signal,
30
+ theme: req.theme
31
+ });
32
+ try {
33
+ req.result = await req.inflight;
34
+ } catch (error) {
35
+ if (req.ac.signal.aborted) {
36
+ if (this.#code.get(req.key) === req) this.#code.delete(req.key);
37
+ } else throw error;
38
+ }
39
+ }));
40
+ return update + 1;
41
+ }, { initialValue: 0 });
42
+ }
43
+ /** Find a highlighted result for a prefix of `code` in the cache. This
44
+ * handles streaming updates where the full code block isn't available yet
45
+ * and prevents flashing un-highlighted text on each update. */
46
+ #streamingHighlight(code, lang, theme) {
47
+ let ret;
48
+ for (const c of this.#code.values()) {
49
+ if (!c.result || c.lang !== lang || c.theme !== theme) continue;
50
+ if (code.startsWith(c.code) && c.code.length > (ret?.code.length ?? 0)) ret = c;
51
+ }
52
+ if (ret) ret.gen = this.#gen;
53
+ return ret?.result ? ret.result + code.slice(ret.code.length) : code;
54
+ }
55
+ #highlight(code, lang, theme) {
56
+ if (!lang) return code;
57
+ const key = shikiWorker.key({
58
+ code,
59
+ lang,
60
+ theme
61
+ });
62
+ const ret = this.#code.get(key);
63
+ if (ret) ret.gen = this.#gen;
64
+ if (ret?.result) return ret.result;
65
+ else if (!ret) this.#code.set(key, {
66
+ code,
67
+ gen: this.#gen,
68
+ key,
69
+ lang,
70
+ theme
71
+ });
72
+ return this.#streamingHighlight(code, lang, theme);
73
+ }
74
+ async _render(ctx) {
75
+ if (!this.#renderer) {
76
+ const { MarkdownRenderer } = await import("./renderer-Dgj_qEOA.mjs");
77
+ this.#renderer = new MarkdownRenderer({
78
+ ...this.state.options,
79
+ parent: this
80
+ });
81
+ }
82
+ let source = await textContent(this.state.content, ctx);
83
+ source = expandTabs(source);
84
+ let formatted;
85
+ if (!hasColors) formatted = this.#renderer.normalizeEol(source, source);
86
+ else {
87
+ this.#gen++;
88
+ formatted = await this.#renderer.render(source, {
89
+ ...ctx,
90
+ highlight: (code, lang) => this.#highlight(code, lang, ctx.style.theme.shiki),
91
+ images: unwrap(this.#images) ?? true
92
+ });
93
+ for (const [k, c] of this.#code.entries()) if (c.gen !== this.#gen) {
94
+ c.ac?.abort();
95
+ if (c.result !== void 0) this.#code.delete(k);
96
+ }
97
+ if (this.#code.values().some((c) => !c.inflight)) {
98
+ this.#update.set(this.#gen);
99
+ this.#worker();
100
+ }
101
+ }
102
+ return formatText(formatted, {
103
+ indent: true,
104
+ style: this.state.style ? ctx.style.add(this.state.style) : void 0,
105
+ width: ctx.width,
106
+ wrap: this.state.wrap,
107
+ wrapBg: true
108
+ });
109
+ }
110
+ async layout(ctx) {
111
+ return calcLayout(await textContent(this.state.content, ctx));
112
+ }
113
+ };
114
+ function markdown(first, style) {
115
+ if (typeof first === "string" || typeof first === "function") return new Markdown({
116
+ content: first,
117
+ ...style
118
+ });
119
+ return new Markdown(first);
120
+ }
121
+ //#endregion
122
+ export { markdown as n, Markdown as t };
123
+
124
+ //# sourceMappingURL=markdown-CTlPe5ks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-CTlPe5ks.mjs","names":["#images","#worker","#update","#code","#gen","#streamingHighlight","#renderer","#highlight"],"sources":["../src/widgets/markdown.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Accessor } from \"../core/reactive.ts\"\nimport type { State } from \"../core/state.ts\"\nimport type { WrapMode } from \"../layout/text.ts\"\nimport type { MarkdownRenderer } from \"../markdown/renderer.ts\"\nimport type { MdOptions } from \"../markdown/types.ts\"\nimport type { ShikiTheme } from \"../shiki/types.ts\"\nimport type { AnyStyle } from \"../style/types.ts\"\nimport type { Image } from \"./image.ts\"\nimport type { TextContent } from \"./text.ts\"\n\nimport { hasColors } from \"@zaly/shared/env\"\nimport { Node } from \"../core/node.ts\"\nimport { createAsync, signal, unwrap, useContext } from \"../core/reactive.ts\"\nimport { RenderContext } from \"../core/render.ts\"\nimport { calcLayout, expandTabs, formatText } from \"../layout/text.ts\"\nimport { shikiWorker } from \"../shiki/client.ts\"\nimport { codeToAnsi } from \"../shiki/shiki.ts\"\nimport { textContent } from \"./text.ts\"\n\nexport interface MarkdownState {\n /** Markdown source. Accepts a plain string or a reactive accessor —\n * pass `signal()` / `memo()` for streaming content that re-parses on\n * each render and subscribes the node to the signal. */\n content: TextContent\n /** Options forwarded to `renderMarkdown`. */\n options?: MdOptions\n /**\n * Enable shiki-backed syntax highlighting for fenced code blocks. Defaults\n * to `true` — code blocks get per-token colors from the shiki theme, with\n * `mdCodeBlock`'s bg applied as a backdrop. Unknown languages fall through\n * as plain text.\n */\n syntax?: boolean\n wrap?: WrapMode\n style?: AnyStyle\n}\n\ntype ShikiCode = {\n key: string\n code: string\n lang: string\n theme?: ShikiTheme\n inflight?: Promise<string>\n ac?: AbortController\n result?: string\n gen: number\n}\n\nexport class Markdown extends Node<MarkdownState> {\n // Image nodes cached per-src per-Markdown-instance. Re-rendering the\n // same markdown (streaming updates) reuses the same `Image` — same\n // `placementId`, which the KGP spec guarantees is a flicker-free\n // move/resize of the existing placement.\n readonly images = new Map<string, Image>()\n\n #renderer?: MarkdownRenderer\n #code = new Map<string, ShikiCode>()\n #update = signal(0)\n #gen = 0\n #worker: Accessor<number>\n #images?: Accessor<boolean>\n\n constructor(state: State<MarkdownState>) {\n super(state)\n\n const context = useContext(RenderContext)\n this.#images = context?.images\n\n this.#worker = createAsync(\n async () => {\n const update = this.#update.get() // track\n const todo = [...this.#code.values()].filter((c) => c.gen === this.#gen && !c.result)\n if (!todo.length) return update // nothing to do, skip\n await Promise.all(\n todo.map(async (req) => {\n req.ac ??= new AbortController()\n req.inflight ??= codeToAnsi(req.code, req.lang, {\n signal: req.ac.signal,\n theme: req.theme,\n })\n try {\n req.result = await req.inflight\n } catch (error) {\n if (req.ac.signal.aborted) {\n if (this.#code.get(req.key) === req) this.#code.delete(req.key)\n } else throw error\n }\n })\n )\n return update + 1\n },\n { initialValue: 0 }\n )\n }\n\n /** Find a highlighted result for a prefix of `code` in the cache. This\n * handles streaming updates where the full code block isn't available yet\n * and prevents flashing un-highlighted text on each update. */\n #streamingHighlight(code: string, lang: string, theme?: ShikiTheme) {\n let ret: ShikiCode | undefined\n for (const c of this.#code.values()) {\n if (!c.result || c.lang !== lang || c.theme !== theme) continue\n if (code.startsWith(c.code) && c.code.length > (ret?.code.length ?? 0)) ret = c\n }\n if (ret) ret.gen = this.#gen // bump gen to keep it alive in cache\n return ret?.result ? ret.result + code.slice(ret.code.length) : code\n }\n\n #highlight(code: string, lang?: string, theme?: ShikiTheme): string {\n if (!lang) return code\n const key = shikiWorker.key({ code, lang, theme })\n const ret = this.#code.get(key)\n if (ret) ret.gen = this.#gen // bump gen to keep it alive in cache\n if (ret?.result) return ret.result\n else if (!ret) this.#code.set(key, { code, gen: this.#gen, key, lang, theme })\n return this.#streamingHighlight(code, lang, theme)\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n if (!this.#renderer) {\n const { MarkdownRenderer } = await import(\"../markdown/renderer.ts\")\n this.#renderer = new MarkdownRenderer({ ...this.state.options, parent: this })\n }\n let source = await textContent(this.state.content, ctx)\n source = expandTabs(source)\n let formatted: string\n\n if (!hasColors) formatted = this.#renderer.normalizeEol(source, source)\n else {\n this.#gen++ // bump generation to track what is still used\n\n formatted = await this.#renderer.render(source, {\n ...ctx,\n highlight: (code, lang) => this.#highlight(code, lang, ctx.style.theme.shiki),\n images: unwrap(this.#images) ?? true,\n })\n\n // prune old entries\n for (const [k, c] of this.#code.entries())\n if (c.gen !== this.#gen) {\n c.ac?.abort()\n if (c.result !== undefined) this.#code.delete(k)\n }\n\n // Trigger the worker if needed\n if (this.#code.values().some((c) => !c.inflight)) {\n this.#update.set(this.#gen) // trigger worker\n this.#worker() // tracked\n }\n }\n\n return formatText(formatted, {\n indent: true,\n style: this.state.style ? ctx.style.add(this.state.style) : undefined,\n width: ctx.width,\n wrap: this.state.wrap,\n wrapBg: true,\n })\n }\n\n override async layout(ctx: RenderCtx) {\n return calcLayout(await textContent(this.state.content, ctx))\n }\n}\n\n/**\n * Render a markdown string as a TUI node. Produces ANSI-styled text that\n * resolves per-element styling through theme slots (`mdHeading1`, `mdCode`,\n * `mdLink`, …). Links become clickable in terminals that support OSC 8.\n *\n * ```ts\n * markdown(\"# Hello\\n\\nThis is **bold** and *italic*.\")\n * markdown({ content, wrap: \"word\", fg: \"fg\" })\n * ```\n */\nexport function markdown(\n content: TextContent,\n style?: Omit<State<MarkdownState>, \"content\">\n): Markdown\nexport function markdown(state: State<MarkdownState>): Markdown\nexport function markdown(\n first: TextContent | MarkdownState,\n style?: Omit<State<MarkdownState>, \"content\">\n): Markdown {\n // Plain strings and accessor functions go through the content path;\n // a non-function object is the full state form.\n if (typeof first === \"string\" || typeof first === \"function\") {\n return new Markdown({ content: first, ...style })\n }\n return new Markdown(first)\n}\n"],"mappings":";;;;;;;;;AAiDA,IAAa,WAAb,cAA8B,KAAoB;CAKhD,yBAAkB,IAAI,IAAmB;CAEzC;CACA,wBAAQ,IAAI,IAAuB;CACnC,UAAU,OAAO,CAAC;CAClB,OAAO;CACP;CACA;CAEA,YAAY,OAA6B;EACvC,MAAM,KAAK;EAEX,MAAM,UAAU,WAAW,aAAa;EACxC,KAAKA,UAAU,SAAS;EAExB,KAAKC,UAAU,YACb,YAAY;GACV,MAAM,SAAS,KAAKC,QAAQ,IAAI;GAChC,MAAM,OAAO,CAAC,GAAG,KAAKC,MAAM,OAAO,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,QAAQ,KAAKC,QAAQ,CAAC,EAAE,MAAM;GACpF,IAAI,CAAC,KAAK,QAAQ,OAAO;GACzB,MAAM,QAAQ,IACZ,KAAK,IAAI,OAAO,QAAQ;IACtB,IAAI,OAAO,IAAI,gBAAgB;IAC/B,IAAI,aAAa,WAAW,IAAI,MAAM,IAAI,MAAM;KAC9C,QAAQ,IAAI,GAAG;KACf,OAAO,IAAI;IACb,CAAC;IACD,IAAI;KACF,IAAI,SAAS,MAAM,IAAI;IACzB,SAAS,OAAO;KACd,IAAI,IAAI,GAAG,OAAO;UACZ,KAAKD,MAAM,IAAI,IAAI,GAAG,MAAM,KAAK,KAAKA,MAAM,OAAO,IAAI,GAAG;KAAA,OACzD,MAAM;IACf;GACF,CAAC,CACH;GACA,OAAO,SAAS;EAClB,GACA,EAAE,cAAc,EAAE,CACpB;CACF;;;;CAKA,oBAAoB,MAAc,MAAc,OAAoB;EAClE,IAAI;EACJ,KAAK,MAAM,KAAK,KAAKA,MAAM,OAAO,GAAG;GACnC,IAAI,CAAC,EAAE,UAAU,EAAE,SAAS,QAAQ,EAAE,UAAU,OAAO;GACvD,IAAI,KAAK,WAAW,EAAE,IAAI,KAAK,EAAE,KAAK,UAAU,KAAK,KAAK,UAAU,IAAI,MAAM;EAChF;EACA,IAAI,KAAK,IAAI,MAAM,KAAKC;EACxB,OAAO,KAAK,SAAS,IAAI,SAAS,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI;CAClE;CAEA,WAAW,MAAc,MAAe,OAA4B;EAClE,IAAI,CAAC,MAAM,OAAO;EAClB,MAAM,MAAM,YAAY,IAAI;GAAE;GAAM;GAAM;EAAM,CAAC;EACjD,MAAM,MAAM,KAAKD,MAAM,IAAI,GAAG;EAC9B,IAAI,KAAK,IAAI,MAAM,KAAKC;EACxB,IAAI,KAAK,QAAQ,OAAO,IAAI;OACvB,IAAI,CAAC,KAAK,KAAKD,MAAM,IAAI,KAAK;GAAE;GAAM,KAAK,KAAKC;GAAM;GAAK;GAAM;EAAM,CAAC;EAC7E,OAAO,KAAKC,oBAAoB,MAAM,MAAM,KAAK;CACnD;CAEA,MAAgB,QAAQ,KAAmC;EACzD,IAAI,CAAC,KAAKC,WAAW;GACnB,MAAM,EAAE,qBAAqB,MAAM,OAAO;GAC1C,KAAKA,YAAY,IAAI,iBAAiB;IAAE,GAAG,KAAK,MAAM;IAAS,QAAQ;GAAK,CAAC;EAC/E;EACA,IAAI,SAAS,MAAM,YAAY,KAAK,MAAM,SAAS,GAAG;EACtD,SAAS,WAAW,MAAM;EAC1B,IAAI;EAEJ,IAAI,CAAC,WAAW,YAAY,KAAKA,UAAU,aAAa,QAAQ,MAAM;OACjE;GACH,KAAKF;GAEL,YAAY,MAAM,KAAKE,UAAU,OAAO,QAAQ;IAC9C,GAAG;IACH,YAAY,MAAM,SAAS,KAAKC,WAAW,MAAM,MAAM,IAAI,MAAM,MAAM,KAAK;IAC5E,QAAQ,OAAO,KAAKP,OAAO,KAAK;GAClC,CAAC;GAGD,KAAK,MAAM,CAAC,GAAG,MAAM,KAAKG,MAAM,QAAQ,GACtC,IAAI,EAAE,QAAQ,KAAKC,MAAM;IACvB,EAAE,IAAI,MAAM;IACZ,IAAI,EAAE,WAAW,KAAA,GAAW,KAAKD,MAAM,OAAO,CAAC;GACjD;GAGF,IAAI,KAAKA,MAAM,OAAO,CAAC,CAAC,MAAM,MAAM,CAAC,EAAE,QAAQ,GAAG;IAChD,KAAKD,QAAQ,IAAI,KAAKE,IAAI;IAC1B,KAAKH,QAAQ;GACf;EACF;EAEA,OAAO,WAAW,WAAW;GAC3B,QAAQ;GACR,OAAO,KAAK,MAAM,QAAQ,IAAI,MAAM,IAAI,KAAK,MAAM,KAAK,IAAI,KAAA;GAC5D,OAAO,IAAI;GACX,MAAM,KAAK,MAAM;GACjB,QAAQ;EACV,CAAC;CACH;CAEA,MAAe,OAAO,KAAgB;EACpC,OAAO,WAAW,MAAM,YAAY,KAAK,MAAM,SAAS,GAAG,CAAC;CAC9D;AACF;AAiBA,SAAgB,SACd,OACA,OACU;CAGV,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAChD,OAAO,IAAI,SAAS;EAAE,SAAS;EAAO,GAAG;CAAM,CAAC;CAElD,OAAO,IAAI,SAAS,KAAK;AAC3B"}
package/dist/markdown.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as MarkdownRenderer } from "./renderer-CdLCkJB-.mjs";
1
+ import { t as MarkdownRenderer } from "./renderer-qSMVeNSV.mjs";
2
2
  export { MarkdownRenderer };
@@ -0,0 +1,18 @@
1
+ import { n as box } from "./box-DepqUtuo.mjs";
2
+ //#region src/widgets/overlay.ts
3
+ function overlay(state, ...children) {
4
+ const node = box({
5
+ visible: false,
6
+ ...state
7
+ }, ...children);
8
+ node.withActions({ "overlay.close": {
9
+ desc: "Close overlay",
10
+ fn: () => node.state.removeOnClose ?? true ? node.ctx?.overlay.remove(node) : node.hide(),
11
+ keys: ["esc", "ctrl-c"]
12
+ } });
13
+ return node;
14
+ }
15
+ //#endregion
16
+ export { overlay as t };
17
+
18
+ //# sourceMappingURL=overlay-9xNgsuuy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-9xNgsuuy.mjs","names":[],"sources":["../src/widgets/overlay.ts"],"sourcesContent":["import type { Emitter } from \"@zaly/shared\"\nimport type { Node } from \"../core/node.ts\"\nimport type { State } from \"../core/state.ts\"\nimport type { Box, BoxStyle } from \"./box.ts\"\n\nimport { box } from \"./box.ts\"\n\nexport interface OverlayState {\n /** Absolute column (1-based) of the overlay's left edge. */\n x: number\n /** Absolute row (1-based) of the overlay's top edge. */\n y: number\n /** Higher zIndex paints on top. Default: 0. */\n zIndex?: number\n verticalAnchor?: \"top\" | \"center\" | \"bottom\"\n horizontalAnchor?: \"left\" | \"center\" | \"right\"\n relative?: \"screen\" | \"ui\" | \"stream\"\n /** If true, the overlay will be automatically removed from the renderer when closed.\n * When false, the overlay will remain in the renderer but will be hidden.\n * Default: true. */\n removeOnClose?: boolean\n}\n\ntype OverlayEvents = {\n close: {}\n}\n\nexport type Overlay<T extends Node[] = Node[]> = Box<OverlayState> & {\n children: T\n} & Emitter<OverlayEvents>\n\nexport function overlay<T extends Node[] = Node[]>(\n state: State<OverlayState & BoxStyle>,\n ...children: T\n): Overlay<T> {\n const node = box({ visible: false, ...state }, ...children) as Overlay<T>\n node.withActions({\n \"overlay.close\": {\n desc: \"Close overlay\",\n fn: () => ((node.state.removeOnClose ?? true) ? node.ctx?.overlay.remove(node) : node.hide()),\n keys: [\"esc\", \"ctrl-c\"],\n },\n })\n return node\n}\n"],"mappings":";;AA+BA,SAAgB,QACd,OACA,GAAG,UACS;CACZ,MAAM,OAAO,IAAI;EAAE,SAAS;EAAO,GAAG;CAAM,GAAG,GAAG,QAAQ;CAC1D,KAAK,YAAY,EACf,iBAAiB;EACf,MAAM;EACN,UAAY,KAAK,MAAM,iBAAiB,OAAQ,KAAK,KAAK,QAAQ,OAAO,IAAI,IAAI,KAAK,KAAK;EAC3F,MAAM,CAAC,OAAO,QAAQ;CACxB,EACF,CAAC;CACD,OAAO;AACT"}
@@ -1,8 +1,8 @@
1
1
  import { S as unwrap, f as effect, h as memo, s as createProgressive, x as untrack } from "./reactive-f7NpAi69.mjs";
2
- import { widget } from "./widgets/widget.mjs";
3
- import { Input } from "./widgets/input.mjs";
4
- import { select } from "./widgets/select.mjs";
5
- import { tree } from "./widgets/tree.mjs";
2
+ import { t as widget } from "./widget-BkMwhY2p.mjs";
3
+ import { t as Input } from "./input-CRBuTrsL.mjs";
4
+ import { n as select } from "./select-m7NE6Rwa.mjs";
5
+ import { t as tree } from "./tree-Bo1afYhe.mjs";
6
6
  import { sliceAnsi, stripAnsi } from "@zaly/shared/ansi";
7
7
  import { TopK } from "@zaly/shared/minheap";
8
8
  //#region src/search/score.ts
@@ -618,4 +618,4 @@ const picker = widget((props) => {
618
618
  //#endregion
619
619
  export { picker as t };
620
620
 
621
- //# sourceMappingURL=picker-ndVVt6qF.mjs.map
621
+ //# sourceMappingURL=picker-cH-rc7-X.mjs.map