@mhmo91/schmancy 0.9.19 → 0.9.21

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 (45) hide show
  1. package/dist/agent/{flow-CaPi2G8y.js.map → flow-CvG1fLW5.js.map} +1 -1
  2. package/dist/agent/{rolldown-runtime-DsMetpgY.js → rolldown-runtime-BIIoCavz.js} +9 -2
  3. package/dist/agent/schmancy.agent.js +3348 -3332
  4. package/dist/agent/schmancy.agent.js.map +1 -1
  5. package/dist/agent/{vendor-highlight-CHJZQQB7.js → vendor-highlight-Dow87ZL_.js} +90 -85
  6. package/dist/agent/{vendor-highlight-CHJZQQB7.js.map → vendor-highlight-Dow87ZL_.js.map} +1 -1
  7. package/dist/agent/{vendor-jsqr-r7GNh4P3.js → vendor-jsqr-Bl4iAtKC.js} +1 -1
  8. package/dist/agent/{vendor-jsqr-r7GNh4P3.js.map → vendor-jsqr-Bl4iAtKC.js.map} +1 -1
  9. package/dist/agent/{vendor-material-color-Be96dpGE.js.map → vendor-material-color-DcL7ZPxx.js.map} +1 -1
  10. package/dist/badge.cjs +1 -1
  11. package/dist/badge.js +1 -1
  12. package/dist/{code-highlight-zSYcSfCz.cjs → code-highlight-B_l8vDzn.cjs} +11 -11
  13. package/dist/code-highlight-B_l8vDzn.cjs.map +1 -0
  14. package/dist/{code-highlight-BgExKEto.js → code-highlight-CI_gqXYX.js} +30 -22
  15. package/dist/code-highlight-CI_gqXYX.js.map +1 -0
  16. package/dist/code-highlight.cjs +1 -1
  17. package/dist/code-highlight.js +1 -1
  18. package/dist/content-drawer.cjs +1 -1
  19. package/dist/content-drawer.js +1 -1
  20. package/dist/handover/agent-runtime-followups.md +1 -1
  21. package/dist/handover/agent-runtime-v1.md +3 -3
  22. package/dist/index.cjs +1 -1
  23. package/dist/index.js +2 -2
  24. package/dist/nav-drawer.cjs +1 -1
  25. package/dist/nav-drawer.js +1 -1
  26. package/dist/navigation-bar.cjs +1 -1
  27. package/dist/navigation-bar.js +1 -1
  28. package/dist/qr-scanner.cjs +5 -5
  29. package/dist/qr-scanner.cjs.map +1 -1
  30. package/dist/qr-scanner.js +10 -6
  31. package/dist/qr-scanner.js.map +1 -1
  32. package/dist/{src-BGj6ufWS.js → src-Dw-PjtMH.js} +1 -1
  33. package/dist/{src-BGj6ufWS.js.map → src-Dw-PjtMH.js.map} +1 -1
  34. package/dist/{src-BPKGdQdp.cjs → src-sG7Ihf0e.cjs} +1 -1
  35. package/dist/{src-BPKGdQdp.cjs.map → src-sG7Ihf0e.cjs.map} +1 -1
  36. package/dist/teleport.cjs +1 -1
  37. package/dist/teleport.js +1 -1
  38. package/package.json +1 -1
  39. package/src/code-highlight/code-highlight.ts +56 -24
  40. package/src/qr-scanner/qr-scanner.ts +27 -2
  41. package/types/src/code-highlight/code-highlight.d.ts +8 -1
  42. package/dist/code-highlight-BgExKEto.js.map +0 -1
  43. package/dist/code-highlight-zSYcSfCz.cjs.map +0 -1
  44. /package/dist/agent/{flow-CaPi2G8y.js → flow-CvG1fLW5.js} +0 -0
  45. /package/dist/agent/{vendor-material-color-Be96dpGE.js → vendor-material-color-DcL7ZPxx.js} +0 -0
package/dist/teleport.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./src-BPKGdQdp.cjs`);exports.HereMorty=e.r,Object.defineProperty(exports,`SchmancyTeleportation`,{enumerable:!0,get:function(){return e.n}}),exports.WhereAreYouRicky=e.i,exports.teleport=e.a;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./src-sG7Ihf0e.cjs`);exports.HereMorty=e.r,Object.defineProperty(exports,`SchmancyTeleportation`,{enumerable:!0,get:function(){return e.n}}),exports.WhereAreYouRicky=e.i,exports.teleport=e.a;
package/dist/teleport.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, r } from "./src-BGj6ufWS.js";
1
+ import { a as e, i as t, n, r } from "./src-Dw-PjtMH.js";
2
2
  export { r as HereMorty, n as SchmancyTeleportation, t as WhereAreYouRicky, e as teleport };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhmo91/schmancy",
3
- "version": "0.9.19",
3
+ "version": "0.9.21",
4
4
  "description": "UI library build with web components",
5
5
  "main": "./dist/index.js",
6
6
  "customElements": "custom-elements.json",
@@ -1,21 +1,37 @@
1
1
  import { TailwindElement } from '@mixins/index'
2
- import hljs from 'highlight.js/lib/core'
3
- import bash from 'highlight.js/lib/languages/bash'
4
- import javascript from 'highlight.js/lib/languages/javascript'
5
- import markdown from 'highlight.js/lib/languages/markdown'
6
- import typescript from 'highlight.js/lib/languages/typescript'
7
- import xml from 'highlight.js/lib/languages/xml'
8
2
  import { css, html } from 'lit'
