@zaly/tui 0.0.4

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 (228) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/assets/schemas/theme.schema.json +899 -0
  4. package/assets/themes/LICENSE-tokyonight.txt +201 -0
  5. package/assets/themes/NOTICES.md +69 -0
  6. package/assets/themes/ayu-dark.json +119 -0
  7. package/assets/themes/catppuccin-frappe.json +124 -0
  8. package/assets/themes/catppuccin-latte.json +124 -0
  9. package/assets/themes/catppuccin-macchiato.json +124 -0
  10. package/assets/themes/catppuccin-mocha.json +124 -0
  11. package/assets/themes/dracula-soft.json +119 -0
  12. package/assets/themes/dracula.json +119 -0
  13. package/assets/themes/everforest-dark.json +118 -0
  14. package/assets/themes/everforest-light.json +118 -0
  15. package/assets/themes/github-dark.json +123 -0
  16. package/assets/themes/github-light.json +123 -0
  17. package/assets/themes/gruvbox-dark-medium.json +112 -0
  18. package/assets/themes/kanagawa-dragon.json +115 -0
  19. package/assets/themes/kanagawa-wave.json +115 -0
  20. package/assets/themes/material-theme-palenight.json +114 -0
  21. package/assets/themes/min-dark.json +55 -0
  22. package/assets/themes/min-light.json +59 -0
  23. package/assets/themes/monokai.json +116 -0
  24. package/assets/themes/night-owl.json +116 -0
  25. package/assets/themes/nord.json +101 -0
  26. package/assets/themes/one-dark-pro.json +110 -0
  27. package/assets/themes/one-light.json +108 -0
  28. package/assets/themes/poimandres.json +123 -0
  29. package/assets/themes/rose-pine.json +98 -0
  30. package/assets/themes/solarized-dark.json +116 -0
  31. package/assets/themes/solarized-light.json +116 -0
  32. package/assets/themes/synthwave-84.json +100 -0
  33. package/assets/themes/tokyonight-day.json +157 -0
  34. package/assets/themes/tokyonight-moon.json +157 -0
  35. package/assets/themes/tokyonight-night.json +157 -0
  36. package/assets/themes/tokyonight-storm.json +157 -0
  37. package/assets/themes/vesper.json +103 -0
  38. package/assets/themes/vitesse-dark.json +126 -0
  39. package/assets/themes/vitesse-light.json +126 -0
  40. package/dist/ansi-Clq0ozyA.mjs +206 -0
  41. package/dist/ansi-Clq0ozyA.mjs.map +1 -0
  42. package/dist/ansi.d.mts +48 -0
  43. package/dist/ansi.d.mts.map +1 -0
  44. package/dist/ansi.mjs +2 -0
  45. package/dist/autocomplete-Dfw-yQDa.d.mts +100 -0
  46. package/dist/autocomplete-Dfw-yQDa.d.mts.map +1 -0
  47. package/dist/box-DyaByEiG.mjs +386 -0
  48. package/dist/box-DyaByEiG.mjs.map +1 -0
  49. package/dist/builder-D49ECBEf.mjs +385 -0
  50. package/dist/builder-D49ECBEf.mjs.map +1 -0
  51. package/dist/callbacks-CNjGNxVw.mjs +279 -0
  52. package/dist/callbacks-CNjGNxVw.mjs.map +1 -0
  53. package/dist/client-D6C_uczF.mjs +142 -0
  54. package/dist/client-D6C_uczF.mjs.map +1 -0
  55. package/dist/clipboard.d.mts +104 -0
  56. package/dist/clipboard.d.mts.map +1 -0
  57. package/dist/clipboard.mjs +404 -0
  58. package/dist/clipboard.mjs.map +1 -0
  59. package/dist/flex-Bguo-fUe.mjs +202 -0
  60. package/dist/flex-Bguo-fUe.mjs.map +1 -0
  61. package/dist/image-Cm5T-uw-.mjs +108 -0
  62. package/dist/image-Cm5T-uw-.mjs.map +1 -0
  63. package/dist/image.d.mts +123 -0
  64. package/dist/image.d.mts.map +1 -0
  65. package/dist/image.mjs +2 -0
  66. package/dist/index.d.mts +64 -0
  67. package/dist/index.d.mts.map +1 -0
  68. package/dist/index.mjs +222 -0
  69. package/dist/index.mjs.map +1 -0
  70. package/dist/input-B5Vy-iaa.d.mts +141 -0
  71. package/dist/input-B5Vy-iaa.d.mts.map +1 -0
  72. package/dist/inspect-D1d9t-ni.mjs +101 -0
  73. package/dist/inspect-D1d9t-ni.mjs.map +1 -0
  74. package/dist/inspect-D6FW_QUo.d.mts +67 -0
  75. package/dist/inspect-D6FW_QUo.d.mts.map +1 -0
  76. package/dist/kitty-JbCJC0iQ.mjs +673 -0
  77. package/dist/kitty-JbCJC0iQ.mjs.map +1 -0
  78. package/dist/markdown.d.mts +24 -0
  79. package/dist/markdown.d.mts.map +1 -0
  80. package/dist/markdown.mjs +2 -0
  81. package/dist/md.bun.d.mts +14 -0
  82. package/dist/md.bun.d.mts.map +1 -0
  83. package/dist/md.bun.mjs +28 -0
  84. package/dist/md.bun.mjs.map +1 -0
  85. package/dist/md.node.d.mts +14 -0
  86. package/dist/md.node.d.mts.map +1 -0
  87. package/dist/md.node.mjs +126 -0
  88. package/dist/md.node.mjs.map +1 -0
  89. package/dist/node-BZ7f6HzU.mjs +316 -0
  90. package/dist/node-BZ7f6HzU.mjs.map +1 -0
  91. package/dist/picker-D8OLb6kZ.d.mts +36 -0
  92. package/dist/picker-D8OLb6kZ.d.mts.map +1 -0
  93. package/dist/picker-ndVVt6qF.mjs +621 -0
  94. package/dist/picker-ndVVt6qF.mjs.map +1 -0
  95. package/dist/queries-DH3bj74K.d.mts +1963 -0
  96. package/dist/queries-DH3bj74K.d.mts.map +1 -0
  97. package/dist/reactive-f7NpAi69.mjs +623 -0
  98. package/dist/reactive-f7NpAi69.mjs.map +1 -0
  99. package/dist/registry-U654j61Y.mjs +356 -0
  100. package/dist/registry-U654j61Y.mjs.map +1 -0
  101. package/dist/render-DxVLqqB9.mjs +74 -0
  102. package/dist/render-DxVLqqB9.mjs.map +1 -0
  103. package/dist/renderer-CdLCkJB-.mjs +42 -0
  104. package/dist/renderer-CdLCkJB-.mjs.map +1 -0
  105. package/dist/renderer-CxL4xbkl.mjs +2644 -0
  106. package/dist/renderer-CxL4xbkl.mjs.map +1 -0
  107. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  108. package/dist/search-FvGnswRl.d.mts +49 -0
  109. package/dist/search-FvGnswRl.d.mts.map +1 -0
  110. package/dist/select-CbmAZdpt.d.mts +116 -0
  111. package/dist/select-CbmAZdpt.d.mts.map +1 -0
  112. package/dist/services/logger.d.mts +2 -0
  113. package/dist/services/logger.mjs +71 -0
  114. package/dist/services/logger.mjs.map +1 -0
  115. package/dist/services/notifier.d.mts +17 -0
  116. package/dist/services/notifier.d.mts.map +1 -0
  117. package/dist/services/notifier.mjs +71 -0
  118. package/dist/services/notifier.mjs.map +1 -0
  119. package/dist/services/picker.d.mts +36 -0
  120. package/dist/services/picker.d.mts.map +1 -0
  121. package/dist/services/picker.mjs +137 -0
  122. package/dist/services/picker.mjs.map +1 -0
  123. package/dist/services/prompt.d.mts +30 -0
  124. package/dist/services/prompt.d.mts.map +1 -0
  125. package/dist/services/prompt.mjs +83 -0
  126. package/dist/services/prompt.mjs.map +1 -0
  127. package/dist/shiki-BrjVUkeh.mjs +423 -0
  128. package/dist/shiki-BrjVUkeh.mjs.map +1 -0
  129. package/dist/size-D8JogYLy.mjs +34 -0
  130. package/dist/size-D8JogYLy.mjs.map +1 -0
  131. package/dist/style.d.mts +10 -0
  132. package/dist/style.d.mts.map +1 -0
  133. package/dist/style.mjs +4 -0
  134. package/dist/text.d.mts +33 -0
  135. package/dist/text.d.mts.map +1 -0
  136. package/dist/text.mjs +111 -0
  137. package/dist/text.mjs.map +1 -0
  138. package/dist/theme.config-CU3B50HN.mjs +832 -0
  139. package/dist/theme.config-CU3B50HN.mjs.map +1 -0
  140. package/dist/themes.d.mts +113 -0
  141. package/dist/themes.d.mts.map +1 -0
  142. package/dist/themes.mjs +2 -0
  143. package/dist/tree-C28QOVIK.d.mts +23 -0
  144. package/dist/tree-C28QOVIK.d.mts.map +1 -0
  145. package/dist/types-B9Eh7k2v.d.mts +212 -0
  146. package/dist/types-B9Eh7k2v.d.mts.map +1 -0
  147. package/dist/types-D3jk1rtk.d.mts +140 -0
  148. package/dist/types-D3jk1rtk.d.mts.map +1 -0
  149. package/dist/utils-3M4D_AXZ.mjs +40 -0
  150. package/dist/utils-3M4D_AXZ.mjs.map +1 -0
  151. package/dist/widgets/autocomplete.d.mts +2 -0
  152. package/dist/widgets/autocomplete.mjs +165 -0
  153. package/dist/widgets/autocomplete.mjs.map +1 -0
  154. package/dist/widgets/box.d.mts +2 -0
  155. package/dist/widgets/box.mjs +2 -0
  156. package/dist/widgets/code.d.mts +48 -0
  157. package/dist/widgets/code.d.mts.map +1 -0
  158. package/dist/widgets/code.mjs +59 -0
  159. package/dist/widgets/code.mjs.map +1 -0
  160. package/dist/widgets/completions/actions.d.mts +41 -0
  161. package/dist/widgets/completions/actions.d.mts.map +1 -0
  162. package/dist/widgets/completions/actions.mjs +48 -0
  163. package/dist/widgets/completions/actions.mjs.map +1 -0
  164. package/dist/widgets/completions/files.d.mts +29 -0
  165. package/dist/widgets/completions/files.d.mts.map +1 -0
  166. package/dist/widgets/completions/files.mjs +42 -0
  167. package/dist/widgets/completions/files.mjs.map +1 -0
  168. package/dist/widgets/completions/github.d.mts +64 -0
  169. package/dist/widgets/completions/github.d.mts.map +1 -0
  170. package/dist/widgets/completions/github.mjs +137 -0
  171. package/dist/widgets/completions/github.mjs.map +1 -0
  172. package/dist/widgets/completions/index.d.mts +4 -0
  173. package/dist/widgets/completions/index.mjs +4 -0
  174. package/dist/widgets/diff.d.mts +57 -0
  175. package/dist/widgets/diff.d.mts.map +1 -0
  176. package/dist/widgets/diff.mjs +199 -0
  177. package/dist/widgets/diff.mjs.map +1 -0
  178. package/dist/widgets/divider.d.mts +11 -0
  179. package/dist/widgets/divider.d.mts.map +1 -0
  180. package/dist/widgets/divider.mjs +9 -0
  181. package/dist/widgets/divider.mjs.map +1 -0
  182. package/dist/widgets/image.d.mts +37 -0
  183. package/dist/widgets/image.d.mts.map +1 -0
  184. package/dist/widgets/image.mjs +77 -0
  185. package/dist/widgets/image.mjs.map +1 -0
  186. package/dist/widgets/input.d.mts +2 -0
  187. package/dist/widgets/input.mjs +497 -0
  188. package/dist/widgets/input.mjs.map +1 -0
  189. package/dist/widgets/log.d.mts +2 -0
  190. package/dist/widgets/log.mjs +130 -0
  191. package/dist/widgets/log.mjs.map +1 -0
  192. package/dist/widgets/markdown.d.mts +45 -0
  193. package/dist/widgets/markdown.d.mts.map +1 -0
  194. package/dist/widgets/markdown.mjs +124 -0
  195. package/dist/widgets/markdown.mjs.map +1 -0
  196. package/dist/widgets/overlay.d.mts +2 -0
  197. package/dist/widgets/overlay.mjs +18 -0
  198. package/dist/widgets/overlay.mjs.map +1 -0
  199. package/dist/widgets/picker.d.mts +2 -0
  200. package/dist/widgets/picker.mjs +2 -0
  201. package/dist/widgets/progress.d.mts +48 -0
  202. package/dist/widgets/progress.d.mts.map +1 -0
  203. package/dist/widgets/progress.mjs +48 -0
  204. package/dist/widgets/progress.mjs.map +1 -0
  205. package/dist/widgets/select.d.mts +2 -0
  206. package/dist/widgets/select.mjs +195 -0
  207. package/dist/widgets/select.mjs.map +1 -0
  208. package/dist/widgets/show.d.mts +55 -0
  209. package/dist/widgets/show.d.mts.map +1 -0
  210. package/dist/widgets/show.mjs +85 -0
  211. package/dist/widgets/show.mjs.map +1 -0
  212. package/dist/widgets/spinner.d.mts +65 -0
  213. package/dist/widgets/spinner.d.mts.map +1 -0
  214. package/dist/widgets/spinner.mjs +147 -0
  215. package/dist/widgets/spinner.mjs.map +1 -0
  216. package/dist/widgets/text.d.mts +2 -0
  217. package/dist/widgets/text.mjs +32 -0
  218. package/dist/widgets/text.mjs.map +1 -0
  219. package/dist/widgets/tree.d.mts +2 -0
  220. package/dist/widgets/tree.mjs +73 -0
  221. package/dist/widgets/tree.mjs.map +1 -0
  222. package/dist/widgets/widget.d.mts +49 -0
  223. package/dist/widgets/widget.d.mts.map +1 -0
  224. package/dist/widgets/widget.mjs +40 -0
  225. package/dist/widgets/widget.mjs.map +1 -0
  226. package/dist/worker-DjHuQSbY.mjs +27 -0
  227. package/dist/worker-DjHuQSbY.mjs.map +1 -0
  228. package/package.json +117 -0
