@elabs-ai/components-ai 4.2.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{_audio-player-media-chrome-T3XVXWRZ.js → _audio-player-media-chrome.js} +1 -1
- package/dist/_code-block-theme.js +12 -0
- package/dist/_code-block-theme.js.map +1 -0
- package/dist/{_flow-boundary-SHNWLQG5.js → _flow-boundary.js} +1 -1
- package/dist/_flow-boundary.js.map +1 -0
- package/dist/_flow-lazy.js +8 -0
- package/dist/_flow-lazy.js.map +1 -0
- package/dist/_lazy-boundary-conformance.js +2 -0
- package/dist/_lazy-boundary-conformance.js.map +1 -0
- package/dist/_lazy-cjk.js +13 -0
- package/dist/_lazy-cjk.js.map +1 -0
- package/dist/_lazy-engine-boundary.js +9 -0
- package/dist/_lazy-engine-boundary.js.map +1 -0
- package/dist/_lazy-math.js +13 -0
- package/dist/_lazy-math.js.map +1 -0
- package/dist/_lazy-mermaid.js +12 -0
- package/dist/_lazy-mermaid.js.map +1 -0
- package/dist/_mermaid-error-panel.js +9 -0
- package/dist/_mermaid-error-panel.js.map +1 -0
- package/dist/{_persona-rive-JEG44YHX.js → _persona-rive.js} +19 -24
- package/dist/_persona-rive.js.map +1 -0
- package/dist/_streamdown-i18n.js +21 -0
- package/dist/_streamdown-i18n.js.map +1 -0
- package/dist/_streamdown-safety.js +10 -0
- package/dist/_streamdown-safety.js.map +1 -0
- package/dist/_theme-scope-store.js +13 -0
- package/dist/_theme-scope-store.js.map +1 -0
- package/dist/a2ui/a2ui-surface.js +17 -0
- package/dist/a2ui/a2ui-surface.js.map +1 -0
- package/dist/a2ui/core/catalog.generated.js +10 -0
- package/dist/a2ui/core/catalog.generated.js.map +1 -0
- package/dist/a2ui/core/complete-json.js +10 -0
- package/dist/a2ui/core/complete-json.js.map +1 -0
- package/dist/a2ui/core/index.js +37 -0
- package/dist/a2ui/core/index.js.map +1 -0
- package/dist/a2ui/core/schema.js +11 -0
- package/dist/a2ui/core/schema.js.map +1 -0
- package/dist/a2ui/core/spec.js +10 -0
- package/dist/a2ui/core/spec.js.map +1 -0
- package/dist/a2ui/core/validate.js +16 -0
- package/dist/a2ui/core/validate.js.map +1 -0
- package/dist/a2ui/index.js +54 -0
- package/dist/a2ui/index.js.map +1 -0
- package/dist/a2ui/ui-catalog.js +18 -0
- package/dist/a2ui/ui-catalog.js.map +1 -0
- package/dist/agent-event.js +10 -0
- package/dist/agent-event.js.map +1 -0
- package/dist/agent-timeline.js +11 -0
- package/dist/agent-timeline.js.map +1 -0
- package/dist/agent.js +25 -0
- package/dist/agent.js.map +1 -0
- package/dist/artifact.js +23 -0
- package/dist/artifact.js.map +1 -0
- package/dist/asset-preview.js +22 -0
- package/dist/asset-preview.js.map +1 -0
- package/dist/attachments.js +33 -0
- package/dist/attachments.js.map +1 -0
- package/dist/audio-player.js +30 -0
- package/dist/audio-player.js.map +1 -0
- package/dist/audio-visualizer.js +9 -0
- package/dist/audio-visualizer.js.map +1 -0
- package/dist/canvas.js +10 -0
- package/dist/canvas.js.map +1 -0
- package/dist/chain-of-thought.js +22 -0
- package/dist/chain-of-thought.js.map +1 -0
- package/dist/chat-greeting.js +8 -0
- package/dist/chat-greeting.js.map +1 -0
- package/dist/chat-shell.js +9 -0
- package/dist/chat-shell.js.map +1 -0
- package/dist/checkpoint.js +13 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/chunk-2XOIG5TG.js +72 -0
- package/dist/chunk-2XOIG5TG.js.map +1 -0
- package/dist/chunk-34CQ2VHM.js +172 -0
- package/dist/chunk-34CQ2VHM.js.map +1 -0
- package/dist/chunk-3TDHPXZZ.js +60 -0
- package/dist/chunk-3TDHPXZZ.js.map +1 -0
- package/dist/chunk-3XNPMDZY.js +478 -0
- package/dist/chunk-3XNPMDZY.js.map +1 -0
- package/dist/chunk-3YPT3V7L.js +56 -0
- package/dist/chunk-3YPT3V7L.js.map +1 -0
- package/dist/chunk-475UEU2Q.js +87 -0
- package/dist/chunk-475UEU2Q.js.map +1 -0
- package/dist/chunk-4CBTII2I.js +95 -0
- package/dist/chunk-4CBTII2I.js.map +1 -0
- package/dist/chunk-4XRNIZMG.js +22 -0
- package/dist/chunk-4XRNIZMG.js.map +1 -0
- package/dist/chunk-5NNWUKK5.js +2 -0
- package/dist/chunk-5NNWUKK5.js.map +1 -0
- package/dist/chunk-5UOMU27Z.js +164 -0
- package/dist/chunk-5UOMU27Z.js.map +1 -0
- package/dist/chunk-5VGYZ62I.js +264 -0
- package/dist/chunk-5VGYZ62I.js.map +1 -0
- package/dist/chunk-6IQPH2OS.js +21 -0
- package/dist/chunk-6IQPH2OS.js.map +1 -0
- package/dist/chunk-6PB2MXCI.js +482 -0
- package/dist/chunk-6PB2MXCI.js.map +1 -0
- package/dist/chunk-7FD5CZEU.js +215 -0
- package/dist/chunk-7FD5CZEU.js.map +1 -0
- package/dist/chunk-7RL6KZDF.js +266 -0
- package/dist/chunk-7RL6KZDF.js.map +1 -0
- package/dist/chunk-ADOYAGGK.js +482 -0
- package/dist/chunk-ADOYAGGK.js.map +1 -0
- package/dist/chunk-BA3AEMOU.js +21 -0
- package/dist/chunk-BA3AEMOU.js.map +1 -0
- package/dist/chunk-BBHFOYML.js +336 -0
- package/dist/chunk-BBHFOYML.js.map +1 -0
- package/dist/chunk-BHUVISIY.js +221 -0
- package/dist/chunk-BHUVISIY.js.map +1 -0
- package/dist/chunk-BM2LWERA.js +100 -0
- package/dist/chunk-BM2LWERA.js.map +1 -0
- package/dist/chunk-CMOYXNPJ.js +211 -0
- package/dist/chunk-CMOYXNPJ.js.map +1 -0
- package/dist/chunk-CZP3RHC4.js +74 -0
- package/dist/chunk-CZP3RHC4.js.map +1 -0
- package/dist/chunk-DDG5JHQT.js +112 -0
- package/dist/chunk-DDG5JHQT.js.map +1 -0
- package/dist/chunk-DJODXO7I.js +38 -0
- package/dist/chunk-DJODXO7I.js.map +1 -0
- package/dist/chunk-DWJDJLPU.js +192 -0
- package/dist/chunk-DWJDJLPU.js.map +1 -0
- package/dist/chunk-DZW6LM22.js +45 -0
- package/dist/chunk-DZW6LM22.js.map +1 -0
- package/dist/chunk-ELGCZLZF.js +305 -0
- package/dist/chunk-ELGCZLZF.js.map +1 -0
- package/dist/chunk-EV3U6ZZB.js +209 -0
- package/dist/chunk-EV3U6ZZB.js.map +1 -0
- package/dist/chunk-EY7LVUKQ.js +87 -0
- package/dist/chunk-EY7LVUKQ.js.map +1 -0
- package/dist/chunk-F4C74F7M.js +230 -0
- package/dist/chunk-F4C74F7M.js.map +1 -0
- package/dist/chunk-FERYDFZA.js +108 -0
- package/dist/chunk-FERYDFZA.js.map +1 -0
- package/dist/chunk-FUIYG2DS.js +166 -0
- package/dist/chunk-FUIYG2DS.js.map +1 -0
- package/dist/chunk-GA7M34KU.js +236 -0
- package/dist/chunk-GA7M34KU.js.map +1 -0
- package/dist/chunk-GKYZT3LA.js +136 -0
- package/dist/chunk-GKYZT3LA.js.map +1 -0
- package/dist/chunk-H42LRUQ4.js +102 -0
- package/dist/chunk-H42LRUQ4.js.map +1 -0
- package/dist/chunk-HVXM2G5F.js +222 -0
- package/dist/chunk-HVXM2G5F.js.map +1 -0
- package/dist/chunk-I4RDAGVY.js +53 -0
- package/dist/chunk-I4RDAGVY.js.map +1 -0
- package/dist/chunk-IQJG4IDX.js +208 -0
- package/dist/chunk-IQJG4IDX.js.map +1 -0
- package/dist/chunk-IX2PXG4Y.js +144 -0
- package/dist/chunk-IX2PXG4Y.js.map +1 -0
- package/dist/chunk-IXICSOOP.js +287 -0
- package/dist/chunk-IXICSOOP.js.map +1 -0
- package/dist/chunk-JY5HSN4D.js +84 -0
- package/dist/chunk-JY5HSN4D.js.map +1 -0
- package/dist/chunk-L4SU3QJV.js +174 -0
- package/dist/chunk-L4SU3QJV.js.map +1 -0
- package/dist/chunk-LMNSBOBG.js +19 -0
- package/dist/chunk-LMNSBOBG.js.map +1 -0
- package/dist/chunk-MBI7D6IL.js +42 -0
- package/dist/chunk-MBI7D6IL.js.map +1 -0
- package/dist/chunk-MLFMYCPH.js +192 -0
- package/dist/chunk-MLFMYCPH.js.map +1 -0
- package/dist/chunk-MOK66734.js +33 -0
- package/dist/chunk-MOK66734.js.map +1 -0
- package/dist/chunk-MXTAWPYM.js +196 -0
- package/dist/chunk-MXTAWPYM.js.map +1 -0
- package/dist/chunk-NCL2UZKI.js +96 -0
- package/dist/chunk-NCL2UZKI.js.map +1 -0
- package/dist/chunk-NET4YLRY.js +107 -0
- package/dist/chunk-NET4YLRY.js.map +1 -0
- package/dist/chunk-NIG67CFM.js +329 -0
- package/dist/chunk-NIG67CFM.js.map +1 -0
- package/dist/chunk-NMVNNO3L.js +10 -0
- package/dist/chunk-NMVNNO3L.js.map +1 -0
- package/dist/chunk-NP7VID4K.js +2 -0
- package/dist/chunk-NP7VID4K.js.map +1 -0
- package/dist/chunk-NPUCMAG2.js +382 -0
- package/dist/chunk-NPUCMAG2.js.map +1 -0
- package/dist/chunk-NSCLRHES.js +102 -0
- package/dist/chunk-NSCLRHES.js.map +1 -0
- package/dist/chunk-OEUXHVFW.js +86 -0
- package/dist/chunk-OEUXHVFW.js.map +1 -0
- package/dist/chunk-ONBHFIMZ.js +137 -0
- package/dist/chunk-ONBHFIMZ.js.map +1 -0
- package/dist/chunk-OPH2HHL2.js +228 -0
- package/dist/chunk-OPH2HHL2.js.map +1 -0
- package/dist/chunk-OQERHIQP.js +287 -0
- package/dist/chunk-OQERHIQP.js.map +1 -0
- package/dist/chunk-P6YJAZFG.js +103 -0
- package/dist/chunk-P6YJAZFG.js.map +1 -0
- package/dist/chunk-PG7ERDOD.js +65 -0
- package/dist/chunk-PG7ERDOD.js.map +1 -0
- package/dist/chunk-PIB5JBMA.js +90 -0
- package/dist/chunk-PIB5JBMA.js.map +1 -0
- package/dist/chunk-PQ5BPIWQ.js +22 -0
- package/dist/chunk-PQ5BPIWQ.js.map +1 -0
- package/dist/chunk-PQBF6ZIQ.js +55 -0
- package/dist/chunk-PQBF6ZIQ.js.map +1 -0
- package/dist/chunk-PTWCTSZL.js +173 -0
- package/dist/chunk-PTWCTSZL.js.map +1 -0
- package/dist/chunk-QJUNPVOS.js +101 -0
- package/dist/chunk-QJUNPVOS.js.map +1 -0
- package/dist/chunk-QOBSEGCG.js +996 -0
- package/dist/chunk-QOBSEGCG.js.map +1 -0
- package/dist/chunk-QUDZOTRV.js +43 -0
- package/dist/chunk-QUDZOTRV.js.map +1 -0
- package/dist/chunk-RB7G65JC.js +213 -0
- package/dist/chunk-RB7G65JC.js.map +1 -0
- package/dist/chunk-RPHAOR7P.js +45 -0
- package/dist/chunk-RPHAOR7P.js.map +1 -0
- package/dist/chunk-RTCSH2AN.js +331 -0
- package/dist/chunk-RTCSH2AN.js.map +1 -0
- package/dist/chunk-S3ISPW3A.js +28 -0
- package/dist/chunk-S3ISPW3A.js.map +1 -0
- package/dist/chunk-SEVN656N.js +36 -0
- package/dist/chunk-SEVN656N.js.map +1 -0
- package/dist/chunk-SKVG672B.js +64 -0
- package/dist/chunk-SKVG672B.js.map +1 -0
- package/dist/chunk-SSGJ6MEM.js +1076 -0
- package/dist/chunk-SSGJ6MEM.js.map +1 -0
- package/dist/chunk-SSKZ2AED.js +118 -0
- package/dist/chunk-SSKZ2AED.js.map +1 -0
- package/dist/chunk-T56JFGXI.js +561 -0
- package/dist/chunk-T56JFGXI.js.map +1 -0
- package/dist/chunk-TCB6O74A.js +137 -0
- package/dist/chunk-TCB6O74A.js.map +1 -0
- package/dist/chunk-TTEYPO6X.js +57 -0
- package/dist/chunk-TTEYPO6X.js.map +1 -0
- package/dist/chunk-TWPHAJNM.js +462 -0
- package/dist/chunk-TWPHAJNM.js.map +1 -0
- package/dist/chunk-TXJJLP4O.js +336 -0
- package/dist/chunk-TXJJLP4O.js.map +1 -0
- package/dist/chunk-TZ6TB7VM.js +245 -0
- package/dist/chunk-TZ6TB7VM.js.map +1 -0
- package/dist/chunk-UBLKJJ7K.js +278 -0
- package/dist/chunk-UBLKJJ7K.js.map +1 -0
- package/dist/chunk-UCJ6IUFS.js +52 -0
- package/dist/chunk-UCJ6IUFS.js.map +1 -0
- package/dist/chunk-UCKFJ3QF.js +197 -0
- package/dist/chunk-UCKFJ3QF.js.map +1 -0
- package/dist/chunk-UPXSLILN.js +20 -0
- package/dist/chunk-UPXSLILN.js.map +1 -0
- package/dist/chunk-V4DORGWJ.js +92 -0
- package/dist/chunk-V4DORGWJ.js.map +1 -0
- package/dist/chunk-V6E5DYZD.js +80 -0
- package/dist/chunk-V6E5DYZD.js.map +1 -0
- package/dist/chunk-VLLYKF3P.js +96 -0
- package/dist/chunk-VLLYKF3P.js.map +1 -0
- package/dist/chunk-VLNBTOH6.js +43 -0
- package/dist/chunk-VLNBTOH6.js.map +1 -0
- package/dist/chunk-WMDSMSPL.js +303 -0
- package/dist/chunk-WMDSMSPL.js.map +1 -0
- package/dist/chunk-WU5BLGTF.js +149 -0
- package/dist/chunk-WU5BLGTF.js.map +1 -0
- package/dist/chunk-WYTZVSGK.js +245 -0
- package/dist/chunk-WYTZVSGK.js.map +1 -0
- package/dist/chunk-X47QMM6K.js +187 -0
- package/dist/chunk-X47QMM6K.js.map +1 -0
- package/dist/chunk-YHUSW7D2.js +40 -0
- package/dist/chunk-YHUSW7D2.js.map +1 -0
- package/dist/chunk-YSKD7UXX.js +126 -0
- package/dist/chunk-YSKD7UXX.js.map +1 -0
- package/dist/chunk-YYRDGWOU.js +72 -0
- package/dist/chunk-YYRDGWOU.js.map +1 -0
- package/dist/chunk-ZIGZMWM7.js +19 -0
- package/dist/chunk-ZIGZMWM7.js.map +1 -0
- package/dist/chunk-ZKRTUKNP.js +40 -0
- package/dist/chunk-ZKRTUKNP.js.map +1 -0
- package/dist/code-block.js +38 -0
- package/dist/code-block.js.map +1 -0
- package/dist/commit.js +51 -0
- package/dist/commit.js.map +1 -0
- package/dist/composer.js +15 -0
- package/dist/composer.js.map +1 -0
- package/dist/confirmation.js +53 -0
- package/dist/confirmation.js.map +1 -0
- package/dist/connection.js +8 -0
- package/dist/connection.js.map +1 -0
- package/dist/context-panel.js +25 -0
- package/dist/context-panel.js.map +1 -0
- package/dist/controls.js +10 -0
- package/dist/controls.js.map +1 -0
- package/dist/conversation.js +19 -0
- package/dist/conversation.js.map +1 -0
- package/dist/diff-view.js +15 -0
- package/dist/diff-view.js.map +1 -0
- package/dist/edge.js +10 -0
- package/dist/edge.js.map +1 -0
- package/dist/environment-variables.js +29 -0
- package/dist/environment-variables.js.map +1 -0
- package/dist/file-tree.js +23 -0
- package/dist/file-tree.js.map +1 -0
- package/dist/gallery.js +9 -0
- package/dist/gallery.js.map +1 -0
- package/dist/grouped-parts.js +21 -0
- package/dist/grouped-parts.js.map +1 -0
- package/dist/image.js +9 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +366 -98
- package/dist/index.js +672 -13577
- package/dist/index.js.map +1 -1
- package/dist/inline-citation.js +39 -0
- package/dist/inline-citation.js.map +1 -0
- package/dist/jsx-preview.js +17 -0
- package/dist/jsx-preview.js.map +1 -0
- package/dist/markdown-view.js +17 -0
- package/dist/markdown-view.js.map +1 -0
- package/dist/message-compare.js +12 -0
- package/dist/message-compare.js.map +1 -0
- package/dist/message-edit.js +19 -0
- package/dist/message-edit.js.map +1 -0
- package/dist/message-feedback.js +11 -0
- package/dist/message-feedback.js.map +1 -0
- package/dist/message-form-spec.js +38 -0
- package/dist/message-form-spec.js.map +1 -0
- package/dist/message-form.js +26 -0
- package/dist/message-form.js.map +1 -0
- package/dist/message-table-spec.js +26 -0
- package/dist/message-table-spec.js.map +1 -0
- package/dist/message-table.js +12 -0
- package/dist/message-table.js.map +1 -0
- package/dist/message.js +51 -0
- package/dist/message.js.map +1 -0
- package/dist/mic-selector.js +27 -0
- package/dist/mic-selector.js.map +1 -0
- package/dist/model-provider-logo.js +13 -0
- package/dist/model-provider-logo.js.map +1 -0
- package/dist/motion-config.js +9 -0
- package/dist/motion-config.js.map +1 -0
- package/dist/node.js +22 -0
- package/dist/node.js.map +1 -0
- package/dist/open-in-chat.js +31 -0
- package/dist/open-in-chat.js.map +1 -0
- package/dist/package-info.js +25 -0
- package/dist/package-info.js.map +1 -0
- package/dist/panel.js +10 -0
- package/dist/panel.js.map +1 -0
- package/dist/part-groups.js +18 -0
- package/dist/part-groups.js.map +1 -0
- package/dist/permission-mode-select.js +9 -0
- package/dist/permission-mode-select.js.map +1 -0
- package/dist/persona-sources.js +8 -0
- package/dist/persona-sources.js.map +1 -0
- package/dist/persona.js +14 -0
- package/dist/persona.js.map +1 -0
- package/dist/plan.js +32 -0
- package/dist/plan.js.map +1 -0
- package/dist/prompt-input-effort.js +9 -0
- package/dist/prompt-input-effort.js.map +1 -0
- package/dist/prompt-input-mode.js +10 -0
- package/dist/prompt-input-mode.js.map +1 -0
- package/dist/prompt-input-slash.js +12 -0
- package/dist/prompt-input-slash.js.map +1 -0
- package/dist/prompt-input.js +89 -0
- package/dist/prompt-input.js.map +1 -0
- package/dist/queue.js +37 -0
- package/dist/queue.js.map +1 -0
- package/dist/reasoning.js +23 -0
- package/dist/reasoning.js.map +1 -0
- package/dist/sandbox.js +28 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/schema-display.js +33 -0
- package/dist/schema-display.js.map +1 -0
- package/dist/selection-toolbar.js +11 -0
- package/dist/selection-toolbar.js.map +1 -0
- package/dist/session-header.js +9 -0
- package/dist/session-header.js.map +1 -0
- package/dist/session-status-bar.js +9 -0
- package/dist/session-status-bar.js.map +1 -0
- package/dist/shimmer.js +9 -0
- package/dist/shimmer.js.map +1 -0
- package/dist/snippet.js +17 -0
- package/dist/snippet.js.map +1 -0
- package/dist/sources.js +17 -0
- package/dist/sources.js.map +1 -0
- package/dist/speech-input.js +9 -0
- package/dist/speech-input.js.map +1 -0
- package/dist/stack-trace.js +27 -0
- package/dist/stack-trace.js.map +1 -0
- package/dist/suggestion.js +16 -0
- package/dist/suggestion.js.map +1 -0
- package/dist/task.js +18 -0
- package/dist/task.js.map +1 -0
- package/dist/test-results.js +43 -0
- package/dist/test-results.js.map +1 -0
- package/dist/token-usage.js +27 -0
- package/dist/token-usage.js.map +1 -0
- package/dist/tool-result-card.js +9 -0
- package/dist/tool-result-card.js.map +1 -0
- package/dist/tool.js +27 -0
- package/dist/tool.js.map +1 -0
- package/dist/toolbar.js +10 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/transcription.js +11 -0
- package/dist/transcription.js.map +1 -0
- package/dist/turn-status.js +9 -0
- package/dist/turn-status.js.map +1 -0
- package/dist/use-audio-level.js +9 -0
- package/dist/use-audio-level.js.map +1 -0
- package/dist/voice-selector.js +47 -0
- package/dist/voice-selector.js.map +1 -0
- package/dist/web-preview.js +19 -0
- package/dist/web-preview.js.map +1 -0
- package/package.json +11 -9
- package/schemas/a2ui-surface.v1.schema.json +5434 -0
- package/src/_chat-shell-rail.tsx +3 -1
- package/src/_flow-boundary.tsx +2 -2
- package/src/_persona-rive.tsx +27 -41
- package/src/a2ui/a2ui-surface.stories.tsx +662 -0
- package/src/a2ui/a2ui-surface.test.tsx +201 -0
- package/src/a2ui/a2ui-surface.tsx +354 -0
- package/src/a2ui/catalog.source.json +772 -0
- package/src/a2ui/core/a2ui-core.test.ts +178 -0
- package/src/a2ui/core/catalog.generated.ts +1019 -0
- package/src/a2ui/core/complete-json.ts +81 -0
- package/src/a2ui/core/index.ts +10 -0
- package/src/a2ui/core/schema.ts +111 -0
- package/src/a2ui/core/spec.ts +148 -0
- package/src/a2ui/core/validate.ts +266 -0
- package/src/a2ui/index.ts +7 -0
- package/src/a2ui/ui-catalog.tsx +225 -0
- package/src/a2ui/wave1-chart-spec.test.ts +87 -0
- package/src/a2ui/wave2-chart-spec.test.ts +108 -0
- package/src/agentic-workspace.stories.tsx +6 -45
- package/src/chat-shell.test.tsx +40 -10
- package/src/chat-shell.tsx +90 -44
- package/src/chat.stories.tsx +47 -42
- package/src/composer.stories.tsx +4 -5
- package/src/composer.test.tsx +45 -0
- package/src/composer.tsx +104 -21
- package/src/context-panel.stories.tsx +1 -1
- package/src/context-panel.tsx +1 -1
- package/src/conversation.stories.tsx +1 -0
- package/src/conversation.test.tsx +16 -0
- package/src/conversation.tsx +16 -2
- package/src/diff-view.stories.tsx +79 -0
- package/src/diff-view.tsx +3 -2
- package/src/file-tree.tsx +24 -17
- package/src/gallery.stories.tsx +42 -0
- package/src/gallery.tsx +2 -2
- package/src/grouped-parts.stories.tsx +23 -0
- package/src/grouped-parts.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/message-compare.stories.tsx +40 -0
- package/src/message-compare.tsx +2 -1
- package/src/message-form.tsx +1 -1
- package/src/message-table.stories.tsx +24 -0
- package/src/message-table.tsx +1 -1
- package/src/package-info.tsx +12 -9
- package/src/reasoning.stories.tsx +27 -0
- package/src/reasoning.tsx +1 -1
- package/src/session-header.stories.tsx +35 -1
- package/src/session-header.tsx +1 -1
- package/src/sources.stories.tsx +30 -0
- package/src/sources.tsx +4 -1
- package/src/templates-ai-assistant.stories.tsx +151 -87
- package/src/tool.stories.tsx +39 -0
- package/src/tool.tsx +3 -3
- package/src/toolbar.tsx +0 -10
- package/dist/_flow-boundary-SHNWLQG5.js.map +0 -1
- package/dist/_persona-rive-JEG44YHX.js.map +0 -1
- /package/dist/{_audio-player-media-chrome-T3XVXWRZ.js.map → _audio-player-media-chrome.js.map} +0 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
highlightCode
|
|
4
|
+
} from "./chunk-TWPHAJNM.js";
|
|
5
|
+
import {
|
|
6
|
+
Shimmer
|
|
7
|
+
} from "./chunk-3YPT3V7L.js";
|
|
8
|
+
import {
|
|
9
|
+
getThemeScope
|
|
10
|
+
} from "./chunk-3TDHPXZZ.js";
|
|
11
|
+
|
|
12
|
+
// src/diff-view.tsx
|
|
13
|
+
import {
|
|
14
|
+
forwardRef,
|
|
15
|
+
useCallback,
|
|
16
|
+
useEffect,
|
|
17
|
+
useMemo,
|
|
18
|
+
useRef,
|
|
19
|
+
useState
|
|
20
|
+
} from "react";
|
|
21
|
+
import {
|
|
22
|
+
Skeleton,
|
|
23
|
+
diffLineAccessibleLabel,
|
|
24
|
+
diffLineMarker,
|
|
25
|
+
useDiffRows,
|
|
26
|
+
useLocale
|
|
27
|
+
} from "@elabs-ai/components-ui";
|
|
28
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
29
|
+
import { cva } from "class-variance-authority";
|
|
30
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
31
|
+
var diffRowVariants = cva(
|
|
32
|
+
"grid grid-cols-[2.75rem_2.75rem_1.25rem_1fr] items-start gap-x-2 px-2 py-0.5",
|
|
33
|
+
{
|
|
34
|
+
variants: {
|
|
35
|
+
type: {
|
|
36
|
+
add: "bg-success/10",
|
|
37
|
+
del: "bg-destructive/10",
|
|
38
|
+
context: "",
|
|
39
|
+
hunk: "bg-muted/40",
|
|
40
|
+
meta: ""
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
defaultVariants: { type: "context" }
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
var GUTTER_CLASS = "select-none text-end text-meta text-muted-foreground tabular-nums";
|
|
47
|
+
var MARKER_TONE = {
|
|
48
|
+
add: "text-success-text",
|
|
49
|
+
del: "text-destructive-text",
|
|
50
|
+
context: "text-muted-foreground"
|
|
51
|
+
};
|
|
52
|
+
function useSideTokens(combinedCode, language, scopeEl, isStreaming) {
|
|
53
|
+
const [result, setResult] = useState(null);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (!language || combinedCode.length === 0) {
|
|
56
|
+
setResult(null);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let cancelled = false;
|
|
60
|
+
const cached = highlightCode(
|
|
61
|
+
combinedCode,
|
|
62
|
+
language,
|
|
63
|
+
(r) => {
|
|
64
|
+
if (!cancelled) setResult(r);
|
|
65
|
+
},
|
|
66
|
+
scopeEl,
|
|
67
|
+
isStreaming
|
|
68
|
+
);
|
|
69
|
+
if (cached) setResult(cached);
|
|
70
|
+
return () => {
|
|
71
|
+
cancelled = true;
|
|
72
|
+
};
|
|
73
|
+
}, [combinedCode, language, scopeEl, isStreaming]);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
function useDiffTokens(lines, language, scopeEl, isStreaming) {
|
|
77
|
+
const oldIndices = useMemo(
|
|
78
|
+
() => lines.map((line, index) => ({ line, index })).filter(({ line }) => line.type === "del" || line.type === "context").map(({ index }) => index),
|
|
79
|
+
[lines]
|
|
80
|
+
);
|
|
81
|
+
const newIndices = useMemo(
|
|
82
|
+
() => lines.map((line, index) => ({ line, index })).filter(({ line }) => line.type === "add" || line.type === "context").map(({ index }) => index),
|
|
83
|
+
[lines]
|
|
84
|
+
);
|
|
85
|
+
const oldCode = useMemo(
|
|
86
|
+
() => oldIndices.map((index) => lines[index]?.text ?? "").join("\n"),
|
|
87
|
+
[oldIndices, lines]
|
|
88
|
+
);
|
|
89
|
+
const newCode = useMemo(
|
|
90
|
+
() => newIndices.map((index) => lines[index]?.text ?? "").join("\n"),
|
|
91
|
+
[newIndices, lines]
|
|
92
|
+
);
|
|
93
|
+
const oldResult = useSideTokens(oldCode, language, scopeEl, isStreaming);
|
|
94
|
+
const newResult = useSideTokens(newCode, language, scopeEl, isStreaming);
|
|
95
|
+
return useMemo(() => {
|
|
96
|
+
if (!language) return null;
|
|
97
|
+
const map = /* @__PURE__ */ new Map();
|
|
98
|
+
if (oldResult) {
|
|
99
|
+
oldIndices.forEach((originalIndex, i) => {
|
|
100
|
+
if (lines[originalIndex]?.type !== "del") return;
|
|
101
|
+
const tokenLine = oldResult.tokens[i];
|
|
102
|
+
if (tokenLine) map.set(originalIndex, tokenLine);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (newResult) {
|
|
106
|
+
newIndices.forEach((originalIndex, i) => {
|
|
107
|
+
const tokenLine = newResult.tokens[i];
|
|
108
|
+
if (tokenLine) map.set(originalIndex, tokenLine);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return map;
|
|
112
|
+
}, [oldIndices, newIndices, oldResult, newResult, language, lines]);
|
|
113
|
+
}
|
|
114
|
+
function TokenText({ tokens, fallback }) {
|
|
115
|
+
if (!tokens) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
|
|
116
|
+
return /* @__PURE__ */ jsx(Fragment, { children: tokens.map((token, i) => (
|
|
117
|
+
// oxlint-disable-next-line eslint(react/no-array-index-key) -- tokens for one line never reorder
|
|
118
|
+
/* @__PURE__ */ jsx("span", { style: { color: token.color }, children: token.content }, i)
|
|
119
|
+
)) });
|
|
120
|
+
}
|
|
121
|
+
function CollapsedRow({ hiddenCount, onExpand }) {
|
|
122
|
+
const { t } = useLocale();
|
|
123
|
+
return /* @__PURE__ */ jsx(
|
|
124
|
+
"div",
|
|
125
|
+
{
|
|
126
|
+
"data-slot": "diff-view-collapsed",
|
|
127
|
+
className: "col-span-full grid grid-cols-[2.75rem_2.75rem_1.25rem_1fr]",
|
|
128
|
+
children: /* @__PURE__ */ jsx(
|
|
129
|
+
"button",
|
|
130
|
+
{
|
|
131
|
+
type: "button",
|
|
132
|
+
onClick: onExpand,
|
|
133
|
+
className: "col-start-4 w-fit rounded-sm px-1 text-info-text text-meta hover:underline focus-ring",
|
|
134
|
+
children: t("ai.diffView.showMore", { count: hiddenCount })
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
function FullWidthRow({ line }) {
|
|
141
|
+
return /* @__PURE__ */ jsx(
|
|
142
|
+
"div",
|
|
143
|
+
{
|
|
144
|
+
"data-slot": "diff-view-row",
|
|
145
|
+
"data-diff-type": line.type,
|
|
146
|
+
className: cn(
|
|
147
|
+
diffRowVariants({ type: line.type }),
|
|
148
|
+
"col-span-full block font-mono text-meta text-muted-foreground",
|
|
149
|
+
line.type === "hunk" && "italic"
|
|
150
|
+
),
|
|
151
|
+
children: line.text || "\xA0"
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
function InlineRow({
|
|
156
|
+
line,
|
|
157
|
+
index,
|
|
158
|
+
tokens
|
|
159
|
+
}) {
|
|
160
|
+
const { t } = useLocale();
|
|
161
|
+
if (line.type === "hunk" || line.type === "meta") {
|
|
162
|
+
return /* @__PURE__ */ jsx(FullWidthRow, { line });
|
|
163
|
+
}
|
|
164
|
+
const type = line.type;
|
|
165
|
+
const polarityKey = diffLineAccessibleLabel(type);
|
|
166
|
+
return /* @__PURE__ */ jsxs(
|
|
167
|
+
"div",
|
|
168
|
+
{
|
|
169
|
+
"data-slot": "diff-view-row",
|
|
170
|
+
"data-diff-type": type,
|
|
171
|
+
"data-diff-index": index,
|
|
172
|
+
className: diffRowVariants({ type }),
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "diff-view-gutter-old", className: GUTTER_CLASS, "aria-hidden": "true", children: type !== "add" ? line.oldNumber ?? "" : "" }),
|
|
175
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "diff-view-gutter-new", className: GUTTER_CLASS, "aria-hidden": "true", children: type !== "del" ? line.newNumber ?? "" : "" }),
|
|
176
|
+
/* @__PURE__ */ jsx(
|
|
177
|
+
"span",
|
|
178
|
+
{
|
|
179
|
+
"data-slot": "diff-view-marker",
|
|
180
|
+
"aria-hidden": "true",
|
|
181
|
+
className: cn("select-none font-bold font-mono text-code", MARKER_TONE[type]),
|
|
182
|
+
children: diffLineMarker(type)
|
|
183
|
+
}
|
|
184
|
+
),
|
|
185
|
+
/* @__PURE__ */ jsxs(
|
|
186
|
+
"span",
|
|
187
|
+
{
|
|
188
|
+
"data-slot": "diff-view-line-text",
|
|
189
|
+
className: "whitespace-pre-wrap break-all font-mono text-code",
|
|
190
|
+
children: [
|
|
191
|
+
polarityKey && /* @__PURE__ */ jsx("span", { className: "sr-only", children: t(polarityKey) }),
|
|
192
|
+
/* @__PURE__ */ jsx(TokenText, { tokens, fallback: line.text || "\xA0" })
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
function SplitSide({
|
|
201
|
+
show,
|
|
202
|
+
number,
|
|
203
|
+
markerType,
|
|
204
|
+
polarityKey,
|
|
205
|
+
text,
|
|
206
|
+
tokens
|
|
207
|
+
}) {
|
|
208
|
+
const { t } = useLocale();
|
|
209
|
+
if (!show) {
|
|
210
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "block", children: "\xA0" });
|
|
211
|
+
}
|
|
212
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[2.75rem_1.25rem_1fr] items-start gap-x-2", children: [
|
|
213
|
+
/* @__PURE__ */ jsx("span", { className: GUTTER_CLASS, "aria-hidden": "true", children: number ?? "" }),
|
|
214
|
+
/* @__PURE__ */ jsx(
|
|
215
|
+
"span",
|
|
216
|
+
{
|
|
217
|
+
"aria-hidden": "true",
|
|
218
|
+
className: cn("select-none font-bold font-mono text-code", MARKER_TONE[markerType]),
|
|
219
|
+
children: diffLineMarker(markerType)
|
|
220
|
+
}
|
|
221
|
+
),
|
|
222
|
+
/* @__PURE__ */ jsxs("span", { className: "whitespace-pre-wrap break-all font-mono text-code", children: [
|
|
223
|
+
polarityKey && /* @__PURE__ */ jsx("span", { className: "sr-only", children: t(polarityKey) }),
|
|
224
|
+
/* @__PURE__ */ jsx(TokenText, { tokens, fallback: text || "\xA0" })
|
|
225
|
+
] })
|
|
226
|
+
] });
|
|
227
|
+
}
|
|
228
|
+
function SplitRow({
|
|
229
|
+
line,
|
|
230
|
+
index,
|
|
231
|
+
tokens
|
|
232
|
+
}) {
|
|
233
|
+
if (line.type === "hunk" || line.type === "meta") {
|
|
234
|
+
return /* @__PURE__ */ jsx(FullWidthRow, { line });
|
|
235
|
+
}
|
|
236
|
+
const type = line.type;
|
|
237
|
+
const showOld = type !== "add";
|
|
238
|
+
const showNew = type !== "del";
|
|
239
|
+
return /* @__PURE__ */ jsxs("div", { "data-slot": "diff-view-row", "data-diff-type": type, "data-diff-index": index, className: "flex", children: [
|
|
240
|
+
/* @__PURE__ */ jsx("div", { className: cn("flex-1 px-2 py-0.5", showOld && diffRowVariants({ type })), children: /* @__PURE__ */ jsx(
|
|
241
|
+
SplitSide,
|
|
242
|
+
{
|
|
243
|
+
show: showOld,
|
|
244
|
+
number: line.oldNumber,
|
|
245
|
+
markerType: type === "del" ? "del" : "context",
|
|
246
|
+
polarityKey: diffLineAccessibleLabel(type),
|
|
247
|
+
text: line.text,
|
|
248
|
+
tokens
|
|
249
|
+
}
|
|
250
|
+
) }),
|
|
251
|
+
/* @__PURE__ */ jsx(
|
|
252
|
+
"div",
|
|
253
|
+
{
|
|
254
|
+
className: cn(
|
|
255
|
+
"flex-1 border-s border-s-border-strong px-2 py-0.5",
|
|
256
|
+
showNew && diffRowVariants({ type })
|
|
257
|
+
),
|
|
258
|
+
children: /* @__PURE__ */ jsx(
|
|
259
|
+
SplitSide,
|
|
260
|
+
{
|
|
261
|
+
show: showNew,
|
|
262
|
+
number: line.newNumber,
|
|
263
|
+
markerType: type === "add" ? "add" : "context",
|
|
264
|
+
polarityKey: diffLineAccessibleLabel(type),
|
|
265
|
+
text: line.text,
|
|
266
|
+
tokens
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
] });
|
|
272
|
+
}
|
|
273
|
+
function SkeletonRow() {
|
|
274
|
+
return /* @__PURE__ */ jsxs("div", { "data-slot": "diff-view-row", className: diffRowVariants({ type: "context" }), children: [
|
|
275
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "ms-auto h-3 w-6" }),
|
|
276
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "ms-auto h-3 w-6" }),
|
|
277
|
+
/* @__PURE__ */ jsx("span", {}),
|
|
278
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-2/3" })
|
|
279
|
+
] });
|
|
280
|
+
}
|
|
281
|
+
function DiffViewHeader({
|
|
282
|
+
file,
|
|
283
|
+
summary,
|
|
284
|
+
stats
|
|
285
|
+
}) {
|
|
286
|
+
const { t } = useLocale();
|
|
287
|
+
return (
|
|
288
|
+
// header-band-exempt: a file header inside the diff card, not shell chrome
|
|
289
|
+
/* @__PURE__ */ jsxs(
|
|
290
|
+
"div",
|
|
291
|
+
{
|
|
292
|
+
"data-slot": "diff-view-header",
|
|
293
|
+
className: "flex items-center justify-between gap-3 border-b bg-muted/80 px-3 py-2 text-meta text-muted-foreground",
|
|
294
|
+
children: [
|
|
295
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
296
|
+
file && /* @__PURE__ */ jsx("span", { className: "truncate font-mono text-code", "data-slot": "diff-view-file", children: file }),
|
|
297
|
+
summary && /* @__PURE__ */ jsx("span", { className: "truncate", children: summary })
|
|
298
|
+
] }),
|
|
299
|
+
stats && /* @__PURE__ */ jsxs("div", { "data-slot": "diff-view-stats", className: "flex shrink-0 items-center gap-2 tabular-nums", children: [
|
|
300
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: t("ai.diffView.statsSummary", {
|
|
301
|
+
additions: stats.additions,
|
|
302
|
+
deletions: stats.deletions
|
|
303
|
+
}) }),
|
|
304
|
+
/* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "font-mono text-success-text", children: [
|
|
305
|
+
"+",
|
|
306
|
+
stats.additions
|
|
307
|
+
] }),
|
|
308
|
+
/* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "font-mono text-destructive-text", children: [
|
|
309
|
+
"\u2212",
|
|
310
|
+
stats.deletions
|
|
311
|
+
] })
|
|
312
|
+
] })
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
)
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
function DiffViewPager({
|
|
319
|
+
children,
|
|
320
|
+
regionLabel
|
|
321
|
+
}) {
|
|
322
|
+
const { t } = useLocale();
|
|
323
|
+
const scrollRef = useRef(null);
|
|
324
|
+
const [percent, setPercent] = useState(0);
|
|
325
|
+
const updatePercent = useCallback(() => {
|
|
326
|
+
const el = scrollRef.current;
|
|
327
|
+
if (!el) return;
|
|
328
|
+
const max = el.scrollHeight - el.clientHeight;
|
|
329
|
+
setPercent(max <= 0 ? 100 : Math.round(el.scrollTop / max * 100));
|
|
330
|
+
}, []);
|
|
331
|
+
const onKeyDown = useCallback((event) => {
|
|
332
|
+
const el = scrollRef.current;
|
|
333
|
+
if (!el) return;
|
|
334
|
+
switch (event.key) {
|
|
335
|
+
case "ArrowDown":
|
|
336
|
+
el.scrollBy({ top: 24 });
|
|
337
|
+
break;
|
|
338
|
+
case "ArrowUp":
|
|
339
|
+
el.scrollBy({ top: -24 });
|
|
340
|
+
break;
|
|
341
|
+
case "PageDown":
|
|
342
|
+
el.scrollBy({ top: el.clientHeight });
|
|
343
|
+
break;
|
|
344
|
+
case "PageUp":
|
|
345
|
+
el.scrollBy({ top: -el.clientHeight });
|
|
346
|
+
break;
|
|
347
|
+
case "Home":
|
|
348
|
+
el.scrollTo({ top: 0 });
|
|
349
|
+
break;
|
|
350
|
+
case "End":
|
|
351
|
+
el.scrollTo({ top: el.scrollHeight });
|
|
352
|
+
break;
|
|
353
|
+
default:
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
event.preventDefault();
|
|
357
|
+
}, []);
|
|
358
|
+
return /* @__PURE__ */ jsxs(
|
|
359
|
+
"div",
|
|
360
|
+
{
|
|
361
|
+
"data-slot": "diff-view-pager",
|
|
362
|
+
role: "region",
|
|
363
|
+
"aria-label": regionLabel,
|
|
364
|
+
className: "flex flex-col",
|
|
365
|
+
children: [
|
|
366
|
+
/* @__PURE__ */ jsx(
|
|
367
|
+
"div",
|
|
368
|
+
{
|
|
369
|
+
ref: scrollRef,
|
|
370
|
+
tabIndex: 0,
|
|
371
|
+
onScroll: updatePercent,
|
|
372
|
+
onKeyDown,
|
|
373
|
+
className: "max-h-[32rem] overflow-y-auto focus-ring-inset",
|
|
374
|
+
children
|
|
375
|
+
}
|
|
376
|
+
),
|
|
377
|
+
/* @__PURE__ */ jsxs(
|
|
378
|
+
"div",
|
|
379
|
+
{
|
|
380
|
+
"data-slot": "diff-view-pager-footer",
|
|
381
|
+
className: "flex items-center justify-between border-t bg-muted/50 px-3 py-1.5 text-meta text-muted-foreground",
|
|
382
|
+
children: [
|
|
383
|
+
/* @__PURE__ */ jsx("span", { children: t("ai.diffView.pagerLegend") }),
|
|
384
|
+
/* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "tabular-nums", children: [
|
|
385
|
+
percent,
|
|
386
|
+
"%"
|
|
387
|
+
] })
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
)
|
|
391
|
+
]
|
|
392
|
+
}
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
var DiffView = forwardRef(function DiffView2({
|
|
396
|
+
lines,
|
|
397
|
+
file,
|
|
398
|
+
summary,
|
|
399
|
+
stats,
|
|
400
|
+
variant = "inline",
|
|
401
|
+
pager = false,
|
|
402
|
+
language,
|
|
403
|
+
contextLines,
|
|
404
|
+
maxLines,
|
|
405
|
+
loading = false,
|
|
406
|
+
isStreaming = false,
|
|
407
|
+
className,
|
|
408
|
+
...props
|
|
409
|
+
}, ref) {
|
|
410
|
+
const { t } = useLocale();
|
|
411
|
+
const containerRef = useRef(null);
|
|
412
|
+
const [scopeEl, setScopeEl] = useState(null);
|
|
413
|
+
useEffect(() => {
|
|
414
|
+
setScopeEl(getThemeScope(containerRef.current));
|
|
415
|
+
}, []);
|
|
416
|
+
const clippedLines = useMemo(
|
|
417
|
+
() => maxLines ? lines.slice(0, maxLines) : lines,
|
|
418
|
+
[lines, maxLines]
|
|
419
|
+
);
|
|
420
|
+
const tokens = useDiffTokens(clippedLines, language, scopeEl, isStreaming);
|
|
421
|
+
const { rows, expand } = useDiffRows(clippedLines, contextLines);
|
|
422
|
+
const RowComponent = variant === "split" ? SplitRow : InlineRow;
|
|
423
|
+
const regionLabel = file ? `${t("ai.diffView.regionLabel")}: ${file}` : t("ai.diffView.regionLabel");
|
|
424
|
+
const body = loading ? /* @__PURE__ */ jsxs("div", { "data-slot": "diff-view-body", children: [
|
|
425
|
+
/* @__PURE__ */ jsx("span", { role: "status", "aria-live": "polite", className: "sr-only", children: t("ai.diffView.loading") }),
|
|
426
|
+
Array.from({
|
|
427
|
+
length: clippedLines.length > 0 ? Math.min(clippedLines.length, 12) : 6
|
|
428
|
+
}).map((_, i) => (
|
|
429
|
+
// oxlint-disable-next-line eslint(react/no-array-index-key) -- fixed-count placeholder rows
|
|
430
|
+
/* @__PURE__ */ jsx(SkeletonRow, {}, i)
|
|
431
|
+
))
|
|
432
|
+
] }) : /* @__PURE__ */ jsx("div", { "data-slot": "diff-view-body", children: rows.map(
|
|
433
|
+
(row) => row.kind === "collapsed" ? /* @__PURE__ */ jsx(
|
|
434
|
+
CollapsedRow,
|
|
435
|
+
{
|
|
436
|
+
hiddenCount: row.hiddenCount,
|
|
437
|
+
onExpand: () => expand(row.runStart)
|
|
438
|
+
},
|
|
439
|
+
`collapsed-${row.runStart}`
|
|
440
|
+
) : /* @__PURE__ */ jsx(
|
|
441
|
+
RowComponent,
|
|
442
|
+
{
|
|
443
|
+
line: row.line,
|
|
444
|
+
index: row.index,
|
|
445
|
+
tokens: tokens?.get(row.index)
|
|
446
|
+
},
|
|
447
|
+
row.index
|
|
448
|
+
)
|
|
449
|
+
) });
|
|
450
|
+
return /* @__PURE__ */ jsxs(
|
|
451
|
+
"div",
|
|
452
|
+
{
|
|
453
|
+
ref: (node) => {
|
|
454
|
+
containerRef.current = node;
|
|
455
|
+
if (typeof ref === "function") ref(node);
|
|
456
|
+
else if (ref) ref.current = node;
|
|
457
|
+
},
|
|
458
|
+
"data-slot": "diff-view",
|
|
459
|
+
className: cn("overflow-hidden rounded-md border bg-background text-foreground", className),
|
|
460
|
+
...props,
|
|
461
|
+
children: [
|
|
462
|
+
(file || summary || stats) && /* @__PURE__ */ jsx(DiffViewHeader, { file, summary, stats }),
|
|
463
|
+
pager ? /* @__PURE__ */ jsx(DiffViewPager, { regionLabel, children: body }) : body,
|
|
464
|
+
isStreaming && /* @__PURE__ */ jsx(
|
|
465
|
+
"div",
|
|
466
|
+
{
|
|
467
|
+
className: "flex items-center gap-2 border-t bg-muted/80 px-3 py-1.5 text-caption text-muted-foreground",
|
|
468
|
+
role: "status",
|
|
469
|
+
"aria-live": "polite",
|
|
470
|
+
children: /* @__PURE__ */ jsx(Shimmer, { children: t("ai.codeBlock.generating") })
|
|
471
|
+
}
|
|
472
|
+
)
|
|
473
|
+
]
|
|
474
|
+
}
|
|
475
|
+
);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
export {
|
|
479
|
+
diffRowVariants,
|
|
480
|
+
DiffView
|
|
481
|
+
};
|
|
482
|
+
//# sourceMappingURL=chunk-6PB2MXCI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/diff-view.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * DiffView — line-level unified diff renderer for an agent transcript (#102).\n *\n * An agent's primary output is a code change; the package had no way to show\n * one line-by-line. DiffView is the presentational surface for a `DiffLine[]`\n * someone else computed (parsed a unified diff, a git patch, an LLM tool\n * result) — it never diffs, fetches or parses a patch itself (D5).\n *\n * Package placement + the `ChangeReview` seam are BINDING decisions, not\n * choices this file makes on its own — see\n * `docs/decisions/2026-09-01-brainless-adoption-architecture.md` § 3:\n * - DiffView ships here (`@elabs-ai/components-ai`), never in\n * `@elabs-ai/components-ui`, because it reuses `highlightCode` (Shiki) and\n * `ui` does not depend on Shiki.\n * - `ChangeHunk` (`ui`) gains NO `lines` field and `DiffLine` never moves to\n * `ui`. A consumer composes the two via `ChangeReview`'s existing\n * injection seams — `renderHunk` or `ChangeHunk.after` (both `ReactNode`)\n * — never a cross-package import in either direction. See the\n * `ChangeReviewComposition` story.\n *\n * Reuses `highlightCode` from `./code-block` (Shiki) for intra-line syntax\n * colour, so a diff and a code block agree on tokenisation and theme — real\n * `add`/`del`/`context` lines are re-joined into one document before\n * highlighting so Shiki sees genuine surrounding context, then the result is\n * mapped back onto the original line indices. `hunk`/`meta` lines (diff\n * headers, not source) are excluded from that document.\n *\n * Colour is never the only channel (accessibility.md, WCAG 1.4.1): every\n * `add`/`del` row carries a screen-reader polarity word AND a `+`/`−` marker\n * glyph in its own column — the row tint (`bg-success/10` / `bg-destructive/10`,\n * the fill rung) is the third, redundant cue, never the only one.\n *\n * The `DiffLine` model and the polarity-prefix technique are adapted from\n * `theswerd/brainless` (MIT) — see `ATTRIBUTION.md`.\n */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentProps,\n type KeyboardEvent,\n} from \"react\";\nimport {\n Skeleton,\n diffLineAccessibleLabel,\n diffLineMarker,\n useDiffRows,\n useLocale,\n type DiffLine,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { cva } from \"class-variance-authority\";\nimport type { BundledLanguage, ThemedToken } from \"shiki\";\nimport { highlightCode } from \"./code-block\";\nimport { Shimmer } from \"./shimmer\";\nimport { getThemeScope } from \"./_theme-scope-store\";\n\n// ─── Public types ───────────────────────────────────────────────────────────\n//\n// `DiffLineType` and `DiffLine` moved to `@elabs-ai/components-ui`\n// (`lib/diff-line.ts`) — the terminal CLI look-alike family's own diff hunk\n// (issue #117) reuses the same model, and `@elabs-ai/components-ai`/\n// `@elabs-ai/components-terminal` are layer-2 DAG siblings that may not\n// import each other (T0; see\n// docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4). Imported\n// above; NOT re-exported from here — `@elabs-ai/components-ai` never\n// re-exports from `@elabs-ai/components-ui` (its barrel stays own-module\n// only). A consumer imports `DiffLine`/`DiffLineType` from\n// `@elabs-ai/components-ui`.\n\nexport interface DiffViewProps extends Omit<ComponentProps<\"div\">, \"children\"> {\n /** The diff, as a flat, ordered line list. */\n lines: DiffLine[];\n /** File path shown in the header. */\n file?: string;\n /** One-line summary shown beside the file name. */\n summary?: string;\n /** Added / removed line counts shown in the header. */\n stats?: { additions: number; deletions: number };\n /** `inline` = unified single column; `split` = side-by-side. @default \"inline\" */\n variant?: \"inline\" | \"split\";\n /**\n * Full-screen reading surface: a scrollable region with a scroll-position\n * indicator, a key legend (↑/↓, Page Up/Down, Home/End), and a named\n * `role=\"region\"`. Absorbs the upstream `CodexDiff` pager shape — this\n * prop, not a second component.\n */\n pager?: boolean;\n /** Shiki language id for intra-line syntax colour. Omit to render plain text. */\n language?: BundledLanguage;\n /** Collapse a run of consecutive `context` lines longer than this behind a \"show more\" control. */\n contextLines?: number;\n /** Hard cap on rendered lines. Extra lines are simply not rendered. */\n maxLines?: number;\n /** No renderable diff yet (loading-states.md) — layout-shaped skeleton rows at the real row height. */\n loading?: boolean;\n /** Lines are still arriving (loading-states.md) — render what exists; never an error surface. */\n isStreaming?: boolean;\n}\n\n// ─── Row styling (one visual axis: line type → tint) ───────────────────────\n\n/**\n * The row's fill-rung tint — the THIRD, redundant cue (accessibility.md /\n * styling-and-tokens.md). Never the only signal: every `add`/`del` row also\n * carries a marker glyph (shape) and an `sr-only` polarity word (name).\n */\nexport const diffRowVariants = cva(\n \"grid grid-cols-[2.75rem_2.75rem_1.25rem_1fr] items-start gap-x-2 px-2 py-0.5\",\n {\n variants: {\n type: {\n add: \"bg-success/10\",\n del: \"bg-destructive/10\",\n context: \"\",\n hunk: \"bg-muted/40\",\n meta: \"\",\n },\n },\n defaultVariants: { type: \"context\" },\n },\n);\n\nconst GUTTER_CLASS = \"select-none text-end text-meta text-muted-foreground tabular-nums\";\n\n// Marker GLYPHS (`diffLineMarker`) and screen-reader polarity LABELS\n// (`diffLineAccessibleLabel`) are promoted to `@elabs-ai/components-ui`\n// (`lib/diff-line.ts`) — imported above. The tint below stays here: it is\n// presentational (Tailwind token classes), not part of the shared model.\n\nconst MARKER_TONE: Record<\"add\" | \"del\" | \"context\", string> = {\n add: \"text-success-text\",\n del: \"text-destructive-text\",\n context: \"text-muted-foreground\",\n};\n\n// `getThemeScope` (nearest `[data-theme]` ancestor, defaulting to `<html>`)\n// comes from the shared `_theme-scope-store` module — the exact same helper\n// `code-block.tsx` uses, not a second copy of it.\n\n// ─── Intra-line syntax highlighting ────────────────────────────────────────\n\ntype TokenizedResult = NonNullable<ReturnType<typeof highlightCode>>;\n\n/**\n * Highlights ONE side's combined document (see `useDiffTokens` below) and\n * returns the raw Shiki result once it resolves. `isStreaming` is forwarded\n * to `highlightCode`'s `skipCache` — a streaming diff re-tokenizes a growing\n * document on every line, and every intermediate value is never seen again,\n * so permanently caching it is pure waste (perf review 1.4a/§3.2).\n */\nfunction useSideTokens(\n combinedCode: string,\n language: BundledLanguage | undefined,\n scopeEl: Element | null,\n isStreaming: boolean,\n): TokenizedResult | null {\n const [result, setResult] = useState<TokenizedResult | null>(null);\n\n useEffect(() => {\n if (!language || combinedCode.length === 0) {\n setResult(null);\n return;\n }\n let cancelled = false;\n const cached = highlightCode(\n combinedCode,\n language,\n (r) => {\n if (!cancelled) setResult(r);\n },\n scopeEl,\n isStreaming,\n );\n if (cached) setResult(cached);\n return () => {\n cancelled = true;\n };\n }, [combinedCode, language, scopeEl, isStreaming]);\n\n return result;\n}\n\n/**\n * Highlights the OLD file (`del` + `context` lines) and the NEW file (`add` +\n * `context` lines) as two SEPARATE Shiki documents, then maps each back onto\n * the original line indices. `hunk` / `meta` lines are diff headers, not\n * code, and are excluded from both documents.\n *\n * The two sides used to be combined into ONE document (every real line,\n * `del`/`add`/`context` alike, joined in original order). That let a\n * still-open construct on one side leak its tokenizer STATE across the\n * boundary onto the other — a deleted, unterminated `/*` opened a block\n * comment that swallowed the immediately-following ADDED line as commented-out\n * text, even though the two lines never coexist in either real version of the\n * file. Tokenizing old/new as their own documents means Shiki only ever sees\n * genuine same-version context around a construct.\n */\nfunction useDiffTokens(\n lines: DiffLine[],\n language: BundledLanguage | undefined,\n scopeEl: Element | null,\n isStreaming: boolean,\n): Map<number, ThemedToken[]> | null {\n const oldIndices = useMemo(\n () =>\n lines\n .map((line, index) => ({ line, index }))\n .filter(({ line }) => line.type === \"del\" || line.type === \"context\")\n .map(({ index }) => index),\n [lines],\n );\n const newIndices = useMemo(\n () =>\n lines\n .map((line, index) => ({ line, index }))\n .filter(({ line }) => line.type === \"add\" || line.type === \"context\")\n .map(({ index }) => index),\n [lines],\n );\n\n const oldCode = useMemo(\n () => oldIndices.map((index) => lines[index]?.text ?? \"\").join(\"\\n\"),\n [oldIndices, lines],\n );\n const newCode = useMemo(\n () => newIndices.map((index) => lines[index]?.text ?? \"\").join(\"\\n\"),\n [newIndices, lines],\n );\n\n const oldResult = useSideTokens(oldCode, language, scopeEl, isStreaming);\n const newResult = useSideTokens(newCode, language, scopeEl, isStreaming);\n\n return useMemo(() => {\n if (!language) return null;\n const map = new Map<number, ThemedToken[]>();\n // `del` lines exist ONLY in the old-file document.\n if (oldResult) {\n oldIndices.forEach((originalIndex, i) => {\n if (lines[originalIndex]?.type !== \"del\") return;\n const tokenLine = oldResult.tokens[i];\n if (tokenLine) map.set(originalIndex, tokenLine);\n });\n }\n // `add` AND `context` lines come from the new-file document — a `context`\n // line reads identically in both versions, and picking one consistently\n // (rather than whichever side happened to resolve last) keeps its color\n // stable across re-highlights.\n if (newResult) {\n newIndices.forEach((originalIndex, i) => {\n const tokenLine = newResult.tokens[i];\n if (tokenLine) map.set(originalIndex, tokenLine);\n });\n }\n return map;\n }, [oldIndices, newIndices, oldResult, newResult, language, lines]);\n}\n\n/** Renders pre-highlighted tokens; colour only (a diff row doesn't need bold/italic/underline). */\nfunction TokenText({ tokens, fallback }: { tokens?: ThemedToken[]; fallback: string }) {\n if (!tokens) return <>{fallback}</>;\n return (\n <>\n {tokens.map((token, i) => (\n // oxlint-disable-next-line eslint(react/no-array-index-key) -- tokens for one line never reorder\n <span key={i} style={{ color: token.color }}>\n {token.content}\n </span>\n ))}\n </>\n );\n}\n\n// ─── Context-run collapsing ─────────────────────────────────────────────────\n//\n// The row-collapsing model (`DiffRow`, `collapseDiffRows`, `useDiffRows`,\n// formerly this file's private `Row`/`useVisibleRows`) is promoted to\n// `@elabs-ai/components-ui` (`lib/diff-rows.ts`) — imported above. It is pure\n// (no Shiki, no DOM) and the terminal CLI look-alike family's own diff hunk\n// (issue #117) reuses it unchanged; see\n// docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4.\n\nfunction CollapsedRow({ hiddenCount, onExpand }: { hiddenCount: number; onExpand: () => void }) {\n const { t } = useLocale();\n return (\n <div\n data-slot=\"diff-view-collapsed\"\n className=\"col-span-full grid grid-cols-[2.75rem_2.75rem_1.25rem_1fr]\"\n >\n <button\n type=\"button\"\n onClick={onExpand}\n className=\"col-start-4 w-fit rounded-sm px-1 text-info-text text-meta hover:underline focus-ring\"\n >\n {t(\"ai.diffView.showMore\", { count: hiddenCount })}\n </button>\n </div>\n );\n}\n\n// ─── Full-width rows (hunk / meta) ──────────────────────────────────────────\n\nfunction FullWidthRow({ line }: { line: DiffLine }) {\n return (\n <div\n data-slot=\"diff-view-row\"\n data-diff-type={line.type}\n className={cn(\n diffRowVariants({ type: line.type as \"hunk\" | \"meta\" }),\n \"col-span-full block font-mono text-meta text-muted-foreground\",\n line.type === \"hunk\" && \"italic\",\n )}\n >\n {line.text || \" \"}\n </div>\n );\n}\n\n// ─── Inline rows ────────────────────────────────────────────────────────────\n\nfunction InlineRow({\n line,\n index,\n tokens,\n}: {\n line: DiffLine;\n index: number;\n tokens?: ThemedToken[];\n}) {\n const { t } = useLocale();\n if (line.type === \"hunk\" || line.type === \"meta\") {\n return <FullWidthRow line={line} />;\n }\n const type = line.type;\n const polarityKey = diffLineAccessibleLabel(type);\n return (\n <div\n data-slot=\"diff-view-row\"\n data-diff-type={type}\n data-diff-index={index}\n className={diffRowVariants({ type })}\n >\n <span data-slot=\"diff-view-gutter-old\" className={GUTTER_CLASS} aria-hidden=\"true\">\n {type !== \"add\" ? (line.oldNumber ?? \"\") : \"\"}\n </span>\n <span data-slot=\"diff-view-gutter-new\" className={GUTTER_CLASS} aria-hidden=\"true\">\n {type !== \"del\" ? (line.newNumber ?? \"\") : \"\"}\n </span>\n <span\n data-slot=\"diff-view-marker\"\n aria-hidden=\"true\"\n className={cn(\"select-none font-bold font-mono text-code\", MARKER_TONE[type])}\n >\n {diffLineMarker(type)}\n </span>\n <span\n data-slot=\"diff-view-line-text\"\n className=\"whitespace-pre-wrap break-all font-mono text-code\"\n >\n {polarityKey && <span className=\"sr-only\">{t(polarityKey)}</span>}\n <TokenText tokens={tokens} fallback={line.text || \" \"} />\n </span>\n </div>\n );\n}\n\n// ─── Split rows (two aligned columns: old-file view | new-file view) ───────\n\nfunction SplitSide({\n show,\n number,\n markerType,\n polarityKey,\n text,\n tokens,\n}: {\n show: boolean;\n number?: number;\n markerType: \"add\" | \"del\" | \"context\";\n polarityKey?: ReturnType<typeof diffLineAccessibleLabel>;\n text: string;\n tokens?: ThemedToken[];\n}) {\n const { t } = useLocale();\n if (!show) {\n return (\n <span aria-hidden=\"true\" className=\"block\">\n {\" \"}\n </span>\n );\n }\n return (\n <div className=\"grid grid-cols-[2.75rem_1.25rem_1fr] items-start gap-x-2\">\n <span className={GUTTER_CLASS} aria-hidden=\"true\">\n {number ?? \"\"}\n </span>\n <span\n aria-hidden=\"true\"\n className={cn(\"select-none font-bold font-mono text-code\", MARKER_TONE[markerType])}\n >\n {diffLineMarker(markerType)}\n </span>\n <span className=\"whitespace-pre-wrap break-all font-mono text-code\">\n {polarityKey && <span className=\"sr-only\">{t(polarityKey)}</span>}\n <TokenText tokens={tokens} fallback={text || \" \"} />\n </span>\n </div>\n );\n}\n\nfunction SplitRow({\n line,\n index,\n tokens,\n}: {\n line: DiffLine;\n index: number;\n tokens?: ThemedToken[];\n}) {\n if (line.type === \"hunk\" || line.type === \"meta\") {\n return <FullWidthRow line={line} />;\n }\n const type = line.type;\n const showOld = type !== \"add\";\n const showNew = type !== \"del\";\n return (\n <div data-slot=\"diff-view-row\" data-diff-type={type} data-diff-index={index} className=\"flex\">\n <div className={cn(\"flex-1 px-2 py-0.5\", showOld && diffRowVariants({ type }))}>\n <SplitSide\n show={showOld}\n number={line.oldNumber}\n markerType={type === \"del\" ? \"del\" : \"context\"}\n polarityKey={diffLineAccessibleLabel(type)}\n text={line.text}\n tokens={tokens}\n />\n </div>\n <div\n className={cn(\n \"flex-1 border-s border-s-border-strong px-2 py-0.5\",\n showNew && diffRowVariants({ type }),\n )}\n >\n <SplitSide\n show={showNew}\n number={line.newNumber}\n markerType={type === \"add\" ? \"add\" : \"context\"}\n polarityKey={diffLineAccessibleLabel(type)}\n text={line.text}\n tokens={tokens}\n />\n </div>\n </div>\n );\n}\n\n// ─── Skeleton (loading-states.md) ───────────────────────────────────────────\n\nfunction SkeletonRow() {\n return (\n <div data-slot=\"diff-view-row\" className={diffRowVariants({ type: \"context\" })}>\n <Skeleton className=\"ms-auto h-3 w-6\" />\n <Skeleton className=\"ms-auto h-3 w-6\" />\n <span />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n );\n}\n\n// ─── Header ─────────────────────────────────────────────────────────────────\n\nfunction DiffViewHeader({\n file,\n summary,\n stats,\n}: {\n file?: string;\n summary?: string;\n stats?: { additions: number; deletions: number };\n}) {\n const { t } = useLocale();\n return (\n // header-band-exempt: a file header inside the diff card, not shell chrome\n <div\n data-slot=\"diff-view-header\"\n className=\"flex items-center justify-between gap-3 border-b bg-muted/80 px-3 py-2 text-meta text-muted-foreground\"\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n {file && (\n <span className=\"truncate font-mono text-code\" data-slot=\"diff-view-file\">\n {file}\n </span>\n )}\n {summary && <span className=\"truncate\">{summary}</span>}\n </div>\n {stats && (\n <div data-slot=\"diff-view-stats\" className=\"flex shrink-0 items-center gap-2 tabular-nums\">\n <span className=\"sr-only\">\n {t(\"ai.diffView.statsSummary\", {\n additions: stats.additions,\n deletions: stats.deletions,\n })}\n </span>\n <span aria-hidden=\"true\" className=\"font-mono text-success-text\">\n +{stats.additions}\n </span>\n <span aria-hidden=\"true\" className=\"font-mono text-destructive-text\">\n {\"−\"}\n {stats.deletions}\n </span>\n </div>\n )}\n </div>\n );\n}\n\n// ─── Pager (absorbs the upstream CodexDiff shape) ──────────────────────────\n\nfunction DiffViewPager({\n children,\n regionLabel,\n}: {\n children: React.ReactNode;\n regionLabel: string;\n}) {\n const { t } = useLocale();\n const scrollRef = useRef<HTMLDivElement>(null);\n const [percent, setPercent] = useState(0);\n\n const updatePercent = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n const max = el.scrollHeight - el.clientHeight;\n setPercent(max <= 0 ? 100 : Math.round((el.scrollTop / max) * 100));\n }, []);\n\n const onKeyDown = useCallback((event: KeyboardEvent<HTMLDivElement>) => {\n const el = scrollRef.current;\n if (!el) return;\n switch (event.key) {\n case \"ArrowDown\":\n el.scrollBy({ top: 24 });\n break;\n case \"ArrowUp\":\n el.scrollBy({ top: -24 });\n break;\n case \"PageDown\":\n el.scrollBy({ top: el.clientHeight });\n break;\n case \"PageUp\":\n el.scrollBy({ top: -el.clientHeight });\n break;\n case \"Home\":\n el.scrollTo({ top: 0 });\n break;\n case \"End\":\n el.scrollTo({ top: el.scrollHeight });\n break;\n default:\n return;\n }\n event.preventDefault();\n }, []);\n\n return (\n <div\n data-slot=\"diff-view-pager\"\n role=\"region\"\n aria-label={regionLabel}\n className=\"flex flex-col\"\n >\n <div\n ref={scrollRef}\n tabIndex={0}\n onScroll={updatePercent}\n onKeyDown={onKeyDown}\n className=\"max-h-[32rem] overflow-y-auto focus-ring-inset\"\n >\n {children}\n </div>\n <div\n data-slot=\"diff-view-pager-footer\"\n className=\"flex items-center justify-between border-t bg-muted/50 px-3 py-1.5 text-meta text-muted-foreground\"\n >\n <span>{t(\"ai.diffView.pagerLegend\")}</span>\n <span aria-hidden=\"true\" className=\"tabular-nums\">\n {percent}%\n </span>\n </div>\n </div>\n );\n}\n\n// ─── Root ───────────────────────────────────────────────────────────────────\n\nexport const DiffView = forwardRef<HTMLDivElement, DiffViewProps>(function DiffView(\n {\n lines,\n file,\n summary,\n stats,\n variant = \"inline\",\n pager = false,\n language,\n contextLines,\n maxLines,\n loading = false,\n isStreaming = false,\n className,\n ...props\n },\n ref,\n) {\n const { t } = useLocale();\n const containerRef = useRef<HTMLDivElement>(null);\n const [scopeEl, setScopeEl] = useState<Element | null>(null);\n\n useEffect(() => {\n setScopeEl(getThemeScope(containerRef.current));\n }, []);\n\n const clippedLines = useMemo(\n () => (maxLines ? lines.slice(0, maxLines) : lines),\n [lines, maxLines],\n );\n const tokens = useDiffTokens(clippedLines, language, scopeEl, isStreaming);\n const { rows, expand } = useDiffRows(clippedLines, contextLines);\n\n const RowComponent = variant === \"split\" ? SplitRow : InlineRow;\n\n const regionLabel = file\n ? `${t(\"ai.diffView.regionLabel\")}: ${file}`\n : t(\"ai.diffView.regionLabel\");\n\n const body = loading ? (\n <div data-slot=\"diff-view-body\">\n <span role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {t(\"ai.diffView.loading\")}\n </span>\n {Array.from({\n length: clippedLines.length > 0 ? Math.min(clippedLines.length, 12) : 6,\n }).map((_, i) => (\n // oxlint-disable-next-line eslint(react/no-array-index-key) -- fixed-count placeholder rows\n <SkeletonRow key={i} />\n ))}\n </div>\n ) : (\n <div data-slot=\"diff-view-body\">\n {rows.map((row) =>\n row.kind === \"collapsed\" ? (\n <CollapsedRow\n key={`collapsed-${row.runStart}`}\n hiddenCount={row.hiddenCount}\n onExpand={() => expand(row.runStart)}\n />\n ) : (\n <RowComponent\n key={row.index}\n line={row.line}\n index={row.index}\n tokens={tokens?.get(row.index)}\n />\n ),\n )}\n </div>\n );\n\n return (\n <div\n ref={(node) => {\n containerRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n data-slot=\"diff-view\"\n className={cn(\"overflow-hidden rounded-md border bg-background text-foreground\", className)}\n {...props}\n >\n {(file || summary || stats) && <DiffViewHeader file={file} summary={summary} stats={stats} />}\n {pager ? <DiffViewPager regionLabel={regionLabel}>{body}</DiffViewPager> : body}\n {isStreaming && (\n <div\n className=\"flex items-center gap-2 border-t bg-muted/80 px-3 py-1.5 text-caption text-muted-foreground\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <Shimmer>{t(\"ai.codeBlock.generating\")}</Shimmer>\n </div>\n )}\n </div>\n );\n});\n"],"mappings":"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","names":["DiffView"]}
|