@orz/ui-ansi 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +232 -2
  3. package/dist/content.d.ts +20 -0
  4. package/dist/content.d.ts.map +1 -0
  5. package/dist/content.js +90 -0
  6. package/dist/content.js.map +1 -0
  7. package/dist/index.d.ts +5 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +3 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/parse/index.d.ts +6 -0
  12. package/dist/parse/index.d.ts.map +1 -0
  13. package/dist/parse/index.js +5 -0
  14. package/dist/parse/index.js.map +1 -0
  15. package/dist/parse/level-tracker.d.ts +14 -0
  16. package/dist/parse/level-tracker.d.ts.map +1 -0
  17. package/dist/parse/level-tracker.js +87 -0
  18. package/dist/parse/level-tracker.js.map +1 -0
  19. package/dist/parse/levels.d.ts +19 -0
  20. package/dist/parse/levels.d.ts.map +1 -0
  21. package/dist/parse/levels.js +167 -0
  22. package/dist/parse/levels.js.map +1 -0
  23. package/dist/parse/line.d.ts +49 -0
  24. package/dist/parse/line.d.ts.map +1 -0
  25. package/dist/parse/line.js +289 -0
  26. package/dist/parse/line.js.map +1 -0
  27. package/dist/parse/palette.d.ts +12 -0
  28. package/dist/parse/palette.d.ts.map +1 -0
  29. package/dist/parse/palette.js +40 -0
  30. package/dist/parse/palette.js.map +1 -0
  31. package/dist/parse/parser.d.ts +18 -0
  32. package/dist/parse/parser.d.ts.map +1 -0
  33. package/dist/parse/parser.js +178 -0
  34. package/dist/parse/parser.js.map +1 -0
  35. package/dist/parse/sgr.d.ts +7 -0
  36. package/dist/parse/sgr.d.ts.map +1 -0
  37. package/dist/parse/sgr.js +179 -0
  38. package/dist/parse/sgr.js.map +1 -0
  39. package/dist/parse/styles.d.ts +15 -0
  40. package/dist/parse/styles.d.ts.map +1 -0
  41. package/dist/parse/styles.js +75 -0
  42. package/dist/parse/styles.js.map +1 -0
  43. package/dist/parse/tokenizer.d.ts +36 -0
  44. package/dist/parse/tokenizer.d.ts.map +1 -0
  45. package/dist/parse/tokenizer.js +287 -0
  46. package/dist/parse/tokenizer.js.map +1 -0
  47. package/dist/parse/types.d.ts +50 -0
  48. package/dist/parse/types.d.ts.map +1 -0
  49. package/dist/parse/types.js +2 -0
  50. package/dist/parse/types.js.map +1 -0
  51. package/dist/view/ansi-view.d.ts +27 -0
  52. package/dist/view/ansi-view.d.ts.map +1 -0
  53. package/dist/view/ansi-view.js +675 -0
  54. package/dist/view/ansi-view.js.map +1 -0
  55. package/dist/view/geometry.d.ts +30 -0
  56. package/dist/view/geometry.d.ts.map +1 -0
  57. package/dist/view/geometry.js +125 -0
  58. package/dist/view/geometry.js.map +1 -0
  59. package/dist/view/metrics.d.ts +17 -0
  60. package/dist/view/metrics.d.ts.map +1 -0
  61. package/dist/view/metrics.js +69 -0
  62. package/dist/view/metrics.js.map +1 -0
  63. package/dist/view/row.d.ts +41 -0
  64. package/dist/view/row.d.ts.map +1 -0
  65. package/dist/view/row.js +113 -0
  66. package/dist/view/row.js.map +1 -0
  67. package/dist/view/run-style.d.ts +11 -0
  68. package/dist/view/run-style.d.ts.map +1 -0
  69. package/dist/view/run-style.js +87 -0
  70. package/dist/view/run-style.js.map +1 -0
  71. package/dist/view/search.d.ts +28 -0
  72. package/dist/view/search.d.ts.map +1 -0
  73. package/dist/view/search.js +76 -0
  74. package/dist/view/search.js.map +1 -0
  75. package/dist/view/shown-lines.d.ts +15 -0
  76. package/dist/view/shown-lines.d.ts.map +1 -0
  77. package/dist/view/shown-lines.js +50 -0
  78. package/dist/view/shown-lines.js.map +1 -0
  79. package/dist/view/time-slices.d.ts +9 -0
  80. package/dist/view/time-slices.d.ts.map +1 -0
  81. package/dist/view/time-slices.js +35 -0
  82. package/dist/view/time-slices.js.map +1 -0
  83. package/dist/view/toolbar.d.ts +47 -0
  84. package/dist/view/toolbar.d.ts.map +1 -0
  85. package/dist/view/toolbar.js +58 -0
  86. package/dist/view/toolbar.js.map +1 -0
  87. package/dist/view/use-ansi-lines.d.ts +28 -0
  88. package/dist/view/use-ansi-lines.d.ts.map +1 -0
  89. package/dist/view/use-ansi-lines.js +103 -0
  90. package/dist/view/use-ansi-lines.js.map +1 -0
  91. package/dist/view/use-search.d.ts +37 -0
  92. package/dist/view/use-search.d.ts.map +1 -0
  93. package/dist/view/use-search.js +205 -0
  94. package/dist/view/use-search.js.map +1 -0
  95. package/dist/view/virtual-rows.d.ts +36 -0
  96. package/dist/view/virtual-rows.d.ts.map +1 -0
  97. package/dist/view/virtual-rows.js +156 -0
  98. package/dist/view/virtual-rows.js.map +1 -0
  99. package/package.json +58 -3
  100. package/styles.css +110 -0