9
3
  import { customElement, property, state } from 'lit/decorators.js'
10
4
  import { unsafeHTML } from 'lit/directives/unsafe-html.js'
11
5
 
12
- // Register only the languages we need
13
- hljs.registerLanguage('javascript', javascript)
14
- hljs.registerLanguage('typescript', typescript)
15
- hljs.registerLanguage('html', xml)
16
- hljs.registerLanguage('xml', xml)
17
- hljs.registerLanguage('markdown', markdown)
18
- hljs.registerLanguage('bash', bash)
6
+ // highlight.js + all 6 language grammars are loaded lazily on first render.
7
+ // Static imports were previously responsible for ~15 KB gzipped (vendor-
8
+ // highlight chunk) being eagerly fetched on every agent-bundle first paint,
9
+ // even for pages that never rendered <schmancy-code>. See ADR 0014 in the
10
+ // parent monorepo.
11
+ type Hljs = typeof import('highlight.js/lib/core').default
12
+
13
+ let hljsPromise: Promise<Hljs> | null = null
14
+ function loadHljs(): Promise<Hljs> {
15
+ if (hljsPromise) return hljsPromise
16
+ hljsPromise = Promise.all([
17
+ import('highlight.js/lib/core'),
18
+ import('highlight.js/lib/languages/bash'),
19
+ import('highlight.js/lib/languages/javascript'),
20
+ import('highlight.js/lib/languages/markdown'),
21
+ import('highlight.js/lib/languages/typescript'),
22
+ import('highlight.js/lib/languages/xml'),
23
+ ]).then(([core, bash, javascript, markdown, typescript, xml]) => {
24
+ const hljs = core.default
25
+ hljs.registerLanguage('javascript', javascript.default)
26
+ hljs.registerLanguage('typescript', typescript.default)
27
+ hljs.registerLanguage('html', xml.default)
28
+ hljs.registerLanguage('xml', xml.default)
29
+ hljs.registerLanguage('markdown', markdown.default)
30
+ hljs.registerLanguage('bash', bash.default)
31
+ return hljs
32
+ })
33
+ return hljsPromise
34
+ }
19
35
 
20
36
  /**
21
37
  * @element schmancy-code
@@ -188,32 +204,48 @@ export class SchmancyCode extends TailwindElement(css`
188
204
  @state()
189
205
  private copied: boolean = false
190
206
 
191
- private get highlightedCode(): string {
192
- if (!this.code) return ''
207
+ /**
208
+ * Fully-rendered highlighted HTML — populated asynchronously after
209
+ * `loadHljs()` resolves. Empty on first render (one microtask) for a
210
+ * cold component; non-empty from then on.
211
+ */
212
+ @state()
213
+ private _highlightedCode: string = ''
193
214
 
194
- let highlightedHtml = ''
215
+ protected override updated(changed: Map<string, unknown>): void {
216
+ super.updated?.(changed)
217
+ if (changed.has('code') || changed.has('language') || changed.has('lineNumbers') || changed.has('highlightLines')) {
218
+ void this._rehighlight()
219
+ }
220
+ }
221
+
222
+ private async _rehighlight(): Promise<void> {
223
+ if (!this.code) {
224
+ this._highlightedCode = ''
225
+ return
226
+ }
227
+ const hljs = await loadHljs()
228
+ // Guard against unmount + racing property changes.
229
+ if (!this.isConnected) return
195
230
 
231
+ let highlightedHtml = ''
196
232
  try {
197
- // Use highlight.js to get highlighted code
198
233
  const result = hljs.highlight(this.code.trim(), { language: this.language })
199
234
  highlightedHtml = result.value
200
235
  } catch {
201
- // Fallback to auto-detection if language is not supported
202
236
  try {
203
237
  const result = hljs.highlightAuto(this.code.trim())
204
238
  highlightedHtml = result.value
205
239
  } catch {
206
- // Final fallback to escaped plain text
207
240
  highlightedHtml = this.escapeHtml(this.code.trim())
208
241
  }
209
242
  }
210
243
 
211
- // Process for line numbers and highlighting if needed
212
244
  if (this.lineNumbers || this.highlightLines) {
213
- return this.addLineFeatures(highlightedHtml)
245
+ this._highlightedCode = this.addLineFeatures(highlightedHtml)
246
+ } else {
247
+ this._highlightedCode = highlightedHtml
214
248
  }
215
-
216
- return highlightedHtml
217
249
  }
218
250
 