@@ -0,0 +1,141 @@
1
+ import { Nt as Size, P as RenderCtx, Z as StyleState, f as BaseEvents, nt as Reactive, p as Node } from "./queries-DH3bj74K.mjs";
2
+ import { a as StyleBuilder } from "./inspect-D6FW_QUo.mjs";
3
+ import { MaybePromise } from "@zaly/shared";
4
+ import { DetectedFile } from "@zaly/shared/detect";
5
+ //#region src/widgets/input.d.ts
6
+ interface InputState extends StyleState {
7
+ /** Current text content. May include `\n` for multi-line input. */
8
+ value?: string;
9
+ /** Shown dim when `value` is empty. */
10
+ placeholder?: Reactive<string | undefined>;
11
+ /** Cursor position as a char index in `value`. Clamped to `[0, value.length]`. */
12
+ cursor?: number;
13
+ /** Render width. Defaults to `fill`. */
14
+ width?: Size;
15
+ /** Submitted input history, newest last. */
16
+ history?: readonly string[];
17
+ /** Threshold for showing pasted content as an attachment rather than raw text */
18
+ pasteMaxLines?: number;
19
+ pasteMaxChars?: number;
20
+ canAttach?: (file: InputAttachment) => boolean;
21
+ format?: (value: string, ctx: {
22
+ style: StyleBuilder;
23
+ }) => MaybePromise<string>;
24
+ validate?: (value: string) => boolean;
25
+ }
26
+ type InputValue = {
27
+ value: string;
28
+ attachments: InputAttachment[];
29
+ };
30
+ /** A clipboard or bracketed paste that exceeds the `pasteMax*` thresholds. **/
31
+ type Paste = {
32
+ type: "paste";
33
+ text: string;
34
+ };
35
+ /** A file or image attachment detected from the clipboard. */
36
+ type InputAttachment = DetectedFile & {
37
+ path: string;
38
+ };
39
+ type InputEvents = BaseEvents & {
40
+ /** Fired when the submitted history changes. */
41
+ history: {
42
+ history: string[];
43
+ added: string;
44
+ };
45
+ /** Fired when plain Enter is pressed. Payload is the current value. */
46
+ submit: {
47
+ value: string;
48
+ attachments: InputAttachment[];
49
+ };
50
+ /** Fired when the user pastes a non-text resource via the
51
+ * `input.paste` action. Images and file references both land here,
52
+ * discriminated by `attachment.kind`. One event fires per image
53
+ * paste; one per file in a multi-file paste.
54
+ *
55
+ * Wrapped under `attachment` because `InputAttachment` carries its
56
+ * own `type` field (MIME) that would shadow the envelope's `type`
57
+ * discriminator if spread directly. */
58
+ attach: {
59
+ attachment: InputAttachment;
60
+ };
61
+ };
62
+ /**
63
+ * Multi-line text input with auto-grow.
64
+ *
65
+ * Editing commands (`cursorLeft`, `deleteWordBack`, `submit`, …) live on
66
+ * `this.actions` as zero-arg methods. The input router maps keymap
67
+ * bindings like `"input.cursorLeft"` onto those methods — users bind
68
+ * different keys by configuring the keymap, not by patching the class.
69
+ * The methods are also callable directly (`input.actions.submit()`),
70
+ * which is handy in tests or for higher-level macros.
71
+ *
72
+ * What this class *still* handles via its `key` event listener:
73
+ * - **Printable character insertion.** An unbound keystroke whose
74
+ * `text` is set and has no ctrl/alt/meta modifier becomes a literal
75
+ * insert at the cursor. There's no action for every printable char
76
+ * in the keymap; the raw-key fallback handles them.
77
+ * - **Paste events.** Whole payload inserted at cursor; always.
78
+ *
79
+ * Everything else (navigation, editing, submit/newline) goes through
80
+ * the router → actions pipeline. Unbound non-printable keys fall back
81
+ * to `emit("key", …)` and bubble to the parent chain.
82
+ *
83
+ * Rendering word-wraps each logical line to `ctx.width`, so long
84
+ * messages naturally grow vertically. The UI surface resizes its
85
+ * reserved footer when the Input's row count changes, so the stream
86
+ * above shifts accordingly.
87
+ */
88
+ declare class Input extends Node<InputState, InputEvents> {
89
+ #private;
90
+ /** Class-level scope tag used by the input router to bind keymaps. */
91
+ static readonly type = "input";
92
+ readonly type = "input";
93
+ /**
94
+ * Editing actions. Parameterless — they close over `this` — so both
95
+ * the router (via keymap dispatch) and application code can invoke
96
+ * them. Add to the keymap in `src/input/actions.ts` to give them
97
+ * default key bindings.
98
+ */
99
+ actions: {
100
+ "input.cursorDown": () => void;
101
+ "input.cursorLeft": () => void;
102
+ "input.cursorLineEnd": () => void;
103
+ "input.cursorLineStart": () => void;
104
+ "input.cursorRight": () => void;
105
+ "input.cursorUp": () => void;
106
+ "input.deleteCharBack": () => void;
107
+ "input.deleteCharForward": () => void;
108
+ "input.deleteWordBack": () => void;
109
+ "input.insertNewline": () => void;
110
+ "input.insertTab": () => void;
111
+ "input.paste": () => void;
112
+ "input.submit": () => void;
113
+ };
114
+ constructor(initial?: InputState);
115
+ get history(): readonly string[];
116
+ set history(v: readonly string[]);
117
+ attach(att: InputAttachment | Paste): void;
118
+ paste(text: string): void;
119
+ insert(text: string): void;
120
+ replace(text: string): void;
121
+ /** Consume the input's current value and attachments.
122
+ * Pastes are replaced inline with their text; file/image
123
+ * attachments are returned in the `attachments` array and removed from the value. */
124
+ consume(): InputValue;
125
+ historyAdd(value: string): void;
126
+ protected _render(ctx: RenderCtx): Promise<string[]>;
127
+ }
128
+ /**
129
+ * Factory for `Input`. All fields optional; default is an empty,
130
+ * focusable input that fills `ctx.width` and has no placeholder.
131
+ *
132
+ * ```ts
133
+ * input({ placeholder: "type a message…" })
134
+ * const i = input({ value: "draft" })
135
+ * i.on("submit", (text) => console.log("user typed", text))
136
+ * ```
137
+ */
138
+ declare function input(state?: InputState): Input;
139
+ //#endregion
140
+ export { InputValue as a, InputState as i, InputAttachment as n, input as o, InputEvents as r, Input as t };
141
+ //# sourceMappingURL=input-B5Vy-iaa.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-B5Vy-iaa.d.mts","names":[],"sources":["../src/widgets/input.ts"],"mappings":";;;;;UAoBiB,mBAAmB;;EAElC;;EAEA,cAAc;;EAEd;;EAEA,QAAQ;;EAER;;EAEA;EACA;EACA,aAAa,MAAM;EACnB,UAAU,eAAe;IAAO,OAAO;QAAmB;EAC1D,YAAY;;KAGF;EAAe;EAAe,aAAa;;;KAMlD;EAAU;EAAe;;;KAGlB,kBAAkB;EAAiB;;KAEnC,cAAc;;EAExB;IAAW;IAAmB;;;EAE9B;IAAU;IAAe,aAAa;;;;;;;;;;EAStC;IAAU,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+BX,cAAc,KAAK,YAAY;;;kBAE1B;WAEE;;;;;;;EAgBT;;;;;;;;;;;;;;;EAyJT,YAAY,UAAS;MA2BjB;MAIA,QAAQ;EAKZ,OAAO,KAAK,kBAAkB;EAqB9B,MAAM;EASN,OAAO;EAWP,QAAQ;;;;EAQR,WAAW;EA2BX,WAAW;YAqHK,QAAQ,KAAK,YAAY;;;;;;;;;;;;iBAyD3B,MAAM,QAAO,aAAkB"}
@@ -0,0 +1,101 @@
1
+ import { t as styleBuilder } from "./builder-D49ECBEf.mjs";
2
+ import { hasAnsi } from "@zaly/shared/ansi";
3
+ import { hasColors } from "@zaly/shared/env";
4
+ import { formatWithOptions, inspect } from "node:util";
5
+ //#region src/style/inspect.ts
6
+ const MD_RE = /[`*_#[\]\->~|]/;
7
+ const JSON_RE = /^\s*[{[]/;
8
+ const FORMAT_RE = /%[sdifjoOc%]/;
9
+ /** True when `s` looks like markdown we should render — contains MD
10
+ * markers and isn't already ANSI-styled. Mirrors rekal's `Formatter.markdown`
11
+ * skip test so we avoid double-rendering pre-styled strings. */
12
+ function isMarkdown(s) {
13
+ return MD_RE.test(s) && !hasAnsi(s) && !JSON_RE.test(s);
14
+ }
15
+ const isFormatString = (v) => typeof v === "string" && FORMAT_RE.test(v) && !hasAnsi(v);
16
+ /**
17
+ * Inspect a list of args the way `console.log` does, returning a single
18
+ * string. Collapses `util.format` placeholders right-to-left, unwraps
19
+ * `Error` values to their message (unless `stacktrace: true`), and falls
20
+ * back to `util.formatWithOptions` for mixed values.
21
+ */
22
+ function inspectFormat(msg, opts = {}) {
23
+ const data = opts.stacktrace ? msg : msg.map((v) => v instanceof Error ? v.message : v);
24
+ opts = {
25
+ colors: hasColors,
26
+ ...opts
27
+ };
28
+ let ret = [];
29
+ for (let i = data.length - 1; i >= 0; i--) {
30
+ const item = data[i];
31
+ if (isFormatString(item)) ret = [formatWithOptions(opts, item, ...ret)];
32
+ else ret.unshift(item);
33
+ }
34
+ if (ret.length > 1 && isFormatString(ret[0])) return formatWithOptions(opts, ...ret);
35
+ return ret.map((v) => typeof v === "string" ? v : inspect$1(v, opts)).join(" ");
36
+ }
37
+ function inspectNumber(value) {
38
+ return new Intl.NumberFormat("en-US", {
39
+ notation: "standard",
40
+ useGrouping: true
41
+ }).format(value).replace(/,/g, "_");
42
+ }
43
+ function inspectField(key, s) {
44
+ if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) return s.syntaxField(key);
45
+ return s.syntaxString(JSON.stringify(key));
46
+ }
47
+ function inspect$1(value, opts = {}) {
48
+ opts = {
49
+ colors: hasColors,
50
+ null: true,
51
+ undefined: true,
52
+ ...opts
53
+ };
54
+ const indent = opts.indent ?? 2;
55
+ const s = opts.colors ? opts.style ?? styleBuilder() : styleBuilder(false);
56
+ const sym = {
57
+ ",": s.syntaxDelimiter(","),
58
+ ":": s.syntaxDelimiter(":"),
59
+ "[": s.syntaxBracket("["),
60
+ "]": s.syntaxBracket("]"),
61
+ "{": s.syntaxBracket("{"),
62
+ "}": s.syntaxBracket("}")
63
+ };
64
+ const seen = /* @__PURE__ */ new Set();
65
+ const $inspect = (v, depth) => {
66
+ if (seen.has(v)) return s.bold("[Circular]");
67
+ if (typeof v === "object" && v !== null) seen.add(v);
68
+ if (v === null) return s.syntaxConstant("null");
69
+ switch (typeof v) {
70
+ case "boolean": return s.syntaxBoolean(String(v));
71
+ case "bigint": return s.syntaxNumber(`${v}n`);
72
+ case "number": return s.syntaxNumber(inspectNumber(v));
73
+ case "string": return s.syntaxString(JSON.stringify(v));
74
+ case "symbol": return s.syntaxSpecial(String(v));
75
+ case "function": return s.syntaxFunction(`[Function${v.name ? `: ${v.name}` : ""}]`);
76
+ case "undefined": return s.syntaxConstant("undefined");
77
+ case "object": {
78
+ if (Array.isArray(v)) {
79
+ const items = v.map((item) => $inspect(item, depth + 1));
80
+ return `${sym["["]} ${items.join(`${sym[","]} `)} ${sym["]"]}`;
81
+ }
82
+ if (!(Object.getPrototypeOf(v) === Object.prototype)) break;
83
+ const entries = Object.entries(v).filter(([_, val]) => !(val === void 0 && !opts.undefined || val === null && !opts.null)).map(([key, val]) => `${inspectField(key, s)}: ${$inspect(val, depth + 1)}`);
84
+ if (indent) {
85
+ const padding = " ".repeat(indent * depth);
86
+ return `${sym["{"]}\n${padding}${entries.join(`${sym[","]}\n${padding}`)}\n${" ".repeat(indent * (depth - 1))}${sym["}"]}`;
87
+ }
88
+ return `${sym["{"]} ${entries.join(`${sym[","]} `)} ${sym["}"]}`;
89
+ }
90
+ }
91
+ return inspect(v, {
92
+ colors: true,
93
+ compact: true
94
+ });
95
+ };
96
+ return $inspect(value, 1);
97
+ }
98
+ //#endregion
99
+ export { inspectFormat as n, isMarkdown as r, inspect$1 as t };
100
+
101
+ //# sourceMappingURL=inspect-D1d9t-ni.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-D1d9t-ni.mjs","names":["inspect","nodeInspect"],"sources":["../src/style/inspect.ts"],"sourcesContent":["import type { StyleBuilder } from \"./builder.ts\"\n\nimport { hasAnsi } from \"@zaly/shared/ansi\"\nimport { hasColors } from \"@zaly/shared/env\"\nimport { formatWithOptions, inspect as nodeInspect } from \"node:util\"\nimport { styleBuilder } from \"./builder.ts\"\n\nexport interface InspectOpts {\n style?: StyleBuilder\n indent?: number\n undefined?: boolean\n null?: boolean\n /** When `true`, preserve Error stack traces. Default: `false` — Error\n * values are reduced to their `.message` so logs stay compact. */\n stacktrace?: boolean\n colors?: boolean\n}\n\n// Markdown-ish characters. Matches rekal's skip regex.\nconst MD_RE = /[`*_#[\\]\\->~|]/\nconst JSON_RE = /^\\s*[{[]/\n\n// `util.format` placeholder tokens (`%s`, `%d`, …).\nconst FORMAT_RE = /%[sdifjoOc%]/\n\n/** True when `s` looks like markdown we should render — contains MD\n * markers and isn't already ANSI-styled. Mirrors rekal's `Formatter.markdown`\n * skip test so we avoid double-rendering pre-styled strings. */\nexport function isMarkdown(s: string): boolean {\n return MD_RE.test(s) && !hasAnsi(s) && !JSON_RE.test(s)\n}\n\nconst isFormatString = (v: unknown): v is string =>\n typeof v === \"string\" && FORMAT_RE.test(v) && !hasAnsi(v)\n\n/**\n * Inspect a list of args the way `console.log` does, returning a single\n * string. Collapses `util.format` placeholders right-to-left, unwraps\n * `Error` values to their message (unless `stacktrace: true`), and falls\n * back to `util.formatWithOptions` for mixed values.\n */\nexport function inspectFormat(msg: unknown[], opts: InspectOpts = {}): string {\n const data = opts.stacktrace ? msg : msg.map((v) => (v instanceof Error ? v.message : v))\n opts = { colors: hasColors, ...opts }\n\n let ret: unknown[] = []\n // oxlint-disable-next-line oxc/no-accumulating-spread\n for (let i = data.length - 1; i >= 0; i--) {\n const item = data[i]\n if (isFormatString(item)) ret = [formatWithOptions(opts, item, ...ret)]\n else ret.unshift(item)\n }\n\n if (ret.length > 1 && isFormatString(ret[0])) return formatWithOptions(opts, ...ret)\n return ret.map((v) => (typeof v === \"string\" ? v : inspect(v, opts))).join(\" \")\n}\n\nfunction inspectNumber(value: number): string {\n return new Intl.NumberFormat(\"en-US\", {\n notation: \"standard\",\n useGrouping: true,\n })\n .format(value)\n .replace(/,/g, \"_\")\n}\n\nfunction inspectField(key: string, s: StyleBuilder): string {\n if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) return s.syntaxField(key)\n return s.syntaxString(JSON.stringify(key))\n}\n\nexport function inspect(value: unknown, opts: InspectOpts = {}): string {\n opts = { colors: hasColors, null: true, undefined: true, ...opts }\n const indent = opts.indent ?? 2\n const s = opts.colors ? (opts.style ?? styleBuilder()) : styleBuilder(false)\n const sym = {\n \",\": s.syntaxDelimiter(\",\"),\n \":\": s.syntaxDelimiter(\":\"),\n \"[\": s.syntaxBracket(\"[\"),\n \"]\": s.syntaxBracket(\"]\"),\n \"{\": s.syntaxBracket(\"{\"),\n \"}\": s.syntaxBracket(\"}\"),\n }\n const seen = new Set()\n\n const $inspect = (v: unknown, depth: number): string => {\n if (seen.has(v)) return s.bold(\"[Circular]\")\n if (typeof v === \"object\" && v !== null) seen.add(v)\n if (v === null) return s.syntaxConstant(\"null\")\n switch (typeof v) {\n case \"boolean\": {\n return s.syntaxBoolean(String(v))\n }\n case \"bigint\": {\n return s.syntaxNumber(`${v}n`)\n }\n case \"number\": {\n return s.syntaxNumber(inspectNumber(v))\n }\n case \"string\": {\n return s.syntaxString(JSON.stringify(v))\n }\n case \"symbol\": {\n return s.syntaxSpecial(String(v))\n }\n case \"function\": {\n return s.syntaxFunction(`[Function${v.name ? `: ${v.name}` : \"\"}]`)\n }\n case \"undefined\": {\n return s.syntaxConstant(\"undefined\")\n }\n case \"object\": {\n if (Array.isArray(v)) {\n const items = v.map((item) => $inspect(item, depth + 1))\n return `${sym[\"[\"]} ${items.join(`${sym[\",\"]} `)} ${sym[\"]\"]}`\n }\n const isPlainObject = Object.getPrototypeOf(v) === Object.prototype\n if (!isPlainObject) break\n const entries = Object.entries(v)\n .filter(\n ([_, val]) => !((val === undefined && !opts.undefined) || (val === null && !opts.null))\n )\n .map(([key, val]) => `${inspectField(key, s)}: ${$inspect(val, depth + 1)}`)\n if (indent) {\n const padding = \" \".repeat(indent * depth)\n return `${sym[\"{\"]}\\n${padding}${entries.join(`${sym[\",\"]}\\n${padding}`)}\\n${\" \".repeat(indent * (depth - 1))}${sym[\"}\"]}`\n }\n return `${sym[\"{\"]} ${entries.join(`${sym[\",\"]} `)} ${sym[\"}\"]}`\n }\n }\n return nodeInspect(v, { colors: true, compact: true })\n }\n return $inspect(value, 1)\n}\n"],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { c as Color, f as Style, i as AnsiColorName, s as BrightAnsiColorName, t as Theme } from "./types-B9Eh7k2v.mjs";
2
+ //#region src/style/builder.d.ts
3
+ type AttrName = "bold" | "dim" | "italic" | "underline" | "inverse" | "strikethrough";
4
+ type AnyThemeKey = Exclude<keyof Theme, "shiki" | "$schema"> | (string & {});
5
+ type ChainSlot = Exclude<keyof Theme, "fg" | "bg" | AttrName>;
6
+ type FgChainKey = AnsiColorName | BrightAnsiColorName | ChainSlot;
7
+ type BgChainKey = `bg${Capitalize<FgChainKey>}`;
8
+ type FgExtractKey = `fg${Capitalize<FgChainKey>}`;
9
+ type StyleBuilder = {
10
+ theme: Theme;
11
+ (text: string): string;
12
+ fg: (color: Color) => StyleBuilder;
13
+ bg: (color: Color) => StyleBuilder;
14
+ add: (slot?: AnyThemeKey | Style) => StyleBuilder;
15
+ lighten: (n: number) => StyleBuilder;
16
+ darken: (n: number) => StyleBuilder;
17
+ } & { readonly [K in AttrName | FgChainKey | BgChainKey | FgExtractKey]: StyleBuilder; };
18
+ /**
19
+ * Build styled strings via chainable property access.
20
+ *
21
+ * ```ts
22
+ * style().red.bold("err") // → "\x1b[1;31merr\x1b[0m"
23
+ * style().primary.bgAccent("x") // theme slots via the default theme
24
+ * style(myTheme).primary("x") // override the bound theme
25
+ * style().fg("#82aaff")("x") // hex via the escape hatch
26
+ * style().primary[300]("x") // tonal variant of the last color
27
+ * style().bgDiffAdd[200].fgDiffAdd("x") // per-channel variants on a Style slot
28
+ * ```
29
+ *
30
+ * Each property access returns a fresh builder, so intermediates can be
31
+ * reused and extended without mutation:
32
+ *
33
+ * ```ts
34
+ * const err = style().red.bold
35
+ * err("oops"); err.underline("fatal")
36
+ * ```
37
+ *
38
+ * Calling an empty builder is a no-op: `styleBuilder()("x")` returns `"x"` unchanged.
39
+ */
40
+ declare function styleBuilder(theme?: Theme | false): StyleBuilder;
41
+ //#endregion
42
+ //#region src/style/inspect.d.ts
43
+ interface InspectOpts {
44
+ style?: StyleBuilder;
45
+ indent?: number;
46
+ undefined?: boolean;
47
+ null?: boolean;
48
+ /** When `true`, preserve Error stack traces. Default: `false` — Error
49
+ * values are reduced to their `.message` so logs stay compact. */
50
+ stacktrace?: boolean;
51
+ colors?: boolean;
52
+ }
53
+ /** True when `s` looks like markdown we should render — contains MD
54
+ * markers and isn't already ANSI-styled. Mirrors rekal's `Formatter.markdown`
55
+ * skip test so we avoid double-rendering pre-styled strings. */
56
+ declare function isMarkdown(s: string): boolean;
57
+ /**
58
+ * Inspect a list of args the way `console.log` does, returning a single
59
+ * string. Collapses `util.format` placeholders right-to-left, unwraps
60
+ * `Error` values to their message (unless `stacktrace: true`), and falls
61
+ * back to `util.formatWithOptions` for mixed values.
62
+ */
63
+ declare function inspectFormat(msg: unknown[], opts?: InspectOpts): string;
64
+ declare function inspect(value: unknown, opts?: InspectOpts): string;
65
+ //#endregion
66
+ export { StyleBuilder as a, isMarkdown as i, inspect as n, styleBuilder as o, inspectFormat as r, InspectOpts as t };
67
+ //# sourceMappingURL=inspect-D6FW_QUo.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-D6FW_QUo.d.mts","names":[],"sources":["../src/style/builder.ts","../src/style/inspect.ts"],"mappings":";;KAOK;KAEA,cAAc,cAAc;KAK5B,YAAY,cAAc,qBAAqB;KAE/C,aAAa,gBAAgB,sBAAsB;KACnD,kBAAkB,WAAW;KAC7B,oBAAoB,WAAW;KAExB;EACV,OAAO;GACN;EACD,KAAK,OAAO,UAAU;EACtB,KAAK,OAAO,UAAU;EACtB,MAAM,OAAO,cAAc,UAAU;EACrC,UAAU,cAAc;EACxB,SAAS,cAAc;gBAGb,KAAK,WAAW,aAAa,aAAa,eAAe;;;;;;;;;;;;;;;;;;;;;;;iBAyBrD,aAAa,QAAO,gBAA+B;;;UChDlD;EACf,QAAQ;EACR;EACA;EACA;;;EAGA;EACA;;;;;iBAac,WAAW;;;;;;;iBAaX,cAAc,gBAAgB,OAAM;iBA8BpC,QAAQ,gBAAgB,OAAM"}