@tuicomponents/box 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BoxComponent: () => BoxComponent,
24
+ alignmentSchema: () => alignmentSchema,
25
+ borderStyleSchema: () => borderStyleSchema,
26
+ boxInputSchema: () => boxInputSchema,
27
+ createBox: () => createBox,
28
+ getBorderChars: () => getBorderChars,
29
+ paddingSchema: () => paddingSchema
30
+ });
31
+ module.exports = __toCommonJS(index_exports);
32
+
33
+ // src/box.ts
34
+ var import_core = require("@tuicomponents/core");
35
+ var import_zod_to_json_schema = require("zod-to-json-schema");
36
+
37
+ // src/schema.ts
38
+ var import_zod = require("zod");
39
+ var borderStyleSchema = import_zod.z.enum([
40
+ "single",
41
+ "double",
42
+ "round",
43
+ "bold",
44
+ "singleDouble",
45
+ "doubleSingle",
46
+ "classic",
47
+ "none"
48
+ ]);
49
+ var alignmentSchema = import_zod.z.enum(["left", "center", "right"]);
50
+ var paddingSchema = import_zod.z.union([
51
+ import_zod.z.number().int().nonnegative(),
52
+ import_zod.z.object({
53
+ top: import_zod.z.number().int().nonnegative().optional().default(0),
54
+ right: import_zod.z.number().int().nonnegative().optional().default(0),
55
+ bottom: import_zod.z.number().int().nonnegative().optional().default(0),
56
+ left: import_zod.z.number().int().nonnegative().optional().default(0)
57
+ })
58
+ ]);
59
+ var boxInputSchema = import_zod.z.object({
60
+ /** Content to display inside the box */
61
+ content: import_zod.z.string(),
62
+ /** Title to display in the top border */
63
+ title: import_zod.z.string().optional(),
64
+ /** Title alignment */
65
+ titleAlignment: alignmentSchema.optional().default("left"),
66
+ /** Border style */
67
+ borderStyle: borderStyleSchema.optional().default("single"),
68
+ /** Padding inside the box */
69
+ padding: paddingSchema.optional().default(0),
70
+ /** Fixed width (if not set, fits content) */
71
+ width: import_zod.z.number().int().positive().optional(),
72
+ /** Text alignment within the box */
73
+ textAlignment: alignmentSchema.optional().default("left"),
74
+ /** Whether to dim the border */
75
+ dimBorder: import_zod.z.boolean().optional().default(false)
76
+ });
77
+
78
+ // src/chars.ts
79
+ var borderCharSets = {
80
+ single: {
81
+ topLeft: "\u250C",
82
+ top: "\u2500",
83
+ topRight: "\u2510",
84
+ right: "\u2502",
85
+ bottomRight: "\u2518",
86
+ bottom: "\u2500",
87
+ bottomLeft: "\u2514",
88
+ left: "\u2502"
89
+ },
90
+ double: {
91
+ topLeft: "\u2554",
92
+ top: "\u2550",
93
+ topRight: "\u2557",
94
+ right: "\u2551",
95
+ bottomRight: "\u255D",
96
+ bottom: "\u2550",
97
+ bottomLeft: "\u255A",
98
+ left: "\u2551"
99
+ },
100
+ round: {
101
+ topLeft: "\u256D",
102
+ top: "\u2500",
103
+ topRight: "\u256E",
104
+ right: "\u2502",
105
+ bottomRight: "\u256F",
106
+ bottom: "\u2500",
107
+ bottomLeft: "\u2570",
108
+ left: "\u2502"
109
+ },
110
+ bold: {
111
+ topLeft: "\u250F",
112
+ top: "\u2501",
113
+ topRight: "\u2513",
114
+ right: "\u2503",
115
+ bottomRight: "\u251B",
116
+ bottom: "\u2501",
117
+ bottomLeft: "\u2517",
118
+ left: "\u2503"
119
+ },
120
+ singleDouble: {
121
+ topLeft: "\u2553",
122
+ top: "\u2500",
123
+ topRight: "\u2556",
124
+ right: "\u2551",
125
+ bottomRight: "\u255C",
126
+ bottom: "\u2500",
127
+ bottomLeft: "\u2559",
128
+ left: "\u2551"
129
+ },
130
+ doubleSingle: {
131
+ topLeft: "\u2552",
132
+ top: "\u2550",
133
+ topRight: "\u2555",
134
+ right: "\u2502",
135
+ bottomRight: "\u255B",
136
+ bottom: "\u2550",
137
+ bottomLeft: "\u2558",
138
+ left: "\u2502"
139
+ },
140
+ classic: {
141
+ topLeft: "+",
142
+ top: "-",
143
+ topRight: "+",
144
+ right: "|",
145
+ bottomRight: "+",
146
+ bottom: "-",
147
+ bottomLeft: "+",
148
+ left: "|"
149
+ },
150
+ none: {
151
+ topLeft: " ",
152
+ top: " ",
153
+ topRight: " ",
154
+ right: " ",
155
+ bottomRight: " ",
156
+ bottom: " ",
157
+ bottomLeft: " ",
158
+ left: " "
159
+ }
160
+ };
161
+ function getBorderChars(style) {
162
+ return borderCharSets[style];
163
+ }
164
+
165
+ // src/box.ts
166
+ function colorBorder(text, theme) {
167
+ if (!theme) {
168
+ return text;
169
+ }
170
+ return theme.semantic.border(text);
171
+ }
172
+ function colorTitle(text, theme) {
173
+ if (!theme) {
174
+ return text;
175
+ }
176
+ return theme.semantic.header(text);
177
+ }
178
+ var BoxComponent = class extends import_core.BaseTuiComponent {
179
+ metadata = {
180
+ name: "box",
181
+ description: "Renders content in a bordered box/panel",
182
+ version: "0.1.0",
183
+ examples: [
184
+ {
185
+ name: "basic",
186
+ description: "Simple box with content",
187
+ input: {
188
+ content: "Hello, World!"
189
+ }
190
+ },
191
+ {
192
+ name: "with-title",
193
+ description: "Box with a title",
194
+ input: {
195
+ content: "This is the content inside the box.",
196
+ title: "My Title"
197
+ }
198
+ },
199
+ {
200
+ name: "rounded",
201
+ description: "Box with rounded corners",
202
+ input: {
203
+ content: "Rounded corners look nice!",
204
+ borderStyle: "round",
205
+ padding: 1
206
+ }
207
+ },
208
+ {
209
+ name: "double-border",
210
+ description: "Box with double-line border",
211
+ input: {
212
+ content: "Double border style",
213
+ borderStyle: "double",
214
+ title: "Important",
215
+ titleAlignment: "center"
216
+ }
217
+ },
218
+ {
219
+ name: "centered-text",
220
+ description: "Box with centered content",
221
+ input: {
222
+ content: "Centered\nMultiple lines\nAll centered",
223
+ textAlignment: "center",
224
+ width: 30,
225
+ padding: { top: 1, bottom: 1, left: 2, right: 2 }
226
+ }
227
+ }
228
+ ]
229
+ };
230
+ schema = boxInputSchema;
231
+ /**
232
+ * Override getJsonSchema to use direct schema generation.
233
+ */
234
+ getJsonSchema() {
235
+ return (0, import_zod_to_json_schema.zodToJsonSchema)(this.schema, {
236
+ name: this.metadata.name,
237
+ $refStrategy: "none"
238
+ });
239
+ }
240
+ render(input, context) {
241
+ const parsed = this.schema.parse(input);
242
+ const chars = getBorderChars(parsed.borderStyle);
243
+ const padding = this.normalizePadding(parsed.padding);
244
+ const theme = context.theme;
245
+ const contentMeasured = (0, import_core.measureLines)(parsed.content);
246
+ const contentLines = contentMeasured.lines;
247
+ const titleWidth = parsed.title ? context.renderMode === "markdown" ? (0, import_core.getMarkdownRenderedWidth)(` ${parsed.title} `) : (0, import_core.getStringWidth)(` ${parsed.title} `) : 0;
248
+ let contentWidth;
249
+ if (parsed.width) {
250
+ contentWidth = parsed.width - 2 - padding.left - padding.right;
251
+ } else {
252
+ const minWidthForTitle = Math.max(
253
+ 0,
254
+ titleWidth - padding.left - padding.right
255
+ );
256
+ contentWidth = Math.max(contentMeasured.maxWidth, minWidthForTitle);
257
+ }
258
+ const innerWidth = contentWidth + padding.left + padding.right;
259
+ const outputLines = [];
260
+ outputLines.push(
261
+ this.buildTopBorder(
262
+ chars,
263
+ innerWidth,
264
+ parsed.title,
265
+ parsed.titleAlignment,
266
+ theme,
267
+ context.renderMode
268
+ )
269
+ );
270
+ for (let i = 0; i < padding.top; i++) {
271
+ outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));
272
+ }
273
+ for (const line of contentLines) {
274
+ outputLines.push(
275
+ this.buildContentLine(
276
+ chars,
277
+ line,
278
+ contentWidth,
279
+ padding,
280
+ parsed.textAlignment,
281
+ theme
282
+ )
283
+ );
284
+ }
285
+ for (let i = 0; i < padding.bottom; i++) {
286
+ outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));
287
+ }
288
+ outputLines.push(this.buildBottomBorder(chars, innerWidth, theme));
289
+ const output = outputLines.join("\n");
290
+ const measured = (0, import_core.measureLines)(output);
291
+ return {
292
+ output,
293
+ actualWidth: measured.maxWidth,
294
+ lineCount: measured.lineCount
295
+ };
296
+ }
297
+ /**
298
+ * Normalize padding to object with all sides.
299
+ */
300
+ normalizePadding(padding) {
301
+ if (typeof padding === "number") {
302
+ return { top: padding, right: padding, bottom: padding, left: padding };
303
+ }
304
+ return {
305
+ top: padding.top,
306
+ right: padding.right,
307
+ bottom: padding.bottom,
308
+ left: padding.left
309
+ };
310
+ }
311
+ /**
312
+ * Build the top border with optional title.
313
+ */
314
+ buildTopBorder(chars, innerWidth, title, titleAlignment, theme, renderMode) {
315
+ if (!title) {
316
+ const border = chars.topLeft + chars.top.repeat(innerWidth) + chars.topRight;
317
+ return colorBorder(border, theme);
318
+ }
319
+ const titleWithSpace = ` ${title} `;
320
+ const titleWidth = renderMode === "markdown" ? (0, import_core.getMarkdownRenderedWidth)(titleWithSpace) : (0, import_core.getStringWidth)(titleWithSpace);
321
+ if (titleWidth > innerWidth) {
322
+ const truncatedTitle = titleWithSpace.slice(0, innerWidth - 1) + "\u2026";
323
+ return colorBorder(chars.topLeft, theme) + colorTitle(truncatedTitle, theme) + colorBorder(chars.topRight, theme);
324
+ }
325
+ const remainingWidth = innerWidth - titleWidth;
326
+ switch (titleAlignment) {
327
+ case "center": {
328
+ const leftPad = Math.floor(remainingWidth / 2);
329
+ const rightPad = remainingWidth - leftPad;
330
+ return colorBorder(chars.topLeft + chars.top.repeat(leftPad), theme) + colorTitle(titleWithSpace, theme) + colorBorder(chars.top.repeat(rightPad) + chars.topRight, theme);
331
+ }
332
+ case "right": {
333
+ return colorBorder(chars.topLeft + chars.top.repeat(remainingWidth), theme) + colorTitle(titleWithSpace, theme) + colorBorder(chars.topRight, theme);
334
+ }
335
+ case "left":
336
+ default: {
337
+ return colorBorder(chars.topLeft, theme) + colorTitle(titleWithSpace, theme) + colorBorder(chars.top.repeat(remainingWidth) + chars.topRight, theme);
338
+ }
339
+ }
340
+ }
341
+ /**
342
+ * Build an empty line (for padding).
343
+ */
344
+ buildEmptyLine(chars, innerWidth, theme) {
345
+ return colorBorder(chars.left, theme) + " ".repeat(innerWidth) + colorBorder(chars.right, theme);
346
+ }
347
+ /**
348
+ * Build a content line with padding and alignment.
349
+ */
350
+ buildContentLine(chars, content, contentWidth, padding, textAlignment, theme) {
351
+ const alignedContent = (0, import_core.padToWidth)(content, contentWidth, {
352
+ align: textAlignment
353
+ });
354
+ const leftPad = " ".repeat(padding.left);
355
+ const rightPad = " ".repeat(padding.right);
356
+ return colorBorder(chars.left, theme) + leftPad + alignedContent + rightPad + colorBorder(chars.right, theme);
357
+ }
358
+ /**
359
+ * Build the bottom border.
360
+ */
361
+ buildBottomBorder(chars, innerWidth, theme) {
362
+ const border = chars.bottomLeft + chars.bottom.repeat(innerWidth) + chars.bottomRight;
363
+ return colorBorder(border, theme);
364
+ }
365
+ };
366
+ function createBox() {
367
+ return new BoxComponent();
368
+ }
369
+ import_core.registry.register(createBox);
370
+ // Annotate the CommonJS export names for ESM import in node:
371
+ 0 && (module.exports = {
372
+ BoxComponent,
373
+ alignmentSchema,
374
+ borderStyleSchema,
375
+ boxInputSchema,
376
+ createBox,
377
+ getBorderChars,
378
+ paddingSchema
379
+ });
380
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/box.ts","../src/schema.ts","../src/chars.ts"],"sourcesContent":["export { createBox, BoxComponent } from \"./box.js\";\nexport {\n boxInputSchema,\n borderStyleSchema,\n alignmentSchema,\n paddingSchema,\n type BoxInput,\n type BoxInputWithDefaults,\n type BorderStyle,\n type Alignment,\n type Padding,\n type NormalizedPadding,\n} from \"./schema.js\";\nexport { getBorderChars, type BorderChars } from \"./chars.js\";\n","import {\n BaseTuiComponent,\n type ComponentMetadata,\n type RenderContext,\n type RenderResult,\n type TuiTheme,\n type RenderMode,\n getStringWidth,\n getMarkdownRenderedWidth,\n padToWidth,\n measureLines,\n registry,\n} from \"@tuicomponents/core\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport {\n boxInputSchema,\n type BoxInput,\n type BoxInputWithDefaults,\n type NormalizedPadding,\n type Padding,\n type Alignment,\n} from \"./schema.js\";\nimport { getBorderChars, type BorderChars } from \"./chars.js\";\n\n/**\n * Apply border color to text.\n */\nfunction colorBorder(text: string, theme: TuiTheme | undefined): string {\n if (!theme) {\n return text;\n }\n return theme.semantic.border(text);\n}\n\n/**\n * Apply header/title color to text.\n */\nfunction colorTitle(text: string, theme: TuiTheme | undefined): string {\n if (!theme) {\n return text;\n }\n return theme.semantic.header(text);\n}\n\n/**\n * Box component for rendering content in bordered panels.\n */\nclass BoxComponent extends BaseTuiComponent<BoxInput, typeof boxInputSchema> {\n readonly metadata: ComponentMetadata<BoxInput> = {\n name: \"box\",\n description: \"Renders content in a bordered box/panel\",\n version: \"0.1.0\",\n examples: [\n {\n name: \"basic\",\n description: \"Simple box with content\",\n input: {\n content: \"Hello, World!\",\n },\n },\n {\n name: \"with-title\",\n description: \"Box with a title\",\n input: {\n content: \"This is the content inside the box.\",\n title: \"My Title\",\n },\n },\n {\n name: \"rounded\",\n description: \"Box with rounded corners\",\n input: {\n content: \"Rounded corners look nice!\",\n borderStyle: \"round\",\n padding: 1,\n },\n },\n {\n name: \"double-border\",\n description: \"Box with double-line border\",\n input: {\n content: \"Double border style\",\n borderStyle: \"double\",\n title: \"Important\",\n titleAlignment: \"center\",\n },\n },\n {\n name: \"centered-text\",\n description: \"Box with centered content\",\n input: {\n content: \"Centered\\nMultiple lines\\nAll centered\",\n textAlignment: \"center\",\n width: 30,\n padding: { top: 1, bottom: 1, left: 2, right: 2 },\n },\n },\n ],\n };\n\n readonly schema = boxInputSchema;\n\n /**\n * Override getJsonSchema to use direct schema generation.\n */\n override getJsonSchema(): object {\n return zodToJsonSchema(this.schema, {\n name: this.metadata.name,\n $refStrategy: \"none\",\n });\n }\n\n render(input: BoxInput, context: RenderContext): RenderResult {\n // Parse and apply defaults\n const parsed: BoxInputWithDefaults = this.schema.parse(input);\n const chars = getBorderChars(parsed.borderStyle);\n const padding = this.normalizePadding(parsed.padding);\n const theme = context.theme;\n\n // Split content into lines\n const contentMeasured = measureLines(parsed.content);\n const contentLines = contentMeasured.lines;\n\n // Calculate title width requirement (title + surrounding spaces)\n // In markdown mode, use visual width (formatting chars like ** and _ are invisible)\n const titleWidth = parsed.title\n ? context.renderMode === \"markdown\"\n ? getMarkdownRenderedWidth(` ${parsed.title} `)\n : getStringWidth(` ${parsed.title} `)\n : 0;\n\n // Determine content width - must fit both content and title\n let contentWidth: number;\n if (parsed.width) {\n contentWidth = parsed.width - 2 - padding.left - padding.right; // Account for borders and padding\n } else {\n // Use the larger of content width or title width (minus padding)\n const minWidthForTitle = Math.max(\n 0,\n titleWidth - padding.left - padding.right\n );\n contentWidth = Math.max(contentMeasured.maxWidth, minWidthForTitle);\n }\n\n // Calculate total inner width (content + horizontal padding)\n const innerWidth = contentWidth + padding.left + padding.right;\n\n // Build output lines\n const outputLines: string[] = [];\n\n // Top border with optional title\n outputLines.push(\n this.buildTopBorder(\n chars,\n innerWidth,\n parsed.title,\n parsed.titleAlignment,\n theme,\n context.renderMode\n )\n );\n\n // Top padding\n for (let i = 0; i < padding.top; i++) {\n outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));\n }\n\n // Content lines\n for (const line of contentLines) {\n outputLines.push(\n this.buildContentLine(\n chars,\n line,\n contentWidth,\n padding,\n parsed.textAlignment,\n theme\n )\n );\n }\n\n // Bottom padding\n for (let i = 0; i < padding.bottom; i++) {\n outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));\n }\n\n // Bottom border\n outputLines.push(this.buildBottomBorder(chars, innerWidth, theme));\n\n const output = outputLines.join(\"\\n\");\n const measured = measureLines(output);\n\n return {\n output,\n actualWidth: measured.maxWidth,\n lineCount: measured.lineCount,\n };\n }\n\n /**\n * Normalize padding to object with all sides.\n */\n private normalizePadding(padding: Padding): NormalizedPadding {\n if (typeof padding === \"number\") {\n return { top: padding, right: padding, bottom: padding, left: padding };\n }\n // After schema parsing with .default(0), all fields are guaranteed to be numbers\n return {\n top: padding.top,\n right: padding.right,\n bottom: padding.bottom,\n left: padding.left,\n };\n }\n\n /**\n * Build the top border with optional title.\n */\n private buildTopBorder(\n chars: BorderChars,\n innerWidth: number,\n title: string | undefined,\n titleAlignment: Alignment,\n theme: TuiTheme | undefined,\n renderMode: RenderMode\n ): string {\n if (!title) {\n const border =\n chars.topLeft + chars.top.repeat(innerWidth) + chars.topRight;\n return colorBorder(border, theme);\n }\n\n const titleWithSpace = ` ${title} `;\n // In markdown mode, use visual width (formatting chars like ** and _ are invisible when rendered)\n const titleWidth =\n renderMode === \"markdown\"\n ? getMarkdownRenderedWidth(titleWithSpace)\n : getStringWidth(titleWithSpace);\n\n // If title is too long, truncate\n if (titleWidth > innerWidth) {\n const truncatedTitle = titleWithSpace.slice(0, innerWidth - 1) + \"…\";\n return (\n colorBorder(chars.topLeft, theme) +\n colorTitle(truncatedTitle, theme) +\n colorBorder(chars.topRight, theme)\n );\n }\n\n const remainingWidth = innerWidth - titleWidth;\n\n switch (titleAlignment) {\n case \"center\": {\n const leftPad = Math.floor(remainingWidth / 2);\n const rightPad = remainingWidth - leftPad;\n return (\n colorBorder(chars.topLeft + chars.top.repeat(leftPad), theme) +\n colorTitle(titleWithSpace, theme) +\n colorBorder(chars.top.repeat(rightPad) + chars.topRight, theme)\n );\n }\n case \"right\": {\n return (\n colorBorder(chars.topLeft + chars.top.repeat(remainingWidth), theme) +\n colorTitle(titleWithSpace, theme) +\n colorBorder(chars.topRight, theme)\n );\n }\n case \"left\":\n default: {\n return (\n colorBorder(chars.topLeft, theme) +\n colorTitle(titleWithSpace, theme) +\n colorBorder(chars.top.repeat(remainingWidth) + chars.topRight, theme)\n );\n }\n }\n }\n\n /**\n * Build an empty line (for padding).\n */\n private buildEmptyLine(\n chars: BorderChars,\n innerWidth: number,\n theme: TuiTheme | undefined\n ): string {\n return (\n colorBorder(chars.left, theme) +\n \" \".repeat(innerWidth) +\n colorBorder(chars.right, theme)\n );\n }\n\n /**\n * Build a content line with padding and alignment.\n */\n private buildContentLine(\n chars: BorderChars,\n content: string,\n contentWidth: number,\n padding: NormalizedPadding,\n textAlignment: Alignment,\n theme: TuiTheme | undefined\n ): string {\n // Pad/align content within content area\n const alignedContent = padToWidth(content, contentWidth, {\n align: textAlignment,\n });\n\n // Add horizontal padding\n const leftPad = \" \".repeat(padding.left);\n const rightPad = \" \".repeat(padding.right);\n\n return (\n colorBorder(chars.left, theme) +\n leftPad +\n alignedContent +\n rightPad +\n colorBorder(chars.right, theme)\n );\n }\n\n /**\n * Build the bottom border.\n */\n private buildBottomBorder(\n chars: BorderChars,\n innerWidth: number,\n theme: TuiTheme | undefined\n ): string {\n const border =\n chars.bottomLeft + chars.bottom.repeat(innerWidth) + chars.bottomRight;\n return colorBorder(border, theme);\n }\n}\n\n/**\n * Factory function to create a box component.\n */\nexport function createBox(): BoxComponent {\n return new BoxComponent();\n}\n\n// Register with global registry\nregistry.register(createBox);\n\nexport { BoxComponent };\n","import { z } from \"zod\";\n\n/**\n * Border style options for box rendering.\n */\nexport const borderStyleSchema = z.enum([\n \"single\",\n \"double\",\n \"round\",\n \"bold\",\n \"singleDouble\",\n \"doubleSingle\",\n \"classic\",\n \"none\",\n]);\n\nexport type BorderStyle = z.infer<typeof borderStyleSchema>;\n\n/**\n * Text alignment options.\n */\nexport const alignmentSchema = z.enum([\"left\", \"center\", \"right\"]);\n\nexport type Alignment = z.infer<typeof alignmentSchema>;\n\n/**\n * Padding configuration - can be a single number or object with sides.\n */\nexport const paddingSchema = z.union([\n z.number().int().nonnegative(),\n z.object({\n top: z.number().int().nonnegative().optional().default(0),\n right: z.number().int().nonnegative().optional().default(0),\n bottom: z.number().int().nonnegative().optional().default(0),\n left: z.number().int().nonnegative().optional().default(0),\n }),\n]);\n\nexport type Padding = z.infer<typeof paddingSchema>;\n\n/**\n * Normalized padding with all sides specified.\n */\nexport interface NormalizedPadding {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/**\n * Schema for box component input.\n */\nexport const boxInputSchema = z.object({\n /** Content to display inside the box */\n content: z.string(),\n /** Title to display in the top border */\n title: z.string().optional(),\n /** Title alignment */\n titleAlignment: alignmentSchema.optional().default(\"left\"),\n /** Border style */\n borderStyle: borderStyleSchema.optional().default(\"single\"),\n /** Padding inside the box */\n padding: paddingSchema.optional().default(0),\n /** Fixed width (if not set, fits content) */\n width: z.number().int().positive().optional(),\n /** Text alignment within the box */\n textAlignment: alignmentSchema.optional().default(\"left\"),\n /** Whether to dim the border */\n dimBorder: z.boolean().optional().default(false),\n});\n\n/**\n * Input type (before defaults applied).\n */\nexport type BoxInput = z.input<typeof boxInputSchema>;\n\n/**\n * Input type (after defaults applied).\n */\nexport type BoxInputWithDefaults = z.output<typeof boxInputSchema>;\n","import type { BorderStyle } from \"./schema.js\";\n\n/**\n * Border character set for box rendering.\n */\nexport interface BorderChars {\n topLeft: string;\n top: string;\n topRight: string;\n right: string;\n bottomRight: string;\n bottom: string;\n bottomLeft: string;\n left: string;\n}\n\n/**\n * Border character sets for different styles.\n */\nconst borderCharSets: Record<BorderStyle, BorderChars> = {\n single: {\n topLeft: \"┌\",\n top: \"─\",\n topRight: \"┐\",\n right: \"│\",\n bottomRight: \"┘\",\n bottom: \"─\",\n bottomLeft: \"└\",\n left: \"│\",\n },\n double: {\n topLeft: \"╔\",\n top: \"═\",\n topRight: \"╗\",\n right: \"║\",\n bottomRight: \"╝\",\n bottom: \"═\",\n bottomLeft: \"╚\",\n left: \"║\",\n },\n round: {\n topLeft: \"╭\",\n top: \"─\",\n topRight: \"╮\",\n right: \"│\",\n bottomRight: \"╯\",\n bottom: \"─\",\n bottomLeft: \"╰\",\n left: \"│\",\n },\n bold: {\n topLeft: \"┏\",\n top: \"━\",\n topRight: \"┓\",\n right: \"┃\",\n bottomRight: \"┛\",\n bottom: \"━\",\n bottomLeft: \"┗\",\n left: \"┃\",\n },\n singleDouble: {\n topLeft: \"╓\",\n top: \"─\",\n topRight: \"╖\",\n right: \"║\",\n bottomRight: \"╜\",\n bottom: \"─\",\n bottomLeft: \"╙\",\n left: \"║\",\n },\n doubleSingle: {\n topLeft: \"╒\",\n top: \"═\",\n topRight: \"╕\",\n right: \"│\",\n bottomRight: \"╛\",\n bottom: \"═\",\n bottomLeft: \"╘\",\n left: \"│\",\n },\n classic: {\n topLeft: \"+\",\n top: \"-\",\n topRight: \"+\",\n right: \"|\",\n bottomRight: \"+\",\n bottom: \"-\",\n bottomLeft: \"+\",\n left: \"|\",\n },\n none: {\n topLeft: \" \",\n top: \" \",\n topRight: \" \",\n right: \" \",\n bottomRight: \" \",\n bottom: \" \",\n bottomLeft: \" \",\n left: \" \",\n },\n};\n\n/**\n * Get border characters for the specified style.\n */\nexport function getBorderChars(style: BorderStyle): BorderChars {\n return borderCharSets[style];\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,224 @@
1
+ import * as zod from 'zod';
2
+ import { z } from 'zod';
3
+ import { BaseTuiComponent, ComponentMetadata, RenderContext, RenderResult } from '@tuicomponents/core';
4
+
5
+ /**
6
+ * Border style options for box rendering.
7
+ */
8
+ declare const borderStyleSchema: z.ZodEnum<["single", "double", "round", "bold", "singleDouble", "doubleSingle", "classic", "none"]>;
9
+ type BorderStyle = z.infer<typeof borderStyleSchema>;
10
+ /**
11
+ * Text alignment options.
12
+ */
13
+ declare const alignmentSchema: z.ZodEnum<["left", "center", "right"]>;
14
+ type Alignment = z.infer<typeof alignmentSchema>;
15
+ /**
16
+ * Padding configuration - can be a single number or object with sides.
17
+ */
18
+ declare const paddingSchema: z.ZodUnion<[z.ZodNumber, z.ZodObject<{
19
+ top: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
20
+ right: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
21
+ bottom: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
22
+ left: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ left: number;
25
+ right: number;
26
+ top: number;
27
+ bottom: number;
28
+ }, {
29
+ left?: number | undefined;
30
+ right?: number | undefined;
31
+ top?: number | undefined;
32
+ bottom?: number | undefined;
33
+ }>]>;
34
+ type Padding = z.infer<typeof paddingSchema>;
35
+ /**
36
+ * Normalized padding with all sides specified.
37
+ */
38
+ interface NormalizedPadding {
39
+ top: number;
40
+ right: number;
41
+ bottom: number;
42
+ left: number;
43
+ }
44
+ /**
45
+ * Schema for box component input.
46
+ */
47
+ declare const boxInputSchema: z.ZodObject<{
48
+ /** Content to display inside the box */
49
+ content: z.ZodString;
50
+ /** Title to display in the top border */
51
+ title: z.ZodOptional<z.ZodString>;
52
+ /** Title alignment */
53
+ titleAlignment: z.ZodDefault<z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>>;
54
+ /** Border style */
55
+ borderStyle: z.ZodDefault<z.ZodOptional<z.ZodEnum<["single", "double", "round", "bold", "singleDouble", "doubleSingle", "classic", "none"]>>>;
56
+ /** Padding inside the box */
57
+ padding: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodObject<{
58
+ top: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
59
+ right: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
60
+ bottom: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
61
+ left: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
62
+ }, "strip", z.ZodTypeAny, {
63
+ left: number;
64
+ right: number;
65
+ top: number;
66
+ bottom: number;
67
+ }, {
68
+ left?: number | undefined;
69
+ right?: number | undefined;
70
+ top?: number | undefined;
71
+ bottom?: number | undefined;
72
+ }>]>>>;
73
+ /** Fixed width (if not set, fits content) */
74
+ width: z.ZodOptional<z.ZodNumber>;
75
+ /** Text alignment within the box */
76
+ textAlignment: z.ZodDefault<z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>>;
77
+ /** Whether to dim the border */
78
+ dimBorder: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
79
+ }, "strip", z.ZodTypeAny, {
80
+ content: string;
81
+ titleAlignment: "left" | "center" | "right";
82
+ borderStyle: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none";
83
+ padding: number | {
84
+ left: number;
85
+ right: number;
86
+ top: number;
87
+ bottom: number;
88
+ };
89
+ textAlignment: "left" | "center" | "right";
90
+ dimBorder: boolean;
91
+ title?: string | undefined;
92
+ width?: number | undefined;
93
+ }, {
94
+ content: string;
95
+ title?: string | undefined;
96
+ titleAlignment?: "left" | "center" | "right" | undefined;
97
+ borderStyle?: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none" | undefined;
98
+ padding?: number | {
99
+ left?: number | undefined;
100
+ right?: number | undefined;
101
+ top?: number | undefined;
102
+ bottom?: number | undefined;
103
+ } | undefined;
104
+ width?: number | undefined;
105
+ textAlignment?: "left" | "center" | "right" | undefined;
106
+ dimBorder?: boolean | undefined;
107
+ }>;
108
+ /**
109
+ * Input type (before defaults applied).
110
+ */
111
+ type BoxInput = z.input<typeof boxInputSchema>;
112
+ /**
113
+ * Input type (after defaults applied).
114
+ */
115
+ type BoxInputWithDefaults = z.output<typeof boxInputSchema>;
116
+
117
+ /**
118
+ * Box component for rendering content in bordered panels.
119
+ */
120
+ declare class BoxComponent extends BaseTuiComponent<BoxInput, typeof boxInputSchema> {
121
+ readonly metadata: ComponentMetadata<BoxInput>;
122
+ readonly schema: zod.ZodObject<{
123
+ content: zod.ZodString;
124
+ title: zod.ZodOptional<zod.ZodString>;
125
+ titleAlignment: zod.ZodDefault<zod.ZodOptional<zod.ZodEnum<["left", "center", "right"]>>>;
126
+ borderStyle: zod.ZodDefault<zod.ZodOptional<zod.ZodEnum<["single", "double", "round", "bold", "singleDouble", "doubleSingle", "classic", "none"]>>>;
127
+ padding: zod.ZodDefault<zod.ZodOptional<zod.ZodUnion<[zod.ZodNumber, zod.ZodObject<{
128
+ top: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
129
+ right: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
130
+ bottom: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
131
+ left: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
132
+ }, "strip", zod.ZodTypeAny, {
133
+ left: number;
134
+ right: number;
135
+ top: number;
136
+ bottom: number;
137
+ }, {
138
+ left?: number | undefined;
139
+ right?: number | undefined;
140
+ top?: number | undefined;
141
+ bottom?: number | undefined;
142
+ }>]>>>;
143
+ width: zod.ZodOptional<zod.ZodNumber>;
144
+ textAlignment: zod.ZodDefault<zod.ZodOptional<zod.ZodEnum<["left", "center", "right"]>>>;
145
+ dimBorder: zod.ZodDefault<zod.ZodOptional<zod.ZodBoolean>>;
146
+ }, "strip", zod.ZodTypeAny, {
147
+ content: string;
148
+ titleAlignment: "left" | "center" | "right";
149
+ borderStyle: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none";
150
+ padding: number | {
151
+ left: number;
152
+ right: number;
153
+ top: number;
154
+ bottom: number;
155
+ };
156
+ textAlignment: "left" | "center" | "right";
157
+ dimBorder: boolean;
158
+ title?: string | undefined;
159
+ width?: number | undefined;
160
+ }, {
161
+ content: string;
162
+ title?: string | undefined;
163
+ titleAlignment?: "left" | "center" | "right" | undefined;
164
+ borderStyle?: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none" | undefined;
165
+ padding?: number | {
166
+ left?: number | undefined;
167
+ right?: number | undefined;
168
+ top?: number | undefined;
169
+ bottom?: number | undefined;
170
+ } | undefined;
171
+ width?: number | undefined;
172
+ textAlignment?: "left" | "center" | "right" | undefined;
173
+ dimBorder?: boolean | undefined;
174
+ }>;
175
+ /**
176
+ * Override getJsonSchema to use direct schema generation.
177
+ */
178
+ getJsonSchema(): object;
179
+ render(input: BoxInput, context: RenderContext): RenderResult;
180
+ /**
181
+ * Normalize padding to object with all sides.
182
+ */
183
+ private normalizePadding;
184
+ /**
185
+ * Build the top border with optional title.
186
+ */
187
+ private buildTopBorder;
188
+ /**
189
+ * Build an empty line (for padding).
190
+ */
191
+ private buildEmptyLine;
192
+ /**
193
+ * Build a content line with padding and alignment.
194
+ */
195
+ private buildContentLine;
196
+ /**
197
+ * Build the bottom border.
198
+ */
199
+ private buildBottomBorder;
200
+ }
201
+ /**
202
+ * Factory function to create a box component.
203
+ */
204
+ declare function createBox(): BoxComponent;
205
+
206
+ /**
207
+ * Border character set for box rendering.
208
+ */
209
+ interface BorderChars {
210
+ topLeft: string;
211
+ top: string;
212
+ topRight: string;
213
+ right: string;
214
+ bottomRight: string;
215
+ bottom: string;
216
+ bottomLeft: string;
217
+ left: string;
218
+ }
219
+ /**
220
+ * Get border characters for the specified style.
221
+ */
222
+ declare function getBorderChars(style: BorderStyle): BorderChars;
223
+
224
+ export { type Alignment, type BorderChars, type BorderStyle, BoxComponent, type BoxInput, type BoxInputWithDefaults, type NormalizedPadding, type Padding, alignmentSchema, borderStyleSchema, boxInputSchema, createBox, getBorderChars, paddingSchema };
@@ -0,0 +1,224 @@
1
+ import * as zod from 'zod';
2
+ import { z } from 'zod';
3
+ import { BaseTuiComponent, ComponentMetadata, RenderContext, RenderResult } from '@tuicomponents/core';
4
+
5
+ /**
6
+ * Border style options for box rendering.
7
+ */
8
+ declare const borderStyleSchema: z.ZodEnum<["single", "double", "round", "bold", "singleDouble", "doubleSingle", "classic", "none"]>;
9
+ type BorderStyle = z.infer<typeof borderStyleSchema>;
10
+ /**
11
+ * Text alignment options.
12
+ */
13
+ declare const alignmentSchema: z.ZodEnum<["left", "center", "right"]>;
14
+ type Alignment = z.infer<typeof alignmentSchema>;
15
+ /**
16
+ * Padding configuration - can be a single number or object with sides.
17
+ */
18
+ declare const paddingSchema: z.ZodUnion<[z.ZodNumber, z.ZodObject<{
19
+ top: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
20
+ right: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
21
+ bottom: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
22
+ left: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ left: number;
25
+ right: number;
26
+ top: number;
27
+ bottom: number;
28
+ }, {
29
+ left?: number | undefined;
30
+ right?: number | undefined;
31
+ top?: number | undefined;
32
+ bottom?: number | undefined;
33
+ }>]>;
34
+ type Padding = z.infer<typeof paddingSchema>;
35
+ /**
36
+ * Normalized padding with all sides specified.
37
+ */
38
+ interface NormalizedPadding {
39
+ top: number;
40
+ right: number;
41
+ bottom: number;
42
+ left: number;
43
+ }
44
+ /**
45
+ * Schema for box component input.
46
+ */
47
+ declare const boxInputSchema: z.ZodObject<{
48
+ /** Content to display inside the box */
49
+ content: z.ZodString;
50
+ /** Title to display in the top border */
51
+ title: z.ZodOptional<z.ZodString>;
52
+ /** Title alignment */
53
+ titleAlignment: z.ZodDefault<z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>>;
54
+ /** Border style */
55
+ borderStyle: z.ZodDefault<z.ZodOptional<z.ZodEnum<["single", "double", "round", "bold", "singleDouble", "doubleSingle", "classic", "none"]>>>;
56
+ /** Padding inside the box */
57
+ padding: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodObject<{
58
+ top: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
59
+ right: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
60
+ bottom: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
61
+ left: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
62
+ }, "strip", z.ZodTypeAny, {
63
+ left: number;
64
+ right: number;
65
+ top: number;
66
+ bottom: number;
67
+ }, {
68
+ left?: number | undefined;
69
+ right?: number | undefined;
70
+ top?: number | undefined;
71
+ bottom?: number | undefined;
72
+ }>]>>>;
73
+ /** Fixed width (if not set, fits content) */
74
+ width: z.ZodOptional<z.ZodNumber>;
75
+ /** Text alignment within the box */
76
+ textAlignment: z.ZodDefault<z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>>;
77
+ /** Whether to dim the border */
78
+ dimBorder: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
79
+ }, "strip", z.ZodTypeAny, {
80
+ content: string;
81
+ titleAlignment: "left" | "center" | "right";
82
+ borderStyle: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none";
83
+ padding: number | {
84
+ left: number;
85
+ right: number;
86
+ top: number;
87
+ bottom: number;
88
+ };
89
+ textAlignment: "left" | "center" | "right";
90
+ dimBorder: boolean;
91
+ title?: string | undefined;
92
+ width?: number | undefined;
93
+ }, {
94
+ content: string;
95
+ title?: string | undefined;
96
+ titleAlignment?: "left" | "center" | "right" | undefined;
97
+ borderStyle?: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none" | undefined;
98
+ padding?: number | {
99
+ left?: number | undefined;
100
+ right?: number | undefined;
101
+ top?: number | undefined;
102
+ bottom?: number | undefined;
103
+ } | undefined;
104
+ width?: number | undefined;
105
+ textAlignment?: "left" | "center" | "right" | undefined;
106
+ dimBorder?: boolean | undefined;
107
+ }>;
108
+ /**
109
+ * Input type (before defaults applied).
110
+ */
111
+ type BoxInput = z.input<typeof boxInputSchema>;
112
+ /**
113
+ * Input type (after defaults applied).
114
+ */
115
+ type BoxInputWithDefaults = z.output<typeof boxInputSchema>;
116
+
117
+ /**
118
+ * Box component for rendering content in bordered panels.
119
+ */
120
+ declare class BoxComponent extends BaseTuiComponent<BoxInput, typeof boxInputSchema> {
121
+ readonly metadata: ComponentMetadata<BoxInput>;
122
+ readonly schema: zod.ZodObject<{
123
+ content: zod.ZodString;
124
+ title: zod.ZodOptional<zod.ZodString>;
125
+ titleAlignment: zod.ZodDefault<zod.ZodOptional<zod.ZodEnum<["left", "center", "right"]>>>;
126
+ borderStyle: zod.ZodDefault<zod.ZodOptional<zod.ZodEnum<["single", "double", "round", "bold", "singleDouble", "doubleSingle", "classic", "none"]>>>;
127
+ padding: zod.ZodDefault<zod.ZodOptional<zod.ZodUnion<[zod.ZodNumber, zod.ZodObject<{
128
+ top: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
129
+ right: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
130
+ bottom: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
131
+ left: zod.ZodDefault<zod.ZodOptional<zod.ZodNumber>>;
132
+ }, "strip", zod.ZodTypeAny, {
133
+ left: number;
134
+ right: number;
135
+ top: number;
136
+ bottom: number;
137
+ }, {
138
+ left?: number | undefined;
139
+ right?: number | undefined;
140
+ top?: number | undefined;
141
+ bottom?: number | undefined;
142
+ }>]>>>;
143
+ width: zod.ZodOptional<zod.ZodNumber>;
144
+ textAlignment: zod.ZodDefault<zod.ZodOptional<zod.ZodEnum<["left", "center", "right"]>>>;
145
+ dimBorder: zod.ZodDefault<zod.ZodOptional<zod.ZodBoolean>>;
146
+ }, "strip", zod.ZodTypeAny, {
147
+ content: string;
148
+ titleAlignment: "left" | "center" | "right";
149
+ borderStyle: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none";
150
+ padding: number | {
151
+ left: number;
152
+ right: number;
153
+ top: number;
154
+ bottom: number;
155
+ };
156
+ textAlignment: "left" | "center" | "right";
157
+ dimBorder: boolean;
158
+ title?: string | undefined;
159
+ width?: number | undefined;
160
+ }, {
161
+ content: string;
162
+ title?: string | undefined;
163
+ titleAlignment?: "left" | "center" | "right" | undefined;
164
+ borderStyle?: "single" | "double" | "round" | "bold" | "singleDouble" | "doubleSingle" | "classic" | "none" | undefined;
165
+ padding?: number | {
166
+ left?: number | undefined;
167
+ right?: number | undefined;
168
+ top?: number | undefined;
169
+ bottom?: number | undefined;
170
+ } | undefined;
171
+ width?: number | undefined;
172
+ textAlignment?: "left" | "center" | "right" | undefined;
173
+ dimBorder?: boolean | undefined;
174
+ }>;
175
+ /**
176
+ * Override getJsonSchema to use direct schema generation.
177
+ */
178
+ getJsonSchema(): object;
179
+ render(input: BoxInput, context: RenderContext): RenderResult;
180
+ /**
181
+ * Normalize padding to object with all sides.
182
+ */
183
+ private normalizePadding;
184
+ /**
185
+ * Build the top border with optional title.
186
+ */
187
+ private buildTopBorder;
188
+ /**
189
+ * Build an empty line (for padding).
190
+ */
191
+ private buildEmptyLine;
192
+ /**
193
+ * Build a content line with padding and alignment.
194
+ */
195
+ private buildContentLine;
196
+ /**
197
+ * Build the bottom border.
198
+ */
199
+ private buildBottomBorder;
200
+ }
201
+ /**
202
+ * Factory function to create a box component.
203
+ */
204
+ declare function createBox(): BoxComponent;
205
+
206
+ /**
207
+ * Border character set for box rendering.
208
+ */
209
+ interface BorderChars {
210
+ topLeft: string;
211
+ top: string;
212
+ topRight: string;
213
+ right: string;
214
+ bottomRight: string;
215
+ bottom: string;
216
+ bottomLeft: string;
217
+ left: string;
218
+ }
219
+ /**
220
+ * Get border characters for the specified style.
221
+ */
222
+ declare function getBorderChars(style: BorderStyle): BorderChars;
223
+
224
+ export { type Alignment, type BorderChars, type BorderStyle, BoxComponent, type BoxInput, type BoxInputWithDefaults, type NormalizedPadding, type Padding, alignmentSchema, borderStyleSchema, boxInputSchema, createBox, getBorderChars, paddingSchema };
package/dist/index.js ADDED
@@ -0,0 +1,354 @@
1
+ // src/box.ts
2
+ import {
3
+ BaseTuiComponent,
4
+ getStringWidth,
5
+ getMarkdownRenderedWidth,
6
+ padToWidth,
7
+ measureLines,
8
+ registry
9
+ } from "@tuicomponents/core";
10
+ import { zodToJsonSchema } from "zod-to-json-schema";
11
+
12
+ // src/schema.ts
13
+ import { z } from "zod";
14
+ var borderStyleSchema = z.enum([
15
+ "single",
16
+ "double",
17
+ "round",
18
+ "bold",
19
+ "singleDouble",
20
+ "doubleSingle",
21
+ "classic",
22
+ "none"
23
+ ]);
24
+ var alignmentSchema = z.enum(["left", "center", "right"]);
25
+ var paddingSchema = z.union([
26
+ z.number().int().nonnegative(),
27
+ z.object({
28
+ top: z.number().int().nonnegative().optional().default(0),
29
+ right: z.number().int().nonnegative().optional().default(0),
30
+ bottom: z.number().int().nonnegative().optional().default(0),
31
+ left: z.number().int().nonnegative().optional().default(0)
32
+ })
33
+ ]);
34
+ var boxInputSchema = z.object({
35
+ /** Content to display inside the box */
36
+ content: z.string(),
37
+ /** Title to display in the top border */
38
+ title: z.string().optional(),
39
+ /** Title alignment */
40
+ titleAlignment: alignmentSchema.optional().default("left"),
41
+ /** Border style */
42
+ borderStyle: borderStyleSchema.optional().default("single"),
43
+ /** Padding inside the box */
44
+ padding: paddingSchema.optional().default(0),
45
+ /** Fixed width (if not set, fits content) */
46
+ width: z.number().int().positive().optional(),
47
+ /** Text alignment within the box */
48
+ textAlignment: alignmentSchema.optional().default("left"),
49
+ /** Whether to dim the border */
50
+ dimBorder: z.boolean().optional().default(false)
51
+ });
52
+
53
+ // src/chars.ts
54
+ var borderCharSets = {
55
+ single: {
56
+ topLeft: "\u250C",
57
+ top: "\u2500",
58
+ topRight: "\u2510",
59
+ right: "\u2502",
60
+ bottomRight: "\u2518",
61
+ bottom: "\u2500",
62
+ bottomLeft: "\u2514",
63
+ left: "\u2502"
64
+ },
65
+ double: {
66
+ topLeft: "\u2554",
67
+ top: "\u2550",
68
+ topRight: "\u2557",
69
+ right: "\u2551",
70
+ bottomRight: "\u255D",
71
+ bottom: "\u2550",
72
+ bottomLeft: "\u255A",
73
+ left: "\u2551"
74
+ },
75
+ round: {
76
+ topLeft: "\u256D",
77
+ top: "\u2500",
78
+ topRight: "\u256E",
79
+ right: "\u2502",
80
+ bottomRight: "\u256F",
81
+ bottom: "\u2500",
82
+ bottomLeft: "\u2570",
83
+ left: "\u2502"
84
+ },
85
+ bold: {
86
+ topLeft: "\u250F",
87
+ top: "\u2501",
88
+ topRight: "\u2513",
89
+ right: "\u2503",
90
+ bottomRight: "\u251B",
91
+ bottom: "\u2501",
92
+ bottomLeft: "\u2517",
93
+ left: "\u2503"
94
+ },
95
+ singleDouble: {
96
+ topLeft: "\u2553",
97
+ top: "\u2500",
98
+ topRight: "\u2556",
99
+ right: "\u2551",
100
+ bottomRight: "\u255C",
101
+ bottom: "\u2500",
102
+ bottomLeft: "\u2559",
103
+ left: "\u2551"
104
+ },
105
+ doubleSingle: {
106
+ topLeft: "\u2552",
107
+ top: "\u2550",
108
+ topRight: "\u2555",
109
+ right: "\u2502",
110
+ bottomRight: "\u255B",
111
+ bottom: "\u2550",
112
+ bottomLeft: "\u2558",
113
+ left: "\u2502"
114
+ },
115
+ classic: {
116
+ topLeft: "+",
117
+ top: "-",
118
+ topRight: "+",
119
+ right: "|",
120
+ bottomRight: "+",
121
+ bottom: "-",
122
+ bottomLeft: "+",
123
+ left: "|"
124
+ },
125
+ none: {
126
+ topLeft: " ",
127
+ top: " ",
128
+ topRight: " ",
129
+ right: " ",
130
+ bottomRight: " ",
131
+ bottom: " ",
132
+ bottomLeft: " ",
133
+ left: " "
134
+ }
135
+ };
136
+ function getBorderChars(style) {
137
+ return borderCharSets[style];
138
+ }
139
+
140
+ // src/box.ts
141
+ function colorBorder(text, theme) {
142
+ if (!theme) {
143
+ return text;
144
+ }
145
+ return theme.semantic.border(text);
146
+ }
147
+ function colorTitle(text, theme) {
148
+ if (!theme) {
149
+ return text;
150
+ }
151
+ return theme.semantic.header(text);
152
+ }
153
+ var BoxComponent = class extends BaseTuiComponent {
154
+ metadata = {
155
+ name: "box",
156
+ description: "Renders content in a bordered box/panel",
157
+ version: "0.1.0",
158
+ examples: [
159
+ {
160
+ name: "basic",
161
+ description: "Simple box with content",
162
+ input: {
163
+ content: "Hello, World!"
164
+ }
165
+ },
166
+ {
167
+ name: "with-title",
168
+ description: "Box with a title",
169
+ input: {
170
+ content: "This is the content inside the box.",
171
+ title: "My Title"
172
+ }
173
+ },
174
+ {
175
+ name: "rounded",
176
+ description: "Box with rounded corners",
177
+ input: {
178
+ content: "Rounded corners look nice!",
179
+ borderStyle: "round",
180
+ padding: 1
181
+ }
182
+ },
183
+ {
184
+ name: "double-border",
185
+ description: "Box with double-line border",
186
+ input: {
187
+ content: "Double border style",
188
+ borderStyle: "double",
189
+ title: "Important",
190
+ titleAlignment: "center"
191
+ }
192
+ },
193
+ {
194
+ name: "centered-text",
195
+ description: "Box with centered content",
196
+ input: {
197
+ content: "Centered\nMultiple lines\nAll centered",
198
+ textAlignment: "center",
199
+ width: 30,
200
+ padding: { top: 1, bottom: 1, left: 2, right: 2 }
201
+ }
202
+ }
203
+ ]
204
+ };
205
+ schema = boxInputSchema;
206
+ /**
207
+ * Override getJsonSchema to use direct schema generation.
208
+ */
209
+ getJsonSchema() {
210
+ return zodToJsonSchema(this.schema, {
211
+ name: this.metadata.name,
212
+ $refStrategy: "none"
213
+ });
214
+ }
215
+ render(input, context) {
216
+ const parsed = this.schema.parse(input);
217
+ const chars = getBorderChars(parsed.borderStyle);
218
+ const padding = this.normalizePadding(parsed.padding);
219
+ const theme = context.theme;
220
+ const contentMeasured = measureLines(parsed.content);
221
+ const contentLines = contentMeasured.lines;
222
+ const titleWidth = parsed.title ? context.renderMode === "markdown" ? getMarkdownRenderedWidth(` ${parsed.title} `) : getStringWidth(` ${parsed.title} `) : 0;
223
+ let contentWidth;
224
+ if (parsed.width) {
225
+ contentWidth = parsed.width - 2 - padding.left - padding.right;
226
+ } else {
227
+ const minWidthForTitle = Math.max(
228
+ 0,
229
+ titleWidth - padding.left - padding.right
230
+ );
231
+ contentWidth = Math.max(contentMeasured.maxWidth, minWidthForTitle);
232
+ }
233
+ const innerWidth = contentWidth + padding.left + padding.right;
234
+ const outputLines = [];
235
+ outputLines.push(
236
+ this.buildTopBorder(
237
+ chars,
238
+ innerWidth,
239
+ parsed.title,
240
+ parsed.titleAlignment,
241
+ theme,
242
+ context.renderMode
243
+ )
244
+ );
245
+ for (let i = 0; i < padding.top; i++) {
246
+ outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));
247
+ }
248
+ for (const line of contentLines) {
249
+ outputLines.push(
250
+ this.buildContentLine(
251
+ chars,
252
+ line,
253
+ contentWidth,
254
+ padding,
255
+ parsed.textAlignment,
256
+ theme
257
+ )
258
+ );
259
+ }
260
+ for (let i = 0; i < padding.bottom; i++) {
261
+ outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));
262
+ }
263
+ outputLines.push(this.buildBottomBorder(chars, innerWidth, theme));
264
+ const output = outputLines.join("\n");
265
+ const measured = measureLines(output);
266
+ return {
267
+ output,
268
+ actualWidth: measured.maxWidth,
269
+ lineCount: measured.lineCount
270
+ };
271
+ }
272
+ /**
273
+ * Normalize padding to object with all sides.
274
+ */
275
+ normalizePadding(padding) {
276
+ if (typeof padding === "number") {
277
+ return { top: padding, right: padding, bottom: padding, left: padding };
278
+ }
279
+ return {
280
+ top: padding.top,
281
+ right: padding.right,
282
+ bottom: padding.bottom,
283
+ left: padding.left
284
+ };
285
+ }
286
+ /**
287
+ * Build the top border with optional title.
288
+ */
289
+ buildTopBorder(chars, innerWidth, title, titleAlignment, theme, renderMode) {
290
+ if (!title) {
291
+ const border = chars.topLeft + chars.top.repeat(innerWidth) + chars.topRight;
292
+ return colorBorder(border, theme);
293
+ }
294
+ const titleWithSpace = ` ${title} `;
295
+ const titleWidth = renderMode === "markdown" ? getMarkdownRenderedWidth(titleWithSpace) : getStringWidth(titleWithSpace);
296
+ if (titleWidth > innerWidth) {
297
+ const truncatedTitle = titleWithSpace.slice(0, innerWidth - 1) + "\u2026";
298
+ return colorBorder(chars.topLeft, theme) + colorTitle(truncatedTitle, theme) + colorBorder(chars.topRight, theme);
299
+ }
300
+ const remainingWidth = innerWidth - titleWidth;
301
+ switch (titleAlignment) {
302
+ case "center": {
303
+ const leftPad = Math.floor(remainingWidth / 2);
304
+ const rightPad = remainingWidth - leftPad;
305
+ return colorBorder(chars.topLeft + chars.top.repeat(leftPad), theme) + colorTitle(titleWithSpace, theme) + colorBorder(chars.top.repeat(rightPad) + chars.topRight, theme);
306
+ }
307
+ case "right": {
308
+ return colorBorder(chars.topLeft + chars.top.repeat(remainingWidth), theme) + colorTitle(titleWithSpace, theme) + colorBorder(chars.topRight, theme);
309
+ }
310
+ case "left":
311
+ default: {
312
+ return colorBorder(chars.topLeft, theme) + colorTitle(titleWithSpace, theme) + colorBorder(chars.top.repeat(remainingWidth) + chars.topRight, theme);
313
+ }
314
+ }
315
+ }
316
+ /**
317
+ * Build an empty line (for padding).
318
+ */
319
+ buildEmptyLine(chars, innerWidth, theme) {
320
+ return colorBorder(chars.left, theme) + " ".repeat(innerWidth) + colorBorder(chars.right, theme);
321
+ }
322
+ /**
323
+ * Build a content line with padding and alignment.
324
+ */
325
+ buildContentLine(chars, content, contentWidth, padding, textAlignment, theme) {
326
+ const alignedContent = padToWidth(content, contentWidth, {
327
+ align: textAlignment
328
+ });
329
+ const leftPad = " ".repeat(padding.left);
330
+ const rightPad = " ".repeat(padding.right);
331
+ return colorBorder(chars.left, theme) + leftPad + alignedContent + rightPad + colorBorder(chars.right, theme);
332
+ }
333
+ /**
334
+ * Build the bottom border.
335
+ */
336
+ buildBottomBorder(chars, innerWidth, theme) {
337
+ const border = chars.bottomLeft + chars.bottom.repeat(innerWidth) + chars.bottomRight;
338
+ return colorBorder(border, theme);
339
+ }
340
+ };
341
+ function createBox() {
342
+ return new BoxComponent();
343
+ }
344
+ registry.register(createBox);
345
+ export {
346
+ BoxComponent,
347
+ alignmentSchema,
348
+ borderStyleSchema,
349
+ boxInputSchema,
350
+ createBox,
351
+ getBorderChars,
352
+ paddingSchema
353
+ };
354
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/box.ts","../src/schema.ts","../src/chars.ts"],"sourcesContent":["import {\n BaseTuiComponent,\n type ComponentMetadata,\n type RenderContext,\n type RenderResult,\n type TuiTheme,\n type RenderMode,\n getStringWidth,\n getMarkdownRenderedWidth,\n padToWidth,\n measureLines,\n registry,\n} from \"@tuicomponents/core\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport {\n boxInputSchema,\n type BoxInput,\n type BoxInputWithDefaults,\n type NormalizedPadding,\n type Padding,\n type Alignment,\n} from \"./schema.js\";\nimport { getBorderChars, type BorderChars } from \"./chars.js\";\n\n/**\n * Apply border color to text.\n */\nfunction colorBorder(text: string, theme: TuiTheme | undefined): string {\n if (!theme) {\n return text;\n }\n return theme.semantic.border(text);\n}\n\n/**\n * Apply header/title color to text.\n */\nfunction colorTitle(text: string, theme: TuiTheme | undefined): string {\n if (!theme) {\n return text;\n }\n return theme.semantic.header(text);\n}\n\n/**\n * Box component for rendering content in bordered panels.\n */\nclass BoxComponent extends BaseTuiComponent<BoxInput, typeof boxInputSchema> {\n readonly metadata: ComponentMetadata<BoxInput> = {\n name: \"box\",\n description: \"Renders content in a bordered box/panel\",\n version: \"0.1.0\",\n examples: [\n {\n name: \"basic\",\n description: \"Simple box with content\",\n input: {\n content: \"Hello, World!\",\n },\n },\n {\n name: \"with-title\",\n description: \"Box with a title\",\n input: {\n content: \"This is the content inside the box.\",\n title: \"My Title\",\n },\n },\n {\n name: \"rounded\",\n description: \"Box with rounded corners\",\n input: {\n content: \"Rounded corners look nice!\",\n borderStyle: \"round\",\n padding: 1,\n },\n },\n {\n name: \"double-border\",\n description: \"Box with double-line border\",\n input: {\n content: \"Double border style\",\n borderStyle: \"double\",\n title: \"Important\",\n titleAlignment: \"center\",\n },\n },\n {\n name: \"centered-text\",\n description: \"Box with centered content\",\n input: {\n content: \"Centered\\nMultiple lines\\nAll centered\",\n textAlignment: \"center\",\n width: 30,\n padding: { top: 1, bottom: 1, left: 2, right: 2 },\n },\n },\n ],\n };\n\n readonly schema = boxInputSchema;\n\n /**\n * Override getJsonSchema to use direct schema generation.\n */\n override getJsonSchema(): object {\n return zodToJsonSchema(this.schema, {\n name: this.metadata.name,\n $refStrategy: \"none\",\n });\n }\n\n render(input: BoxInput, context: RenderContext): RenderResult {\n // Parse and apply defaults\n const parsed: BoxInputWithDefaults = this.schema.parse(input);\n const chars = getBorderChars(parsed.borderStyle);\n const padding = this.normalizePadding(parsed.padding);\n const theme = context.theme;\n\n // Split content into lines\n const contentMeasured = measureLines(parsed.content);\n const contentLines = contentMeasured.lines;\n\n // Calculate title width requirement (title + surrounding spaces)\n // In markdown mode, use visual width (formatting chars like ** and _ are invisible)\n const titleWidth = parsed.title\n ? context.renderMode === \"markdown\"\n ? getMarkdownRenderedWidth(` ${parsed.title} `)\n : getStringWidth(` ${parsed.title} `)\n : 0;\n\n // Determine content width - must fit both content and title\n let contentWidth: number;\n if (parsed.width) {\n contentWidth = parsed.width - 2 - padding.left - padding.right; // Account for borders and padding\n } else {\n // Use the larger of content width or title width (minus padding)\n const minWidthForTitle = Math.max(\n 0,\n titleWidth - padding.left - padding.right\n );\n contentWidth = Math.max(contentMeasured.maxWidth, minWidthForTitle);\n }\n\n // Calculate total inner width (content + horizontal padding)\n const innerWidth = contentWidth + padding.left + padding.right;\n\n // Build output lines\n const outputLines: string[] = [];\n\n // Top border with optional title\n outputLines.push(\n this.buildTopBorder(\n chars,\n innerWidth,\n parsed.title,\n parsed.titleAlignment,\n theme,\n context.renderMode\n )\n );\n\n // Top padding\n for (let i = 0; i < padding.top; i++) {\n outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));\n }\n\n // Content lines\n for (const line of contentLines) {\n outputLines.push(\n this.buildContentLine(\n chars,\n line,\n contentWidth,\n padding,\n parsed.textAlignment,\n theme\n )\n );\n }\n\n // Bottom padding\n for (let i = 0; i < padding.bottom; i++) {\n outputLines.push(this.buildEmptyLine(chars, innerWidth, theme));\n }\n\n // Bottom border\n outputLines.push(this.buildBottomBorder(chars, innerWidth, theme));\n\n const output = outputLines.join(\"\\n\");\n const measured = measureLines(output);\n\n return {\n output,\n actualWidth: measured.maxWidth,\n lineCount: measured.lineCount,\n };\n }\n\n /**\n * Normalize padding to object with all sides.\n */\n private normalizePadding(padding: Padding): NormalizedPadding {\n if (typeof padding === \"number\") {\n return { top: padding, right: padding, bottom: padding, left: padding };\n }\n // After schema parsing with .default(0), all fields are guaranteed to be numbers\n return {\n top: padding.top,\n right: padding.right,\n bottom: padding.bottom,\n left: padding.left,\n };\n }\n\n /**\n * Build the top border with optional title.\n */\n private buildTopBorder(\n chars: BorderChars,\n innerWidth: number,\n title: string | undefined,\n titleAlignment: Alignment,\n theme: TuiTheme | undefined,\n renderMode: RenderMode\n ): string {\n if (!title) {\n const border =\n chars.topLeft + chars.top.repeat(innerWidth) + chars.topRight;\n return colorBorder(border, theme);\n }\n\n const titleWithSpace = ` ${title} `;\n // In markdown mode, use visual width (formatting chars like ** and _ are invisible when rendered)\n const titleWidth =\n renderMode === \"markdown\"\n ? getMarkdownRenderedWidth(titleWithSpace)\n : getStringWidth(titleWithSpace);\n\n // If title is too long, truncate\n if (titleWidth > innerWidth) {\n const truncatedTitle = titleWithSpace.slice(0, innerWidth - 1) + \"…\";\n return (\n colorBorder(chars.topLeft, theme) +\n colorTitle(truncatedTitle, theme) +\n colorBorder(chars.topRight, theme)\n );\n }\n\n const remainingWidth = innerWidth - titleWidth;\n\n switch (titleAlignment) {\n case \"center\": {\n const leftPad = Math.floor(remainingWidth / 2);\n const rightPad = remainingWidth - leftPad;\n return (\n colorBorder(chars.topLeft + chars.top.repeat(leftPad), theme) +\n colorTitle(titleWithSpace, theme) +\n colorBorder(chars.top.repeat(rightPad) + chars.topRight, theme)\n );\n }\n case \"right\": {\n return (\n colorBorder(chars.topLeft + chars.top.repeat(remainingWidth), theme) +\n colorTitle(titleWithSpace, theme) +\n colorBorder(chars.topRight, theme)\n );\n }\n case \"left\":\n default: {\n return (\n colorBorder(chars.topLeft, theme) +\n colorTitle(titleWithSpace, theme) +\n colorBorder(chars.top.repeat(remainingWidth) + chars.topRight, theme)\n );\n }\n }\n }\n\n /**\n * Build an empty line (for padding).\n */\n private buildEmptyLine(\n chars: BorderChars,\n innerWidth: number,\n theme: TuiTheme | undefined\n ): string {\n return (\n colorBorder(chars.left, theme) +\n \" \".repeat(innerWidth) +\n colorBorder(chars.right, theme)\n );\n }\n\n /**\n * Build a content line with padding and alignment.\n */\n private buildContentLine(\n chars: BorderChars,\n content: string,\n contentWidth: number,\n padding: NormalizedPadding,\n textAlignment: Alignment,\n theme: TuiTheme | undefined\n ): string {\n // Pad/align content within content area\n const alignedContent = padToWidth(content, contentWidth, {\n align: textAlignment,\n });\n\n // Add horizontal padding\n const leftPad = \" \".repeat(padding.left);\n const rightPad = \" \".repeat(padding.right);\n\n return (\n colorBorder(chars.left, theme) +\n leftPad +\n alignedContent +\n rightPad +\n colorBorder(chars.right, theme)\n );\n }\n\n /**\n * Build the bottom border.\n */\n private buildBottomBorder(\n chars: BorderChars,\n innerWidth: number,\n theme: TuiTheme | undefined\n ): string {\n const border =\n chars.bottomLeft + chars.bottom.repeat(innerWidth) + chars.bottomRight;\n return colorBorder(border, theme);\n }\n}\n\n/**\n * Factory function to create a box component.\n */\nexport function createBox(): BoxComponent {\n return new BoxComponent();\n}\n\n// Register with global registry\nregistry.register(createBox);\n\nexport { BoxComponent };\n","import { z } from \"zod\";\n\n/**\n * Border style options for box rendering.\n */\nexport const borderStyleSchema = z.enum([\n \"single\",\n \"double\",\n \"round\",\n \"bold\",\n \"singleDouble\",\n \"doubleSingle\",\n \"classic\",\n \"none\",\n]);\n\nexport type BorderStyle = z.infer<typeof borderStyleSchema>;\n\n/**\n * Text alignment options.\n */\nexport const alignmentSchema = z.enum([\"left\", \"center\", \"right\"]);\n\nexport type Alignment = z.infer<typeof alignmentSchema>;\n\n/**\n * Padding configuration - can be a single number or object with sides.\n */\nexport const paddingSchema = z.union([\n z.number().int().nonnegative(),\n z.object({\n top: z.number().int().nonnegative().optional().default(0),\n right: z.number().int().nonnegative().optional().default(0),\n bottom: z.number().int().nonnegative().optional().default(0),\n left: z.number().int().nonnegative().optional().default(0),\n }),\n]);\n\nexport type Padding = z.infer<typeof paddingSchema>;\n\n/**\n * Normalized padding with all sides specified.\n */\nexport interface NormalizedPadding {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/**\n * Schema for box component input.\n */\nexport const boxInputSchema = z.object({\n /** Content to display inside the box */\n content: z.string(),\n /** Title to display in the top border */\n title: z.string().optional(),\n /** Title alignment */\n titleAlignment: alignmentSchema.optional().default(\"left\"),\n /** Border style */\n borderStyle: borderStyleSchema.optional().default(\"single\"),\n /** Padding inside the box */\n padding: paddingSchema.optional().default(0),\n /** Fixed width (if not set, fits content) */\n width: z.number().int().positive().optional(),\n /** Text alignment within the box */\n textAlignment: alignmentSchema.optional().default(\"left\"),\n /** Whether to dim the border */\n dimBorder: z.boolean().optional().default(false),\n});\n\n/**\n * Input type (before defaults applied).\n */\nexport type BoxInput = z.input<typeof boxInputSchema>;\n\n/**\n * Input type (after defaults applied).\n */\nexport type BoxInputWithDefaults = z.output<typeof boxInputSchema>;\n","import type { BorderStyle } from \"./schema.js\";\n\n/**\n * Border character set for box rendering.\n */\nexport interface BorderChars {\n topLeft: string;\n top: string;\n topRight: string;\n right: string;\n bottomRight: string;\n bottom: string;\n bottomLeft: string;\n left: string;\n}\n\n/**\n * Border character sets for different styles.\n */\nconst borderCharSets: Record<BorderStyle, BorderChars> = {\n single: {\n topLeft: \"┌\",\n top: \"─\",\n topRight: \"┐\",\n right: \"│\",\n bottomRight: \"┘\",\n bottom: \"─\",\n bottomLeft: \"└\",\n left: \"│\",\n },\n double: {\n topLeft: \"╔\",\n top: \"═\",\n topRight: \"╗\",\n right: \"║\",\n bottomRight: \"╝\",\n bottom: \"═\",\n bottomLeft: \"╚\",\n left: \"║\",\n },\n round: {\n topLeft: \"╭\",\n top: \"─\",\n topRight: \"╮\",\n right: \"│\",\n bottomRight: \"╯\",\n bottom: \"─\",\n bottomLeft: \"╰\",\n left: \"│\",\n },\n bold: {\n topLeft: \"┏\",\n top: \"━\",\n topRight: \"┓\",\n right: \"┃\",\n bottomRight: \"┛\",\n bottom: \"━\",\n bottomLeft: \"┗\",\n left: \"┃\",\n },\n singleDouble: {\n topLeft: \"╓\",\n top: \"─\",\n topRight: \"╖\",\n right: \"║\",\n bottomRight: \"╜\",\n bottom: \"─\",\n bottomLeft: \"╙\",\n left: \"║\",\n },\n doubleSingle: {\n topLeft: \"╒\",\n top: \"═\",\n topRight: \"╕\",\n right: \"│\",\n bottomRight: \"╛\",\n bottom: \"═\",\n bottomLeft: \"╘\",\n left: \"│\",\n },\n classic: {\n topLeft: \"+\",\n top: \"-\",\n topRight: \"+\",\n right: \"|\",\n bottomRight: \"+\",\n bottom: \"-\",\n bottomLeft: \"+\",\n left: \"|\",\n },\n none: {\n topLeft: \" \",\n top: \" \",\n topRight: \" \",\n right: \" \",\n bottomRight: \" \",\n bottom: \" \",\n bottomLeft: \" \",\n left: \" \",\n },\n};\n\n/**\n * Get border characters for the specified style.\n */\nexport function getBorderChars(style: BorderStyle): BorderChars {\n return borderCharSets[style];\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@tuicomponents/box",
3
+ "version": "0.1.1",
4
+ "description": "Box component for TUI - renders content in bordered panels",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "keywords": [
25
+ "tui",
26
+ "terminal",
27
+ "box",
28
+ "panel",
29
+ "border"
30
+ ],
31
+ "license": "UNLICENSED",
32
+ "dependencies": {
33
+ "zod": "^3.24.0",
34
+ "zod-to-json-schema": "^3.24.0",
35
+ "@tuicomponents/core": "0.1.1"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^22.0.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "typecheck": "tsc --noEmit",
43
+ "lint": "eslint src",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "api-report": "api-extractor run",
47
+ "api-report:update": "api-extractor run --local",
48
+ "clean": "rm -rf dist"
49
+ }
50
+ }