@astryxdesign/core 0.6.1 → 0.6.2

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 (62) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/DateRangeInput/DateRangeInput.d.ts +3 -0
  3. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  4. package/dist/DateRangeInput/DateRangeInput.js +16 -9
  5. package/dist/Dialog/DialogHeader.d.ts +1 -1
  6. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  7. package/dist/Dialog/DialogHeader.js +10 -7
  8. package/dist/FileInput/FileInput.d.ts.map +1 -1
  9. package/dist/FileInput/FileInput.js +9 -3
  10. package/dist/Markdown/Markdown.d.ts +10 -2
  11. package/dist/Markdown/Markdown.d.ts.map +1 -1
  12. package/dist/Markdown/Markdown.js +58 -14
  13. package/dist/Markdown/index.d.ts +1 -1
  14. package/dist/Markdown/index.d.ts.map +1 -1
  15. package/dist/Markdown/parser.d.ts +126 -12
  16. package/dist/Markdown/parser.d.ts.map +1 -1
  17. package/dist/Markdown/parser.js +369 -34
  18. package/dist/Markdown/utils.d.ts +1 -1
  19. package/dist/Markdown/utils.d.ts.map +1 -1
  20. package/dist/Slider/Slider.d.ts.map +1 -1
  21. package/dist/Slider/Slider.js +5 -2
  22. package/dist/Spinner/Spinner.d.ts +1 -1
  23. package/dist/Spinner/Spinner.d.ts.map +1 -1
  24. package/dist/Spinner/Spinner.js +23 -15
  25. package/dist/astryx.css +2 -1
  26. package/locales/en.json +16 -0
  27. package/locales/pseudo.json +12 -0
  28. package/package.json +6 -4
  29. package/scripts/agent-doc-state.mjs +1 -1
  30. package/src/DateRangeInput/DateRangeInput.doc.mjs +35 -7
  31. package/src/DateRangeInput/DateRangeInput.spec.md +203 -0
  32. package/src/DateRangeInput/DateRangeInput.test.tsx +100 -4
  33. package/src/DateRangeInput/DateRangeInput.tsx +29 -20
  34. package/src/Dialog/Dialog.doc.mjs +3 -0
  35. package/src/Dialog/Dialog.spec.md +1 -1
  36. package/src/Dialog/DialogHeader.doc.mjs +38 -0
  37. package/src/Dialog/DialogHeader.test.tsx +49 -0
  38. package/src/Dialog/DialogHeader.tsx +23 -4
  39. package/src/Dialog/modules/DialogHeader.spec.md +152 -0
  40. package/src/FileInput/FileInput.doc.mjs +2 -0
  41. package/src/FileInput/FileInput.spec.md +199 -0
  42. package/src/FileInput/FileInput.test.tsx +14 -0
  43. package/src/FileInput/FileInput.tsx +13 -3
  44. package/src/Markdown/Markdown.doc.mjs +167 -42
  45. package/src/Markdown/Markdown.public.test.ts +157 -0
  46. package/src/Markdown/Markdown.spec.md +149 -70
  47. package/src/Markdown/Markdown.test.tsx +107 -3
  48. package/src/Markdown/Markdown.tsx +116 -35
  49. package/src/Markdown/incremental.test.ts +175 -7
  50. package/src/Markdown/index.ts +6 -0
  51. package/src/Markdown/parser.perf.test.ts +3 -1
  52. package/src/Markdown/parser.test.ts +122 -0
  53. package/src/Markdown/parser.ts +609 -81
  54. package/src/Markdown/utils.ts +6 -0
  55. package/src/Slider/Slider.doc.mjs +16 -0
  56. package/src/Slider/Slider.spec.md +61 -47
  57. package/src/Slider/Slider.test.tsx +18 -0
  58. package/src/Slider/Slider.tsx +12 -6
  59. package/src/Spinner/Spinner.doc.mjs +6 -3
  60. package/src/Spinner/Spinner.test.tsx +37 -0
  61. package/src/Spinner/Spinner.tsx +31 -14
  62. package/src/theme/derivedVarRegistry.test.ts +6 -4