@@ -0,0 +1,28 @@
1
+ import type { AnsiLine } from "../parse/types.ts";
2
+ /** Matches stored past this many set {@link MatchSink.capped} and stop the scan. */
3
+ export declare const MATCH_CAP = 100000;
4
+ export interface SearchFlags {
5
+ caseSensitive: boolean;
6
+ regex: boolean;
7
+ }
8
+ /** The pattern for `query`; `null` when it is empty, `"invalid"` when it does not compile. */
9
+ export declare function compileQuery(query: string, { caseSensitive, regex }: SearchFlags): RegExp | "invalid" | null;
10
+ export interface MatchSink {
11
+ /** `(lineId, from, to)` triples, UTF-16 offsets into the line's text; the first `count * 3` are set. */
12
+ matches: Uint32Array;
13
+ count: number;
14
+ /** 1 at each line id with a stored match; at least as long as the lines scanned. */
15
+ matchLines: Uint8Array;
16
+ /** True once a match past {@link MATCH_CAP} was found; nothing more is stored. */
17
+ capped: boolean;
18
+ }
19
+ export declare function createMatchSink(lineCount?: number): MatchSink;
20
+ /** Makes `sink.matchLines` cover `lineCount` lines, replacing the array when it grows. */
21
+ export declare function growMatchLines(sink: MatchSink, lineCount: number): void;
22
+ /**
23
+ * Appends every match of `re` (a `g` pattern) in the lines at positions
24
+ * `[from, to)` of `ids`, or of `lines` itself when `ids` is null. Zero-length
25
+ * matches are skipped. Stops early once the sink is capped.
26
+ */
27
+ export declare function scanLines(re: RegExp, lines: readonly Pick<AnsiLine, "text">[], ids: Uint32Array | null, from: number, to: number, sink: MatchSink): void;
28
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/view/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,oFAAoF;AACpF,eAAO,MAAM,SAAS,SAAU,CAAC;AAEjC,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAKD,8FAA8F;AAC9F,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,WAAW,GACpC,MAAM,GAAG,SAAS,GAAG,IAAI,CAQ3B;AAED,MAAM,WAAW,SAAS;IACxB,wGAAwG;IACxG,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,UAAU,EAAE,UAAU,CAAC;IACvB,kFAAkF;IAClF,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,eAAe,CAAC,SAAS,SAAI,GAAG,SAAS,CAOxD;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAKvE;AAkBD;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,SAAS,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EACxC,GAAG,EAAE,WAAW,GAAG,IAAI,EACvB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,SAAS,GACd,IAAI,CAuBN"}
@@ -0,0 +1,76 @@
1
+ /** Matches stored past this many set {@link MatchSink.capped} and stop the scan. */
2
+ export const MATCH_CAP = 100_000;
3
+ // Only the syntax characters: `u` mode rejects identity escapes such as `\-`.
4
+ const SYNTAX = /[\\^$.*+?()[\]{}|/]/g;
5
+ /** The pattern for `query`; `null` when it is empty, `"invalid"` when it does not compile. */
6
+ export function compileQuery(query, { caseSensitive, regex }) {
7
+ if (query === "")
8
+ return null;
9
+ const source = regex ? query : query.replace(SYNTAX, "\\$&");
10
+ try {
11
+ return new RegExp(source, caseSensitive ? "gu" : "giu");
12
+ }
13
+ catch {
14
+ return "invalid";
15
+ }
16
+ }
17
+ export function createMatchSink(lineCount = 0) {
18
+ return {
19
+ matches: new Uint32Array(3 * 64),
20
+ count: 0,
21
+ matchLines: new Uint8Array(Math.max(lineCount, 64)),
22
+ capped: false,
23
+ };
24
+ }
25
+ /** Makes `sink.matchLines` cover `lineCount` lines, replacing the array when it grows. */
26
+ export function growMatchLines(sink, lineCount) {
27
+ if (sink.matchLines.length >= lineCount)
28
+ return;
29
+ const next = new Uint8Array(Math.max(lineCount, 2 * sink.matchLines.length));
30
+ next.set(sink.matchLines);
31
+ sink.matchLines = next;
32
+ }
33
+ function store(sink, id, from, to) {
34
+ const at = sink.count * 3;
35
+ if (at + 3 > sink.matches.length) {
36
+ const next = new Uint32Array(Math.min(2 * sink.matches.length, 3 * MATCH_CAP));
37
+ next.set(sink.matches);
38
+ sink.matches = next;
39
+ }
40
+ sink.matches[at] = id;
41
+ sink.matches[at + 1] = from;
42
+ sink.matches[at + 2] = to;
43
+ sink.count++;
44
+ sink.matchLines[id] = 1;
45
+ }
46
+ /**
47
+ * Appends every match of `re` (a `g` pattern) in the lines at positions
48
+ * `[from, to)` of `ids`, or of `lines` itself when `ids` is null. Zero-length
49
+ * matches are skipped. Stops early once the sink is capped.
50
+ */
51
+ export function scanLines(re, lines, ids, from, to, sink) {
52
+ if (sink.capped || from >= to)
53
+ return;
54
+ // `ids` ascend, so its last id is the highest this call can flag.
55
+ growMatchLines(sink, (ids ? ids[to - 1] : to - 1) + 1);
56
+ for (let pos = from; pos < to; pos++) {
57
+ const id = ids ? ids[pos] : pos;
58
+ const text = lines[id].text;
59
+ re.lastIndex = 0;
60
+ for (let m = re.exec(text); m; m = re.exec(text)) {
61
+ const end = m.index + m[0].length;
62
+ if (end === m.index) {
63
+ // Step over a whole code point, or `u` would match inside a surrogate pair.
64
+ const cp = text.codePointAt(end);
65
+ re.lastIndex = end + (cp !== undefined && cp > 0xffff ? 2 : 1);
66
+ continue;
67
+ }
68
+ if (sink.count === MATCH_CAP) {
69
+ sink.capped = true;
70
+ return;
71
+ }
72
+ store(sink, id, m.index, end);
73
+ }
74
+ }
75
+ }
76
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/view/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type LogLevel } from "../parse/levels.ts";
2
+ /** Bit `c` set for each level code `c` the filter shows; bit 0 is Other. */
3
+ export declare function levelMask(hidden: ReadonlySet<LogLevel | "other">): number;
4
+ /**
5
+ * The ids of lines `[0, count)` whose level `mask` shows and, with
6
+ * `matchLines`, that have a match; `null` when no line can be filtered out.
7
+ * `levels` of `null` makes every line Other.
8
+ */
9
+ export declare function buildShownLines(count: number, levels: Uint8Array | null, mask: number, matchLines: Uint8Array | null): Uint32Array | null;
10
+ /**
11
+ * `prev`, built by {@link buildShownLines} over lines before `from`, extended
12
+ * with the ids in `[from, to)` that pass. `prev` keeps reading as it did.
13
+ */
14
+ export declare function appendShownLines(prev: Uint32Array | null, from: number, to: number, levels: Uint8Array | null, mask: number, matchLines: Uint8Array | null): Uint32Array | null;
15
+ //# sourceMappingURL=shown-lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shown-lines.d.ts","sourceRoot":"","sources":["../../src/view/shown-lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,QAAQ,EAAa,MAAM,oBAAoB,CAAC;AAI/E,4EAA4E;AAC5E,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,MAAM,CAMzE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,GAAG,IAAI,GAC5B,WAAW,GAAG,IAAI,CAEpB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,GAAG,IAAI,GAC5B,WAAW,GAAG,IAAI,CAqBpB"}
@@ -0,0 +1,50 @@
1
+ import { LEVEL_INHERITED, levelCode } from "../parse/levels.js";
2
+ const ALL_LEVELS = 0x7f;
3
+ /** Bit `c` set for each level code `c` the filter shows; bit 0 is Other. */
4
+ export function levelMask(hidden) {
5
+ let mask = ALL_LEVELS;
6
+ for (const level of hidden) {
7
+ mask &= ~(1 << (level === "other" ? 0 : levelCode(level)));
8
+ }
9
+ return mask;
10
+ }
11
+ /**
12
+ * The ids of lines `[0, count)` whose level `mask` shows and, with
13
+ * `matchLines`, that have a match; `null` when no line can be filtered out.
14
+ * `levels` of `null` makes every line Other.
15
+ */
16
+ export function buildShownLines(count, levels, mask, matchLines) {
17
+ return appendShownLines(null, 0, count, levels, mask, matchLines);
18
+ }
19
+ /**
20
+ * `prev`, built by {@link buildShownLines} over lines before `from`, extended
21
+ * with the ids in `[from, to)` that pass. `prev` keeps reading as it did.
22
+ */
23
+ export function appendShownLines(prev, from, to, levels, mask, matchLines) {
24
+ if ((mask & ALL_LEVELS) === ALL_LEVELS && !matchLines)
25
+ return null;
26
+ const start = prev ? prev.length : 0;
27
+ const needed = start + Math.max(0, to - from);
28
+ let out;
29
+ // Lines and matches arrive a slice at a time; spare capacity keeps each
30
+ // append from copying the whole list.
31
+ if (prev && prev.byteOffset === 0 && prev.buffer.byteLength >= needed * 4) {
32
+ out = new Uint32Array(prev.buffer, 0, needed);
33
+ }
34
+ else {
35
+ out = new Uint32Array(Math.max(needed, 2 * start));
36
+ if (prev)
37
+ out.set(prev);
38
+ }
39
+ let n = start;
40
+ for (let i = from; i < to; i++) {
41
+ const code = levels ? levels[i] & ~LEVEL_INHERITED : 0;
42
+ if (!(mask & (1 << code)))
43
+ continue;
44
+ if (matchLines && !matchLines[i])
45
+ continue;
46
+ out[n++] = i;
47
+ }
48
+ return out.subarray(0, n);
49
+ }
50
+ //# sourceMappingURL=shown-lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shown-lines.js","sourceRoot":"","sources":["../../src/view/shown-lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAiB,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/E,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,MAAuC;IAC/D,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,MAAyB,EACzB,IAAY,EACZ,UAA6B;IAE7B,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAwB,EACxB,IAAY,EACZ,EAAU,EACV,MAAyB,EACzB,IAAY,EACZ,UAA6B;IAE7B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,UAAU,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IAC9C,IAAI,GAAgB,CAAC;IACrB,wEAAwE;IACxE,sCAAsC;IACtC,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,GAAG,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,GAAG,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;QACnD,IAAI,IAAI;YAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,CAAC,GAAG,KAAK,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;YAAE,SAAS;QACpC,IAAI,UAAU,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,SAAS;QAC3C,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** How long one slice may run before it yields to the browser. */
2
+ export declare const SLICE_BUDGET_MS = 8;
3
+ /**
4
+ * Calls `step` once per macrotask, each time with a deadline
5
+ * {@link SLICE_BUDGET_MS} away, until it returns true or the returned stop is
6
+ * called. `onSlice` runs after every step, including the last.
7
+ */
8
+ export declare function runSlices(step: (deadline: number) => boolean, onSlice: () => void): () => void;
9
+ //# sourceMappingURL=time-slices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-slices.d.ts","sourceRoot":"","sources":["../../src/view/time-slices.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,EACnC,OAAO,EAAE,MAAM,IAAI,GAClB,MAAM,IAAI,CAsBZ"}
@@ -0,0 +1,35 @@
1
+ /** How long one slice may run before it yields to the browser. */
2
+ export const SLICE_BUDGET_MS = 8;
3
+ /**
4
+ * Calls `step` once per macrotask, each time with a deadline
5
+ * {@link SLICE_BUDGET_MS} away, until it returns true or the returned stop is
6
+ * called. `onSlice` runs after every step, including the last.
7
+ */
8
+ export function runSlices(step, onSlice) {
9
+ // MessageChannel rather than setTimeout: nested timeouts are clamped to 4 ms,
10
+ // which would idle half of every slice.
11
+ const channel = new MessageChannel();
12
+ const port = channel.port2;
13
+ let stopped = false;
14
+ const stop = () => {
15
+ stopped = true;
16
+ channel.port1.close();
17
+ port.close();
18
+ };
19
+ channel.port1.onmessage = () => {
20
+ // A tick queued before stop can still be delivered.
21
+ if (stopped)
22
+ return;
23
+ const done = step(performance.now() + SLICE_BUDGET_MS);
24
+ onSlice();
25
+ if (stopped)
26
+ return;
27
+ if (done)
28
+ stop();
29
+ else
30
+ port.postMessage(null);
31
+ };
32
+ port.postMessage(null);
33
+ return stop;
34
+ }
35
+ //# sourceMappingURL=time-slices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-slices.js","sourceRoot":"","sources":["../../src/view/time-slices.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,IAAmC,EACnC,OAAmB;IAEnB,8EAA8E;IAC9E,wCAAwC;IACxC,MAAM,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC;IAC3B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,OAAO,GAAG,IAAI,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC,CAAC;IACF,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,EAAE;QAC7B,oDAAoD;QACpD,IAAI,OAAO;YAAE,OAAO;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC,CAAC;QACvD,OAAO,EAAE,CAAC;QACV,IAAI,OAAO;YAAE,OAAO;QACpB,IAAI,IAAI;YAAE,IAAI,EAAE,CAAC;;YACZ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { RefObject } from "react";
2
+ import type { LevelCounts } from "../parse/level-tracker.ts";
3
+ import { type LogLevel } from "../parse/levels.ts";
4
+ export type LevelKey = LogLevel | "other";
5
+ /** The chips' order: the levels from fatal to trace, then Other. */
6
+ export declare const LEVEL_KEYS: readonly LevelKey[];
7
+ /**
8
+ * The filter after a click on the chip of `key`: a click toggles it, a
9
+ * shift+click shows it alone, or everything again when it already was.
10
+ */
11
+ export declare function toggleLevel(hidden: ReadonlySet<LevelKey>, key: LevelKey, solo: boolean, present: readonly LevelKey[]): Set<LevelKey>;
12
+ export interface LevelChipsProps {
13
+ counts: LevelCounts;
14
+ hidden: ReadonlySet<LevelKey>;
15
+ onChange: (hidden: Set<LevelKey>) => void;
16
+ }
17
+ /** A toggle chip per level that occurs, with its line count. */
18
+ export declare function LevelChips({ counts, hidden, onChange }: LevelChipsProps): import("react").JSX.Element;
19
+ export interface SearchCounter {
20
+ /** The current match's index, or -1. */
21
+ current: number;
22
+ count: number;
23
+ capped: boolean;
24
+ scanning: boolean;
25
+ error: "invalid" | null;
26
+ }
27
+ /** "3 / 41", with "…" while the scan runs and "100,000+" past the cap. */
28
+ export declare function counterLabel(query: string, c: SearchCounter): string;
29
+ export interface SearchBoxProps {
30
+ inputRef: RefObject<HTMLInputElement | null>;
31
+ query: string;
32
+ onQuery: (query: string) => void;
33
+ counter: SearchCounter;
34
+ caseSensitive: boolean;
35
+ onCaseSensitive: (on: boolean) => void;
36
+ regex: boolean;
37
+ onRegex: (on: boolean) => void;
38
+ onlyMatching: boolean;
39
+ onOnlyMatching: (on: boolean) => void;
40
+ /** Goes to the next match, or the previous with `back`. */
41
+ onStep: (back: boolean) => void;
42
+ /** Escape: leaves the box, keeping the query. */
43
+ onLeave: () => void;
44
+ className?: string;
45
+ }
46
+ export declare function SearchBox({ inputRef, query, onQuery, counter, caseSensitive, onCaseSensitive, regex, onRegex, onlyMatching, onOnlyMatching, onStep, onLeave, className, }: SearchBoxProps): import("react").JSX.Element;
47
+ //# sourceMappingURL=toolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../../src/view/toolbar.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAwC,SAAS,EAAE,MAAM,OAAO,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG3D,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1C,oEAAoE;AACpE,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAAyB,CAAC;AAIpE;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,SAAS,QAAQ,EAAE,GAC3B,GAAG,CAAC,QAAQ,CAAC,CAUf;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;CAC3C;AAED,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,eAAe,+BA8BvE;AAED,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,GAAG,MAAM,CAKpE;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,aAAa,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,2DAA2D;IAC3D,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAChC,iDAAiD;IACjD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4BD,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,KAAK,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,eAAe,EACf,KAAK,EACL,OAAO,EACP,YAAY,EACZ,cAAc,EACd,MAAM,EACN,OAAO,EACP,SAAS,GACV,EAAE,cAAc,+BA+EhB"}
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@orz/ui/components/button";
3
+ import { cn } from "@orz/ui/lib/utils";
4
+ import { CaseSensitiveIcon, ChevronDownIcon, ChevronUpIcon, ListFilterIcon, RegexIcon, SearchIcon, } from "lucide-react";
5
+ import { LEVELS } from "../parse/levels.js";
6
+ import { MATCH_CAP } from "./search.js";
7
+ /** The chips' order: the levels from fatal to trace, then Other. */
8
+ export const LEVEL_KEYS = [...LEVELS, "other"];
9
+ const formatCount = (n) => n.toLocaleString("en-US");
10
+ /**
11
+ * The filter after a click on the chip of `key`: a click toggles it, a
12
+ * shift+click shows it alone, or everything again when it already was.
13
+ */
14
+ export function toggleLevel(hidden, key, solo, present) {
15
+ if (!solo) {
16
+ const next = new Set(hidden);
17
+ if (next.has(key))
18
+ next.delete(key);
19
+ else
20
+ next.add(key);
21
+ return next;
22
+ }
23
+ const alone = !hidden.has(key) && present.every((k) => k === key || hidden.has(k));
24
+ return alone ? new Set() : new Set(LEVEL_KEYS.filter((k) => k !== key));
25
+ }
26
+ /** A toggle chip per level that occurs, with its line count. */
27
+ export function LevelChips({ counts, hidden, onChange }) {
28
+ const present = LEVEL_KEYS.filter((key) => counts[key] > 0);
29
+ const onClick = (key) => (event) => onChange(toggleLevel(hidden, key, event.shiftKey, present));
30
+ return (_jsx("div", { className: "flex flex-wrap gap-1", children: present.map((key) => (_jsxs(Button, { size: "xs", variant: "ghost", "aria-pressed": !hidden.has(key), title: "Click to show or hide; shift+click to show only this level", "data-level": key === "other" ? undefined : key, className: "rounded-full font-mono text-muted-foreground line-through opacity-60 aria-pressed:bg-muted aria-pressed:text-foreground aria-pressed:no-underline aria-pressed:opacity-100", onClick: onClick(key), children: [_jsx("span", { "aria-hidden": true, className: "size-2 rounded-full bg-[var(--log-level,var(--color-muted-foreground))]" }), key === "other" ? "Other" : key.toUpperCase(), " ", _jsx("span", { className: "text-muted-foreground", children: formatCount(counts[key]) })] }, key))) }));
31
+ }
32
+ /** "3 / 41", with "…" while the scan runs and "100,000+" past the cap. */
33
+ export function counterLabel(query, c) {
34
+ if (query === "")
35
+ return "";
36
+ if (c.error)
37
+ return "Invalid regex";
38
+ const total = c.capped ? `${formatCount(MATCH_CAP)}+` : formatCount(c.count);
39
+ return `${formatCount(c.current + 1)} / ${total}${c.scanning ? "…" : ""}`;
40
+ }
41
+ function Toggle({ label, pressed, onPressed, children, }) {
42
+ return (_jsx(Button, { size: "icon-xs", variant: "ghost", "aria-label": label, title: label, "aria-pressed": pressed, className: "aria-pressed:bg-muted aria-pressed:text-foreground", onClick: () => onPressed(!pressed), children: children }));
43
+ }
44
+ export function SearchBox({ inputRef, query, onQuery, counter, caseSensitive, onCaseSensitive, regex, onRegex, onlyMatching, onOnlyMatching, onStep, onLeave, className, }) {
45
+ const onKeyDown = (event) => {
46
+ if (event.key === "Enter") {
47
+ event.preventDefault();
48
+ onStep(event.shiftKey);
49
+ }
50
+ else if (event.key === "Escape") {
51
+ event.preventDefault();
52
+ onLeave();
53
+ }
54
+ };
55
+ const invalid = counter.error !== null && query !== "";
56
+ return (_jsxs("div", { className: cn("flex min-w-0 items-center gap-0.5 rounded-md border border-border bg-background pl-1.5", className), children: [_jsx(SearchIcon, { "aria-hidden": true, className: "size-3 shrink-0 text-muted-foreground" }), _jsx("input", { ref: inputRef, type: "search", "aria-label": "Search log", placeholder: "Search", "aria-invalid": invalid || undefined, value: query, onChange: (event) => onQuery(event.target.value), onKeyDown: onKeyDown, className: "h-6 w-36 min-w-0 flex-auto bg-transparent px-1 font-mono text-foreground outline-none aria-invalid:text-destructive" }), _jsx("span", { "aria-live": "polite", className: cn("shrink-0 text-right text-muted-foreground tabular-nums", invalid && "text-destructive"), children: counterLabel(query, counter) }), _jsx(Button, { size: "icon-xs", variant: "ghost", "aria-label": "Previous match", title: "Previous match (Shift+Enter)", onClick: () => onStep(true), children: _jsx(ChevronUpIcon, {}) }), _jsx(Button, { size: "icon-xs", variant: "ghost", "aria-label": "Next match", title: "Next match (Enter)", onClick: () => onStep(false), children: _jsx(ChevronDownIcon, {}) }), _jsx(Toggle, { label: "Match case", pressed: caseSensitive, onPressed: onCaseSensitive, children: _jsx(CaseSensitiveIcon, {}) }), _jsx(Toggle, { label: "Regular expression", pressed: regex, onPressed: onRegex, children: _jsx(RegexIcon, {}) }), _jsx(Toggle, { label: "Only matching lines", pressed: onlyMatching, onPressed: onOnlyMatching, children: _jsx(ListFilterIcon, {}) })] }));
57
+ }
58
+ //# sourceMappingURL=toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../src/view/toolbar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { type LevelCounts } from "../parse/level-tracker.ts";
2
+ import type { LevelDetector } from "../parse/levels.ts";
3
+ import type { AnsiParse } from "../parse/types.ts";
4
+ /** Text up to this many UTF-16 units is parsed in one go during render. */
5
+ export declare const SYNC_PARSE_MAX: number;
6
+ export interface AnsiLines extends AnsiParse {
7
+ /** False while a large text is still being parsed in the background. */
8
+ readonly done: boolean;
9
+ /** Bumped on every publish; `lines` itself grows in place. */
10
+ readonly version: number;
11
+ /** The share of the text parsed so far, from 0 to 1. */
12
+ readonly parsed: number;
13
+ /**
14
+ * One level code per line of `lines`, null when levels are off. Like
15
+ * `lines`, it covers the lines parsed so far.
16
+ */
17
+ readonly levels: Uint8Array | null;
18
+ readonly levelCounts: LevelCounts | null;
19
+ }
20
+ /**
21
+ * The parsed lines of `text`. A text over {@link SYNC_PARSE_MAX} is parsed in
22
+ * time slices, and the lines so far are returned with `done` false.
23
+ *
24
+ * With a `levels` detector, each line is classified as it is parsed. A new
25
+ * detector restarts the parse, so it should be stable across renders.
26
+ */
27
+ export declare function useAnsiLines(text: string, levels?: LevelDetector | false): AnsiLines;
28
+ //# sourceMappingURL=use-ansi-lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-ansi-lines.d.ts","sourceRoot":"","sources":["../../src/view/use-ansi-lines.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAG/D,2EAA2E;AAC3E,eAAO,MAAM,cAAc,QAAU,CAAC;AAGtC,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;CAC1C;AAoGD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,aAAa,GAAG,KAAa,GACpC,SAAS,CAcX"}
@@ -0,0 +1,103 @@
1
+ import { useEffect, useMemo, useSyncExternalStore } from "react";
2
+ import { createLevelTracker, } from "../parse/level-tracker.js";
3
+ import { createAnsiParser, parseAnsi } from "../parse/parser.js";
4
+ import { runSlices, SLICE_BUDGET_MS } from "./time-slices.js";
5
+ /** Text up to this many UTF-16 units is parsed in one go during render. */
6
+ export const SYNC_PARSE_MAX = 1 << 20;
7
+ const SLICE = 1 << 16;
8
+ const noop = () => { };
9
+ function staticStore(snapshot) {
10
+ return {
11
+ subscribe: () => noop,
12
+ getSnapshot: () => snapshot,
13
+ start: () => noop,
14
+ };
15
+ }
16
+ function staticParse(text, detect) {
17
+ const parse = parseAnsi(text);
18
+ let tracker = null;
19
+ if (detect) {
20
+ tracker = createLevelTracker(detect);
21
+ tracker.push(parse.lines, 0, parse.lines.length);
22
+ }
23
+ return {
24
+ ...parse,
25
+ done: true,
26
+ version: 0,
27
+ parsed: 1,
28
+ levels: tracker?.levels ?? null,
29
+ levelCounts: tracker?.counts ?? null,
30
+ };
31
+ }
32
+ function slicedStore(text, detect) {
33
+ const parser = createAnsiParser();
34
+ const tracker = detect ? createLevelTracker(detect) : null;
35
+ const listeners = new Set();
36
+ let offset = 0;
37
+ let version = 0;
38
+ function take(done) {
39
+ return {
40
+ lines: parser.lines,
41
+ styles: parser.styles,
42
+ maxCells: parser.maxCells,
43
+ done,
44
+ version: version++,
45
+ parsed: Math.min(1, offset / text.length),
46
+ levels: tracker?.levels ?? null,
47
+ levelCounts: tracker?.counts ?? null,
48
+ };
49
+ }
50
+ function classify() {
51
+ tracker?.push(parser.lines, tracker.count, parser.lines.length);
52
+ }
53
+ function step(deadline) {
54
+ do {
55
+ parser.push(text.slice(offset, offset + SLICE));
56
+ offset += SLICE;
57
+ if (offset >= text.length) {
58
+ parser.end();
59
+ classify();
60
+ return true;
61
+ }
62
+ classify();
63
+ } while (performance.now() < deadline);
64
+ return false;
65
+ }
66
+ // The first batch runs at once so the first paint already has lines.
67
+ let snapshot = take(step(performance.now() + SLICE_BUDGET_MS));
68
+ return {
69
+ subscribe(listener) {
70
+ listeners.add(listener);
71
+ return () => listeners.delete(listener);
72
+ },
73
+ getSnapshot: () => snapshot,
74
+ start() {
75
+ if (snapshot.done)
76
+ return noop;
77
+ let done = false;
78
+ return runSlices((deadline) => {
79
+ done = step(deadline);
80
+ return done;
81
+ }, () => {
82
+ snapshot = take(done);
83
+ for (const listener of listeners)
84
+ listener();
85
+ });
86
+ },
87
+ };
88
+ }
89
+ /**
90
+ * The parsed lines of `text`. A text over {@link SYNC_PARSE_MAX} is parsed in
91
+ * time slices, and the lines so far are returned with `done` false.
92
+ *
93
+ * With a `levels` detector, each line is classified as it is parsed. A new
94
+ * detector restarts the parse, so it should be stable across renders.
95
+ */
96
+ export function useAnsiLines(text, levels = false) {
97
+ const store = useMemo(() => text.length > SYNC_PARSE_MAX
98
+ ? slicedStore(text, levels)
99
+ : staticStore(staticParse(text, levels)), [text, levels]);
100
+ useEffect(() => store.start(), [store]);
101
+ return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
102
+ }
103
+ //# sourceMappingURL=use-ansi-lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-ansi-lines.js","sourceRoot":"","sources":["../../src/view/use-ansi-lines.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { AnsiLine } from "../parse/types.ts";
2
+ import { type SearchFlags } from "./search.ts";
3
+ /** How long the query and flags must stay unchanged before a scan starts. */
4
+ export declare const SEARCH_DEBOUNCE_MS = 150;
5
+ export interface SearchInput extends SearchFlags {
6
+ query: string;
7
+ /** Grows in place while a large text is parsed. */
8
+ lines: readonly AnsiLine[];
9
+ /** The lines complete so far; a rise means `lines` grew. */
10
+ count: number;
11
+ /** False while more lines may still arrive. */
12
+ done: boolean;
13
+ /** The ids the level filter shows, ascending; `null` for every line. */
14
+ shown: Uint32Array | null;
15
+ }
16
+ export interface SearchState {
17
+ /** `(lineId, from, to)` triples, `count * 3` long. */
18
+ readonly matches: Uint32Array;
19
+ readonly count: number;
20
+ /** More matches exist than were stored. */
21
+ readonly capped: boolean;
22
+ /** The counts may still rise: a scan is pending, running, or waiting for lines. */
23
+ readonly scanning: boolean;
24
+ /** 1 at each line id with a match; at least `count` lines long. Replaced as it grows. */
25
+ readonly matchLines: Uint8Array;
26
+ readonly error: "invalid" | null;
27
+ /** Changes whenever the scan starts over, so a match index is only good within one. */
28
+ readonly generation: number;
29
+ }
30
+ /**
31
+ * Every match of `query` in the lines `shown` lists, found in time slices
32
+ * {@link SEARCH_DEBOUNCE_MS} after the query or flags last changed. Lines that
33
+ * arrive while parsing, and ids appended to `shown`, are scanned as they come;
34
+ * any other change to `lines` or `shown` starts the scan over.
35
+ */
36
+ export declare function useSearch(input: SearchInput): SearchState;
37
+ //# sourceMappingURL=use-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-search.d.ts","sourceRoot":"","sources":["../../src/view/use-search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAKL,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;AAGrB,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAItC,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC3B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,IAAI,EAAE,OAAO,CAAC;IACd,wEAAwE;IACxE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACjC,uFAAuF;IACvF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AA8LD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAYzD"}