219
251
  private escapeHtml(text: string): string {
@@ -330,7 +362,7 @@ export class SchmancyCode extends TailwindElement(css`
330
362
  </section>
331
363
  <!-- Code -->
332
364
  <div class="overflow-auto" style="${this.maxHeight ? `max-height: ${this.maxHeight}` : ''}">
333
- <pre class="m-0"><code class="${codeClass}">${unsafeHTML(this.highlightedCode)}</code></pre>
365
+ <pre class="m-0"><code class="${codeClass}">${unsafeHTML(this._highlightedCode)}</code></pre>
334
366
  </div>
335
367
  </schmancy-details>
336
368
  `
@@ -1,11 +1,25 @@
1
1
  import { $LitElement } from '@mixins/litElement.mixin'
2
- import jsQR from 'jsqr'
3
2
  import { css, html } from 'lit'
4
3
  import { customElement, property, state } from 'lit/decorators.js'
5
4
  import { when } from 'lit/directives/when.js'
6
5
  import { animationFrames, Subject, timer } from 'rxjs'
7
6
  import { distinctUntilChanged, filter, map, takeUntil, throttleTime } from 'rxjs/operators'
8
7
 
8
+ // jsQR (~53 KB gzipped) is loaded lazily the first time a camera stream
9
+ // is attached — see ADR 0014. Until this resolves, scanFrame() returns
10
+ // null and no decode happens, so the animationFrames loop spins harmlessly.
11
+ type JsQR = typeof import('jsqr').default
12
+ let jsQRFn: JsQR | null = null
13
+ let jsQRPromise: Promise<JsQR> | null = null
14
+ function loadJsQR(): Promise<JsQR> {
15
+ if (jsQRPromise) return jsQRPromise
16
+ jsQRPromise = import('jsqr').then(m => {
17
+ jsQRFn = m.default
18
+ return m.default
19
+ })
20
+ return jsQRPromise
21
+ }
22
+
9
23
  interface QRScanResult {
10
24
  data: string
11
25
  timestamp: number
@@ -55,6 +69,12 @@ export class SchmancyQRScanner extends $LitElement(css`
55
69
  if (this.videoElement) {
56
70
  this.videoElement.srcObject = this.stream
57
71
  await this.videoElement.play()
72
+ // Preload jsQR before starting the animationFrames loop so the
73
+ // first few frames have the decoder available. If the fetch
74
+ // hasn't finished by the time a frame fires, scanFrame() just
75
+ // returns null for that tick — no decode, no error.
76
+ await loadJsQR()
77
+ if (!this.isConnected) return
58
78
  this.startScanning()
59
79
  }
60
80
  } catch (error) {
@@ -122,7 +142,12 @@ export class SchmancyQRScanner extends $LitElement(css`
122
142
  ctx.drawImage(this.videoElement, 0, 0)
123
143
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
124
144
 
125
- const code = jsQR(imageData.data, imageData.width, imageData.height)
145
+ // Skip this frame if jsQR hasn't resolved yet — startCamera awaits
146
+ // loadJsQR() before this path runs, so in practice jsQRFn is
147
+ // always set here. Keeping the guard for safety during racy
148
+ // disconnects.
149
+ if (!jsQRFn) return null
150
+ const code = jsQRFn(imageData.data, imageData.width, imageData.height)
126
151
 
127
152
  if (code && code.data) {
128
153
  return {
@@ -33,7 +33,14 @@ export declare class SchmancyCode extends SchmancyCode_base {
33
33
  */
34
34
  maxHeight?: string;
35
35
  private copied;
36
- private get highlightedCode();
36
+ /**
37
+ * Fully-rendered highlighted HTML — populated asynchronously after
38
+ * `loadHljs()` resolves. Empty on first render (one microtask) for a
39
+ * cold component; non-empty from then on.
40
+ */
41
+ private _highlightedCode;
42
+ protected updated(changed: Map<string, unknown>): void;
43
+ private _rehighlight;
37
44
  private escapeHtml;
38
45
  private getHighlightedLines;
39
46
  private addLineFeatures;
@@ -1 +0,0 @@
1
- {"version":3,"file":"code-highlight-BgExKEto.js","names":[],"sources":["../src/code-highlight/code-highlight.ts","../src/code-highlight/code-preview.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport hljs from 'highlight.js/lib/core'\nimport bash from 'highlight.js/lib/languages/bash'\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport markdown from 'highlight.js/lib/languages/markdown'\nimport typescript from 'highlight.js/lib/languages/typescript'\nimport xml from 'highlight.js/lib/languages/xml'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\n// Register only the languages we need\nhljs.registerLanguage('javascript', javascript)\nhljs.registerLanguage('typescript', typescript)\nhljs.registerLanguage('html', xml)\nhljs.registerLanguage('xml', xml)\nhljs.registerLanguage('markdown', markdown)\nhljs.registerLanguage('bash', bash)\n\n/**\n * @element schmancy-code\n * Code highlighting component using highlight.js with schmancy theming support\n */\n@customElement('schmancy-code')\nexport class SchmancyCode extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\toverflow: hidden;\n\t}\n\n\t/* Code block styling using schmancy color system */\n\t.hljs {\n\t\tdisplay: block;\n\t\toverflow-x: auto;\n\t\tpadding: 0.5em;\n\t\tcolor: var(--md-sys-color-on-surface-variant);\n\t\tbackground: var(--md-sys-color-surface-container-lowest);\n\t\tfont-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n\t}\n\n\t/* Comments and documentation */\n\t.hljs-comment,\n\t.hljs-quote {\n\t\tcolor: var(--md-sys-color-outline);\n\t\tfont-style: italic;\n\t}\n\n\t/* Keywords, doctags, formulas */\n\t.hljs-doctag,\n\t.hljs-keyword,\n\t.hljs-formula {\n\t\tcolor: var(--md-sys-color-primary);\n\t}\n\n\t/* Tags, sections, names, deletions */\n\t.hljs-section,\n\t.hljs-name,\n\t.hljs-selector-tag,\n\t.hljs-deletion,\n\t.hljs-subst {\n\t\tcolor: var(--md-sys-color-error);\n\t}\n\n\t/* Literals */\n\t.hljs-literal {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Strings, regex, additions */\n\t.hljs-string,\n\t.hljs-regexp,\n\t.hljs-addition,\n\t.hljs-attribute,\n\t.hljs-meta-string {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t/* Built-ins and class titles */\n\t.hljs-built_in,\n\t.hljs-class .hljs-title {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Variables, attributes, types */\n\t.hljs-attr,\n\t.hljs-variable,\n\t.hljs-template-variable,\n\t.hljs-type,\n\t.hljs-selector-class,\n\t.hljs-selector-attr,\n\t.hljs-selector-pseudo,\n\t.hljs-number {\n\t\tcolor: var(--md-sys-color-on-surface);\n\t}\n\n\t/* Symbols, bullets, links, meta */\n\t.hljs-symbol,\n\t.hljs-bullet,\n\t.hljs-link,\n\t.hljs-meta,\n\t.hljs-selector-id,\n\t.hljs-title {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t.hljs-emphasis {\n\t\tfont-style: italic;\n\t}\n\n\t.hljs-strong {\n\t\tfont-weight: bold;\n\t}\n\n\t.hljs-link {\n\t\ttext-decoration: underline;\n\t}\n\n\t/* Line features styling */\n\t.code-with-lines {\n\t\tbackground: transparent;\n\t\tpadding: 0;\n\t}\n\n\t.code-line {\n\t\tdisplay: block;\n\t\tpadding-left: 0;\n\t\ttransition: background-color 0.2s ease;\n\t}\n\n\t.code-line.highlighted {\n\t\tbackground-color: var(--md-sys-color-primary-container);\n\t\topacity: 0.2;\n\t}\n\n\t.line-number {\n\t\tdisplay: inline-block;\n\t\twidth: 3rem;\n\t\tpadding-right: 1rem;\n\t\ttext-align: right;\n\t\tcolor: var(--md-sys-color-outline);\n\t\tuser-select: none;\n\t\tfont-size: inherit;\n\t}\n`) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'javascript'\n\n\t/**\n\t * Code content to highlight\n\t */\n\t@property({ type: String })\n\tcode: string = ''\n\n\t/**\n\t * Optional filename or title to display in header\n\t */\n\t@property({ type: String })\n\tfilename?: string\n\n\t/**\n\t * Show line numbers\n\t */\n\t@property({ type: Boolean })\n\tlineNumbers: boolean = false\n\n\t/**\n\t * Show copy button\n\t */\n\t@property({ type: Boolean })\n\tcopyButton: boolean = true\n\n\t/**\n\t * Highlighted line numbers (comma-separated or ranges like \"1-3,5,7-9\")\n\t */\n\t@property({ type: String })\n\thighlightLines?: string\n\n\t/**\n\t * Maximum height before scrolling\n\t */\n\t@property({ type: String })\n\tmaxHeight?: string\n\n\t@state()\n\tprivate copied: boolean = false\n\n\tprivate get highlightedCode(): string {\n\t\tif (!this.code) return ''\n\n\t\tlet highlightedHtml = ''\n\n\t\ttry {\n\t\t\t// Use highlight.js to get highlighted code\n\t\t\tconst result = hljs.highlight(this.code.trim(), { language: this.language })\n\t\t\thighlightedHtml = result.value\n\t\t} catch {\n\t\t\t// Fallback to auto-detection if language is not supported\n\t\t\ttry {\n\t\t\t\tconst result = hljs.highlightAuto(this.code.trim())\n\t\t\t\thighlightedHtml = result.value\n\t\t\t} catch {\n\t\t\t\t// Final fallback to escaped plain text\n\t\t\t\thighlightedHtml = this.escapeHtml(this.code.trim())\n\t\t\t}\n\t\t}\n\n\t\t// Process for line numbers and highlighting if needed\n\t\tif (this.lineNumbers || this.highlightLines) {\n\t\t\treturn this.addLineFeatures(highlightedHtml)\n\t\t}\n\n\t\treturn highlightedHtml\n\t}\n\n\tprivate escapeHtml(text: string): string {\n\t\tconst div = document.createElement('div')\n\t\tdiv.textContent = text\n\t\treturn div.innerHTML\n\t}\n\n\tprivate getHighlightedLines(): Set<number> {\n\t\tconst lines = new Set<number>()\n\t\tif (!this.highlightLines) return lines\n\n\t\tconst parts = this.highlightLines.split(',')\n\t\tfor (const part of parts) {\n\t\t\tconst trimmed = part.trim()\n\t\t\tif (trimmed.includes('-')) {\n\t\t\t\tconst [start, end] = trimmed.split('-').map(n => parseInt(n.trim()))\n\t\t\t\tif (!isNaN(start) && !isNaN(end)) {\n\t\t\t\t\tfor (let i = start; i <= end; i++) {\n\t\t\t\t\t\tlines.add(i)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst lineNum = parseInt(trimmed)\n\t\t\t\tif (!isNaN(lineNum)) {\n\t\t\t\t\tlines.add(lineNum)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn lines\n\t}\n\n\tprivate addLineFeatures(highlightedHtml: string): string {\n\t\tconst lines = highlightedHtml.split('\\n')\n\t\tconst highlightedLines = this.getHighlightedLines()\n\n\t\treturn lines\n\t\t\t.map((line, index) => {\n\t\t\t\tconst lineNumber = index + 1\n\t\t\t\tconst isHighlighted = highlightedLines.has(lineNumber)\n\t\t\t\tconst lineClass = isHighlighted ? 'code-line highlighted' : 'code-line'\n\n\t\t\t\tlet content = ''\n\t\t\t\tif (this.lineNumbers) {\n\t\t\t\t\tcontent += `<span class=\"line-number\">${lineNumber}</span>`\n\t\t\t\t}\n\t\t\t\tcontent += line\n\n\t\t\t\treturn `<div class=\"${lineClass}\">${content}</div>`\n\t\t\t})\n\t\t\t.join('')\n\t}\n\n\tprivate async copyCode() {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(this.code)\n\t\t\tthis.copied = true\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.copied = false\n\t\t\t}, 2000)\n\t\t} catch (err) {\n\t\t\tconsole.error('Failed to copy code:', err)\n\t\t}\n\t}\n\n\tprivate getLanguageLabel(): string {\n\t\tconst languageMap: Record<string, string> = {\n\t\t\tjavascript: 'JavaScript',\n\t\t\ttypescript: 'TypeScript',\n\t\t\thtml: 'HTML',\n\t\t\tmarkdown: 'Markdown',\n\t\t\tbash: 'Bash',\n\t\t}\n\n\t\tif (this.filename) {\n\t\t\treturn this.filename\n\t\t}\n\n\t\treturn languageMap[this.language.toLowerCase()] || this.language.toUpperCase()\n\t}\n\n\trender() {\n\t\tconst codeClass = this.lineNumbers || this.highlightLines ? 'code-with-lines' : 'hljs'\n\n\t\treturn html`\n\t\t\t<schmancy-details class=\"bg-surface-default\">\n\t\t\t\t<section slot=\"summary\">\n\t\t\t\t\t<!-- Header -->\n\t\t\t\t\t<div class=\"flex items-center justify-between\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<div class=\"flex gap-1.5\">\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-error);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-tertiary);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-secondary);\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<span class=\"text-xs font-medium opacity-70 ml-2\" style=\"color: var(--md-sys-color-on-surface-variant);\">\n\t\t\t\t\t\t\t\t${this.getLanguageLabel()}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t${this.copyButton\n\t\t\t\t\t\t\t? html`\n\t\t\t\t\t\t\t\t\t<schmancy-button\n\t\t\t\t\t\t\t\t\t\t.variant=\"${this.copied ? 'filled tonal' : 'text'}\"\n\t\t\t\t\t\t\t\t\t\t@click=${this.copyCode}\n\t\t\t\t\t\t\t\t\t\tclass=\"transition-all\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<schmancy-icon > ${this.copied ? 'check' : 'content_copy'} </schmancy-icon>\n\t\t\t\t\t\t\t\t\t\t<span class=\"ml-1\">${this.copied ? 'Copied!' : 'Copy'}</span>\n\t\t\t\t\t\t\t\t\t</schmancy-button>\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t\t<!-- Code -->\n\t\t\t\t<div class=\"overflow-auto\" style=\"${this.maxHeight ? `max-height: ${this.maxHeight}` : ''}\">\n\t\t\t\t\t<pre class=\"m-0\"><code class=\"${codeClass}\">${unsafeHTML(this.highlightedCode)}</code></pre>\n\t\t\t\t</div>\n\t\t\t</schmancy-details>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code': SchmancyCode\n\t}\n}\n","import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { timer } from 'rxjs'\nimport { take } from 'rxjs/operators'\n\n/**\n * @element schmancy-code-preview\n * A component that shows code and its rendered preview side by side\n * Takes the content as a slot and displays both the source and rendered result\n */\n@customElement('schmancy-code-preview')\nexport class SchmancyCodePreview extends TailwindElement(\n\tcss`:host{\n\t\tdisplay:block;\n\t\toverflow:hidden;\n\t\tposition:relative;\n\t\tinset:0;\n\t}`\n) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'html'\n\n\t/**\n\t * Show code on top or side-by-side\n\t */\n\t@property({ type: String })\n\tlayout: 'vertical' | 'horizontal' = 'vertical'\n\n\t/**\n\t * Whether to render/execute the code in preview section\n\t * When false, only shows the code without rendering\n\t */\n\t@property({ type: Boolean })\n\tpreview: boolean = true\n\n\t@state()\n\tprivate slotContent: string = ''\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\t// Capture the slot content as HTML string\n\t\ttimer(0).pipe(take(1)).subscribe(() => {\n\t\t\tconst slot = this.shadowRoot?.querySelector('slot')\n\t\t\tif (slot) {\n\t\t\t\tconst nodes = slot.assignedNodes({ flatten: true })\n\t\t\t\tconst htmlStrings = nodes.map(node => {\n\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\treturn (node as HTMLElement).outerHTML\n\t\t\t\t\t} else if (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\treturn node.textContent || ''\n\t\t\t\t\t}\n\t\t\t\t\treturn ''\n\t\t\t\t})\n\t\t\t\t\n\t\t\t\t// Clean up the HTML string\n\t\t\t\tconst rawContent = htmlStrings.join('')\n\t\t\t\t\n\t\t\t\t// Find the minimum indentation (excluding empty lines)\n\t\t\t\tconst lines = rawContent.split('\\n')\n\t\t\t\tconst minIndent = lines\n\t\t\t\t\t.filter(line => line.trim().length > 0)\n\t\t\t\t\t.reduce((min, line) => {\n\t\t\t\t\t\tconst indent = line.match(/^(\\s*)/)?.[1].length || 0\n\t\t\t\t\t\treturn Math.min(min, indent)\n\t\t\t\t\t}, Infinity)\n\t\t\t\t\n\t\t\t\t// Remove the minimum indentation from all lines\n\t\t\t\tthis.slotContent = lines\n\t\t\t\t\t.map(line => line.slice(minIndent))\n\t\t\t\t\t.join('\\n')\n\t\t\t\t\t.trim()\n\t\t\t}\n\t\t})\n\t}\n\n\trender() {\n\t\tconst containerClass = this.layout === 'horizontal' \n\t\t\t? 'grid grid-cols-1 lg:grid-cols-2 gap-0' \n\t\t\t: 'flex flex-col'\n\n\t\tconst showPreview = this.preview && this.language.toLowerCase() === 'html'\n\t\t\n\t\treturn html`\n\t\t\t<schmancy-surface class=\"rounded-lg overflow-hidden\">\n\t\t\t\t<div class=\"${showPreview ? containerClass : ''}\">\n\t\t\t\t\t<!-- Code section with proper overflow handling -->\n\t\t\t\t\t<div class=\"min-w-0 overflow-hidden\">\n\t\t\t\t\t\t<schmancy-code\n\t\t\t\t\t\t\tlanguage=\"${this.language}\"\n\t\t\t\t\t\t\t.code=\"${this.slotContent}\"\n\t\t\t\t\t\t\t?copyButton=\"${true}\"\n\t\t\t\t\t\t\tclass=\"block w-full\"\n\t\t\t\t\t\t></schmancy-code>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<!-- Preview section (only visible for HTML and when preview is enabled) -->\n\t\t\t\t\t${showPreview ? html`\n\t\t\t\t\t\t<div class=\"min-w-0 overflow-auto\">\n\t\t\t\t\t\t\t<schmancy-surface type=\"solid\" class=\"p-2 h-full\">\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t\t</schmancy-surface>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t` : html`\n\t\t\t\t\t\t<!-- Hidden slot to capture content -->\n\t\t\t\t\t\t<div class=\"hidden\">\n\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`}\n\t\t\t\t</div>\n\t\t\t</schmancy-surface>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code-preview': SchmancyCodePreview\n\t}\n}"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"code-highlight-zSYcSfCz.cjs","names":[],"sources":["../src/code-highlight/code-highlight.ts","../src/code-highlight/code-preview.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport hljs from 'highlight.js/lib/core'\nimport bash from 'highlight.js/lib/languages/bash'\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport markdown from 'highlight.js/lib/languages/markdown'\nimport typescript from 'highlight.js/lib/languages/typescript'\nimport xml from 'highlight.js/lib/languages/xml'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\n// Register only the languages we need\nhljs.registerLanguage('javascript', javascript)\nhljs.registerLanguage('typescript', typescript)\nhljs.registerLanguage('html', xml)\nhljs.registerLanguage('xml', xml)\nhljs.registerLanguage('markdown', markdown)\nhljs.registerLanguage('bash', bash)\n\n/**\n * @element schmancy-code\n * Code highlighting component using highlight.js with schmancy theming support\n */\n@customElement('schmancy-code')\nexport class SchmancyCode extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\toverflow: hidden;\n\t}\n\n\t/* Code block styling using schmancy color system */\n\t.hljs {\n\t\tdisplay: block;\n\t\toverflow-x: auto;\n\t\tpadding: 0.5em;\n\t\tcolor: var(--md-sys-color-on-surface-variant);\n\t\tbackground: var(--md-sys-color-surface-container-lowest);\n\t\tfont-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n\t}\n\n\t/* Comments and documentation */\n\t.hljs-comment,\n\t.hljs-quote {\n\t\tcolor: var(--md-sys-color-outline);\n\t\tfont-style: italic;\n\t}\n\n\t/* Keywords, doctags, formulas */\n\t.hljs-doctag,\n\t.hljs-keyword,\n\t.hljs-formula {\n\t\tcolor: var(--md-sys-color-primary);\n\t}\n\n\t/* Tags, sections, names, deletions */\n\t.hljs-section,\n\t.hljs-name,\n\t.hljs-selector-tag,\n\t.hljs-deletion,\n\t.hljs-subst {\n\t\tcolor: var(--md-sys-color-error);\n\t}\n\n\t/* Literals */\n\t.hljs-literal {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Strings, regex, additions */\n\t.hljs-string,\n\t.hljs-regexp,\n\t.hljs-addition,\n\t.hljs-attribute,\n\t.hljs-meta-string {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t/* Built-ins and class titles */\n\t.hljs-built_in,\n\t.hljs-class .hljs-title {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Variables, attributes, types */\n\t.hljs-attr,\n\t.hljs-variable,\n\t.hljs-template-variable,\n\t.hljs-type,\n\t.hljs-selector-class,\n\t.hljs-selector-attr,\n\t.hljs-selector-pseudo,\n\t.hljs-number {\n\t\tcolor: var(--md-sys-color-on-surface);\n\t}\n\n\t/* Symbols, bullets, links, meta */\n\t.hljs-symbol,\n\t.hljs-bullet,\n\t.hljs-link,\n\t.hljs-meta,\n\t.hljs-selector-id,\n\t.hljs-title {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t.hljs-emphasis {\n\t\tfont-style: italic;\n\t}\n\n\t.hljs-strong {\n\t\tfont-weight: bold;\n\t}\n\n\t.hljs-link {\n\t\ttext-decoration: underline;\n\t}\n\n\t/* Line features styling */\n\t.code-with-lines {\n\t\tbackground: transparent;\n\t\tpadding: 0;\n\t}\n\n\t.code-line {\n\t\tdisplay: block;\n\t\tpadding-left: 0;\n\t\ttransition: background-color 0.2s ease;\n\t}\n\n\t.code-line.highlighted {\n\t\tbackground-color: var(--md-sys-color-primary-container);\n\t\topacity: 0.2;\n\t}\n\n\t.line-number {\n\t\tdisplay: inline-block;\n\t\twidth: 3rem;\n\t\tpadding-right: 1rem;\n\t\ttext-align: right;\n\t\tcolor: var(--md-sys-color-outline);\n\t\tuser-select: none;\n\t\tfont-size: inherit;\n\t}\n`) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'javascript'\n\n\t/**\n\t * Code content to highlight\n\t */\n\t@property({ type: String })\n\tcode: string = ''\n\n\t/**\n\t * Optional filename or title to display in header\n\t */\n\t@property({ type: String })\n\tfilename?: string\n\n\t/**\n\t * Show line numbers\n\t */\n\t@property({ type: Boolean })\n\tlineNumbers: boolean = false\n\n\t/**\n\t * Show copy button\n\t */\n\t@property({ type: Boolean })\n\tcopyButton: boolean = true\n\n\t/**\n\t * Highlighted line numbers (comma-separated or ranges like \"1-3,5,7-9\")\n\t */\n\t@property({ type: String })\n\thighlightLines?: string\n\n\t/**\n\t * Maximum height before scrolling\n\t */\n\t@property({ type: String })\n\tmaxHeight?: string\n\n\t@state()\n\tprivate copied: boolean = false\n\n\tprivate get highlightedCode(): string {\n\t\tif (!this.code) return ''\n\n\t\tlet highlightedHtml = ''\n\n\t\ttry {\n\t\t\t// Use highlight.js to get highlighted code\n\t\t\tconst result = hljs.highlight(this.code.trim(), { language: this.language })\n\t\t\thighlightedHtml = result.value\n\t\t} catch {\n\t\t\t// Fallback to auto-detection if language is not supported\n\t\t\ttry {\n\t\t\t\tconst result = hljs.highlightAuto(this.code.trim())\n\t\t\t\thighlightedHtml = result.value\n\t\t\t} catch {\n\t\t\t\t// Final fallback to escaped plain text\n\t\t\t\thighlightedHtml = this.escapeHtml(this.code.trim())\n\t\t\t}\n\t\t}\n\n\t\t// Process for line numbers and highlighting if needed\n\t\tif (this.lineNumbers || this.highlightLines) {\n\t\t\treturn this.addLineFeatures(highlightedHtml)\n\t\t}\n\n\t\treturn highlightedHtml\n\t}\n\n\tprivate escapeHtml(text: string): string {\n\t\tconst div = document.createElement('div')\n\t\tdiv.textContent = text\n\t\treturn div.innerHTML\n\t}\n\n\tprivate getHighlightedLines(): Set<number> {\n\t\tconst lines = new Set<number>()\n\t\tif (!this.highlightLines) return lines\n\n\t\tconst parts = this.highlightLines.split(',')\n\t\tfor (const part of parts) {\n\t\t\tconst trimmed = part.trim()\n\t\t\tif (trimmed.includes('-')) {\n\t\t\t\tconst [start, end] = trimmed.split('-').map(n => parseInt(n.trim()))\n\t\t\t\tif (!isNaN(start) && !isNaN(end)) {\n\t\t\t\t\tfor (let i = start; i <= end; i++) {\n\t\t\t\t\t\tlines.add(i)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst lineNum = parseInt(trimmed)\n\t\t\t\tif (!isNaN(lineNum)) {\n\t\t\t\t\tlines.add(lineNum)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn lines\n\t}\n\n\tprivate addLineFeatures(highlightedHtml: string): string {\n\t\tconst lines = highlightedHtml.split('\\n')\n\t\tconst highlightedLines = this.getHighlightedLines()\n\n\t\treturn lines\n\t\t\t.map((line, index) => {\n\t\t\t\tconst lineNumber = index + 1\n\t\t\t\tconst isHighlighted = highlightedLines.has(lineNumber)\n\t\t\t\tconst lineClass = isHighlighted ? 'code-line highlighted' : 'code-line'\n\n\t\t\t\tlet content = ''\n\t\t\t\tif (this.lineNumbers) {\n\t\t\t\t\tcontent += `<span class=\"line-number\">${lineNumber}</span>`\n\t\t\t\t}\n\t\t\t\tcontent += line\n\n\t\t\t\treturn `<div class=\"${lineClass}\">${content}</div>`\n\t\t\t})\n\t\t\t.join('')\n\t}\n\n\tprivate async copyCode() {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(this.code)\n\t\t\tthis.copied = true\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.copied = false\n\t\t\t}, 2000)\n\t\t} catch (err) {\n\t\t\tconsole.error('Failed to copy code:', err)\n\t\t}\n\t}\n\n\tprivate getLanguageLabel(): string {\n\t\tconst languageMap: Record<string, string> = {\n\t\t\tjavascript: 'JavaScript',\n\t\t\ttypescript: 'TypeScript',\n\t\t\thtml: 'HTML',\n\t\t\tmarkdown: 'Markdown',\n\t\t\tbash: 'Bash',\n\t\t}\n\n\t\tif (this.filename) {\n\t\t\treturn this.filename\n\t\t}\n\n\t\treturn languageMap[this.language.toLowerCase()] || this.language.toUpperCase()\n\t}\n\n\trender() {\n\t\tconst codeClass = this.lineNumbers || this.highlightLines ? 'code-with-lines' : 'hljs'\n\n\t\treturn html`\n\t\t\t<schmancy-details class=\"bg-surface-default\">\n\t\t\t\t<section slot=\"summary\">\n\t\t\t\t\t<!-- Header -->\n\t\t\t\t\t<div class=\"flex items-center justify-between\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<div class=\"flex gap-1.5\">\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-error);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-tertiary);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-secondary);\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<span class=\"text-xs font-medium opacity-70 ml-2\" style=\"color: var(--md-sys-color-on-surface-variant);\">\n\t\t\t\t\t\t\t\t${this.getLanguageLabel()}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t${this.copyButton\n\t\t\t\t\t\t\t? html`\n\t\t\t\t\t\t\t\t\t<schmancy-button\n\t\t\t\t\t\t\t\t\t\t.variant=\"${this.copied ? 'filled tonal' : 'text'}\"\n\t\t\t\t\t\t\t\t\t\t@click=${this.copyCode}\n\t\t\t\t\t\t\t\t\t\tclass=\"transition-all\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<schmancy-icon > ${this.copied ? 'check' : 'content_copy'} </schmancy-icon>\n\t\t\t\t\t\t\t\t\t\t<span class=\"ml-1\">${this.copied ? 'Copied!' : 'Copy'}</span>\n\t\t\t\t\t\t\t\t\t</schmancy-button>\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t\t<!-- Code -->\n\t\t\t\t<div class=\"overflow-auto\" style=\"${this.maxHeight ? `max-height: ${this.maxHeight}` : ''}\">\n\t\t\t\t\t<pre class=\"m-0\"><code class=\"${codeClass}\">${unsafeHTML(this.highlightedCode)}</code></pre>\n\t\t\t\t</div>\n\t\t\t</schmancy-details>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code': SchmancyCode\n\t}\n}\n","import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { timer } from 'rxjs'\nimport { take } from 'rxjs/operators'\n\n/**\n * @element schmancy-code-preview\n * A component that shows code and its rendered preview side by side\n * Takes the content as a slot and displays both the source and rendered result\n */\n@customElement('schmancy-code-preview')\nexport class SchmancyCodePreview extends TailwindElement(\n\tcss`:host{\n\t\tdisplay:block;\n\t\toverflow:hidden;\n\t\tposition:relative;\n\t\tinset:0;\n\t}`\n) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'html'\n\n\t/**\n\t * Show code on top or side-by-side\n\t */\n\t@property({ type: String })\n\tlayout: 'vertical' | 'horizontal' = 'vertical'\n\n\t/**\n\t * Whether to render/execute the code in preview section\n\t * When false, only shows the code without rendering\n\t */\n\t@property({ type: Boolean })\n\tpreview: boolean = true\n\n\t@state()\n\tprivate slotContent: string = ''\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\t// Capture the slot content as HTML string\n\t\ttimer(0).pipe(take(1)).subscribe(() => {\n\t\t\tconst slot = this.shadowRoot?.querySelector('slot')\n\t\t\tif (slot) {\n\t\t\t\tconst nodes = slot.assignedNodes({ flatten: true })\n\t\t\t\tconst htmlStrings = nodes.map(node => {\n\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\treturn (node as HTMLElement).outerHTML\n\t\t\t\t\t} else if (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\treturn node.textContent || ''\n\t\t\t\t\t}\n\t\t\t\t\treturn ''\n\t\t\t\t})\n\t\t\t\t\n\t\t\t\t// Clean up the HTML string\n\t\t\t\tconst rawContent = htmlStrings.join('')\n\t\t\t\t\n\t\t\t\t// Find the minimum indentation (excluding empty lines)\n\t\t\t\tconst lines = rawContent.split('\\n')\n\t\t\t\tconst minIndent = lines\n\t\t\t\t\t.filter(line => line.trim().length > 0)\n\t\t\t\t\t.reduce((min, line) => {\n\t\t\t\t\t\tconst indent = line.match(/^(\\s*)/)?.[1].length || 0\n\t\t\t\t\t\treturn Math.min(min, indent)\n\t\t\t\t\t}, Infinity)\n\t\t\t\t\n\t\t\t\t// Remove the minimum indentation from all lines\n\t\t\t\tthis.slotContent = lines\n\t\t\t\t\t.map(line => line.slice(minIndent))\n\t\t\t\t\t.join('\\n')\n\t\t\t\t\t.trim()\n\t\t\t}\n\t\t})\n\t}\n\n\trender() {\n\t\tconst containerClass = this.layout === 'horizontal' \n\t\t\t? 'grid grid-cols-1 lg:grid-cols-2 gap-0' \n\t\t\t: 'flex flex-col'\n\n\t\tconst showPreview = this.preview && this.language.toLowerCase() === 'html'\n\t\t\n\t\treturn html`\n\t\t\t<schmancy-surface class=\"rounded-lg overflow-hidden\">\n\t\t\t\t<div class=\"${showPreview ? containerClass : ''}\">\n\t\t\t\t\t<!-- Code section with proper overflow handling -->\n\t\t\t\t\t<div class=\"min-w-0 overflow-hidden\">\n\t\t\t\t\t\t<schmancy-code\n\t\t\t\t\t\t\tlanguage=\"${this.language}\"\n\t\t\t\t\t\t\t.code=\"${this.slotContent}\"\n\t\t\t\t\t\t\t?copyButton=\"${true}\"\n\t\t\t\t\t\t\tclass=\"block w-full\"\n\t\t\t\t\t\t></schmancy-code>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<!-- Preview section (only visible for HTML and when preview is enabled) -->\n\t\t\t\t\t${showPreview ? html`\n\t\t\t\t\t\t<div class=\"min-w-0 overflow-auto\">\n\t\t\t\t\t\t\t<schmancy-surface type=\"solid\" class=\"p-2 h-full\">\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t\t</schmancy-surface>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t` : html`\n\t\t\t\t\t\t<!-- Hidden slot to capture content -->\n\t\t\t\t\t\t<div class=\"hidden\">\n\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`}\n\t\t\t\t</div>\n\t\t\t</schmancy-surface>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code-preview': SchmancyCodePreview\n\t}\n}"],"mappings":"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"}