@@ -3,7 +3,8 @@
3
3
  /**
4
4
  * @file parser.ts
5
5
  * @input Markdown string
6
- * @output Array of MarkdownNode AST nodes; heading slug helpers
6
+ * @output Array of MarkdownNode AST nodes, including opt-in math; heading slug
7
+ * helpers
7
8
  * (inlineText, slugify, uniqueSlug) shared by Markdown rendering and
8
9
  * Outline's parseOutlineFromMarkdown
9
10
  * @position Core parser; consumed by Markdown.tsx and Outline
@@ -13,6 +14,18 @@
13
14
  // Types
14
15
  // ---------------------------------------------------------------------------
15
16
 
17
+ /** Nodes returned by default and legacy parser calls. */
18
+
19
+ /** The additional inline node returned only when parsing with `math: true`. */
20
+
21
+ /** Nodes returned by an explicitly math-enabled inline parse. */
22
+
23
+ /** Blocks returned by default and legacy parser calls. */
24
+
25
+ /** The additional block returned only when parsing with `math: true`. */
26
+
27
+ /** Blocks returned by an explicitly math-enabled block parse. */
28
+
16
29
  /**
17
30
  * Where a block sits in the source string handed to `parseMarkdown`:
18
31
  * `source.slice(start, end)` is the block, and `end` excludes the block's
@@ -35,6 +48,14 @@
35
48
  * `ReadonlySet<string>` shape as the second argument.
36
49
  */
37
50
 
