@zakmandhro/bunti 0.1.5 → 0.2.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.
Files changed (192) hide show
  1. package/AGENTS.md +65 -0
  2. package/README.md +86 -11
  3. package/dist/cli.d.ts +44 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +147 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/colors.d.ts +77 -7
  8. package/dist/colors.d.ts.map +1 -1
  9. package/dist/colors.js +238 -39
  10. package/dist/colors.js.map +1 -1
  11. package/dist/components/Box.d.ts +6 -0
  12. package/dist/components/Box.d.ts.map +1 -1
  13. package/dist/components/Box.js +5 -0
  14. package/dist/components/Box.js.map +1 -1
  15. package/dist/components/Button.d.ts +15 -2
  16. package/dist/components/Button.d.ts.map +1 -1
  17. package/dist/components/Button.js +45 -25
  18. package/dist/components/Button.js.map +1 -1
  19. package/dist/components/Card.d.ts +24 -2
  20. package/dist/components/Card.d.ts.map +1 -1
  21. package/dist/components/Card.js +56 -14
  22. package/dist/components/Card.js.map +1 -1
  23. package/dist/components/Header.d.ts +11 -1
  24. package/dist/components/Header.d.ts.map +1 -1
  25. package/dist/components/Header.js +12 -8
  26. package/dist/components/Header.js.map +1 -1
  27. package/dist/components/Input.d.ts +10 -1
  28. package/dist/components/Input.d.ts.map +1 -1
  29. package/dist/components/Input.js +176 -41
  30. package/dist/components/Input.js.map +1 -1
  31. package/dist/components/Link.d.ts +21 -0
  32. package/dist/components/Link.d.ts.map +1 -0
  33. package/dist/components/Link.js +38 -0
  34. package/dist/components/Link.js.map +1 -0
  35. package/dist/components/Modal.d.ts +25 -0
  36. package/dist/components/Modal.d.ts.map +1 -1
  37. package/dist/components/Modal.js +88 -24
  38. package/dist/components/Modal.js.map +1 -1
  39. package/dist/components/Progress.d.ts +27 -0
  40. package/dist/components/Progress.d.ts.map +1 -0
  41. package/dist/components/Progress.js +39 -0
  42. package/dist/components/Progress.js.map +1 -0
  43. package/dist/components/Spinner.d.ts +19 -0
  44. package/dist/components/Spinner.d.ts.map +1 -0
  45. package/dist/components/Spinner.js +27 -0
  46. package/dist/components/Spinner.js.map +1 -0
  47. package/dist/components/index.d.ts +3 -0
  48. package/dist/components/index.d.ts.map +1 -1
  49. package/dist/components/index.js +3 -0
  50. package/dist/components/index.js.map +1 -1
  51. package/dist/data/nf-glyphs.d.ts +11 -0
  52. package/dist/data/nf-glyphs.d.ts.map +1 -0
  53. package/dist/data/nf-glyphs.js +535 -0
  54. package/dist/data/nf-glyphs.js.map +1 -0
  55. package/dist/data/nf-names.d.ts +8 -0
  56. package/dist/data/nf-names.d.ts.map +1 -0
  57. package/dist/data/nf-names.js +2 -0
  58. package/dist/data/nf-names.js.map +1 -0
  59. package/dist/demo-registry.d.ts +27 -0
  60. package/dist/demo-registry.d.ts.map +1 -0
  61. package/dist/demo-registry.js +57 -0
  62. package/dist/demo-registry.js.map +1 -0
  63. package/dist/demos/2048.ts +743 -0
  64. package/dist/demos/animation.ts +246 -0
  65. package/dist/demos/demo-layout.ts +124 -0
  66. package/dist/demos/engine.ts +374 -0
  67. package/dist/demos/interaction.ts +91 -0
  68. package/dist/demos/login.ts +203 -0
  69. package/dist/demos/mission-control.ts +558 -0
  70. package/dist/demos/showcase.ts +224 -0
  71. package/dist/detect.d.ts +92 -3
  72. package/dist/detect.d.ts.map +1 -1
  73. package/dist/detect.js +218 -40
  74. package/dist/detect.js.map +1 -1
  75. package/dist/diagnostics.d.ts +73 -0
  76. package/dist/diagnostics.d.ts.map +1 -0
  77. package/dist/diagnostics.js +225 -0
  78. package/dist/diagnostics.js.map +1 -0
  79. package/dist/dsl/context.d.ts +11 -0
  80. package/dist/dsl/context.d.ts.map +1 -0
  81. package/dist/dsl/context.js +658 -0
  82. package/dist/dsl/context.js.map +1 -0
  83. package/dist/dsl/hooks.d.ts +12 -0
  84. package/dist/dsl/hooks.d.ts.map +1 -0
  85. package/dist/dsl/hooks.js +148 -0
  86. package/dist/dsl/hooks.js.map +1 -0
  87. package/dist/dsl/interaction.d.ts +31 -0
  88. package/dist/dsl/interaction.d.ts.map +1 -0
  89. package/dist/dsl/interaction.js +150 -0
  90. package/dist/dsl/interaction.js.map +1 -0
  91. package/dist/dsl/layers.d.ts +14 -0
  92. package/dist/dsl/layers.d.ts.map +1 -0
  93. package/dist/dsl/layers.js +87 -0
  94. package/dist/dsl/layers.js.map +1 -0
  95. package/dist/dsl/motion.d.ts +10 -0
  96. package/dist/dsl/motion.d.ts.map +1 -0
  97. package/dist/dsl/motion.js +150 -0
  98. package/dist/dsl/motion.js.map +1 -0
  99. package/dist/dsl/render.d.ts +22 -0
  100. package/dist/dsl/render.d.ts.map +1 -0
  101. package/dist/dsl/render.js +69 -0
  102. package/dist/dsl/render.js.map +1 -0
  103. package/dist/dsl/types.d.ts +555 -0
  104. package/dist/dsl/types.d.ts.map +1 -0
  105. package/dist/dsl/types.js +33 -0
  106. package/dist/dsl/types.js.map +1 -0
  107. package/dist/dsl.d.ts +13 -154
  108. package/dist/dsl.d.ts.map +1 -1
  109. package/dist/dsl.js +12 -658
  110. package/dist/dsl.js.map +1 -1
  111. package/dist/easing.d.ts +41 -1
  112. package/dist/easing.d.ts.map +1 -1
  113. package/dist/easing.js +105 -2
  114. package/dist/easing.js.map +1 -1
  115. package/dist/geometry.d.ts +39 -0
  116. package/dist/geometry.d.ts.map +1 -1
  117. package/dist/geometry.js +20 -0
  118. package/dist/geometry.js.map +1 -1
  119. package/dist/icons-full.d.ts +5 -0
  120. package/dist/icons-full.d.ts.map +1 -0
  121. package/dist/icons-full.js +31 -0
  122. package/dist/icons-full.js.map +1 -0
  123. package/dist/icons.d.ts +426 -5
  124. package/dist/icons.d.ts.map +1 -1
  125. package/dist/icons.js +144 -15
  126. package/dist/icons.js.map +1 -1
  127. package/dist/index.d.ts +95 -23
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +17 -7
  130. package/dist/index.js.map +1 -1
  131. package/dist/input.d.ts +177 -0
  132. package/dist/input.d.ts.map +1 -0
  133. package/dist/input.js +533 -0
  134. package/dist/input.js.map +1 -0
  135. package/dist/layout.d.ts +153 -7
  136. package/dist/layout.d.ts.map +1 -1
  137. package/dist/layout.js +221 -34
  138. package/dist/layout.js.map +1 -1
  139. package/dist/render.d.ts +33 -1
  140. package/dist/render.d.ts.map +1 -1
  141. package/dist/render.js +431 -116
  142. package/dist/render.js.map +1 -1
  143. package/dist/state.d.ts +156 -3
  144. package/dist/state.d.ts.map +1 -1
  145. package/dist/state.js +25 -0
  146. package/dist/state.js.map +1 -1
  147. package/dist/theme.d.ts +129 -0
  148. package/dist/theme.d.ts.map +1 -0
  149. package/dist/theme.js +167 -0
  150. package/dist/theme.js.map +1 -0
  151. package/dist/themes/catppuccin-mocha.d.ts +19 -0
  152. package/dist/themes/catppuccin-mocha.d.ts.map +1 -0
  153. package/dist/themes/catppuccin-mocha.js +36 -0
  154. package/dist/themes/catppuccin-mocha.js.map +1 -0
  155. package/dist/themes/dracula.d.ts +21 -0
  156. package/dist/themes/dracula.d.ts.map +1 -0
  157. package/dist/themes/dracula.js +37 -0
  158. package/dist/themes/dracula.js.map +1 -0
  159. package/dist/themes/github-light.d.ts +21 -0
  160. package/dist/themes/github-light.d.ts.map +1 -0
  161. package/dist/themes/github-light.js +36 -0
  162. package/dist/themes/github-light.js.map +1 -0
  163. package/dist/themes/index.d.ts +19 -0
  164. package/dist/themes/index.d.ts.map +1 -0
  165. package/dist/themes/index.js +17 -0
  166. package/dist/themes/index.js.map +1 -0
  167. package/dist/themes/nord.d.ts +23 -0
  168. package/dist/themes/nord.d.ts.map +1 -0
  169. package/dist/themes/nord.js +38 -0
  170. package/dist/themes/nord.js.map +1 -0
  171. package/dist/themes/one-dark-pro.d.ts +21 -0
  172. package/dist/themes/one-dark-pro.d.ts.map +1 -0
  173. package/dist/themes/one-dark-pro.js +36 -0
  174. package/dist/themes/one-dark-pro.js.map +1 -0
  175. package/dist/themes/tokyo-night.d.ts +20 -0
  176. package/dist/themes/tokyo-night.d.ts.map +1 -0
  177. package/dist/themes/tokyo-night.js +37 -0
  178. package/dist/themes/tokyo-night.js.map +1 -0
  179. package/dist/utils.d.ts +1 -0
  180. package/dist/utils.d.ts.map +1 -1
  181. package/dist/utils.js +1 -0
  182. package/dist/utils.js.map +1 -1
  183. package/dist/vendor/colors.d.ts +45 -0
  184. package/dist/vendor/colors.d.ts.map +1 -0
  185. package/dist/vendor/colors.js +72 -0
  186. package/dist/vendor/colors.js.map +1 -0
  187. package/llms.txt +79 -0
  188. package/package.json +23 -7
  189. package/dist/data/glyphs.d.ts +0 -5
  190. package/dist/data/glyphs.d.ts.map +0 -1
  191. package/dist/data/glyphs.js +0 -29
  192. package/dist/data/glyphs.js.map +0 -1
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Bunti DSL motion helpers: animate, fade, typewriter, flicker, transition,
3
+ * stagger, restartAnimation, and per-frame timing (dt / frame).
4
+ */
5
+ import { fade } from '../colors';
6
+ import { clamp01 } from '../easing';
7
+ function graphemes(text) {
8
+ const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
9
+ return Array.from(segmenter.segment(text), ({ segment }) => segment);
10
+ }
11
+ /** Deterministic 0-1 hash (FNV-1a) for time-bucketed flicker. */
12
+ function hash01(seed) {
13
+ let h = 2166136261;
14
+ for (let i = 0; i < seed.length; i++) {
15
+ h ^= seed.charCodeAt(i);
16
+ h = Math.imul(h, 16777619);
17
+ }
18
+ return ((h >>> 0) % 100000) / 100000;
19
+ }
20
+ const identity = (t) => t;
21
+ /** Namespaced componentState key for transition edge tracking. */
22
+ const transitionKey = (id) => `_motion:transition:${id}`;
23
+ export function createMotion(state, useState) {
24
+ return {
25
+ // loop() owns timing: it stamps state.dt / state.frameCount each tick.
26
+ // Outside a loop (tests, one-shot renders) both default to 0.
27
+ dt: state.dt ?? 0,
28
+ frame: state.frameCount ?? 0,
29
+ animate(duration, options = {}) {
30
+ const now = Date.now();
31
+ const start = options.id
32
+ ? useState(`${options.id}_start`, now)[0]
33
+ : state.startTime;
34
+ const elapsed = now - start - (options.delay || 0);
35
+ const ease = options.easing ?? identity;
36
+ if (elapsed < 0 || duration <= 0)
37
+ return ease(0);
38
+ if (options.loop === 'yoyo') {
39
+ // 0 -> 1 -> 0 over two durations; easing applies to each leg.
40
+ const phase = (elapsed % (duration * 2)) / duration;
41
+ return ease(phase <= 1 ? phase : 2 - phase);
42
+ }
43
+ if (options.loop)
44
+ return ease((elapsed % duration) / duration);
45
+ return ease(Math.min(1, elapsed / duration));
46
+ },
47
+ fade,
48
+ /**
49
+ * Visibility-driven enter/exit progress for immediate-mode UIs.
50
+ * Tracks visible-flag edges in componentState; `mounted` stays true
51
+ * through the exit animation so callers keep rendering while a panel
52
+ * animates out. Mid-animation flips retarget from the current progress
53
+ * (no jumps).
54
+ */
55
+ transition(id, visible, options = {}) {
56
+ const now = Date.now();
57
+ const duration = Math.max(0, options.duration ?? 300);
58
+ const exitDuration = Math.max(0, options.exitDuration ?? duration);
59
+ const ease = options.easing ?? identity;
60
+ const key = transitionKey(id);
61
+ let rec = state.componentState.get(key);
62
+ if (rec === undefined) {
63
+ // First sight: visible components animate in from 0; hidden ones
64
+ // start fully exited (mounted false immediately).
65
+ rec = { visible, flippedAt: visible ? now : now - exitDuration - 1 };
66
+ state.componentState.set(key, rec);
67
+ }
68
+ const rawAt = (r) => {
69
+ if (r.visible) {
70
+ return duration <= 0 ? 1 : clamp01((now - r.flippedAt) / duration);
71
+ }
72
+ return exitDuration <= 0
73
+ ? 0
74
+ : 1 - clamp01((now - r.flippedAt) / exitDuration);
75
+ };
76
+ if (rec.visible !== visible) {
77
+ // Retarget from the current raw progress so mid-animation flips
78
+ // continue smoothly instead of restarting the full leg.
79
+ const current = rawAt(rec);
80
+ rec.visible = visible;
81
+ rec.flippedAt = visible
82
+ ? now - current * duration
83
+ : now - (1 - current) * exitDuration;
84
+ }
85
+ const raw = rawAt(rec);
86
+ return {
87
+ progress: ease(raw),
88
+ mounted: visible || raw > 0,
89
+ };
90
+ },
91
+ /**
92
+ * Cascading entrance progress: item `index` starts `index * delay` ms
93
+ * into the timeline and runs for `duration` ms. The timeline is the
94
+ * screen's elapsed time, or an animate()-style `id` clock when given
95
+ * (restartAnimation(id) then replays the cascade).
96
+ */
97
+ stagger(index, options) {
98
+ const now = Date.now();
99
+ const start = options.id
100
+ ? useState(`${options.id}_start`, now)[0]
101
+ : state.startTime;
102
+ const elapsed = now - start - index * options.delay;
103
+ const ease = options.easing ?? identity;
104
+ if (options.duration <= 0)
105
+ return ease(elapsed >= 0 ? 1 : 0);
106
+ return ease(clamp01(elapsed / options.duration));
107
+ },
108
+ /** Resets an animate()/typewriter()/stagger() id clock to "now". */
109
+ restartAnimation(id) {
110
+ state.componentState.set(`${id}_start`, Date.now());
111
+ state.requestTick?.();
112
+ },
113
+ typewriter(text, options = {}) {
114
+ const now = Date.now();
115
+ const start = options.id
116
+ ? useState(`${options.id}_start`, now)[0]
117
+ : state.startTime;
118
+ const delay = options.delay ?? 0;
119
+ const elapsed = Math.max(0, now - start - delay);
120
+ const cps = options.cps ?? 24;
121
+ const chars = graphemes(text);
122
+ const rawIndex = Math.floor((elapsed / 1000) * cps);
123
+ const index = options.loop && chars.length > 0
124
+ ? rawIndex % (chars.length + 1)
125
+ : Math.min(chars.length, rawIndex);
126
+ const blinkRate = options.blinkRate ?? 450;
127
+ const showCursor = options.blink === false ||
128
+ Math.floor(elapsed / blinkRate) % 2 === 0 ||
129
+ index < chars.length;
130
+ return {
131
+ text: chars.slice(0, index).join(''),
132
+ cursor: showCursor ? (options.cursor ?? '█') : ' ',
133
+ done: index >= chars.length,
134
+ index,
135
+ progress: chars.length === 0 ? 1 : index / chars.length,
136
+ };
137
+ },
138
+ /**
139
+ * Time-based flicker: deterministic per interval bucket (hash of the
140
+ * bucket + id), so the flicker rate is fps-independent while keeping
141
+ * the same visual character as the old per-frame Math.random.
142
+ */
143
+ flicker(intensity = 0.5, options = {}) {
144
+ const interval = Math.max(1, options.interval ?? 50);
145
+ const bucket = Math.floor((Date.now() - state.startTime) / interval);
146
+ return hash01(`${options.id ?? ''}:${bucket}`) > 1 - intensity;
147
+ },
148
+ };
149
+ }
150
+ //# sourceMappingURL=motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/dsl/motion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Bunti DSL primary entry point: render.
3
+ */
4
+ import { type ScreenOptions } from '../state';
5
+ import type { BuntiContext } from './types';
6
+ /**
7
+ * Starts a Bunti app: runs `callback` every frame (immediate mode —
8
+ * redraw the whole screen from state each call) and flushes only the
9
+ * changed cells to the terminal. The returned promise resolves when the
10
+ * loop stops (ctx.requestStop() or Ctrl+C). Pass `once: true` to render
11
+ * a single frame and return. Keyboard input needs a real TTY on stdin:
12
+ * piped input is ignored.
13
+ * @example
14
+ * await render((ctx) => {
15
+ * ctx.box({ width: 30, border: 'rounded' }, (s) => s.text('hi'));
16
+ * if (ctx.lastKey === 'q') ctx.requestStop();
17
+ * }, { keyboard: true, mouse: true, alternateBuffer: true, hideCursor: true });
18
+ */
19
+ export declare function render(callback: ((b: BuntiContext) => void) | string, options?: ScreenOptions & {
20
+ once?: boolean;
21
+ }): Promise<void>;
22
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/dsl/render.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,wBAAsB,MAAM,CAC1B,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,MAAM,EAC9C,OAAO,GAAE,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,iBAkDjD"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Bunti DSL primary entry point: render.
3
+ */
4
+ import { init } from '../icons';
5
+ import { flush, loop } from '../render';
6
+ import { ANSI, clearBackBuffer, createScreenState, } from '../state';
7
+ import { createScreenContext } from './context';
8
+ /**
9
+ * Starts a Bunti app: runs `callback` every frame (immediate mode —
10
+ * redraw the whole screen from state each call) and flushes only the
11
+ * changed cells to the terminal. The returned promise resolves when the
12
+ * loop stops (ctx.requestStop() or Ctrl+C). Pass `once: true` to render
13
+ * a single frame and return. Keyboard input needs a real TTY on stdin:
14
+ * piped input is ignored.
15
+ * @example
16
+ * await render((ctx) => {
17
+ * ctx.box({ width: 30, border: 'rounded' }, (s) => s.text('hi'));
18
+ * if (ctx.lastKey === 'q') ctx.requestStop();
19
+ * }, { keyboard: true, mouse: true, alternateBuffer: true, hideCursor: true });
20
+ */
21
+ export async function render(callback, options = {}) {
22
+ if (typeof Bun === 'undefined') {
23
+ throw new Error('Bunti is Bun-native and uses Bun runtime APIs. ' +
24
+ 'Run with Bun >=1.0: https://bun.sh — Node.js is not supported.');
25
+ }
26
+ // createScreenState runs env detection once per render() (state.terminal).
27
+ const state = createScreenState(options);
28
+ // Icon tier: an explicit ScreenOptions.nerdFont always wins; otherwise the
29
+ // detected profile decides ('yes'/'assumed-yes' -> Nerd Font glyphs).
30
+ if (options.nerdFont !== undefined) {
31
+ await init({ nerdFont: options.nerdFont });
32
+ }
33
+ else {
34
+ await init({ profile: state.terminal });
35
+ }
36
+ const tick = () => {
37
+ clearBackBuffer(state);
38
+ const b = createScreenContext(state);
39
+ if (typeof callback === 'string') {
40
+ b.blit(0, 0, callback);
41
+ }
42
+ else {
43
+ callback(b);
44
+ }
45
+ if (state.isStopped)
46
+ return;
47
+ b.flushFlow();
48
+ if (state.isStopped)
49
+ return;
50
+ flush(state);
51
+ };
52
+ if (options.once) {
53
+ tick();
54
+ // Let the terminal settle for a frame, then resolve. No interval or
55
+ // stdin listener was started in once mode, so nothing keeps the event
56
+ // loop alive and the host process (never killed by the library) can
57
+ // continue or exit naturally.
58
+ await new Promise((resolve) => {
59
+ setTimeout(resolve, 50);
60
+ });
61
+ // flush() hides the cursor per-frame when requested; a once-shot must
62
+ // not leave the user's cursor invisible.
63
+ if (options.hideCursor)
64
+ process.stdout.write(ANSI.showCursor);
65
+ return;
66
+ }
67
+ await loop(state, (_s) => tick());
68
+ }
69
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/dsl/render.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EACL,IAAI,EACJ,eAAe,EACf,iBAAiB,GAElB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGhD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,QAA8C,EAC9C,UAA8C,EAAE;IAEhD,IAAI,OAAO,GAAG,KAAK,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,iDAAiD;YAC/C,gEAAgE,CACnE,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEzC,2EAA2E;IAC3E,sEAAsE;IACtE,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,eAAe,CAAC,KAAK,CAAC,CAAC;QACvB,MAAM,CAAC,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;QACD,IAAI,KAAK,CAAC,SAAS;YAAE,OAAO;QAC5B,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,IAAI,KAAK,CAAC,SAAS;YAAE,OAAO;QAC5B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,IAAI,EAAE,CAAC;QACP,oEAAoE;QACpE,sEAAsE;QACtE,oEAAoE;QACpE,8BAA8B;QAC9B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,sEAAsE;QACtE,yCAAyC;QACzC,IAAI,OAAO,CAAC,UAAU;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AACpC,CAAC"}