@suds-cli/table 0.0.1-alpha.0 → 0.1.0-alpha.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,420 @@
1
+ 'use strict';
2
+
3
+ var chapstick = require('@suds-cli/chapstick');
4
+ var key = require('@suds-cli/key');
5
+ var tea = require('@suds-cli/tea');
6
+
7
+ // src/model.ts
8
+ var defaultKeyMap = {
9
+ lineUp: key.newBinding({
10
+ keys: ["up", "k"],
11
+ help: { key: "\u2191/k", desc: "up" }
12
+ }),
13
+ lineDown: key.newBinding({
14
+ keys: ["down", "j"],
15
+ help: { key: "\u2193/j", desc: "down" }
16
+ }),
17
+ pageUp: key.newBinding({
18
+ keys: ["pgup", "b", "ctrl+u"],
19
+ help: { key: "pgup/b", desc: "page up" }
20
+ }),
21
+ pageDown: key.newBinding({
22
+ keys: ["pgdown", "f", "ctrl+d"],
23
+ help: { key: "pgdn/f", desc: "page down" }
24
+ }),
25
+ halfPageUp: key.newBinding({
26
+ keys: ["u"],
27
+ help: { key: "u", desc: "\xBD page up" }
28
+ }),
29
+ halfPageDown: key.newBinding({
30
+ keys: ["d"],
31
+ help: { key: "d", desc: "\xBD page down" }
32
+ }),
33
+ gotoTop: key.newBinding({
34
+ keys: ["home", "g"],
35
+ help: { key: "home/g", desc: "go to start" }
36
+ }),
37
+ gotoBottom: key.newBinding({
38
+ keys: ["end", "G"],
39
+ help: { key: "end/G", desc: "go to end" }
40
+ })
41
+ };
42
+ function defaultStyles() {
43
+ return {
44
+ header: new chapstick.Style().bold(true).padding(0, 1),
45
+ cell: new chapstick.Style().padding(0, 1),
46
+ selected: new chapstick.Style().background("#7D56F4").foreground("#FFFFFF"),
47
+ border: new chapstick.Style().foreground("#383838"),
48
+ borderStyle: chapstick.borderStyles.normal
49
+ };
50
+ }
51
+
52
+ // src/model.ts
53
+ var ELLIPSIS = "\u2026";
54
+ function clamp(value, min, max) {
55
+ if (Number.isNaN(value)) return min;
56
+ if (max < min) return min;
57
+ return Math.min(max, Math.max(min, value));
58
+ }
59
+ function clampOffset(offset, rowCount, height, cursor) {
60
+ if (height <= 0) return 0;
61
+ const maxOffset = Math.max(0, rowCount - height);
62
+ let nextOffset = clamp(offset, 0, maxOffset);
63
+ if (cursor < nextOffset) {
64
+ nextOffset = cursor;
65
+ } else if (cursor >= nextOffset + height) {
66
+ nextOffset = Math.max(0, cursor - height + 1);
67
+ }
68
+ return nextOffset;
69
+ }
70
+ function truncateWithEllipsis(text, width) {
71
+ const target = Math.max(0, width);
72
+ if (target === 0) return "";
73
+ if (chapstick.width(text) <= target) return text;
74
+ if (target === 1) return ELLIPSIS;
75
+ let acc = "";
76
+ for (const ch of text) {
77
+ if (chapstick.width(acc + ch) >= target) {
78
+ break;
79
+ }
80
+ acc += ch;
81
+ if (chapstick.width(acc) === target - 1) {
82
+ break;
83
+ }
84
+ }
85
+ return `${acc}${ELLIPSIS}`;
86
+ }
87
+ function padToWidth(input, width) {
88
+ const current = chapstick.width(input);
89
+ const missing = Math.max(0, width - current);
90
+ return `${input}${" ".repeat(missing)}`;
91
+ }
92
+ function calculateColumnWidths(columns, totalWidth, bordered) {
93
+ const borderWidth = bordered ? columns.length + 1 : 0;
94
+ const available = Math.max(0, totalWidth - borderWidth);
95
+ const fixed = columns.map((c) => Math.max(0, c.width));
96
+ const totalFixed = fixed.reduce((a, b) => a + b, 0);
97
+ if (totalFixed > available && totalFixed > 0) {
98
+ const scale = available / totalFixed;
99
+ return fixed.map((w) => Math.max(0, Math.floor(w * scale)));
100
+ }
101
+ return fixed;
102
+ }
103
+ function mergeKeyMap(base, overrides) {
104
+ return {
105
+ lineUp: overrides?.lineUp ?? base.lineUp,
106
+ lineDown: overrides?.lineDown ?? base.lineDown,
107
+ pageUp: overrides?.pageUp ?? base.pageUp,
108
+ pageDown: overrides?.pageDown ?? base.pageDown,
109
+ halfPageUp: overrides?.halfPageUp ?? base.halfPageUp,
110
+ halfPageDown: overrides?.halfPageDown ?? base.halfPageDown,
111
+ gotoTop: overrides?.gotoTop ?? base.gotoTop,
112
+ gotoBottom: overrides?.gotoBottom ?? base.gotoBottom
113
+ };
114
+ }
115
+ function mergeStyles(overrides, borderStyleOverride) {
116
+ const base = defaultStyles();
117
+ const merged = {
118
+ ...base,
119
+ ...overrides
120
+ };
121
+ if (borderStyleOverride) {
122
+ merged.borderStyle = borderStyleOverride;
123
+ } else if (!merged.borderStyle) {
124
+ merged.borderStyle = chapstick.defaultBorderStyle;
125
+ }
126
+ return merged;
127
+ }
128
+ function totalColumnWidth(columns, bordered) {
129
+ const base = columns.reduce((sum, col) => sum + Math.max(0, col.width), 0);
130
+ return bordered ? base + Math.max(0, columns.length - 1) : base;
131
+ }
132
+ function fixedWidthCell(text, width) {
133
+ if (width <= 0) return "";
134
+ const truncated = truncateWithEllipsis(text, width);
135
+ return new chapstick.Style().width(width).maxWidth(width).alignHorizontal("left").inline(true).render(truncated);
136
+ }
137
+ function wrapWithBorder(line, innerWidth, styles) {
138
+ const width = Math.max(0, innerWidth);
139
+ const padded = padToWidth(line, width);
140
+ const wrapped = `${styles.borderStyle.left}${padded}${styles.borderStyle.right}`;
141
+ return styles.border.render(wrapped);
142
+ }
143
+ function renderTopBorder(innerWidth, styles) {
144
+ const line = `${styles.borderStyle.topLeft}${styles.borderStyle.top.repeat(Math.max(0, innerWidth))}${styles.borderStyle.topRight}`;
145
+ return styles.border.render(line);
146
+ }
147
+ function renderSeparator(innerWidth, styles) {
148
+ const line = `${styles.borderStyle.left}${styles.borderStyle.top.repeat(Math.max(0, innerWidth))}${styles.borderStyle.right}`;
149
+ return styles.border.render(line);
150
+ }
151
+ function renderBottomBorder(innerWidth, styles) {
152
+ const line = `${styles.borderStyle.bottomLeft}${styles.borderStyle.bottom.repeat(Math.max(0, innerWidth))}${styles.borderStyle.bottomRight}`;
153
+ return styles.border.render(line);
154
+ }
155
+ var TableModel = class _TableModel {
156
+ columns;
157
+ rows;
158
+ cursor;
159
+ offset;
160
+ focused;
161
+ height;
162
+ width;
163
+ autoWidth;
164
+ keyMap;
165
+ styles;
166
+ bordered;
167
+ columnWidths;
168
+ constructor(state) {
169
+ this.columns = state.columns;
170
+ this.rows = state.rows;
171
+ this.cursor = state.cursor;
172
+ this.offset = state.offset;
173
+ this.focused = state.focused;
174
+ this.height = state.height;
175
+ this.width = state.width;
176
+ this.autoWidth = state.autoWidth;
177
+ this.keyMap = state.keyMap;
178
+ this.styles = state.styles;
179
+ this.bordered = state.bordered;
180
+ this.columnWidths = state.columnWidths;
181
+ }
182
+ /** Create a new table model. */
183
+ static new(options) {
184
+ const rows = [...options.rows ?? []];
185
+ const bordered = options.bordered ?? false;
186
+ const styles = mergeStyles(options.styles, options.borderStyle);
187
+ const width = options.width ?? totalColumnWidth(options.columns, bordered) ?? 0;
188
+ const autoWidth = options.width === void 0;
189
+ const height = Math.max(0, options.height ?? rows.length);
190
+ const columnWidths = autoWidth ? options.columns.map((c) => Math.max(0, c.width)) : calculateColumnWidths(options.columns, width, bordered);
191
+ const cursor = clamp(
192
+ options.focused ? 0 : 0,
193
+ 0,
194
+ Math.max(rows.length - 1, 0)
195
+ );
196
+ const offset = clampOffset(0, rows.length, height, cursor);
197
+ return new _TableModel({
198
+ columns: [...options.columns],
199
+ rows,
200
+ cursor,
201
+ offset,
202
+ focused: options.focused ?? false,
203
+ height,
204
+ width,
205
+ autoWidth,
206
+ keyMap: mergeKeyMap(defaultKeyMap, options.keyMap),
207
+ styles,
208
+ bordered,
209
+ columnWidths
210
+ });
211
+ }
212
+ /** Tea init hook (no-op). */
213
+ init() {
214
+ return null;
215
+ }
216
+ /** Handle key messages when focused. */
217
+ update(msg) {
218
+ if (!this.focused || !(msg instanceof tea.KeyMsg)) {
219
+ return [this, null];
220
+ }
221
+ if (key.matches(msg, this.keyMap.lineUp)) {
222
+ return [this.moveUp(1), null];
223
+ }
224
+ if (key.matches(msg, this.keyMap.lineDown)) {
225
+ return [this.moveDown(1), null];
226
+ }
227
+ if (key.matches(msg, this.keyMap.pageUp)) {
228
+ return [this.moveUp(this.height || 1), null];
229
+ }
230
+ if (key.matches(msg, this.keyMap.pageDown)) {
231
+ return [this.moveDown(this.height || 1), null];
232
+ }
233
+ if (key.matches(msg, this.keyMap.halfPageUp)) {
234
+ return [this.moveUp(Math.max(1, Math.floor(this.height / 2))), null];
235
+ }
236
+ if (key.matches(msg, this.keyMap.halfPageDown)) {
237
+ return [this.moveDown(Math.max(1, Math.floor(this.height / 2))), null];
238
+ }
239
+ if (key.matches(msg, this.keyMap.gotoTop)) {
240
+ return [this.gotoTop(), null];
241
+ }
242
+ if (key.matches(msg, this.keyMap.gotoBottom)) {
243
+ return [this.gotoBottom(), null];
244
+ }
245
+ return [this, null];
246
+ }
247
+ /** Render the header and visible rows as a string. */
248
+ view() {
249
+ const header = this.renderHeader();
250
+ const headerWidth = chapstick.width(header);
251
+ const start = this.offset;
252
+ const end = Math.min(start + this.height, this.rows.length);
253
+ const visibleRows = this.renderAllRows().slice(start, end);
254
+ const paddedRows = [...visibleRows];
255
+ while (paddedRows.length < this.height) {
256
+ paddedRows.push(this.renderEmptyRow());
257
+ }
258
+ const rowWidth = paddedRows.length > 0 ? chapstick.width(paddedRows[0] ?? "") : 0;
259
+ const innerWidth = Math.max(headerWidth, rowWidth);
260
+ if (!this.bordered) {
261
+ return [
262
+ padToWidth(header, innerWidth),
263
+ ...paddedRows.map((r) => padToWidth(r, innerWidth))
264
+ ].join("\n");
265
+ }
266
+ const wrap = (line) => wrapWithBorder(line, innerWidth, this.styles);
267
+ return [
268
+ renderTopBorder(innerWidth, this.styles),
269
+ wrap(padToWidth(header, innerWidth)),
270
+ renderSeparator(innerWidth, this.styles),
271
+ ...paddedRows.map((r) => wrap(padToWidth(r, innerWidth))),
272
+ renderBottomBorder(innerWidth, this.styles)
273
+ ].join("\n");
274
+ }
275
+ /** Current selected row, if any. */
276
+ selectedRow() {
277
+ if (this.rows.length === 0) return void 0;
278
+ return this.rows[this.cursor];
279
+ }
280
+ /** Current selected index. */
281
+ selectedIndex() {
282
+ return this.cursor;
283
+ }
284
+ /** Replace columns. */
285
+ setColumns(columns) {
286
+ return this.with({
287
+ columns: [...columns]
288
+ });
289
+ }
290
+ /** Replace rows. */
291
+ setRows(rows) {
292
+ return this.with({
293
+ rows: [...rows]
294
+ });
295
+ }
296
+ /** Append a single row. */
297
+ appendRow(row) {
298
+ return this.setRows([...this.rows, row]);
299
+ }
300
+ /** Remove a row by index. */
301
+ removeRow(index) {
302
+ if (index < 0 || index >= this.rows.length) return this;
303
+ const next = [...this.rows];
304
+ next.splice(index, 1);
305
+ return this.setRows(next);
306
+ }
307
+ /** Set the selected index (clamped). */
308
+ setSelectedIndex(index) {
309
+ return this.with({ cursor: index });
310
+ }
311
+ /** Move the cursor up by n rows. */
312
+ moveUp(n = 1) {
313
+ const delta = Math.max(1, n);
314
+ return this.with({ cursor: this.cursor - delta });
315
+ }
316
+ /** Move the cursor down by n rows. */
317
+ moveDown(n = 1) {
318
+ const delta = Math.max(1, n);
319
+ return this.with({ cursor: this.cursor + delta });
320
+ }
321
+ /** Jump to the first row. */
322
+ gotoTop() {
323
+ return this.with({ cursor: 0 });
324
+ }
325
+ /** Jump to the last row. */
326
+ gotoBottom() {
327
+ return this.with({ cursor: this.rows.length - 1 });
328
+ }
329
+ /** Focus the table. */
330
+ focus() {
331
+ if (this.focused) return this;
332
+ return this.with({ focused: true });
333
+ }
334
+ /** Blur the table. */
335
+ blur() {
336
+ if (!this.focused) return this;
337
+ return this.with({ focused: false });
338
+ }
339
+ /** Set the visible height (rows). */
340
+ setHeight(height) {
341
+ return this.with({ height });
342
+ }
343
+ /** Set the total width. */
344
+ setWidth(width) {
345
+ return this.with({ width });
346
+ }
347
+ renderHeader() {
348
+ const cells = this.columns.map((col, i) => {
349
+ const width = this.columnWidths[i] ?? col.width;
350
+ const fixedCell = fixedWidthCell(col.title, width);
351
+ return this.styles.header.render(fixedCell);
352
+ });
353
+ return chapstick.joinHorizontal(...cells);
354
+ }
355
+ renderRow(row, index) {
356
+ const isSelected = this.focused && index === this.cursor;
357
+ const cells = this.columns.map((col, i) => {
358
+ const width = this.columnWidths[i] ?? col.width;
359
+ const value = row[i] ?? "";
360
+ const fixedCell = fixedWidthCell(value, width);
361
+ return this.styles.cell.render(fixedCell);
362
+ });
363
+ const joined = chapstick.joinHorizontal(...cells);
364
+ if (isSelected) {
365
+ return this.styles.selected.render(joined);
366
+ }
367
+ return joined;
368
+ }
369
+ renderEmptyRow() {
370
+ const cells = this.columns.map((col, i) => {
371
+ const width = this.columnWidths[i] ?? col.width;
372
+ const fixedCell = fixedWidthCell("", width);
373
+ return this.styles.cell.render(fixedCell);
374
+ });
375
+ return chapstick.joinHorizontal(...cells);
376
+ }
377
+ renderAllRows() {
378
+ return this.rows.map((row, i) => this.renderRow(row, i));
379
+ }
380
+ with(patch) {
381
+ const nextColumns = patch.columns ?? this.columns;
382
+ const nextRows = patch.rows ?? this.rows;
383
+ const nextHeight = patch.height ?? this.height;
384
+ const nextWidth = patch.width ?? this.width;
385
+ const autoWidth = patch.width !== void 0 ? false : this.autoWidth;
386
+ const nextBordered = patch.bordered ?? this.bordered;
387
+ const nextColumnWidths = autoWidth ? nextColumns.map((c) => Math.max(0, c.width)) : calculateColumnWidths(nextColumns, nextWidth, nextBordered);
388
+ const cursor = clamp(
389
+ patch.cursor ?? this.cursor,
390
+ 0,
391
+ Math.max(nextRows.length - 1, 0)
392
+ );
393
+ const offset = clampOffset(
394
+ patch.offset ?? this.offset,
395
+ nextRows.length,
396
+ nextHeight,
397
+ cursor
398
+ );
399
+ return new _TableModel({
400
+ columns: [...nextColumns],
401
+ rows: [...nextRows],
402
+ cursor,
403
+ offset,
404
+ focused: patch.focused ?? this.focused,
405
+ height: Math.max(0, nextHeight),
406
+ width: Math.max(0, nextWidth),
407
+ autoWidth,
408
+ keyMap: patch.keyMap ?? this.keyMap,
409
+ styles: patch.styles ?? this.styles,
410
+ bordered: nextBordered,
411
+ columnWidths: nextColumnWidths
412
+ });
413
+ }
414
+ };
415
+
416
+ exports.TableModel = TableModel;
417
+ exports.defaultKeyMap = defaultKeyMap;
418
+ exports.defaultStyles = defaultStyles;
419
+ //# sourceMappingURL=index.cjs.map
420
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/keymap.ts","../src/styles.ts","../src/model.ts"],"names":["newBinding","Style","borderStyles","textWidth","defaultBorderStyle","KeyMsg","matches","joinHorizontal"],"mappings":";;;;;;;AAeO,IAAM,aAAA,GAA6B;AAAA,EACxC,QAAQA,cAAA,CAAW;AAAA,IACjB,IAAA,EAAM,CAAC,IAAA,EAAM,GAAG,CAAA;AAAA,IAChB,IAAA,EAAM,EAAE,GAAA,EAAK,UAAA,EAAO,MAAM,IAAA;AAAK,GAChC,CAAA;AAAA,EACD,UAAUA,cAAA,CAAW;AAAA,IACnB,IAAA,EAAM,CAAC,MAAA,EAAQ,GAAG,CAAA;AAAA,IAClB,IAAA,EAAM,EAAE,GAAA,EAAK,UAAA,EAAO,MAAM,MAAA;AAAO,GAClC,CAAA;AAAA,EACD,QAAQA,cAAA,CAAW;AAAA,IACjB,IAAA,EAAM,CAAC,MAAA,EAAQ,GAAA,EAAK,QAAQ,CAAA;AAAA,IAC5B,IAAA,EAAM,EAAE,GAAA,EAAK,QAAA,EAAU,MAAM,SAAA;AAAU,GACxC,CAAA;AAAA,EACD,UAAUA,cAAA,CAAW;AAAA,IACnB,IAAA,EAAM,CAAC,QAAA,EAAU,GAAA,EAAK,QAAQ,CAAA;AAAA,IAC9B,IAAA,EAAM,EAAE,GAAA,EAAK,QAAA,EAAU,MAAM,WAAA;AAAY,GAC1C,CAAA;AAAA,EACD,YAAYA,cAAA,CAAW;AAAA,IACrB,IAAA,EAAM,CAAC,GAAG,CAAA;AAAA,IACV,IAAA,EAAM,EAAE,GAAA,EAAK,GAAA,EAAK,MAAM,cAAA;AAAY,GACrC,CAAA;AAAA,EACD,cAAcA,cAAA,CAAW;AAAA,IACvB,IAAA,EAAM,CAAC,GAAG,CAAA;AAAA,IACV,IAAA,EAAM,EAAE,GAAA,EAAK,GAAA,EAAK,MAAM,gBAAA;AAAc,GACvC,CAAA;AAAA,EACD,SAASA,cAAA,CAAW;AAAA,IAClB,IAAA,EAAM,CAAC,MAAA,EAAQ,GAAG,CAAA;AAAA,IAClB,IAAA,EAAM,EAAE,GAAA,EAAK,QAAA,EAAU,MAAM,aAAA;AAAc,GAC5C,CAAA;AAAA,EACD,YAAYA,cAAA,CAAW;AAAA,IACrB,IAAA,EAAM,CAAC,KAAA,EAAO,GAAG,CAAA;AAAA,IACjB,IAAA,EAAM,EAAE,GAAA,EAAK,OAAA,EAAS,MAAM,WAAA;AAAY,GACzC;AACH;ACpCO,SAAS,aAAA,GAA6B;AAC3C,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,IAAIC,eAAA,EAAM,CAAE,KAAK,IAAI,CAAA,CAAE,OAAA,CAAQ,CAAA,EAAG,CAAC,CAAA;AAAA,IAC3C,MAAM,IAAIA,eAAA,EAAM,CAAE,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,IAC9B,QAAA,EAAU,IAAIA,eAAA,EAAM,CAAE,WAAW,SAAS,CAAA,CAAE,WAAW,SAAS,CAAA;AAAA,IAChE,MAAA,EAAQ,IAAIA,eAAA,EAAM,CAAE,WAAW,SAAS,CAAA;AAAA,IACxC,aAAaC,sBAAA,CAAa;AAAA,GAC5B;AACF;;;ACNA,IAAM,QAAA,GAAW,QAAA;AAEjB,SAAS,KAAA,CAAM,KAAA,EAAe,GAAA,EAAa,GAAA,EAAqB;AAC9D,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA,EAAG,OAAO,GAAA;AAChC,EAAA,IAAI,GAAA,GAAM,KAAK,OAAO,GAAA;AACtB,EAAA,OAAO,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AAC3C;AAEA,SAAS,WAAA,CACP,MAAA,EACA,QAAA,EACA,MAAA,EACA,MAAA,EACQ;AACR,EAAA,IAAI,MAAA,IAAU,GAAG,OAAO,CAAA;AACxB,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAW,MAAM,CAAA;AAC/C,EAAA,IAAI,UAAA,GAAa,KAAA,CAAM,MAAA,EAAQ,CAAA,EAAG,SAAS,CAAA;AAC3C,EAAA,IAAI,SAAS,UAAA,EAAY;AACvB,IAAA,UAAA,GAAa,MAAA;AAAA,EACf,CAAA,MAAA,IAAW,MAAA,IAAU,UAAA,GAAa,MAAA,EAAQ;AACxC,IAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAA,GAAS,SAAS,CAAC,CAAA;AAAA,EAC9C;AACA,EAAA,OAAO,UAAA;AACT;AAEA,SAAS,oBAAA,CAAqB,MAAc,KAAA,EAAuB;AACjE,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAA;AAChC,EAAA,IAAI,MAAA,KAAW,GAAG,OAAO,EAAA;AACzB,EAAA,IAAIC,eAAA,CAAU,IAAI,CAAA,IAAK,MAAA,EAAQ,OAAO,IAAA;AACtC,EAAA,IAAI,MAAA,KAAW,GAAG,OAAO,QAAA;AAEzB,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,MAAW,MAAM,IAAA,EAAM;AACrB,IAAA,IAAIA,eAAA,CAAU,GAAA,GAAM,EAAE,CAAA,IAAK,MAAA,EAAQ;AACjC,MAAA;AAAA,IACF;AACA,IAAA,GAAA,IAAO,EAAA;AACP,IAAA,IAAIA,eAAA,CAAU,GAAG,CAAA,KAAM,MAAA,GAAS,CAAA,EAAG;AACjC,MAAA;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,QAAQ,CAAA,CAAA;AAC1B;AAEA,SAAS,UAAA,CAAW,OAAe,KAAA,EAAuB;AACxD,EAAA,MAAM,OAAA,GAAUA,gBAAU,KAAK,CAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,OAAO,CAAA;AAC3C,EAAA,OAAO,GAAG,KAAK,CAAA,EAAG,GAAA,CAAI,MAAA,CAAO,OAAO,CAAC,CAAA,CAAA;AACvC;AAEA,SAAS,qBAAA,CACP,OAAA,EACA,UAAA,EACA,QAAA,EACU;AACV,EAAA,MAAM,WAAA,GAAc,QAAA,GAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,CAAA;AACpD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,aAAa,WAAW,CAAA;AACtD,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,KAAK,GAAA,CAAI,CAAA,EAAG,CAAA,CAAE,KAAK,CAAC,CAAA;AACrD,EAAA,MAAM,UAAA,GAAa,MAAM,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,GAAG,CAAC,CAAA;AAElD,EAAA,IAAI,UAAA,GAAa,SAAA,IAAa,UAAA,GAAa,CAAA,EAAG;AAC5C,IAAA,MAAM,QAAQ,SAAA,GAAY,UAAA;AAC1B,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,KAAK,CAAC,CAAC,CAAA;AAAA,EAC5D;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,WAAA,CACP,MACA,SAAA,EACa;AACb,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,SAAA,EAAW,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,IAClC,QAAA,EAAU,SAAA,EAAW,QAAA,IAAY,IAAA,CAAK,QAAA;AAAA,IACtC,MAAA,EAAQ,SAAA,EAAW,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,IAClC,QAAA,EAAU,SAAA,EAAW,QAAA,IAAY,IAAA,CAAK,QAAA;AAAA,IACtC,UAAA,EAAY,SAAA,EAAW,UAAA,IAAc,IAAA,CAAK,UAAA;AAAA,IAC1C,YAAA,EAAc,SAAA,EAAW,YAAA,IAAgB,IAAA,CAAK,YAAA;AAAA,IAC9C,OAAA,EAAS,SAAA,EAAW,OAAA,IAAW,IAAA,CAAK,OAAA;AAAA,IACpC,UAAA,EAAY,SAAA,EAAW,UAAA,IAAc,IAAA,CAAK;AAAA,GAC5C;AACF;AAEA,SAAS,WAAA,CACP,WACA,mBAAA,EACa;AACb,EAAA,MAAM,OAAO,aAAA,EAAc;AAC3B,EAAA,MAAM,MAAA,GAAsB;AAAA,IAC1B,GAAG,IAAA;AAAA,IACH,GAAG;AAAA,GACL;AACA,EAAA,IAAI,mBAAA,EAAqB;AACvB,IAAA,MAAA,CAAO,WAAA,GAAc,mBAAA;AAAA,EACvB,CAAA,MAAA,IAAW,CAAC,MAAA,CAAO,WAAA,EAAa;AAC9B,IAAA,MAAA,CAAO,WAAA,GAAcC,4BAAA;AAAA,EACvB;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,gBAAA,CAAiB,SAAmB,QAAA,EAA2B;AACtE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,GAAA,EAAK,GAAA,KAAQ,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,GAAA,CAAI,KAAK,GAAG,CAAC,CAAA;AACzE,EAAA,OAAO,QAAA,GAAW,OAAO,IAAA,CAAK,GAAA,CAAI,GAAG,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,GAAI,IAAA;AAC7D;AAYA,SAAS,cAAA,CAAe,MAAc,KAAA,EAAuB;AAC3D,EAAA,IAAI,KAAA,IAAS,GAAG,OAAO,EAAA;AACvB,EAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,IAAA,EAAM,KAAK,CAAA;AAElD,EAAA,OAAO,IAAIH,eAAAA,EAAM,CACd,KAAA,CAAM,KAAK,EACX,QAAA,CAAS,KAAK,CAAA,CACd,eAAA,CAAgB,MAAM,CAAA,CACtB,MAAA,CAAO,IAAI,CAAA,CACX,OAAO,SAAS,CAAA;AACrB;AAMA,SAAS,cAAA,CACP,IAAA,EACA,UAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAA;AACpC,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,IAAA,EAAM,KAAK,CAAA;AACrC,EAAA,MAAM,OAAA,GAAU,CAAA,EAAG,MAAA,CAAO,WAAA,CAAY,IAAI,GAAG,MAAM,CAAA,EAAG,MAAA,CAAO,WAAA,CAAY,KAAK,CAAA,CAAA;AAC9E,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA;AACrC;AAEA,SAAS,eAAA,CAAgB,YAAoB,MAAA,EAA6B;AACxE,EAAA,MAAM,OAAO,CAAA,EAAG,MAAA,CAAO,YAAY,OAAO,CAAA,EAAG,OAAO,WAAA,CAAY,GAAA,CAAI,OAAO,IAAA,CAAK,GAAA,CAAI,GAAG,UAAU,CAAC,CAAC,CAAA,EAAG,MAAA,CAAO,YAAY,QAAQ,CAAA,CAAA;AACjI,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAClC;AAEA,SAAS,eAAA,CAAgB,YAAoB,MAAA,EAA6B;AACxE,EAAA,MAAM,OAAO,CAAA,EAAG,MAAA,CAAO,YAAY,IAAI,CAAA,EAAG,OAAO,WAAA,CAAY,GAAA,CAAI,OAAO,IAAA,CAAK,GAAA,CAAI,GAAG,UAAU,CAAC,CAAC,CAAA,EAAG,MAAA,CAAO,YAAY,KAAK,CAAA,CAAA;AAC3H,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAClC;AAEA,SAAS,kBAAA,CAAmB,YAAoB,MAAA,EAA6B;AAC3E,EAAA,MAAM,OAAO,CAAA,EAAG,MAAA,CAAO,YAAY,UAAU,CAAA,EAAG,OAAO,WAAA,CAAY,MAAA,CAAO,OAAO,IAAA,CAAK,GAAA,CAAI,GAAG,UAAU,CAAC,CAAC,CAAA,EAAG,MAAA,CAAO,YAAY,WAAW,CAAA,CAAA;AAC1I,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAClC;AAqBO,IAAM,UAAA,GAAN,MAAM,WAAA,CAAW;AAAA,EACb,OAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EAED,YAAY,KAAA,EAAmB;AACrC,IAAA,IAAA,CAAK,UAAU,KAAA,CAAM,OAAA;AACrB,IAAA,IAAA,CAAK,OAAO,KAAA,CAAM,IAAA;AAClB,IAAA,IAAA,CAAK,SAAS,KAAA,CAAM,MAAA;AACpB,IAAA,IAAA,CAAK,SAAS,KAAA,CAAM,MAAA;AACpB,IAAA,IAAA,CAAK,UAAU,KAAA,CAAM,OAAA;AACrB,IAAA,IAAA,CAAK,SAAS,KAAA,CAAM,MAAA;AACpB,IAAA,IAAA,CAAK,QAAQ,KAAA,CAAM,KAAA;AACnB,IAAA,IAAA,CAAK,YAAY,KAAA,CAAM,SAAA;AACvB,IAAA,IAAA,CAAK,SAAS,KAAA,CAAM,MAAA;AACpB,IAAA,IAAA,CAAK,SAAS,KAAA,CAAM,MAAA;AACpB,IAAA,IAAA,CAAK,WAAW,KAAA,CAAM,QAAA;AACtB,IAAA,IAAA,CAAK,eAAe,KAAA,CAAM,YAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,OAAO,IAAI,OAAA,EAAmC;AAC5C,IAAA,MAAM,OAAO,CAAC,GAAI,OAAA,CAAQ,IAAA,IAAQ,EAAG,CAAA;AACrC,IAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,KAAA;AACrC,IAAA,MAAM,MAAA,GAAS,WAAA,CAAY,OAAA,CAAQ,MAAA,EAAQ,QAAQ,WAAW,CAAA;AAC9D,IAAA,MAAM,QACJ,OAAA,CAAQ,KAAA,IAAS,iBAAiB,OAAA,CAAQ,OAAA,EAAS,QAAQ,CAAA,IAAK,CAAA;AAClE,IAAA,MAAM,SAAA,GAAY,QAAQ,KAAA,KAAU,MAAA;AACpC,IAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,GAAG,OAAA,CAAQ,MAAA,IAAU,KAAK,MAAM,CAAA;AACxD,IAAA,MAAM,eAAe,SAAA,GACjB,OAAA,CAAQ,QAAQ,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAA,CAAE,KAAK,CAAC,CAAA,GAC/C,sBAAsB,OAAA,CAAQ,OAAA,EAAS,OAAO,QAAQ,CAAA;AAC1D,IAAA,MAAM,MAAA,GAAS,KAAA;AAAA,MACb,OAAA,CAAQ,UAAU,CAAA,GAAI,CAAA;AAAA,MACtB,CAAA;AAAA,MACA,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,MAAA,GAAS,GAAG,CAAC;AAAA,KAC7B;AACA,IAAA,MAAM,SAAS,WAAA,CAAY,CAAA,EAAG,IAAA,CAAK,MAAA,EAAQ,QAAQ,MAAM,CAAA;AACzD,IAAA,OAAO,IAAI,WAAA,CAAW;AAAA,MACpB,OAAA,EAAS,CAAC,GAAG,OAAA,CAAQ,OAAO,CAAA;AAAA,MAC5B,IAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA,EAAS,QAAQ,OAAA,IAAW,KAAA;AAAA,MAC5B,MAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,MAAA,EAAQ,WAAA,CAAY,aAAA,EAAe,OAAA,CAAQ,MAAM,CAAA;AAAA,MACjD,MAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,IAAA,GAAiB;AACf,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,GAAA,EAAkC;AACvC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,EAAE,eAAeI,UAAA,CAAA,EAAS;AAC7C,MAAA,OAAO,CAAC,MAAM,IAAI,CAAA;AAAA,IACpB;AAEA,IAAA,IAAIC,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG;AACpC,MAAA,OAAO,CAAC,IAAA,CAAK,MAAA,CAAO,CAAC,GAAG,IAAI,CAAA;AAAA,IAC9B;AACA,IAAA,IAAIA,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,EAAG;AACtC,MAAA,OAAO,CAAC,IAAA,CAAK,QAAA,CAAS,CAAC,GAAG,IAAI,CAAA;AAAA,IAChC;AACA,IAAA,IAAIA,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG;AACpC,MAAA,OAAO,CAAC,IAAA,CAAK,MAAA,CAAO,KAAK,MAAA,IAAU,CAAC,GAAG,IAAI,CAAA;AAAA,IAC7C;AACA,IAAA,IAAIA,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,EAAG;AACtC,MAAA,OAAO,CAAC,IAAA,CAAK,QAAA,CAAS,KAAK,MAAA,IAAU,CAAC,GAAG,IAAI,CAAA;AAAA,IAC/C;AACA,IAAA,IAAIA,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,EAAG;AACxC,MAAA,OAAO,CAAC,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,GAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;AAAA,IACrE;AACA,IAAA,IAAIA,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA,EAAG;AAC1C,MAAA,OAAO,CAAC,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,GAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;AAAA,IACvE;AACA,IAAA,IAAIA,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG;AACrC,MAAA,OAAO,CAAC,IAAA,CAAK,OAAA,EAAQ,EAAG,IAAI,CAAA;AAAA,IAC9B;AACA,IAAA,IAAIA,WAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,EAAG;AACxC,MAAA,OAAO,CAAC,IAAA,CAAK,UAAA,EAAW,EAAG,IAAI,CAAA;AAAA,IACjC;AACA,IAAA,OAAO,CAAC,MAAM,IAAI,CAAA;AAAA,EACpB;AAAA;AAAA,EAGA,IAAA,GAAe;AACb,IAAA,MAAM,MAAA,GAAS,KAAK,YAAA,EAAa;AACjC,IAAA,MAAM,WAAA,GAAcH,gBAAU,MAAM,CAAA;AAEpC,IAAA,MAAM,QAAQ,IAAA,CAAK,MAAA;AACnB,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,CAAI,KAAA,GAAQ,KAAK,MAAA,EAAQ,IAAA,CAAK,KAAK,MAAM,CAAA;AAC1D,IAAA,MAAM,cAAc,IAAA,CAAK,aAAA,EAAc,CAAE,KAAA,CAAM,OAAO,GAAG,CAAA;AAGzD,IAAA,MAAM,UAAA,GAAa,CAAC,GAAG,WAAW,CAAA;AAClC,IAAA,OAAO,UAAA,CAAW,MAAA,GAAS,IAAA,CAAK,MAAA,EAAQ;AACtC,MAAA,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,CAAA;AAAA,IACvC;AAGA,IAAA,MAAM,QAAA,GAAW,WAAW,MAAA,GAAS,CAAA,GAAIA,gBAAU,UAAA,CAAW,CAAC,CAAA,IAAK,EAAE,CAAA,GAAI,CAAA;AAC1E,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,QAAQ,CAAA;AAEjD,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,OAAO;AAAA,QACL,UAAA,CAAW,QAAQ,UAAU,CAAA;AAAA,QAC7B,GAAG,WAAW,GAAA,CAAI,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,UAAU,CAAC;AAAA,OACpD,CAAE,KAAK,IAAI,CAAA;AAAA,IACb;AAEA,IAAA,MAAM,OAAO,CAAC,IAAA,KAAiB,eAAe,IAAA,EAAM,UAAA,EAAY,KAAK,MAAM,CAAA;AAC3E,IAAA,OAAO;AAAA,MACL,eAAA,CAAgB,UAAA,EAAY,IAAA,CAAK,MAAM,CAAA;AAAA,MACvC,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,UAAU,CAAC,CAAA;AAAA,MACnC,eAAA,CAAgB,UAAA,EAAY,IAAA,CAAK,MAAM,CAAA;AAAA,MACvC,GAAG,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,KAAK,UAAA,CAAW,CAAA,EAAG,UAAU,CAAC,CAAC,CAAA;AAAA,MACxD,kBAAA,CAAmB,UAAA,EAAY,IAAA,CAAK,MAAM;AAAA,KAC5C,CAAE,KAAK,IAAI,CAAA;AAAA,EACb;AAAA;AAAA,EAGA,WAAA,GAA+B;AAC7B,IAAA,IAAI,IAAA,CAAK,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AACnC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA;AAAA,EAC9B;AAAA;AAAA,EAGA,aAAA,GAAwB;AACtB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA,EAGA,WAAW,OAAA,EAA+B;AACxC,IAAA,OAAO,KAAK,IAAA,CAAK;AAAA,MACf,OAAA,EAAS,CAAC,GAAG,OAAO;AAAA,KACrB,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,QAAQ,IAAA,EAAyB;AAC/B,IAAA,OAAO,KAAK,IAAA,CAAK;AAAA,MACf,IAAA,EAAM,CAAC,GAAG,IAAI;AAAA,KACf,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,UAAU,GAAA,EAAsB;AAC9B,IAAA,OAAO,KAAK,OAAA,CAAQ,CAAC,GAAG,IAAA,CAAK,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,EACzC;AAAA;AAAA,EAGA,UAAU,KAAA,EAA2B;AACnC,IAAA,IAAI,QAAQ,CAAA,IAAK,KAAA,IAAS,IAAA,CAAK,IAAA,CAAK,QAAQ,OAAO,IAAA;AACnD,IAAA,MAAM,IAAA,GAAO,CAAC,GAAG,IAAA,CAAK,IAAI,CAAA;AAC1B,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AACpB,IAAA,OAAO,IAAA,CAAK,QAAQ,IAAI,CAAA;AAAA,EAC1B;AAAA;AAAA,EAGA,iBAAiB,KAAA,EAA2B;AAC1C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,OAAO,CAAA;AAAA,EACpC;AAAA;AAAA,EAGA,MAAA,CAAO,IAAI,CAAA,EAAe;AACxB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAA;AAC3B,IAAA,OAAO,KAAK,IAAA,CAAK,EAAE,QAAQ,IAAA,CAAK,MAAA,GAAS,OAAO,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,QAAA,CAAS,IAAI,CAAA,EAAe;AAC1B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAA;AAC3B,IAAA,OAAO,KAAK,IAAA,CAAK,EAAE,QAAQ,IAAA,CAAK,MAAA,GAAS,OAAO,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,OAAA,GAAsB;AACpB,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,GAAG,CAAA;AAAA,EAChC;AAAA;AAAA,EAGA,UAAA,GAAyB;AACvB,IAAA,OAAO,IAAA,CAAK,KAAK,EAAE,MAAA,EAAQ,KAAK,IAAA,CAAK,MAAA,GAAS,GAAG,CAAA;AAAA,EACnD;AAAA;AAAA,EAGA,KAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,SAAS,OAAO,IAAA;AACzB,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,EACpC;AAAA;AAAA,EAGA,IAAA,GAAmB;AACjB,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,OAAO,IAAA;AAC1B,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,EACrC;AAAA;AAAA,EAGA,UAAU,MAAA,EAA4B;AACpC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,CAAA;AAAA,EAC7B;AAAA;AAAA,EAGA,SAAS,KAAA,EAA2B;AAClC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA;AAAA,EAC5B;AAAA,EAEQ,YAAA,GAAuB;AAE7B,IAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAK,CAAA,KAAM;AACzC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,YAAA,CAAa,CAAC,KAAK,GAAA,CAAI,KAAA;AAC1C,MAAA,MAAM,SAAA,GAAY,cAAA,CAAe,GAAA,CAAI,KAAA,EAAO,KAAK,CAAA;AACjD,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAAA,IAC5C,CAAC,CAAA;AACD,IAAA,OAAOI,wBAAA,CAAe,GAAG,KAAK,CAAA;AAAA,EAChC;AAAA,EAEQ,SAAA,CAAU,KAAU,KAAA,EAAuB;AAEjD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,IAAW,KAAA,KAAU,IAAA,CAAK,MAAA;AAElD,IAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAK,CAAA,KAAM;AACzC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,YAAA,CAAa,CAAC,KAAK,GAAA,CAAI,KAAA;AAC1C,MAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,CAAC,CAAA,IAAK,EAAA;AACxB,MAAA,MAAM,SAAA,GAAY,cAAA,CAAe,KAAA,EAAO,KAAK,CAAA;AAC7C,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,SAAS,CAAA;AAAA,IAC1C,CAAC,CAAA;AAED,IAAA,MAAM,MAAA,GAASA,wBAAA,CAAe,GAAG,KAAK,CAAA;AAGtC,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA;AAAA,IAC3C;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,cAAA,GAAyB;AAE/B,IAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAK,CAAA,KAAM;AACzC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,YAAA,CAAa,CAAC,KAAK,GAAA,CAAI,KAAA;AAC1C,MAAA,MAAM,SAAA,GAAY,cAAA,CAAe,EAAA,EAAI,KAAK,CAAA;AAC1C,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,SAAS,CAAA;AAAA,IAC1C,CAAC,CAAA;AACD,IAAA,OAAOA,wBAAA,CAAe,GAAG,KAAK,CAAA;AAAA,EAChC;AAAA,EAEQ,aAAA,GAA0B;AAChC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,EAAK,MAAM,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,CAAC,CAAC,CAAA;AAAA,EACzD;AAAA,EAEQ,KAAK,KAAA,EAAwC;AACnD,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,OAAA,IAAW,IAAA,CAAK,OAAA;AAC1C,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,IAAA,IAAQ,IAAA,CAAK,IAAA;AACpC,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,MAAA,IAAU,IAAA,CAAK,MAAA;AACxC,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,KAAA,IAAS,IAAA,CAAK,KAAA;AACtC,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,KAAA,KAAU,MAAA,GAAY,QAAQ,IAAA,CAAK,SAAA;AAC3D,IAAA,MAAM,YAAA,GAAe,KAAA,CAAM,QAAA,IAAY,IAAA,CAAK,QAAA;AAC5C,IAAA,MAAM,mBAAmB,SAAA,GACrB,WAAA,CAAY,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAA,CAAE,KAAK,CAAC,CAAA,GAC3C,qBAAA,CAAsB,WAAA,EAAa,WAAW,YAAY,CAAA;AAC9D,IAAA,MAAM,MAAA,GAAS,KAAA;AAAA,MACb,KAAA,CAAM,UAAU,IAAA,CAAK,MAAA;AAAA,MACrB,CAAA;AAAA,MACA,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,MAAA,GAAS,GAAG,CAAC;AAAA,KACjC;AACA,IAAA,MAAM,MAAA,GAAS,WAAA;AAAA,MACb,KAAA,CAAM,UAAU,IAAA,CAAK,MAAA;AAAA,MACrB,QAAA,CAAS,MAAA;AAAA,MACT,UAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,IAAI,WAAA,CAAW;AAAA,MACpB,OAAA,EAAS,CAAC,GAAG,WAAW,CAAA;AAAA,MACxB,IAAA,EAAM,CAAC,GAAG,QAAQ,CAAA;AAAA,MAClB,MAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA,EAAS,KAAA,CAAM,OAAA,IAAW,IAAA,CAAK,OAAA;AAAA,MAC/B,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAA;AAAA,MAC9B,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,SAAS,CAAA;AAAA,MAC5B,SAAA;AAAA,MACA,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,MAC7B,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,MAC7B,QAAA,EAAU,YAAA;AAAA,MACV,YAAA,EAAc;AAAA,KACf,CAAA;AAAA,EACH;AACF","file":"index.cjs","sourcesContent":["import { newBinding, type Binding } from '@suds-cli/key'\n\n/** Key bindings for table navigation. @public */\nexport interface TableKeyMap {\n lineUp: Binding\n lineDown: Binding\n pageUp: Binding\n pageDown: Binding\n halfPageUp: Binding\n halfPageDown: Binding\n gotoTop: Binding\n gotoBottom: Binding\n}\n\n/** Default key bindings matching Bubble Tea tables. @public */\nexport const defaultKeyMap: TableKeyMap = {\n lineUp: newBinding({\n keys: ['up', 'k'],\n help: { key: '↑/k', desc: 'up' },\n }),\n lineDown: newBinding({\n keys: ['down', 'j'],\n help: { key: '↓/j', desc: 'down' },\n }),\n pageUp: newBinding({\n keys: ['pgup', 'b', 'ctrl+u'],\n help: { key: 'pgup/b', desc: 'page up' },\n }),\n pageDown: newBinding({\n keys: ['pgdown', 'f', 'ctrl+d'],\n help: { key: 'pgdn/f', desc: 'page down' },\n }),\n halfPageUp: newBinding({\n keys: ['u'],\n help: { key: 'u', desc: '½ page up' },\n }),\n halfPageDown: newBinding({\n keys: ['d'],\n help: { key: 'd', desc: '½ page down' },\n }),\n gotoTop: newBinding({\n keys: ['home', 'g'],\n help: { key: 'home/g', desc: 'go to start' },\n }),\n gotoBottom: newBinding({\n keys: ['end', 'G'],\n help: { key: 'end/G', desc: 'go to end' },\n }),\n}\n","import { Style, borderStyles, type BorderStyle } from '@suds-cli/chapstick'\n\n/** Styles applied to parts of the table. @public */\nexport interface TableStyles {\n header: Style\n cell: Style\n selected: Style\n border: Style\n borderStyle: BorderStyle\n}\n\n/** Default table styles. @public */\nexport function defaultStyles(): TableStyles {\n return {\n header: new Style().bold(true).padding(0, 1),\n cell: new Style().padding(0, 1),\n selected: new Style().background('#7D56F4').foreground('#FFFFFF'),\n border: new Style().foreground('#383838'),\n borderStyle: borderStyles.normal,\n }\n}\n","import {\n Style,\n borderStyles,\n defaultBorderStyle,\n joinHorizontal,\n width as textWidth,\n type BorderStyle,\n} from '@suds-cli/chapstick'\nimport { matches } from '@suds-cli/key'\nimport { KeyMsg, type Cmd, type Msg } from '@suds-cli/tea'\nimport { defaultKeyMap, type TableKeyMap } from './keymap.js'\nimport { defaultStyles, type TableStyles } from './styles.js'\nimport type { Column, Row, TableOptions } from './types.js'\n\nconst ELLIPSIS = '…'\n\nfunction clamp(value: number, min: number, max: number): number {\n if (Number.isNaN(value)) return min\n if (max < min) return min\n return Math.min(max, Math.max(min, value))\n}\n\nfunction clampOffset(\n offset: number,\n rowCount: number,\n height: number,\n cursor: number,\n): number {\n if (height <= 0) return 0\n const maxOffset = Math.max(0, rowCount - height)\n let nextOffset = clamp(offset, 0, maxOffset)\n if (cursor < nextOffset) {\n nextOffset = cursor\n } else if (cursor >= nextOffset + height) {\n nextOffset = Math.max(0, cursor - height + 1)\n }\n return nextOffset\n}\n\nfunction truncateWithEllipsis(text: string, width: number): string {\n const target = Math.max(0, width)\n if (target === 0) return ''\n if (textWidth(text) <= target) return text\n if (target === 1) return ELLIPSIS\n\n let acc = ''\n for (const ch of text) {\n if (textWidth(acc + ch) >= target) {\n break\n }\n acc += ch\n if (textWidth(acc) === target - 1) {\n break\n }\n }\n return `${acc}${ELLIPSIS}`\n}\n\nfunction padToWidth(input: string, width: number): string {\n const current = textWidth(input)\n const missing = Math.max(0, width - current)\n return `${input}${' '.repeat(missing)}`\n}\n\nfunction calculateColumnWidths(\n columns: Column[],\n totalWidth: number,\n bordered: boolean,\n): number[] {\n const borderWidth = bordered ? columns.length + 1 : 0\n const available = Math.max(0, totalWidth - borderWidth)\n const fixed = columns.map((c) => Math.max(0, c.width))\n const totalFixed = fixed.reduce((a, b) => a + b, 0)\n\n if (totalFixed > available && totalFixed > 0) {\n const scale = available / totalFixed\n return fixed.map((w) => Math.max(0, Math.floor(w * scale)))\n }\n return fixed\n}\n\nfunction mergeKeyMap(\n base: TableKeyMap,\n overrides?: Partial<TableKeyMap>,\n): TableKeyMap {\n return {\n lineUp: overrides?.lineUp ?? base.lineUp,\n lineDown: overrides?.lineDown ?? base.lineDown,\n pageUp: overrides?.pageUp ?? base.pageUp,\n pageDown: overrides?.pageDown ?? base.pageDown,\n halfPageUp: overrides?.halfPageUp ?? base.halfPageUp,\n halfPageDown: overrides?.halfPageDown ?? base.halfPageDown,\n gotoTop: overrides?.gotoTop ?? base.gotoTop,\n gotoBottom: overrides?.gotoBottom ?? base.gotoBottom,\n }\n}\n\nfunction mergeStyles(\n overrides?: Partial<TableStyles>,\n borderStyleOverride?: BorderStyle,\n): TableStyles {\n const base = defaultStyles()\n const merged: TableStyles = {\n ...base,\n ...overrides,\n }\n if (borderStyleOverride) {\n merged.borderStyle = borderStyleOverride\n } else if (!merged.borderStyle) {\n merged.borderStyle = defaultBorderStyle\n }\n return merged\n}\n\nfunction totalColumnWidth(columns: Column[], bordered: boolean): number {\n const base = columns.reduce((sum, col) => sum + Math.max(0, col.width), 0)\n return bordered ? base + Math.max(0, columns.length - 1) : base\n}\n\nfunction _innerWidthFrom(\n widths: number[],\n bordered: boolean,\n columnCount: number,\n): number {\n const base = widths.reduce((sum, w) => sum + Math.max(0, w), 0)\n return bordered ? base + Math.max(0, columnCount - 1) : base\n}\n\n/** Create a fixed-width cell (like lipgloss Width+MaxWidth+Inline). */\nfunction fixedWidthCell(text: string, width: number): string {\n if (width <= 0) return ''\n const truncated = truncateWithEllipsis(text, width)\n // Use alignHorizontal to ensure padding to target width\n return new Style()\n .width(width)\n .maxWidth(width)\n .alignHorizontal('left')\n .inline(true)\n .render(truncated)\n}\n\nfunction _verticalChar(styles: TableStyles): string {\n return styles.borderStyle?.left ?? borderStyles.normal.left\n}\n\nfunction wrapWithBorder(\n line: string,\n innerWidth: number,\n styles: TableStyles,\n): string {\n const width = Math.max(0, innerWidth)\n const padded = padToWidth(line, width)\n const wrapped = `${styles.borderStyle.left}${padded}${styles.borderStyle.right}`\n return styles.border.render(wrapped)\n}\n\nfunction renderTopBorder(innerWidth: number, styles: TableStyles): string {\n const line = `${styles.borderStyle.topLeft}${styles.borderStyle.top.repeat(Math.max(0, innerWidth))}${styles.borderStyle.topRight}`\n return styles.border.render(line)\n}\n\nfunction renderSeparator(innerWidth: number, styles: TableStyles): string {\n const line = `${styles.borderStyle.left}${styles.borderStyle.top.repeat(Math.max(0, innerWidth))}${styles.borderStyle.right}`\n return styles.border.render(line)\n}\n\nfunction renderBottomBorder(innerWidth: number, styles: TableStyles): string {\n const line = `${styles.borderStyle.bottomLeft}${styles.borderStyle.bottom.repeat(Math.max(0, innerWidth))}${styles.borderStyle.bottomRight}`\n return styles.border.render(line)\n}\n\ninterface TableState {\n columns: Column[]\n rows: Row[]\n cursor: number\n offset: number\n focused: boolean\n height: number\n width: number\n autoWidth: boolean\n keyMap: TableKeyMap\n styles: TableStyles\n bordered: boolean\n columnWidths: number[]\n}\n\n/**\n * Scrollable, selectable table model.\n * @public\n */\nexport class TableModel {\n readonly columns: Column[]\n readonly rows: Row[]\n readonly cursor: number\n readonly offset: number\n readonly focused: boolean\n readonly height: number\n readonly width: number\n readonly autoWidth: boolean\n readonly keyMap: TableKeyMap\n readonly styles: TableStyles\n readonly bordered: boolean\n readonly columnWidths: number[]\n\n private constructor(state: TableState) {\n this.columns = state.columns\n this.rows = state.rows\n this.cursor = state.cursor\n this.offset = state.offset\n this.focused = state.focused\n this.height = state.height\n this.width = state.width\n this.autoWidth = state.autoWidth\n this.keyMap = state.keyMap\n this.styles = state.styles\n this.bordered = state.bordered\n this.columnWidths = state.columnWidths\n }\n\n /** Create a new table model. */\n static new(options: TableOptions): TableModel {\n const rows = [...(options.rows ?? [])]\n const bordered = options.bordered ?? false\n const styles = mergeStyles(options.styles, options.borderStyle)\n const width =\n options.width ?? totalColumnWidth(options.columns, bordered) ?? 0\n const autoWidth = options.width === undefined\n const height = Math.max(0, options.height ?? rows.length)\n const columnWidths = autoWidth\n ? options.columns.map((c) => Math.max(0, c.width))\n : calculateColumnWidths(options.columns, width, bordered)\n const cursor = clamp(\n options.focused ? 0 : 0,\n 0,\n Math.max(rows.length - 1, 0),\n )\n const offset = clampOffset(0, rows.length, height, cursor)\n return new TableModel({\n columns: [...options.columns],\n rows,\n cursor,\n offset,\n focused: options.focused ?? false,\n height,\n width,\n autoWidth,\n keyMap: mergeKeyMap(defaultKeyMap, options.keyMap),\n styles,\n bordered,\n columnWidths,\n })\n }\n\n /** Tea init hook (no-op). */\n init(): Cmd<Msg> {\n return null\n }\n\n /** Handle key messages when focused. */\n update(msg: Msg): [TableModel, Cmd<Msg>] {\n if (!this.focused || !(msg instanceof KeyMsg)) {\n return [this, null]\n }\n\n if (matches(msg, this.keyMap.lineUp)) {\n return [this.moveUp(1), null]\n }\n if (matches(msg, this.keyMap.lineDown)) {\n return [this.moveDown(1), null]\n }\n if (matches(msg, this.keyMap.pageUp)) {\n return [this.moveUp(this.height || 1), null]\n }\n if (matches(msg, this.keyMap.pageDown)) {\n return [this.moveDown(this.height || 1), null]\n }\n if (matches(msg, this.keyMap.halfPageUp)) {\n return [this.moveUp(Math.max(1, Math.floor(this.height / 2))), null]\n }\n if (matches(msg, this.keyMap.halfPageDown)) {\n return [this.moveDown(Math.max(1, Math.floor(this.height / 2))), null]\n }\n if (matches(msg, this.keyMap.gotoTop)) {\n return [this.gotoTop(), null]\n }\n if (matches(msg, this.keyMap.gotoBottom)) {\n return [this.gotoBottom(), null]\n }\n return [this, null]\n }\n\n /** Render the header and visible rows as a string. */\n view(): string {\n const header = this.renderHeader()\n const headerWidth = textWidth(header)\n\n const start = this.offset\n const end = Math.min(start + this.height, this.rows.length)\n const visibleRows = this.renderAllRows().slice(start, end)\n\n // Pad with empty rows if needed\n const paddedRows = [...visibleRows]\n while (paddedRows.length < this.height) {\n paddedRows.push(this.renderEmptyRow())\n }\n\n // Calculate inner width for borders (max of header and all rows)\n const rowWidth = paddedRows.length > 0 ? textWidth(paddedRows[0] ?? '') : 0\n const innerWidth = Math.max(headerWidth, rowWidth)\n\n if (!this.bordered) {\n return [\n padToWidth(header, innerWidth),\n ...paddedRows.map((r) => padToWidth(r, innerWidth)),\n ].join('\\n')\n }\n\n const wrap = (line: string) => wrapWithBorder(line, innerWidth, this.styles)\n return [\n renderTopBorder(innerWidth, this.styles),\n wrap(padToWidth(header, innerWidth)),\n renderSeparator(innerWidth, this.styles),\n ...paddedRows.map((r) => wrap(padToWidth(r, innerWidth))),\n renderBottomBorder(innerWidth, this.styles),\n ].join('\\n')\n }\n\n /** Current selected row, if any. */\n selectedRow(): Row | undefined {\n if (this.rows.length === 0) return undefined\n return this.rows[this.cursor]\n }\n\n /** Current selected index. */\n selectedIndex(): number {\n return this.cursor\n }\n\n /** Replace columns. */\n setColumns(columns: Column[]): TableModel {\n return this.with({\n columns: [...columns],\n })\n }\n\n /** Replace rows. */\n setRows(rows: Row[]): TableModel {\n return this.with({\n rows: [...rows],\n })\n }\n\n /** Append a single row. */\n appendRow(row: Row): TableModel {\n return this.setRows([...this.rows, row])\n }\n\n /** Remove a row by index. */\n removeRow(index: number): TableModel {\n if (index < 0 || index >= this.rows.length) return this\n const next = [...this.rows]\n next.splice(index, 1)\n return this.setRows(next)\n }\n\n /** Set the selected index (clamped). */\n setSelectedIndex(index: number): TableModel {\n return this.with({ cursor: index })\n }\n\n /** Move the cursor up by n rows. */\n moveUp(n = 1): TableModel {\n const delta = Math.max(1, n)\n return this.with({ cursor: this.cursor - delta })\n }\n\n /** Move the cursor down by n rows. */\n moveDown(n = 1): TableModel {\n const delta = Math.max(1, n)\n return this.with({ cursor: this.cursor + delta })\n }\n\n /** Jump to the first row. */\n gotoTop(): TableModel {\n return this.with({ cursor: 0 })\n }\n\n /** Jump to the last row. */\n gotoBottom(): TableModel {\n return this.with({ cursor: this.rows.length - 1 })\n }\n\n /** Focus the table. */\n focus(): TableModel {\n if (this.focused) return this\n return this.with({ focused: true })\n }\n\n /** Blur the table. */\n blur(): TableModel {\n if (!this.focused) return this\n return this.with({ focused: false })\n }\n\n /** Set the visible height (rows). */\n setHeight(height: number): TableModel {\n return this.with({ height })\n }\n\n /** Set the total width. */\n setWidth(width: number): TableModel {\n return this.with({ width })\n }\n\n private renderHeader(): string {\n // Match Go: fixed-width cell → header style (with padding) → joinHorizontal\n const cells = this.columns.map((col, i) => {\n const width = this.columnWidths[i] ?? col.width\n const fixedCell = fixedWidthCell(col.title, width)\n return this.styles.header.render(fixedCell)\n })\n return joinHorizontal(...cells)\n }\n\n private renderRow(row: Row, index: number): string {\n // Match Go: fixed-width cell → cell style (with padding) → join → selected wraps whole row\n const isSelected = this.focused && index === this.cursor\n\n const cells = this.columns.map((col, i) => {\n const width = this.columnWidths[i] ?? col.width\n const value = row[i] ?? ''\n const fixedCell = fixedWidthCell(value, width)\n return this.styles.cell.render(fixedCell)\n })\n\n const joined = joinHorizontal(...cells)\n\n // Selected style wraps the entire row (just colors, no padding change)\n if (isSelected) {\n return this.styles.selected.render(joined)\n }\n return joined\n }\n\n private renderEmptyRow(): string {\n // Same as renderRow but with empty content\n const cells = this.columns.map((col, i) => {\n const width = this.columnWidths[i] ?? col.width\n const fixedCell = fixedWidthCell('', width)\n return this.styles.cell.render(fixedCell)\n })\n return joinHorizontal(...cells)\n }\n\n private renderAllRows(): string[] {\n return this.rows.map((row, i) => this.renderRow(row, i))\n }\n\n private with(patch: Partial<TableState>): TableModel {\n const nextColumns = patch.columns ?? this.columns\n const nextRows = patch.rows ?? this.rows\n const nextHeight = patch.height ?? this.height\n const nextWidth = patch.width ?? this.width\n const autoWidth = patch.width !== undefined ? false : this.autoWidth\n const nextBordered = patch.bordered ?? this.bordered\n const nextColumnWidths = autoWidth\n ? nextColumns.map((c) => Math.max(0, c.width))\n : calculateColumnWidths(nextColumns, nextWidth, nextBordered)\n const cursor = clamp(\n patch.cursor ?? this.cursor,\n 0,\n Math.max(nextRows.length - 1, 0),\n )\n const offset = clampOffset(\n patch.offset ?? this.offset,\n nextRows.length,\n nextHeight,\n cursor,\n )\n return new TableModel({\n columns: [...nextColumns],\n rows: [...nextRows],\n cursor,\n offset,\n focused: patch.focused ?? this.focused,\n height: Math.max(0, nextHeight),\n width: Math.max(0, nextWidth),\n autoWidth,\n keyMap: patch.keyMap ?? this.keyMap,\n styles: patch.styles ?? this.styles,\n bordered: nextBordered,\n columnWidths: nextColumnWidths,\n })\n }\n}\n"]}
@@ -1,12 +1,57 @@
1
- import { type Cmd, type Msg } from '@suds-cli/tea';
2
- import { type TableKeyMap } from './keymap.js';
3
- import { type TableStyles } from './styles.js';
4
- import type { Column, Row, TableOptions } from './types.js';
1
+ import { Cmd, Msg } from '@suds-cli/tea';
2
+ import { Binding } from '@suds-cli/key';
3
+ import { Style, BorderStyle } from '@suds-cli/chapstick';
4
+
5
+ /** Key bindings for table navigation. @public */
6
+ interface TableKeyMap {
7
+ lineUp: Binding;
8
+ lineDown: Binding;
9
+ pageUp: Binding;
10
+ pageDown: Binding;
11
+ halfPageUp: Binding;
12
+ halfPageDown: Binding;
13
+ gotoTop: Binding;
14
+ gotoBottom: Binding;
15
+ }
16
+ /** Default key bindings matching Bubble Tea tables. @public */
17
+ declare const defaultKeyMap: TableKeyMap;
18
+
19
+ /** Styles applied to parts of the table. @public */
20
+ interface TableStyles {
21
+ header: Style;
22
+ cell: Style;
23
+ selected: Style;
24
+ border: Style;
25
+ borderStyle: BorderStyle;
26
+ }
27
+ /** Default table styles. @public */
28
+ declare function defaultStyles(): TableStyles;
29
+
30
+ /** Column definition for a table. @public */
31
+ interface Column {
32
+ title: string;
33
+ width: number;
34
+ }
35
+ /** Row data. Each entry corresponds to a column. @public */
36
+ type Row = string[];
37
+ /** Options for creating a table. @public */
38
+ interface TableOptions {
39
+ columns: Column[];
40
+ rows?: Row[];
41
+ height?: number;
42
+ width?: number;
43
+ focused?: boolean;
44
+ styles?: Partial<TableStyles>;
45
+ keyMap?: Partial<TableKeyMap>;
46
+ bordered?: boolean;
47
+ borderStyle?: BorderStyle;
48
+ }
49
+
5
50
  /**
6
51
  * Scrollable, selectable table model.
7
52
  * @public
8
53
  */
9
- export declare class TableModel {
54
+ declare class TableModel {
10
55
  readonly columns: Column[];
11
56
  readonly rows: Row[];
12
57
  readonly cursor: number;
@@ -64,4 +109,5 @@ export declare class TableModel {
64
109
  private renderAllRows;
65
110
  private with;
66
111
  }
67
- //# sourceMappingURL=model.d.ts.map
112
+
113
+ export { type Column, type Row, type TableKeyMap, TableModel, type TableOptions, type TableStyles, defaultKeyMap, defaultStyles };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,113 @@
1
- export { TableModel } from './model.js';
2
- export type { TableKeyMap } from './keymap.js';
3
- export { defaultKeyMap } from './keymap.js';
4
- export type { Column, Row, TableOptions } from './types.js';
5
- export type { TableStyles } from './styles.js';
6
- export { defaultStyles } from './styles.js';
7
- //# sourceMappingURL=index.d.ts.map
1
+ import { Cmd, Msg } from '@suds-cli/tea';
2
+ import { Binding } from '@suds-cli/key';
3
+ import { Style, BorderStyle } from '@suds-cli/chapstick';
4
+
5
+ /** Key bindings for table navigation. @public */
6
+ interface TableKeyMap {
7
+ lineUp: Binding;
8
+ lineDown: Binding;
9
+ pageUp: Binding;
10
+ pageDown: Binding;
11
+ halfPageUp: Binding;
12
+ halfPageDown: Binding;
13
+ gotoTop: Binding;
14
+ gotoBottom: Binding;
15
+ }
16
+ /** Default key bindings matching Bubble Tea tables. @public */
17
+ declare const defaultKeyMap: TableKeyMap;
18
+
19
+ /** Styles applied to parts of the table. @public */
20
+ interface TableStyles {
21
+ header: Style;
22
+ cell: Style;
23
+ selected: Style;
24
+ border: Style;
25
+ borderStyle: BorderStyle;
26
+ }
27
+ /** Default table styles. @public */
28
+ declare function defaultStyles(): TableStyles;
29
+
30
+ /** Column definition for a table. @public */
31
+ interface Column {
32
+ title: string;
33
+ width: number;
34
+ }
35
+ /** Row data. Each entry corresponds to a column. @public */
36
+ type Row = string[];
37
+ /** Options for creating a table. @public */
38
+ interface TableOptions {
39
+ columns: Column[];
40
+ rows?: Row[];
41
+ height?: number;
42
+ width?: number;
43
+ focused?: boolean;
44
+ styles?: Partial<TableStyles>;
45
+ keyMap?: Partial<TableKeyMap>;
46
+ bordered?: boolean;
47
+ borderStyle?: BorderStyle;
48
+ }
49
+
50
+ /**
51
+ * Scrollable, selectable table model.
52
+ * @public
53
+ */
54
+ declare class TableModel {
55
+ readonly columns: Column[];
56
+ readonly rows: Row[];
57
+ readonly cursor: number;
58
+ readonly offset: number;
59
+ readonly focused: boolean;
60
+ readonly height: number;
61
+ readonly width: number;
62
+ readonly autoWidth: boolean;
63
+ readonly keyMap: TableKeyMap;
64
+ readonly styles: TableStyles;
65
+ readonly bordered: boolean;
66
+ readonly columnWidths: number[];
67
+ private constructor();
68
+ /** Create a new table model. */
69
+ static new(options: TableOptions): TableModel;
70
+ /** Tea init hook (no-op). */
71
+ init(): Cmd<Msg>;
72
+ /** Handle key messages when focused. */
73
+ update(msg: Msg): [TableModel, Cmd<Msg>];
74
+ /** Render the header and visible rows as a string. */
75
+ view(): string;
76
+ /** Current selected row, if any. */
77
+ selectedRow(): Row | undefined;
78
+ /** Current selected index. */
79
+ selectedIndex(): number;
80
+ /** Replace columns. */
81
+ setColumns(columns: Column[]): TableModel;
82
+ /** Replace rows. */
83
+ setRows(rows: Row[]): TableModel;
84
+ /** Append a single row. */
85
+ appendRow(row: Row): TableModel;
86
+ /** Remove a row by index. */
87
+ removeRow(index: number): TableModel;
88
+ /** Set the selected index (clamped). */
89
+ setSelectedIndex(index: number): TableModel;
90
+ /** Move the cursor up by n rows. */
91
+ moveUp(n?: number): TableModel;
92
+ /** Move the cursor down by n rows. */
93
+ moveDown(n?: number): TableModel;
94
+ /** Jump to the first row. */
95
+ gotoTop(): TableModel;
96
+ /** Jump to the last row. */
97
+ gotoBottom(): TableModel;
98
+ /** Focus the table. */
99
+ focus(): TableModel;
100
+ /** Blur the table. */
101
+ blur(): TableModel;
102
+ /** Set the visible height (rows). */
103
+ setHeight(height: number): TableModel;
104
+ /** Set the total width. */
105
+ setWidth(width: number): TableModel;
106
+ private renderHeader;
107
+ private renderRow;
108
+ private renderEmptyRow;
109
+ private renderAllRows;
110
+ private with;
111
+ }
112
+
113
+ export { type Column, type Row, type TableKeyMap, TableModel, type TableOptions, type TableStyles, defaultKeyMap, defaultStyles };