51
+ /** Options for default and legacy parser results. */
52
+
53
+ /**
54
+ * Options that explicitly parse `$…$` and `$$…$$` into math-enabled result
55
+ * unions. Keeping this separate prevents a legacy `ParseOptions` annotation
56
+ * from silently widening an exhaustive node switch.
57
+ */
58
+
38
59
  const EMPTY_OPTS = {
39
60
  sourceIds: undefined,
40
61
  autolink: undefined
@@ -58,6 +79,7 @@ function resolveOptions(arg) {
58
79
  return {
59
80
  sourceIds: opts.sourceIds,
60
81
  autolink: opts.autolink,
82
+ math: opts.math === true ? true : undefined,
61
83
  sourceRanges: opts.sourceRanges
62
84
  };
63
85
  }
@@ -83,6 +105,106 @@ const LINK_TITLE_ONLY_RE = /^ {0,3}(?:"[^"\n]*"|'[^'\n]*'|\([^()\n]*\))[ \t]*$/;
83
105
  function normalizeLinkLabel(label) {
84
106
  return label.trim().replace(/\s+/g, ' ').toLowerCase();
85
107
  }
108
+ function stripBlockquoteMarkers(line) {
109
+ let content = line.endsWith('\r') ? line.slice(0, -1) : line;
110
+ let quoteDepth = 0;
111
+ while (true) {
112
+ const marker = /^ {0,3}> ?/.exec(content);
113
+ if (marker == null) {
114
+ return {
115
+ content,
116
+ quoteDepth
117
+ };
118
+ }
119
+ content = content.slice(marker[0].length);
120
+ quoteDepth++;
121
+ }
122
+ }
123
+ function stripExactBlockquoteDepth(line, quoteDepth) {
124
+ let content = line;
125
+ for (let depth = 0; depth < quoteDepth; depth++) {
126
+ const marker = /^ {0,3}> ?/.exec(content);
127
+ if (marker == null) {
128
+ return null;
129
+ }
130
+ content = content.slice(marker[0].length);
131
+ }
132
+ return content;
133
+ }
134
+
135
+ /**
136
+ * Recognize a standalone display-math marker at the current container boundary.
137
+ * A list opener carries its base indent so an indented continuation marker can
138
+ * close it; blockquotes must keep the same quote depth.
139
+ */
140
+ function displayMathContainer(line) {
141
+ const outer = stripBlockquoteMarkers(line);
142
+ const listMarker = /^( {0,9})(?:[-*+]|\d+[.)]) +(.*)$/.exec(outer.content);
143
+ if (listMarker != null) {
144
+ const taskMarker = /^\[[ xX]\] +(.*)$/.exec(listMarker[2]);
145
+ const inner = stripBlockquoteMarkers(taskMarker?.[1] ?? listMarker[2]);
146
+ return inner.content.trim() === '$$' ? {
147
+ outerQuoteDepth: outer.quoteDepth,
148
+ listBaseIndent: listMarker[1].length,
149
+ innerQuoteDepth: inner.quoteDepth
150
+ } : null;
151
+ }
152
+ return outer.content.trim() === '$$' ? {
153
+ outerQuoteDepth: outer.quoteDepth,
154
+ listBaseIndent: null,
155
+ innerQuoteDepth: 0
156
+ } : null;
157
+ }
158
+ function displayMathLineState(line, container) {
159
+ const outerContent = stripExactBlockquoteDepth(line, container.outerQuoteDepth);
160
+ if (outerContent == null) {
161
+ return 'outside';
162
+ }
163
+ if (container.listBaseIndent == null) {
164
+ // A deeper quote starts a different container. It cannot close or continue
165
+ // the math expression owned by the shallower quote.
166
+ if (/^ {0,3}> ?/.test(outerContent)) {
167
+ return 'outside';
168
+ }
169
+ return outerContent.trim() === '$$' ? 'close' : 'inside';
170
+ }
171
+ const continuationIndent = outerContent.length - outerContent.trimStart().length;
172
+ if (continuationIndent <= container.listBaseIndent) {
173
+ return 'outside';
174
+ }
175
+ const innerContent = stripExactBlockquoteDepth(outerContent.trimStart(), container.innerQuoteDepth);
176
+ if (innerContent == null || /^ {0,3}> ?/.test(innerContent)) {
177
+ return 'outside';
178
+ }
179
+ return innerContent.trim() === '$$' ? 'close' : 'inside';
180
+ }
181
+
182
+ /** Match a complete `$$…$$` display-math block without consuming partial input. */
183
+ function matchDisplayMathBlock(lines, lineIndex) {
184
+ const trimmed = lines[lineIndex].trim();
185
+ if (trimmed.length > 4 && trimmed.startsWith('$$') && trimmed.endsWith('$$')) {
186
+ const value = trimmed.slice(2, -2);
187
+ return value.trim() === '' ? null : {
188
+ value,
189
+ nextIndex: lineIndex + 1,
190
+ endLine: lineIndex
191
+ };
192
+ }
193
+ if (trimmed !== '$$') {
194
+ return null;
195
+ }
196
+ for (let index = lineIndex + 1; index < lines.length; index++) {
197
+ if (lines[index].trim() === '$$') {
198
+ const value = lines.slice(lineIndex + 1, index).join('\n');
199
+ return value.trim() === '' ? null : {
200
+ value,
201
+ nextIndex: index + 1,
202
+ endLine: index
203
+ };
204
+ }
205
+ }
206
+ return null;
207
+ }
86
208
  function matchLinkDefinition(line) {
87
209
  const match = LINK_DEFINITION_RE.exec(line);
88
210
  if (match == null) {
@@ -121,7 +243,7 @@ function matchLinkDefinition(line) {
121
243
  * where every definition is global. Separating a footer definition block with
122
244
  * a blank line — the usual form — always works.
123
245
  */
124
- function extractLinkDefinitions(input) {
246
+ function extractLinkDefinitions(input, math = false) {
125
247
  const lines = input.split('\n');
126
248
  const defs = new Map();
127
249
  const keep = new Array(lines.length).fill(true);
@@ -141,6 +263,16 @@ function extractLinkDefinitions(input) {
141
263
  }
142
264
  continue;
143
265
  }
266
+ if (math) {
267
+ const displayMath = matchDisplayMathBlock(lines, index);
268
+ if (displayMath != null) {
269
+ // Math is opaque Markdown content: definition-shaped TeX must not leak
270
+ // into the document-wide link-definition map.
271
+ index = displayMath.endLine;
272
+ atBoundary = true;
273
+ continue;
274
+ }
275
+ }
144
276
  const fenceMatch = line.match(/^(`{3,}|~{3,})/);
145
277
  if (fenceMatch) {
146
278
  inFence = true;
@@ -324,6 +456,49 @@ function isWordChar(ch) {
324
456
  return /\w/.test(ch);
325
457
  }
326
458
 
459
+ /** True when the character at `index` is preceded by an odd backslash run. */
460
+ function isEscaped(text, index) {
461
+ let backslashes = 0;
462
+ for (let i = index - 1; i >= 0 && text[i] === '\\'; i--) {
463
+ backslashes++;
464
+ }
465
+ return backslashes % 2 === 1;
466
+ }
467
+
468
+ /**
469
+ * Find the closing delimiter for `$…$` math on the same line.
470
+ *
471
+ * The whitespace and numeric-edge rules mirror common dollar-math parsers:
472
+ * whitespace cannot hug the delimiters, a digit cannot sit immediately before
473
+ * the opener or after the closer, and `$$` is reserved for display math. The
474
+ * numeric guard prevents ordinary prose such as "$20 and $30" from becoming a
475
+ * formula even in a math-enabled document.
476
+ */
477
+ function isInlineMathStart(text, index) {
478
+ return text[index] === '$' && text[index - 1] !== '$' && text[index + 1] !== '$' && text[index + 1] != null && !/\s/.test(text[index + 1]) && !/\d/.test(text[index - 1] ?? '') && !isEscaped(text, index);
479
+ }
480
+ function findInlineMathEnd(text, start) {
481
+ if (!isInlineMathStart(text, start)) {
482
+ return -1;
483
+ }
484
+ for (let index = start + 1; index < text.length; index++) {
485
+ if (text[index] === '\n') {
486
+ return -1;
487
+ }
488
+ if (text[index] !== '$' || isEscaped(text, index)) {
489
+ continue;
490
+ }
491
+ // An unescaped dollar ends this candidate: it either forms a valid closer
492
+ // or makes the whole span literal. Never skip over one and pair with a
493
+ // later dollar, which would swallow currency or another expression.
494
+ if (text[index - 1] === '$' || text[index + 1] === '$' || /\s/.test(text[index - 1]) || /\d/.test(text[index + 1] ?? '')) {
495
+ return -1;
496
+ }
497
+ return index;
498
+ }
499
+ return -1;
500
+ }
501
+
327
502
  // ---------------------------------------------------------------------------
328
503
  // URL scheme sanitization
329
504
  // ---------------------------------------------------------------------------
@@ -406,7 +581,7 @@ export function parseInline(text, arg) {
406
581
  * wrapper and call `parseInlineImpl` directly so the transform runs only on
407
582
  * the outermost block's inline tree — letting `transformAutolinks` decide
408
583
  * which subtrees to descend into (text, bold, italic, strikethrough) and
409
- * which to skip (link, code, image, citation, break).
584
+ * which to skip (link, code, math, image, citation, break).
410
585
  */
411
586
  function parseInlineEntry(text, opts) {
412
587
  const nodes = parseInlineImpl(text, opts);
@@ -441,6 +616,19 @@ function parseInlineImpl(text, opts) {
441
616
  }
442
617
  }
443
618
 
619
+ // --- Inline math (opt-in; code takes precedence) ---
620
+ if (opts.math && text[i] === '$') {
621
+ const closeIndex = findInlineMathEnd(text, i);
622
+ if (closeIndex !== -1) {
623
+ nodes.push({
624
+ type: 'math',
625
+ value: text.slice(i + 1, closeIndex)
626
+ });
627
+ i = closeIndex + 1;
628
+ continue;
629
+ }
630
+ }
631
+
444
632
  // --- Citation: fullwidth 【id】 ---
445
633
  {
446
634
  const citation = matchFullwidthCitation(text, i, opts);
@@ -613,7 +801,7 @@ function parseInlineImpl(text, opts) {
613
801
 
614
802
  // --- Plain text (with line-break detection) ---
615
803
  let end = i + 1;
616
- while (end < text.length && !'*_~`[!\\\n\u3010'.includes(text[end])) {
804
+ while (end < text.length && !'*_~`[!\\\n\u3010'.includes(text[end]) && !(opts.math && text[end] === '$')) {
617
805
  end++;
618
806
  }
619
807
  const content = text.slice(i, end);
@@ -1195,7 +1383,7 @@ function parseMarkdownImpl(input, baseOpts) {
1195
1383
  defs,
1196
1384
  cleaned,
1197
1385
  lineMap
1198
- } = extractLinkDefinitions(input);
1386
+ } = extractLinkDefinitions(input, baseOpts.math);
1199
1387
  const inherited = baseOpts.linkDefs;
1200
1388
  let linkDefs;
1201
1389
  if (defs.size === 0) {
@@ -1256,6 +1444,19 @@ function parseMarkdownImpl(input, baseOpts) {
1256
1444
  continue;
1257
1445
  }
1258
1446
 
1447
+ // --- Display math (opt-in; fenced code takes precedence) ---
1448
+ if (opts.math) {
1449
+ const displayMath = matchDisplayMathBlock(lines, index);
1450
+ if (displayMath != null) {
1451
+ pushBlock({
1452
+ type: 'math',
1453
+ value: displayMath.value
1454
+ }, displayMath.endLine);
1455
+ index = displayMath.nextIndex;
1456
+ continue;
1457
+ }
1458
+ }
1459
+
1259
1460
  // --- Heading ---
1260
1461
  const headingMatch = line.match(/^(#{1,6}) +(.*)/);
1261
1462
  if (headingMatch) {
@@ -1332,7 +1533,7 @@ function parseMarkdownImpl(input, baseOpts) {
1332
1533
  // --- Paragraph ---
1333
1534
  const paraLines = [line];
1334
1535
  index++;
1335
- while (index < lines.length && !isBlockStart(lines[index]) && lines[index].trim() !== '') {
1536
+ while (index < lines.length && !isBlockStart(lines[index]) && !(opts.math && matchDisplayMathBlock(lines, index) != null) && lines[index].trim() !== '') {
1336
1537
  paraLines.push(lines[index]);
1337
1538
  index++;
1338
1539
  }
@@ -1401,7 +1602,7 @@ const incrementalCaches = new WeakMap();
1401
1602
  function makeIncrementalCache(state) {
1402
1603
  const {
1403
1604
  defs
1404
- } = extractLinkDefinitions(state.settledText);
1605
+ } = extractLinkDefinitions(state.settledText, state.math);
1405
1606
  const cache = {
1406
1607
  settledEnd: state.settledText.length,
1407
1608
  settledLinkDefs: new Map(defs),
@@ -1418,6 +1619,11 @@ function makeIncrementalCache(state) {
1418
1619
  incrementalCaches.set(state, cache);
1419
1620
  return cache;
1420
1621
  }
1622
+
1623
+ /**
1624
+ * Create an incremental parser cache. Use the `<true>` type argument with
1625
+ * `MathParseOptions` so the cache and returned nodes share the math contract.
1626
+ */
1421
1627
  export function createIncrementalState() {
1422
1628
  const state = {
1423
1629
  prevInput: '',
@@ -1456,33 +1662,70 @@ export function getIncrementalParseWork(state) {
1456
1662
  * the boundary to -1 even though the content before the fence opened cannot be
1457
1663
  * changed by anything typed inside it.
1458
1664
  */
1459
- function findSettledBoundary(lines) {
1665
+ function findSettledBoundary(lines, math = false) {
1460
1666
  let inFence = false;
1461
1667
  let fenceMarker = '';
1668
+ let mathContainer = null;
1669
+ let suppressMathUntilBoundary = false;
1462
1670
  let lastBoundary = -1;
1463
1671
  let boundaryBeforeFence = -1;
1672
+ let boundaryBeforeMath = -1;
1464
1673
  for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
1465
1674
  const line = lines[lineIndex];
1466
-
1467
- // Fence open / close — match the specific marker character and length
1468
- const fenceMatch = line.match(/^(`{3,}|~{3,})/);
1469
- if (fenceMatch) {
1470
- if (!inFence) {
1471
- inFence = true;
1472
- fenceMarker = fenceMatch[1];
1473
- boundaryBeforeFence = lastBoundary;
1474
- } else if (fenceMatch[1].startsWith(fenceMarker[0]) && fenceMatch[1].length >= fenceMarker.length) {
1675
+ if (inFence) {
1676
+ const fenceMatch = line.match(/^(`{3,}|~{3,})/);
1677
+ if (fenceMatch && fenceMatch[1].startsWith(fenceMarker[0]) && fenceMatch[1].length >= fenceMarker.length) {
1475
1678
  inFence = false;
1476
1679
  fenceMarker = '';
1477
1680
  }
1681
+ continue;
1478
1682
  }
1479
- if (!inFence && line.trim() === '' && lineIndex > 0 && lineIndex < lines.length - 1) {
1480
- lastBoundary = lineIndex;
1683
+ if (mathContainer != null) {
1684
+ const state = displayMathLineState(line, mathContainer);
1685
+ if (state === 'close') {
1686
+ mathContainer = null;
1687
+ continue;
1688
+ }
1689
+ if (state === 'inside') {
1690
+ continue;
1691
+ }
1692
+ // The list item or blockquote ended before a closer arrived. The parser
1693
+ // treats that unmatched opener literally, so resume ordinary boundary
1694
+ // detection on this first line outside the container.
1695
+ mathContainer = null;
1696
+ suppressMathUntilBoundary = true;
1697
+ }
1698
+
1699
+ // A complete same-line `$$…$$` expression never changes boundary state.
1700
+ // A standalone marker may belong to the top level, a blockquote, or one
1701
+ // list item; remember that container so its continuation marker closes the
1702
+ // same expression instead of opening a new one.
1703
+ if (math && !suppressMathUntilBoundary) {
1704
+ const container = displayMathContainer(line);
1705
+ if (container != null) {
1706
+ mathContainer = container;
1707
+ boundaryBeforeMath = lastBoundary;
1708
+ continue;
1709
+ }
1710
+ }
1711
+ const fenceMatch = line.match(/^(`{3,}|~{3,})/);
1712
+ if (fenceMatch) {
1713
+ inFence = true;
1714
+ fenceMarker = fenceMatch[1];
1715
+ boundaryBeforeFence = lastBoundary;
1716
+ continue;
1717
+ }
1718
+ if (line.trim() === '') {
1719
+ suppressMathUntilBoundary = false;
1720
+ if (lineIndex > 0 && lineIndex < lines.length - 1) {
1721
+ lastBoundary = lineIndex;
1722
+ }
1481
1723
  }
1482
1724
  }
1483
1725
  return {
1484
- boundary: inFence ? boundaryBeforeFence : lastBoundary,
1485
- openFence: inFence
1726
+ boundary: inFence ? boundaryBeforeFence : mathContainer != null ? boundaryBeforeMath : lastBoundary,
1727
+ openFence: inFence,
1728
+ openMath: mathContainer != null
1486
1729
  };
1487
1730
  }
1488
1731
 
@@ -1490,10 +1733,45 @@ function findSettledBoundary(lines) {
1490
1733
  * Strip trailing incomplete inline syntax that appears during streaming.
1491
1734
  * Only affects the tail of the last line — safe to apply to the full string.
1492
1735
  */
1493
- export function trimStreamingArtifacts(input) {
1494
- const lastNL = input.lastIndexOf('\n');
1495
- const prefix = lastNL === -1 ? '' : input.slice(0, lastNL + 1);
1496
- let tail = lastNL === -1 ? input : input.slice(lastNL + 1);
1736
+ export function trimStreamingArtifacts(input, options) {
1737
+ // First remove an incomplete display expression as one structural unit. This
1738
+ // full-input scan distinguishes a terminal nested closer from a new opener;
1739
+ // looking only at the final `$$` line cannot.
1740
+ const displayTrimmed = options?.math ? trimOpenDisplayMath(input) : input;
1741
+ const lastNL = displayTrimmed.lastIndexOf('\n');
1742
+ const prefix = lastNL === -1 ? '' : displayTrimmed.slice(0, lastNL + 1);
1743
+ let tail = lastNL === -1 ? displayTrimmed : displayTrimmed.slice(lastNL + 1);
1744
+ if (options?.math) {
1745
+ // Hold an unmatched inline opener so raw TeX syntax does not flash while
1746
+ // streaming. If another unescaped dollar is already present but fails the
1747
+ // closing-boundary rule, keep both literal (the currency case).
1748
+ for (let index = 0; index < tail.length; index++) {
1749
+ if (tail[index] === '$' && tail[index + 1] == null && tail[index - 1] !== '$' && !/\d/.test(tail[index - 1] ?? '') && !isEscaped(tail, index)) {
1750
+ tail = tail.slice(0, index);
1751
+ break;
1752
+ }
1753
+ if (!isInlineMathStart(tail, index)) {
1754
+ continue;
1755
+ }
1756
+ const close = findInlineMathEnd(tail, index);
1757
+ if (close !== -1) {
1758
+ index = close;
1759
+ continue;
1760
+ }
1761
+ let laterDollar = -1;
1762
+ for (let next = index + 1; next < tail.length; next++) {
1763
+ if (tail[next] === '$' && !isEscaped(tail, next)) {
1764
+ laterDollar = next;
1765
+ break;
1766
+ }
1767
+ }
1768
+ if (laterDollar === -1) {
1769
+ tail = tail.slice(0, index);
1770
+ break;
1771
+ }
1772
+ index = laterDollar;
1773
+ }
1774
+ }
1497
1775
 
1498
1776
  // Scan backwards for unclosed syntax markers — no regex to avoid ReDoS
1499
1777
  // Find the last unclosed [ or ![ (link/image start)
@@ -1650,6 +1928,54 @@ export function trimStreamingArtifacts(input) {
1650
1928
  * Once a table is established (header + separator exist), new data rows
1651
1929
  * render immediately — no suppression.
1652
1930
  */
1931
+ function trimOpenDisplayMath(text) {
1932
+ const lines = text.split('\n');
1933
+ let inFence = false;
1934
+ let fenceMarker = '';
1935
+ let mathContainer = null;
1936
+ let suppressMathUntilBoundary = false;
1937
+ let mathStartLine = -1;
1938
+ for (let index = 0; index < lines.length; index++) {
1939
+ const line = lines[index];
1940
+ if (inFence) {
1941
+ const fence = line.match(/^(`{3,}|~{3,})/);
1942
+ if (fence != null && fence[1].startsWith(fenceMarker[0]) && fence[1].length >= fenceMarker.length) {
1943
+ inFence = false;
1944
+ fenceMarker = '';
1945
+ }
1946
+ continue;
1947
+ }
1948
+ if (mathContainer != null) {
1949
+ const state = displayMathLineState(line, mathContainer);
1950
+ if (state === 'close') {
1951
+ mathContainer = null;
1952
+ mathStartLine = -1;
1953
+ continue;
1954
+ }
1955
+ if (state === 'inside') {
1956
+ continue;
1957
+ }
1958
+ mathContainer = null;
1959
+ mathStartLine = -1;
1960
+ suppressMathUntilBoundary = true;
1961
+ }
1962
+ if (line.trim() === '') {
1963
+ suppressMathUntilBoundary = false;
1964
+ }
1965
+ const fence = line.match(/^(`{3,}|~{3,})/);
1966
+ if (fence != null) {
1967
+ inFence = true;
1968
+ fenceMarker = fence[1];
1969
+ continue;
1970
+ }
1971
+ const container = suppressMathUntilBoundary ? null : displayMathContainer(line);
1972
+ if (container != null) {
1973
+ mathContainer = container;
1974
+ mathStartLine = index;
1975
+ }
1976
+ }
1977
+ return mathContainer != null && mathStartLine >= 0 ? lines.slice(0, mathStartLine).join('\n').trimEnd() : text;
1978
+ }
1653
1979
  function trimUnsettledStructural(text) {
1654
1980
  const lines = text.split('\n');
1655
1981
 
@@ -1806,6 +2132,7 @@ function resetIncrementalCache(state, cache) {
1806
2132
  state.settledBlocks = [];
1807
2133
  state.settledUpTo = 0;
1808
2134
  state.linkDefsKey = undefined;
2135
+ state.math = undefined;
1809
2136
  cache.settledEnd = 0;
1810
2137
  cache.settledLinkDefs.clear();
1811
2138
  cache.tailLinkDefs = new Map();
@@ -1836,12 +2163,13 @@ export function parseMarkdownIncremental(input, state, arg) {
1836
2163
  const cache = incrementalCaches.get(state) ?? makeIncrementalCache(state);
1837
2164
  let reparseSettled = false;
1838
2165
 
1839
- // Invalidate cache when the autolink or sourceRanges option flips — cached
2166
+ // Invalidate cache when an option that changes parsed nodes flips — cached
1840
2167
  // settled blocks were parsed with the previous setting and would otherwise
1841
2168
  // be reused unchanged.
1842
- if (state.autolink !== opts.autolink || Boolean(state.sourceRanges) !== Boolean(opts.sourceRanges)) {
2169
+ if (state.autolink !== opts.autolink || state.math !== opts.math || Boolean(state.sourceRanges) !== Boolean(opts.sourceRanges)) {
1843
2170
  reparseSettled = true;
1844
2171
  state.autolink = opts.autolink;
2172
+ state.math = opts.math;
1845
2173
  state.sourceRanges = opts.sourceRanges;
1846
2174
  }
1847
2175
  if (input === '') {
@@ -1860,6 +2188,7 @@ export function parseMarkdownIncremental(input, state, arg) {
1860
2188
  if (state.settledText.length !== cache.settledEnd || !input.startsWith(state.settledText)) {
1861
2189
  resetIncrementalCache(state, cache);
1862
2190
  state.autolink = opts.autolink;
2191
+ state.math = opts.math;
1863
2192
  state.sourceRanges = opts.sourceRanges;
1864
2193
  }
1865
2194
 
@@ -1871,8 +2200,9 @@ export function parseMarkdownIncremental(input, state, arg) {
1871
2200
  const tailLines = tailRaw.split('\n');
1872
2201
  const {
1873
2202
  boundary,
1874
- openFence
1875
- } = findSettledBoundary(tailLines);
2203
+ openFence,
2204
+ openMath
2205
+ } = findSettledBoundary(tailLines, opts.math);
1876
2206
  const settledDelta = boundary >= 0 ? tailLines.slice(0, boundary).join('\n') : '';
1877
2207
  const nextSettledEnd = oldSettledEnd + settledDelta.length;
1878
2208
  const unsettledInput = input.slice(nextSettledEnd);
@@ -1885,7 +2215,7 @@ export function parseMarkdownIncremental(input, state, arg) {
1885
2215
  if (settledDelta !== '') {
1886
2216
  const {
1887
2217
  defs: deltaDefs
1888
- } = extractLinkDefinitions(settledDelta);
2218
+ } = extractLinkDefinitions(settledDelta, opts.math);
1889
2219
  for (const [label, destination] of deltaDefs) {
1890
2220
  if (!cache.settledLinkDefs.has(label)) {
1891
2221
  cache.settledLinkDefs.set(label, destination);
@@ -1897,7 +2227,7 @@ export function parseMarkdownIncremental(input, state, arg) {
1897
2227
  }
1898
2228
  const {
1899
2229
  defs: tailLinkDefs
1900
- } = extractLinkDefinitions(unsettledInput);
2230
+ } = extractLinkDefinitions(unsettledInput, opts.math);
1901
2231
  if (!sameUnsettledDefinitions(cache.tailLinkDefs, tailLinkDefs, cache.settledLinkDefs)) {
1902
2232
  definitionsChanged = true;
1903
2233
  }
@@ -1921,11 +2251,15 @@ export function parseMarkdownIncremental(input, state, arg) {
1921
2251
  }
1922
2252
  cache.settledEnd = nextSettledEnd;
1923
2253
  }
1924
- const unsettledRaw = unsettledInput.trim();
2254
+ const trimmedUnsettledInput = unsettledInput.trim();
2255
+ // String#trim removes the CR that belongs to the final content line of a
2256
+ // CRLF snapshot along with trailing blank lines. Keep that one byte so
2257
+ // source ranges and delimiter content remain identical to a full parse.
2258
+ const unsettledRaw = trimmedUnsettledInput !== '' && /\r(?:\n[\s]*)?$/.test(unsettledInput) ? `${trimmedUnsettledInput}\r` : trimmedUnsettledInput;
1925
2259
  // Structural trimming holds back lines that look like an incomplete list or
1926
2260
  // table, which inside a fence is ordinary code: a TypeScript union or a `- `
1927
2261
  // would disappear from the code block as it streams.
1928
- const unsettledText = openFence ? unsettledRaw : trimUnsettledStructural(unsettledRaw);
2262
+ const unsettledText = openFence ? unsettledRaw : openMath ? trimOpenDisplayMath(unsettledRaw) : trimUnsettledStructural(unsettledRaw);
1929
2263
  let parsedSettledBlocks = 0;
1930
2264
  if (reparseSettled) {
1931
2265
  state.settledBlocks = state.settledText ? parseMarkdownImpl(state.settledText, parseOpts) : [];
@@ -1973,7 +2307,8 @@ export function inlineText(nodes) {
1973
2307
  switch (node.type) {
1974
2308
  case 'text':
1975
2309
  case 'code':
1976
- return node.content;
2310
+ case 'math':
2311
+ return node.type === 'math' ? node.value : node.content;
1977
2312
  case 'bold':
1978
2313
  case 'italic':
1979
2314
  case 'strikethrough':
@@ -4,5 +4,5 @@
4
4
  * @position Subpath entry point: `@astryxdesign/core/Markdown/utils`
5
5
  */
6
6
  export { parseMarkdown, parseInline, parseMarkdownIncremental, createIncrementalState, trimStreamingArtifacts, } from './parser';
7
- export type { InlineNode, BlockNode, ListItemNode, TableCellNode, TableAlignment, IncrementalState, } from './parser';
7
+ export type { InlineNode, InlineNodeWithMath, MathInlineNode, BlockNode, BlockNodeWithMath, MathBlockNode, ListItemNode, TableCellNode, TableAlignment, ParseOptions, MathParseOptions, IncrementalState, } from './parser';
8
8
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/Markdown/utils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,WAAW,EACX,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,UAAU,EACV,SAAS,EACT,YAAY,EACZ,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/Markdown/utils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,WAAW,EACX,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../src/Slider/Slider.tsx"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAQhD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAQ9C,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,uEAAuE;IACvE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC3C,8DAA8D;IAC9D,KAAK,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,8CAA8C;IAC9C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC7C,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAChD,8CAA8C;IAC9C,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAoS/D;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,EAAC,GAAG,EAAE,GAAG,KAAK,EAAC,EAAE,WAAW,+BAsqBlD;yBAtqBe,MAAM"}
1
+ {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../src/Slider/Slider.tsx"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAQhD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAQ9C,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,uEAAuE;IACvE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC3C,8DAA8D;IAC9D,KAAK,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,8CAA8C;IAC9C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC7C,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAChD,8CAA8C;IAC9C,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAoS/D;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,EAAC,GAAG,EAAE,GAAG,KAAK,EAAC,EAAE,WAAW,+BA4qBlD;yBA5qBe,MAAM"}
@@ -660,7 +660,10 @@ export function Slider({
660
660
  onPointerMove: handlePointerMove,
661
661
  onPointerUp: handlePointerUp,
662
662
  onPointerCancel: handlePointerUp,
663
- ...{
663
+ ...mergeProps(themeProps('slider-control', {
664
+ orientation,
665
+ disabled: isDisabled ? 'disabled' : null
666
+ }), {
664
667
  0: {
665
668
  className: "x1n2onr6 x78zum5 x6s0dn4 x1iyjqo2 x5ve5x3 x87ps6o xc8icb0 xw4jnvo x1ymw6g xkagaj0 xdt5ytf xl56j7k x1ypdohk x16khyan"
666
669
  },
@@ -673,7 +676,7 @@ export function Slider({
673
676
  3: {
674
677
  className: "x1n2onr6 x78zum5 x6s0dn4 x1iyjqo2 x5ve5x3 x87ps6o xc8icb0 x1qx5ct2 x80b3aj xh8yej3 xbyyjgo xt0e3qv"
675
678
  }
676
- }[!!isHorizontal << 1 | !!isDisabled << 0],
679
+ }[!!isHorizontal << 1 | !!isDisabled << 0]),
677
680
  children: [/*#__PURE__*/_jsx("div", {
678
681
  "aria-hidden": "true",
679
682
  ...mergeProps(themeProps('slider-track', {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file Spinner.tsx
3
- * @input Uses React, StyleX, SVG rendering
3
+ * @input Uses React, i18n (useTranslator), StyleX, SVG rendering
4
4
  * @output Exports Spinner component, SpinnerProps, SpinnerSize, SpinnerShade types
5
5
  * @position Core implementation of spinner loading indicator
6
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../src/Spinner/Spinner.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAyB5C,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;CAKV,CAAC;AA+VF,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,KAAK,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExE,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAW,EACX,KAAiB,EACjB,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,SAAS,EACb,EAAE,YAAY,+BAoHd;yBA/He,OAAO"}
1
+ {"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../src/Spinner/Spinner.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAuB5C,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;CAKV,CAAC;AA6WF,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,KAAK,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExE,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAW,EACX,KAAiB,EACjB,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,SAAS,EACb,EAAE,YAAY,+BAyHd;yBApIe,OAAO"}