@kitn.ai/ui 0.28.0 → 0.30.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 +11 -7
- package/dist/{Icon-DObhsRtm.js → Icon-BzBET3E-.js} +1 -1
- package/dist/{action-icons-CcgNN2oT.js → action-icons-DaW2pU6m.js} +1 -1
- package/dist/agent-tooling/construct/public.d.ts +15 -0
- package/dist/agent-tooling/construct/schema.d.ts +111 -0
- package/dist/arrow-down-D783iMJj.js +1 -0
- package/dist/arrow-left-0VLM5kyg.js +1 -0
- package/dist/artifact-DGjzHYUT.js +1 -0
- package/dist/{attachments-Qr4kg-2b.js → attachments-YvXHlg88.js} +1 -1
- package/dist/{audio-visualizer-DToYdfSc.js → audio-visualizer-9lz5IHsL.js} +1 -1
- package/dist/{badge-CdEu_jn2.js → badge-Dh_vp8A5.js} +1 -1
- package/dist/{bell-DQAAOpDz.js → bell-CT7_WUwS.js} +1 -1
- package/dist/{button-DkuOnGLy.js → button-C_3te6fm.js} +1 -1
- package/dist/{card-renderer-Jx70m6_l.js → card-renderer-DZVaGH2e.js} +1 -1
- package/dist/check-CiEOVnEN.js +1 -0
- package/dist/{checkbox-D7iRB3nL.js → checkbox-Bu2T2e0U.js} +1 -1
- package/dist/{checkbox-group-B2_rpoPM.js → checkbox-group-BiryEXPQ.js} +1 -1
- package/dist/chevron-down-CSobuZRG.js +1 -0
- package/dist/chevron-right-DR9ZAP-2.js +1 -0
- package/dist/{choice-card-m0BYqqOK.js → choice-card-CM6IjkmL.js} +1 -1
- package/dist/circle-BC66EYF7.js +1 -0
- package/dist/circle-check-BqmahW0O.js +1 -0
- package/dist/{circle-x-BPG0iPst.js → circle-x-Bk-dA5Wf.js} +1 -1
- package/dist/{code-block-ClMLKb7C.js → code-block-B26t-Q7q.js} +1 -1
- package/dist/{collapsible-B4DlWicL.js → collapsible-Bhc636Cf.js} +1 -1
- package/dist/components/builder-composer-triggers.d.ts +62 -0
- package/dist/components/builder-layout.d.ts +54 -0
- package/dist/components/builder-message-actions.d.ts +72 -0
- package/dist/components/builder-panel.d.ts +189 -0
- package/dist/components/builder-preview.d.ts +11 -0
- package/dist/components/builder-shell-controls.d.ts +69 -0
- package/dist/components/builder-skeleton.d.ts +58 -0
- package/dist/components/builder-start.d.ts +75 -0
- package/dist/components/builder-workspace-variants.d.ts +23 -0
- package/dist/components/captions.d.ts +66 -0
- package/dist/{composer-sQ0HcvyG.js → composer-DMI85B6j.js} +1 -1
- package/dist/{confirm-card-rQWDQsnC.js → confirm-card-B0YIAwXp.js} +1 -1
- package/dist/construct-cli.es.js +3 -3
- package/dist/construct.d.ts +5 -0
- package/dist/construct.js +327 -0
- package/dist/{context-0kg4ZX1J.js → context-DWgfhqWp.js} +1 -1
- package/dist/controllable-BagRpyHv.js +1 -0
- package/dist/{conversation-item-BxwQLaFJ.js → conversation-item-BsOsVGmT.js} +1 -1
- package/dist/{conversation-list-BCfGN1JU.js → conversation-list-aX3Vtc7L.js} +1 -1
- package/dist/{copy-n9u9rqpi.js → copy-BmEwsNhJ.js} +1 -1
- package/dist/core-C8fzo39E.js +1 -12
- package/dist/{create-tween-uPkArjIG.js → create-tween-CNOAU3Fx.js} +1 -1
- package/dist/{create-tween-C-q-JCM-.js → create-tween-WfqiENls.js} +1 -1
- package/dist/{create-tween-CRrJXxBd.js → create-tween-wlFtW9Kh.js} +1 -1
- package/dist/{create-tween-DZ3RRDHD.js → create-tween-zt79ba32.js} +1 -1
- package/dist/{default-input-CaMrJkgH.js → default-input-DMV5Eaze.js} +1 -1
- package/dist/define-CI0y3eE4.js +1 -0
- package/dist/define.js +40 -40
- package/dist/define.server.js +45 -45
- package/dist/{disclosure-WUImBbDv.js → disclosure-NnACBxsC.js} +1 -1
- package/dist/{dropdown-wZVeJOMd.js → dropdown-DT7G0RGR.js} +1 -1
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/badge.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/card.js +1 -1
- package/dist/elements/cards.js +1 -1
- package/dist/elements/chain-of-thought.js +1 -1
- package/dist/elements/chat-scope-picker.js +1 -1
- package/dist/elements/chat-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkbox-group.js +1 -1
- package/dist/elements/checkbox.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-item.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.js +1 -1
- package/dist/elements/dropdown.js +1 -1
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/embed.js +1 -1
- package/dist/elements/empty.js +1 -1
- package/dist/elements/feedback-bar.js +1 -1
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/form.js +1 -1
- package/dist/elements/hover-card.js +1 -1
- package/dist/elements/icon.js +1 -1
- package/dist/elements/image.js +1 -1
- package/dist/elements/input.js +1 -1
- package/dist/elements/kbd.js +1 -1
- package/dist/elements/link-preview.js +1 -1
- package/dist/elements/loader.js +1 -1
- package/dist/elements/markdown.js +1 -1
- package/dist/elements/menu.js +1 -1
- package/dist/elements/message-skills.js +1 -1
- package/dist/elements/message.js +1 -1
- package/dist/elements/model-switcher.js +1 -1
- package/dist/elements/nav.js +1 -1
- package/dist/elements/notice.js +1 -1
- package/dist/elements/pane-grid.js +1 -1
- package/dist/elements/pane-group.js +1 -1
- package/dist/elements/pane.js +1 -1
- package/dist/elements/popover.js +1 -1
- package/dist/elements/progress-bar.js +1 -1
- package/dist/elements/prompt-dock.js +1 -1
- package/dist/elements/prompt-input.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/radio-group.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +1 -1
- package/dist/elements/screen.js +1 -1
- package/dist/elements/scroll-area.js +1 -1
- package/dist/elements/scroll-button.js +1 -1
- package/dist/elements/search.js +1 -1
- package/dist/elements/segmented.js +1 -1
- package/dist/elements/select.js +1 -1
- package/dist/elements/separator.js +1 -1
- package/dist/elements/setting-item.js +1 -1
- package/dist/elements/settings-group.js +1 -1
- package/dist/elements/skeleton.js +1 -1
- package/dist/elements/slider.js +1 -1
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/{ellipsis-CbOpJnU3.js → ellipsis-6pJ7SxYT.js} +1 -1
- package/dist/{embed-CrfjkbUG.js → embed-BMje-nxj.js} +1 -1
- package/dist/engine-javascript-C1x7zo1_.js +1 -141
- package/dist/{external-link-ByXAwBBQ.js → external-link-Beh9DKeR.js} +1 -1
- package/dist/{file-text-DMib2qwt.js → file-text-D1GPfZ8Q.js} +1 -1
- package/dist/{file-tree-CJqM2aP7.js → file-tree-Dwj2lqg-.js} +1 -1
- package/dist/{folder-_BAb929C.js → folder-b6D8x1DY.js} +1 -1
- package/dist/{form-DSZgZQZk.js → form-DWgdxDXu.js} +1 -1
- package/dist/{hover-card-BQbul9eq.js → hover-card-CWRkqm40.js} +1 -1
- package/dist/{icon-CdcfRhYI.js → icon-CL0jdhsf.js} +1 -1
- package/dist/index.js +1741 -1725
- package/dist/index.server.js +1582 -1566
- package/dist/{info-DsFjGuI_.js → info-0cOUherQ.js} +1 -1
- package/dist/{input-DKbmkMos.js → input-BH6Ru91Q.js} +1 -1
- package/dist/kai.es.js +1 -1
- package/dist/{kbd-PvdGhX4s.js → kbd-DRAnVtNX.js} +1 -1
- package/dist/{link-zF8PzWfF.js → link-Dlr0vssB.js} +1 -1
- package/dist/{link-preview-DbM1866N.js → link-preview-DODgRyV9.js} +1 -1
- package/dist/loader-KvJB6NrT.js +1 -0
- package/dist/{markdown-LMvmAyBk.js → markdown-DX9tuJVj.js} +1 -1
- package/dist/mcp.es.js +9 -5
- package/dist/{message-BYZECyek.js → message-BqQ7Ot5q.js} +1 -1
- package/dist/{message-BSsgvHvf.js → message-DkaGfBd8.js} +1 -1
- package/dist/message-circle-BPpp5QKv.js +1 -0
- package/dist/message-square-BLbsd9BJ.js +1 -0
- package/dist/{minimize-2-BQRoBV1V.js → minimize-2-CyOHJwcN.js} +1 -1
- package/dist/{model-switcher-CMpCOYcB.js → model-switcher-0hrKDiK2.js} +1 -1
- package/dist/{overlay-Cb-MkyDa.js → overlay-DBMFXie6.js} +1 -1
- package/dist/{panel-right-i8warFxT.js → panel-right-t8SWJL6e.js} +1 -1
- package/dist/{paperclip-ByY3UVO6.js → paperclip-CdzuOjbU.js} +1 -1
- package/dist/play-BXy1u7rW.js +1 -0
- package/dist/primitives/use-auto-resize.d.ts +11 -0
- package/dist/{progress-bar-jVAHvMUf.js → progress-bar-CiBtxMWT.js} +1 -1
- package/dist/{prompt-suggestion-CD-qtNgC.js → prompt-suggestion-I_DHP21i.js} +1 -1
- package/dist/{radio-BsoBMhkF.js → radio-C_p3n39l.js} +1 -1
- package/dist/{reasoning-4kBPtlTx.js → reasoning-BDwy_tIe.js} +1 -1
- package/dist/register-impl-DvEnhIxx.js +424 -0
- package/dist/{resizable-uPmY9VY-.js → resizable-SYC-fStM.js} +1 -1
- package/dist/{rotate-ccw-B2xn93py.js → rotate-ccw-B1nwmwuY.js} +1 -1
- package/dist/{rotate-cw-CMVLoCyH.js → rotate-cw-CLAnBcm1.js} +1 -1
- package/dist/{scroll-area-BqLUo8ZZ.js → scroll-area-zRyXoLhI.js} +1 -1
- package/dist/{scroll-button-DslXiJyL.js → scroll-button-jzrbYCG9.js} +1 -1
- package/dist/{select-2cLRtPGT.js → select-DM-0nEe0.js} +1 -1
- package/dist/{separator-BWQtNJcM.js → separator-BToOOoOt.js} +1 -1
- package/dist/{settings-BBR63jLg.js → settings-PaGo_S4U.js} +1 -1
- package/dist/{settings-group-B2ciy-Iw.js → settings-group-BFXGIfXq.js} +1 -1
- package/dist/{skeleton-CkHI-HgC.js → skeleton-DYpmFnnm.js} +1 -1
- package/dist/{slider-DDR9U-i0.js → slider-ebutAmkQ.js} +1 -1
- package/dist/{solid-DruVOXnf.js → solid-15v_3WVL.js} +3563 -3412
- package/dist/{solid-BzCFdL25.js → solid-5P-otgdi.js} +4502 -4296
- package/dist/solid.d.ts +6 -0
- package/dist/solid.js +259 -254
- package/dist/solid.server.js +259 -254
- package/dist/{source-GEnFF528.js → source-c1gpRl9h.js} +1 -1
- package/dist/{star-CilHq8GP.js → star-pcV_3LqF.js} +1 -1
- package/dist/{store-Ciyk6eZG.js → store-CSgbFFCg.js} +1 -1
- package/dist/{switch-KkeQIbuH.js → switch-Bh2OdLV2.js} +1 -1
- package/dist/{tasks-card-BrN4bggJ.js → tasks-card-CbqQAn2S.js} +1 -1
- package/dist/text-shimmer-BSzgEnDH.js +1 -0
- package/dist/textarea-DrYNt_0z.js +1 -0
- package/dist/theme.tokens.css +22 -21
- package/dist/{thumbs-up-CsT9Wzb9.js → thumbs-up-BL3-NenK.js} +1 -1
- package/dist/{toast-store-tgK6MuMv.js → toast-store-DkOlYczt.js} +1 -1
- package/dist/{tool-DzUjIBT8.js → tool-CeIWUVUe.js} +1 -1
- package/dist/{tooltip-Bkkg_4t0.js → tooltip-GA-nmg06.js} +1 -1
- package/dist/{trash-2-jBKxjGGQ.js → trash-2-CT66QWlm.js} +1 -1
- package/dist/{triangle-alert-DlQ68ppf.js → triangle-alert-CeHLWxhD.js} +1 -1
- package/dist/ui/color-field.d.ts +48 -0
- package/dist/ui/textarea.d.ts +4 -0
- package/dist/ui/toggle-chip.d.ts +40 -0
- package/dist/{upload-TcAHXv9W.js → upload-9Csb0F0J.js} +1 -1
- package/dist/{use-card-resolution-DaZqAdWf.js → use-card-resolution-Zg0a08Z-.js} +1 -1
- package/dist/{variant-aurora-DbW_OWL2.js → variant-aurora-4VBQHIKV.js} +1 -1
- package/dist/{variant-aurora-CNmfHhcx.js → variant-aurora-DBeCAQNk.js} +2 -2
- package/dist/{variant-aurora-D6GsdTPA.js → variant-aurora-FzHVXHby.js} +2 -2
- package/dist/{variant-aurora-BhLuYxJR.js → variant-aurora-LE3fqxgw.js} +1 -1
- package/dist/{variant-custom-BvYHR62b.js → variant-custom-AFRGcOBS.js} +1 -1
- package/dist/{variant-custom-DV2x254s.js → variant-custom-BQkNuPpE.js} +2 -2
- package/dist/{variant-custom-BRvaNHSi.js → variant-custom-DI5R0rln.js} +1 -1
- package/dist/{variant-custom-DMTrEO5w.js → variant-custom-WWnrrRHS.js} +2 -2
- package/dist/{variant-wave-CyBueXj9.js → variant-wave-DUCbH5oI.js} +2 -2
- package/dist/{variant-wave-BNMGrDfj.js → variant-wave-DuQV7DhQ.js} +2 -2
- package/dist/{variant-wave-BpDd8t3Z.js → variant-wave-nSI2sfII.js} +1 -1
- package/dist/{variant-wave-sp-qwsdI.js → variant-wave-wTP5v_jU.js} +1 -1
- package/dist/x-eiO9V6J6.js +1 -0
- package/{src/elements/styles.css → kit-base.css} +27 -44
- package/package.json +32 -17
- package/solid.css +33 -0
- package/theme.css +39 -23
- package/bin/route.test.js +0 -58
- package/dist/arrow-down-CjRU3JgV.js +0 -1
- package/dist/arrow-left-Bnpb1UEW.js +0 -1
- package/dist/artifact-Bwt7OgcR.js +0 -1
- package/dist/check-njkVdZu2.js +0 -1
- package/dist/chevron-down-B72s6PXR.js +0 -1
- package/dist/chevron-right-BatuHzUm.js +0 -1
- package/dist/circle-check-B62pODB3.js +0 -1
- package/dist/circle-zx0ByzY9.js +0 -1
- package/dist/controllable-CnGpMF6r.js +0 -1
- package/dist/define-By-uL588.js +0 -1
- package/dist/loader-BM4CEz4G.js +0 -1
- package/dist/message-circle-DruwObfX.js +0 -1
- package/dist/message-square-BG6q6mlm.js +0 -1
- package/dist/play-BvKKq3fX.js +0 -1
- package/dist/register-impl-B1hLkrI8.js +0 -424
- package/dist/text-shimmer-Dcj1MHuq.js +0 -1
- package/dist/textarea-Dpvbngbg.js +0 -1
- package/dist/x-Z5UntkIJ.js +0 -1
- package/src/agent-tooling/README.md +0 -192
- package/src/agent-tooling/archetypes.ts +0 -205
- package/src/agent-tooling/catalog/README.md +0 -676
- package/src/agent-tooling/catalog/catalog-types.ts +0 -231
- package/src/agent-tooling/catalog/fabrications.ts +0 -96
- package/src/agent-tooling/catalog/invariants.ts +0 -284
- package/src/agent-tooling/catalog/labs-titles.ts +0 -114
- package/src/agent-tooling/catalog/scenarios.ts +0 -87
- package/src/agent-tooling/catalog/surfaces.ts +0 -347
- package/src/agent-tooling/construct/cli-entry.ts +0 -8
- package/src/agent-tooling/construct/cli.ts +0 -147
- package/src/agent-tooling/construct/codegen.ts +0 -1635
- package/src/agent-tooling/construct/construct.v1.schema.json +0 -319
- package/src/agent-tooling/construct/dev.ts +0 -148
- package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
- package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
- package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -32
- package/src/agent-tooling/construct/schema.ts +0 -452
- package/src/agent-tooling/integrations/anthropic.ts +0 -442
- package/src/agent-tooling/integrations/cloudflare.ts +0 -218
- package/src/agent-tooling/integrations/langgraph.ts +0 -133
- package/src/agent-tooling/integrations/mastra.ts +0 -182
- package/src/agent-tooling/integrations/mock.ts +0 -148
- package/src/agent-tooling/integrations/ollama.ts +0 -97
- package/src/agent-tooling/integrations/openai.ts +0 -95
- package/src/agent-tooling/integrations/openrouter.ts +0 -82
- package/src/agent-tooling/integrations/pi.ts +0 -176
- package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
- package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
- package/src/agent-tooling/mcp/manifest.ts +0 -422
- package/src/agent-tooling/mcp/server.ts +0 -116
- package/src/agent-tooling/mcp/stdio.ts +0 -18
- package/src/agent-tooling/mcp/tools/construct.ts +0 -130
- package/src/agent-tooling/mcp/tools/debug.ts +0 -621
- package/src/agent-tooling/mcp/tools/reference.ts +0 -980
- package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
- package/src/agent-tooling/mcp/tools/theme.ts +0 -456
- package/src/agent-tooling/mcp/tools/types.ts +0 -14
- package/src/agent-tooling/mcp/validate-args.ts +0 -141
- package/src/agent-tooling/recipes/composed-thread.ts +0 -714
- package/src/agent-tooling/recipes/index.ts +0 -22
- package/src/agent-tooling/recipes/types.ts +0 -32
- package/src/agent-tooling/registry.ts +0 -132
- package/src/agent-tooling/route-emit.ts +0 -305
- package/src/agent-tooling/types.ts +0 -390
- package/src/components/artifact-card.tsx +0 -120
- package/src/components/artifact.tsx +0 -914
- package/src/components/attachment-types.ts +0 -66
- package/src/components/attachments.tsx +0 -536
- package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
- package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
- package/src/components/audio-visualizer/fit-scale.ts +0 -112
- package/src/components/audio-visualizer/index.tsx +0 -528
- package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
- package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
- package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
- package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
- package/src/components/audio-visualizer/sizes.ts +0 -54
- package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
- package/src/components/audio-visualizer/variant-bar.tsx +0 -175
- package/src/components/audio-visualizer/variant-custom.tsx +0 -344
- package/src/components/audio-visualizer/variant-grid.tsx +0 -175
- package/src/components/audio-visualizer/variant-radial.tsx +0 -163
- package/src/components/audio-visualizer/variant-wave.tsx +0 -130
- package/src/components/audio-visualizer/wave.glsl.ts +0 -130
- package/src/components/card-fallback.tsx +0 -60
- package/src/components/card-renderer.tsx +0 -220
- package/src/components/card.tsx +0 -212
- package/src/components/chain-of-thought.tsx +0 -348
- package/src/components/chat-container.tsx +0 -89
- package/src/components/chat-scope-picker.tsx +0 -57
- package/src/components/chat-thread.tsx +0 -1014
- package/src/components/checkpoint.tsx +0 -88
- package/src/components/choice-card.tsx +0 -743
- package/src/components/coachmark.tsx +0 -249
- package/src/components/code-block.tsx +0 -181
- package/src/components/composer-dom.ts +0 -159
- package/src/components/composer-highlight.ts +0 -242
- package/src/components/composer-history.ts +0 -82
- package/src/components/composer.tsx +0 -1075
- package/src/components/confirm-card.tsx +0 -402
- package/src/components/context.tsx +0 -377
- package/src/components/conversation-item.tsx +0 -241
- package/src/components/conversation-list.tsx +0 -429
- package/src/components/conversation-panel.tsx +0 -118
- package/src/components/dismissed-stub.tsx +0 -80
- package/src/components/embed.tsx +0 -200
- package/src/components/empty.tsx +0 -177
- package/src/components/feedback-bar.tsx +0 -166
- package/src/components/file-tree.tsx +0 -530
- package/src/components/file-upload.tsx +0 -167
- package/src/components/form-widgets.tsx +0 -525
- package/src/components/form.tsx +0 -1296
- package/src/components/home-panel.tsx +0 -159
- package/src/components/image.tsx +0 -65
- package/src/components/link-preview.tsx +0 -195
- package/src/components/loader.tsx +0 -367
- package/src/components/markdown.tsx +0 -162
- package/src/components/message-skills.tsx +0 -40
- package/src/components/message.tsx +0 -765
- package/src/components/model-switcher.tsx +0 -132
- package/src/components/prompt-input.tsx +0 -188
- package/src/components/prompt-suggestion.tsx +0 -150
- package/src/components/reasoning.tsx +0 -293
- package/src/components/response-compare-types.ts +0 -152
- package/src/components/response-compare.tsx +0 -455
- package/src/components/response-stream.tsx +0 -109
- package/src/components/screen.tsx +0 -181
- package/src/components/scroll-button.tsx +0 -93
- package/src/components/source.tsx +0 -192
- package/src/components/tasks-card.tsx +0 -801
- package/src/components/text-shimmer.tsx +0 -37
- package/src/components/thinking-bar.tsx +0 -50
- package/src/components/thread.tsx +0 -228
- package/src/components/toast.tsx +0 -503
- package/src/components/tool-classify.ts +0 -26
- package/src/components/tool-types.ts +0 -49
- package/src/components/tool.tsx +0 -190
- package/src/components/use-card-resolution.ts +0 -44
- package/src/components/voice-input.tsx +0 -222
- package/src/components/voice-output.tsx +0 -242
- package/src/components/widget-tab-bar.tsx +0 -73
- package/src/components/workspace-shell.tsx +0 -285
- package/src/diagnostics/hook.ts +0 -352
- package/src/diagnostics/index.ts +0 -82
- package/src/diagnostics/report-request.ts +0 -296
- package/src/elements/agent-card.tsx +0 -67
- package/src/elements/artifact.tsx +0 -194
- package/src/elements/attachments.tsx +0 -140
- package/src/elements/audio-visualizer.tsx +0 -227
- package/src/elements/autoloader.ts +0 -89
- package/src/elements/avatar.tsx +0 -33
- package/src/elements/badge.tsx +0 -32
- package/src/elements/button.tsx +0 -149
- package/src/elements/card.tsx +0 -133
- package/src/elements/cards.tsx +0 -266
- package/src/elements/chain-of-thought.tsx +0 -141
- package/src/elements/chat-scope-picker.tsx +0 -65
- package/src/elements/chat-types.ts +0 -102
- package/src/elements/chat-workspace.tsx +0 -188
- package/src/elements/chat.tsx +0 -304
- package/src/elements/checkbox-group.tsx +0 -164
- package/src/elements/checkbox.tsx +0 -134
- package/src/elements/checkpoint.tsx +0 -47
- package/src/elements/choice.tsx +0 -100
- package/src/elements/coachmark.tsx +0 -90
- package/src/elements/code-block.tsx +0 -60
- package/src/elements/command.tsx +0 -197
- package/src/elements/compare.tsx +0 -111
- package/src/elements/compiled.css +0 -2
- package/src/elements/composer.tsx +0 -162
- package/src/elements/confirm-card.tsx +0 -76
- package/src/elements/context-meter.tsx +0 -107
- package/src/elements/conversation-item.tsx +0 -120
- package/src/elements/conversation-list.tsx +0 -203
- package/src/elements/css.ts +0 -5
- package/src/elements/default-input.tsx +0 -392
- package/src/elements/define-entry.ts +0 -12
- package/src/elements/define.tsx +0 -563
- package/src/elements/diagnostic-events.ts +0 -114
- package/src/elements/dialog.tsx +0 -145
- package/src/elements/disclosure.ts +0 -95
- package/src/elements/dock.tsx +0 -215
- package/src/elements/dropdown.tsx +0 -123
- package/src/elements/editable-label.tsx +0 -140
- package/src/elements/element-data-types.ts +0 -152
- package/src/elements/element-diagnostics.ts +0 -392
- package/src/elements/element-manifest.json +0 -354
- package/src/elements/element-nonscalar.json +0 -187
- package/src/elements/element-types.d.ts +0 -4353
- package/src/elements/embed.tsx +0 -35
- package/src/elements/empty.tsx +0 -29
- package/src/elements/feedback-bar.tsx +0 -66
- package/src/elements/file-tree.tsx +0 -62
- package/src/elements/file-upload.tsx +0 -44
- package/src/elements/form.tsx +0 -94
- package/src/elements/hover-card.tsx +0 -80
- package/src/elements/icon.tsx +0 -41
- package/src/elements/image.tsx +0 -32
- package/src/elements/input.tsx +0 -492
- package/src/elements/kbd.tsx +0 -45
- package/src/elements/link-preview.tsx +0 -34
- package/src/elements/loader.tsx +0 -25
- package/src/elements/markdown.tsx +0 -38
- package/src/elements/menu.tsx +0 -241
- package/src/elements/message-skills.tsx +0 -83
- package/src/elements/message.tsx +0 -361
- package/src/elements/model-switcher.tsx +0 -121
- package/src/elements/nav.tsx +0 -87
- package/src/elements/notice.tsx +0 -53
- package/src/elements/pane-grid.tsx +0 -111
- package/src/elements/pane-group.tsx +0 -119
- package/src/elements/pane.tsx +0 -129
- package/src/elements/popover.tsx +0 -81
- package/src/elements/progress-bar.tsx +0 -39
- package/src/elements/prompt-dock.tsx +0 -82
- package/src/elements/prompt-input.tsx +0 -240
- package/src/elements/prompt-suggestions.tsx +0 -113
- package/src/elements/radio-group.tsx +0 -129
- package/src/elements/reasoning.tsx +0 -71
- package/src/elements/register-impl.ts +0 -148
- package/src/elements/register.ts +0 -76
- package/src/elements/remote.tsx +0 -225
- package/src/elements/resizable.globals.d.ts +0 -36
- package/src/elements/resizable.tsx +0 -704
- package/src/elements/response-stream.tsx +0 -40
- package/src/elements/screen.tsx +0 -90
- package/src/elements/scroll-area.tsx +0 -33
- package/src/elements/scroll-button.tsx +0 -179
- package/src/elements/search.tsx +0 -185
- package/src/elements/segmented.tsx +0 -129
- package/src/elements/select.tsx +0 -165
- package/src/elements/separator.tsx +0 -36
- package/src/elements/setting-item.tsx +0 -50
- package/src/elements/settings-group.tsx +0 -37
- package/src/elements/skeleton.tsx +0 -45
- package/src/elements/slider.tsx +0 -171
- package/src/elements/slot-text.ts +0 -73
- package/src/elements/slots.ts +0 -787
- package/src/elements/source.tsx +0 -126
- package/src/elements/status.tsx +0 -42
- package/src/elements/switch.tsx +0 -118
- package/src/elements/tabs.tsx +0 -95
- package/src/elements/tasks.tsx +0 -103
- package/src/elements/text-shimmer.tsx +0 -28
- package/src/elements/thinking-bar.tsx +0 -43
- package/src/elements/thread.tsx +0 -139
- package/src/elements/toast.tsx +0 -106
- package/src/elements/tool.tsx +0 -78
- package/src/elements/tooltip.tsx +0 -85
- package/src/elements/validate-messages.ts +0 -76
- package/src/elements/voice-input.tsx +0 -100
- package/src/elements/voice-output.tsx +0 -82
- package/src/index.ts +0 -430
- package/src/primitives/audio-bands.ts +0 -174
- package/src/primitives/card-component-types.ts +0 -63
- package/src/primitives/card-contract.ts +0 -80
- package/src/primitives/card-data-types.ts +0 -361
- package/src/primitives/card-host.tsx +0 -37
- package/src/primitives/card-recovery.ts +0 -160
- package/src/primitives/card-registry.tsx +0 -78
- package/src/primitives/card-resolution.ts +0 -36
- package/src/primitives/card-routing.ts +0 -85
- package/src/primitives/card-schemas/artifact.schema.json +0 -92
- package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
- package/src/primitives/card-schemas/card-event.schema.json +0 -12
- package/src/primitives/card-schemas/choice.schema.json +0 -75
- package/src/primitives/card-schemas/confirm.schema.json +0 -65
- package/src/primitives/card-schemas/embed.schema.json +0 -63
- package/src/primitives/card-schemas/form.result.schema.json +0 -7
- package/src/primitives/card-schemas/form.schema.json +0 -53
- package/src/primitives/card-schemas/link.schema.json +0 -54
- package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
- package/src/primitives/card-schemas/tasks.schema.json +0 -83
- package/src/primitives/card-tags.ts +0 -61
- package/src/primitives/card-validate-cards.ts +0 -255
- package/src/primitives/card-validate-schemas.ts +0 -58
- package/src/primitives/card-validate.ts +0 -131
- package/src/primitives/chat-config.tsx +0 -103
- package/src/primitives/composer-model.ts +0 -49
- package/src/primitives/composer-triggers.ts +0 -35
- package/src/primitives/controllable.ts +0 -21
- package/src/primitives/conversation-store.ts +0 -248
- package/src/primitives/create-kai-chat.ts +0 -66
- package/src/primitives/create-tween.ts +0 -266
- package/src/primitives/embed-providers.ts +0 -254
- package/src/primitives/field-mask.ts +0 -256
- package/src/primitives/field-semantics.ts +0 -115
- package/src/primitives/highlighter.ts +0 -157
- package/src/primitives/input-mask.ts +0 -853
- package/src/primitives/link-preview.ts +0 -87
- package/src/primitives/message-feedback.ts +0 -124
- package/src/primitives/pdf-preview.ts +0 -121
- package/src/primitives/toast-store.ts +0 -338
- package/src/primitives/url-scheme-policy.ts +0 -70
- package/src/primitives/use-audio-analysis.ts +0 -340
- package/src/primitives/use-auto-resize.ts +0 -31
- package/src/primitives/use-resize-observer.ts +0 -45
- package/src/primitives/use-sequencer.ts +0 -72
- package/src/primitives/use-speech-recognition.ts +0 -146
- package/src/primitives/use-stick-to-bottom.ts +0 -75
- package/src/primitives/use-text-stream.ts +0 -143
- package/src/primitives/use-voice-recorder.ts +0 -62
- package/src/primitives/visualizer-sequences.ts +0 -350
- package/src/remote/host-embed.ts +0 -345
- package/src/remote/index.ts +0 -2
- package/src/remote/origin.ts +0 -30
- package/src/remote/provider-runtime.ts +0 -262
- package/src/remote/provider.ts +0 -2
- package/src/remote/validate.ts +0 -22
- package/src/remote/version.ts +0 -12
- package/src/remote/wire.ts +0 -48
- package/src/schemas/from-tool-call.ts +0 -151
- package/src/schemas/index.ts +0 -341
- package/src/schemas/provider-subsets.ts +0 -538
- package/src/schemas/registry.ts +0 -355
- package/src/schemas/tool-defs.ts +0 -793
- package/src/solid.ts +0 -173
- package/src/state/index.ts +0 -44
- package/src/state/messages.ts +0 -53
- package/src/state/mock.ts +0 -297
- package/src/state/parts.ts +0 -295
- package/src/state/persistence.ts +0 -180
- package/src/state/stream.ts +0 -246
- package/src/state/suggestions.ts +0 -9
- package/src/state/threads.ts +0 -142
- package/src/test-utils/fake-clock.ts +0 -88
- package/src/types.ts +0 -95
- package/src/ui/action-icons.ts +0 -53
- package/src/ui/agent-card.tsx +0 -218
- package/src/ui/avatar.tsx +0 -23
- package/src/ui/badge.tsx +0 -21
- package/src/ui/button.tsx +0 -49
- package/src/ui/card.tsx +0 -245
- package/src/ui/checkbox-group.tsx +0 -153
- package/src/ui/checkbox.tsx +0 -63
- package/src/ui/collapsible.tsx +0 -163
- package/src/ui/command.tsx +0 -103
- package/src/ui/dialog.tsx +0 -223
- package/src/ui/dock.tsx +0 -630
- package/src/ui/dropdown.tsx +0 -636
- package/src/ui/editable-label.tsx +0 -112
- package/src/ui/hover-card.tsx +0 -345
- package/src/ui/icon.tsx +0 -167
- package/src/ui/input.tsx +0 -391
- package/src/ui/kbd.tsx +0 -118
- package/src/ui/nav.tsx +0 -282
- package/src/ui/notice.tsx +0 -84
- package/src/ui/overlay.tsx +0 -277
- package/src/ui/pane-grid.tsx +0 -117
- package/src/ui/pane-group.tsx +0 -291
- package/src/ui/pane.tsx +0 -193
- package/src/ui/popover.tsx +0 -106
- package/src/ui/progress-bar.tsx +0 -83
- package/src/ui/prompt-dock.tsx +0 -145
- package/src/ui/radio.tsx +0 -150
- package/src/ui/resizable.tsx +0 -693
- package/src/ui/scroll-area.tsx +0 -26
- package/src/ui/segmented.tsx +0 -109
- package/src/ui/select.tsx +0 -168
- package/src/ui/separator.tsx +0 -10
- package/src/ui/settings-group.tsx +0 -67
- package/src/ui/skeleton.tsx +0 -73
- package/src/ui/slider.tsx +0 -178
- package/src/ui/status.tsx +0 -48
- package/src/ui/switch.tsx +0 -119
- package/src/ui/tabs.tsx +0 -168
- package/src/ui/textarea.tsx +0 -21
- package/src/ui/tooltip.tsx +0 -118
- package/src/utils/cn.ts +0 -30
- package/src/wire/chunk.ts +0 -248
- package/src/wire/consume.ts +0 -599
- package/src/wire/diagnostics.ts +0 -727
- package/src/wire/encode-probe.ts +0 -214
- package/src/wire/encode.ts +0 -947
- package/src/wire/files.ts +0 -342
- package/src/wire/formats/anthropic.ts +0 -274
- package/src/wire/formats/openai.ts +0 -228
- package/src/wire/index.ts +0 -95
- package/src/wire/media-types.ts +0 -344
- package/src/wire/read.ts +0 -396
- package/src/wire/sink-helpers.ts +0 -50
- package/src/wire/sse.ts +0 -153
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { For, Show } from 'solid-js';
|
|
2
|
-
import { cn } from '../utils/cn';
|
|
3
|
-
import { Button } from '../ui/button';
|
|
4
|
-
import { renderIcon } from '../ui/icon';
|
|
5
|
-
import { isSafeUrl } from '../primitives/url-scheme-policy';
|
|
6
|
-
import { relativeTimeShort, isConversationUnread } from './conversation-item';
|
|
7
|
-
import type { ConversationSummary, HomeLinkEntry } from '../types';
|
|
8
|
-
|
|
9
|
-
export interface HomePanelProps {
|
|
10
|
-
greeting?: { title?: string; subtitle?: string };
|
|
11
|
-
/** The most-recent conversation, host-derived. `undefined` hides the card
|
|
12
|
-
* entirely — this component never fetches or picks one itself. */
|
|
13
|
-
recent?: ConversationSummary;
|
|
14
|
-
/** Defaults to `true`. */
|
|
15
|
-
showNewConversation?: boolean;
|
|
16
|
-
/** Defaults to `'Send us a message'`. */
|
|
17
|
-
newChatLabel?: string;
|
|
18
|
-
links?: HomeLinkEntry[];
|
|
19
|
-
onSelectRecent?: (id: string) => void;
|
|
20
|
-
onNewChat: () => void;
|
|
21
|
-
/** Fired only for href-less link entries — an entry with a safe `href`
|
|
22
|
-
* navigates as a real anchor instead. */
|
|
23
|
-
onLink?: (entry: HomeLinkEntry) => void;
|
|
24
|
-
class?: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* The widget home screen (Intercom-pattern, H-1): greeting, the most-recent
|
|
29
|
-
* conversation, a "start a new conversation" CTA, and a list of host-defined
|
|
30
|
-
* links. Pure props in, events out — no fetching, no routing; a later task
|
|
31
|
-
* wires this behind `ChatThread`'s Home/Messages tab bar.
|
|
32
|
-
*
|
|
33
|
-
* Unsafe-href rule: a `links` entry with an `href` that fails `isSafeUrl`
|
|
34
|
-
* (e.g. `javascript:`) is NOT silently promoted into a button/event-emitter —
|
|
35
|
-
* that would let a host-authored-but-attacker-influenced config still fire a
|
|
36
|
-
* handler off a scheme SAFE_SCHEMES rejects. It renders as a plain,
|
|
37
|
-
* non-interactive row: label visible, no anchor, no button, no click handler.
|
|
38
|
-
*/
|
|
39
|
-
export function HomePanel(props: HomePanelProps) {
|
|
40
|
-
const title = () => props.greeting?.title ?? 'Hi there 👋';
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<div
|
|
44
|
-
data-kai-home-panel
|
|
45
|
-
class={cn('flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-5', props.class)}
|
|
46
|
-
>
|
|
47
|
-
<div class="flex flex-col gap-1">
|
|
48
|
-
<h2 class="text-xl font-semibold text-foreground">{title()}</h2>
|
|
49
|
-
<Show when={props.greeting?.subtitle}>
|
|
50
|
-
<p class="text-sm text-muted-foreground">{props.greeting!.subtitle}</p>
|
|
51
|
-
</Show>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<Show when={props.recent}>
|
|
55
|
-
{(recent) => {
|
|
56
|
-
const time = () => relativeTimeShort(recent().updatedAt ?? recent().lastMessageAt);
|
|
57
|
-
const unread = () => isConversationUnread(recent());
|
|
58
|
-
return (
|
|
59
|
-
<button
|
|
60
|
-
type="button"
|
|
61
|
-
data-kai-home-recent
|
|
62
|
-
onClick={() => props.onSelectRecent?.(recent().id)}
|
|
63
|
-
class="flex flex-col gap-1 rounded-xl border border-border p-4 text-left transition-colors hover:bg-accent"
|
|
64
|
-
>
|
|
65
|
-
<span class="flex items-center gap-2 text-sm font-semibold text-foreground">
|
|
66
|
-
<span class="min-w-0 flex-1 truncate">{recent().title}</span>
|
|
67
|
-
<Show when={unread()}>
|
|
68
|
-
<span aria-hidden="true" class="size-1.5 shrink-0 rounded-full bg-unread" />
|
|
69
|
-
</Show>
|
|
70
|
-
<Show when={time()}>
|
|
71
|
-
<span class="shrink-0 text-xs font-normal text-muted-foreground">{time()}</span>
|
|
72
|
-
</Show>
|
|
73
|
-
</span>
|
|
74
|
-
<Show when={recent().trailing}>
|
|
75
|
-
<span class="line-clamp-1 text-sm text-muted-foreground">{recent().trailing}</span>
|
|
76
|
-
</Show>
|
|
77
|
-
</button>
|
|
78
|
-
);
|
|
79
|
-
}}
|
|
80
|
-
</Show>
|
|
81
|
-
|
|
82
|
-
<Show when={props.showNewConversation !== false}>
|
|
83
|
-
<Button
|
|
84
|
-
type="button"
|
|
85
|
-
data-kai-home-new
|
|
86
|
-
full
|
|
87
|
-
align="start"
|
|
88
|
-
onClick={() => props.onNewChat()}
|
|
89
|
-
class="justify-between"
|
|
90
|
-
>
|
|
91
|
-
<span>{props.newChatLabel ?? 'Send us a message'}</span>
|
|
92
|
-
{renderIcon('arrow-right', { class: 'size-4 shrink-0' })}
|
|
93
|
-
</Button>
|
|
94
|
-
</Show>
|
|
95
|
-
|
|
96
|
-
<Show when={props.links && props.links.length > 0}>
|
|
97
|
-
<div class="flex flex-col overflow-hidden rounded-xl border border-border">
|
|
98
|
-
<For each={props.links}>
|
|
99
|
-
{(entry) => {
|
|
100
|
-
const safeHref = () => (entry.href && isSafeUrl(entry.href) ? entry.href : undefined);
|
|
101
|
-
const inner = (
|
|
102
|
-
<>
|
|
103
|
-
<span class="flex min-w-0 items-center gap-2">
|
|
104
|
-
<Show when={entry.icon}>{renderIcon(entry.icon, { class: 'size-4 shrink-0 text-muted-foreground' })}</Show>
|
|
105
|
-
<span class="flex min-w-0 flex-col text-left">
|
|
106
|
-
<span class="truncate text-sm font-medium text-foreground">{entry.label}</span>
|
|
107
|
-
<Show when={entry.description}>
|
|
108
|
-
<span class="truncate text-xs text-muted-foreground">{entry.description}</span>
|
|
109
|
-
</Show>
|
|
110
|
-
</span>
|
|
111
|
-
</span>
|
|
112
|
-
{renderIcon('chevron-right', { class: 'size-4 shrink-0 text-muted-foreground' })}
|
|
113
|
-
</>
|
|
114
|
-
);
|
|
115
|
-
const rowClass = 'flex items-center justify-between gap-2 border-b border-border p-3 last:border-b-0';
|
|
116
|
-
return (
|
|
117
|
-
<Show
|
|
118
|
-
when={!entry.href}
|
|
119
|
-
fallback={
|
|
120
|
-
<Show
|
|
121
|
-
when={safeHref()}
|
|
122
|
-
fallback={
|
|
123
|
-
// Unsafe href: a non-interactive row. No anchor, no
|
|
124
|
-
// button, no handler — the label stays visible, it
|
|
125
|
-
// just never becomes clickable.
|
|
126
|
-
<div data-kai-home-link class={rowClass}>
|
|
127
|
-
{inner}
|
|
128
|
-
</div>
|
|
129
|
-
}
|
|
130
|
-
>
|
|
131
|
-
<a
|
|
132
|
-
data-kai-home-link
|
|
133
|
-
href={safeHref()}
|
|
134
|
-
target="_blank"
|
|
135
|
-
rel="noreferrer noopener"
|
|
136
|
-
class={cn(rowClass, 'transition-colors hover:bg-accent')}
|
|
137
|
-
>
|
|
138
|
-
{inner}
|
|
139
|
-
</a>
|
|
140
|
-
</Show>
|
|
141
|
-
}
|
|
142
|
-
>
|
|
143
|
-
<button
|
|
144
|
-
type="button"
|
|
145
|
-
data-kai-home-link
|
|
146
|
-
onClick={() => props.onLink?.(entry)}
|
|
147
|
-
class={cn(rowClass, 'w-full text-left transition-colors hover:bg-accent')}
|
|
148
|
-
>
|
|
149
|
-
{inner}
|
|
150
|
-
</button>
|
|
151
|
-
</Show>
|
|
152
|
-
);
|
|
153
|
-
}}
|
|
154
|
-
</For>
|
|
155
|
-
</div>
|
|
156
|
-
</Show>
|
|
157
|
-
</div>
|
|
158
|
-
);
|
|
159
|
-
}
|
package/src/components/image.tsx
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { type JSX, splitProps, createSignal, createEffect, onCleanup, Show } from 'solid-js';
|
|
2
|
-
import { cn } from '../utils/cn';
|
|
3
|
-
import { Skeleton } from '../ui/skeleton';
|
|
4
|
-
|
|
5
|
-
export interface GeneratedImageLike {
|
|
6
|
-
base64?: string;
|
|
7
|
-
uint8Array?: Uint8Array;
|
|
8
|
-
mediaType?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ImageProps extends GeneratedImageLike {
|
|
12
|
-
alt: string;
|
|
13
|
-
class?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function getImageSrc(base64?: string, mediaType?: string): string | undefined {
|
|
17
|
-
if (base64 && mediaType) {
|
|
18
|
-
return `data:${mediaType};base64,${base64}`;
|
|
19
|
-
}
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function Image(props: ImageProps) {
|
|
24
|
-
const [local, rest] = splitProps(props, ['base64', 'uint8Array', 'mediaType', 'class', 'alt']);
|
|
25
|
-
const [objectUrl, setObjectUrl] = createSignal<string | undefined>(undefined);
|
|
26
|
-
|
|
27
|
-
const mediaType = () => local.mediaType ?? 'image/png';
|
|
28
|
-
|
|
29
|
-
createEffect(() => {
|
|
30
|
-
const arr = local.uint8Array;
|
|
31
|
-
const mt = mediaType();
|
|
32
|
-
if (arr && mt) {
|
|
33
|
-
const blob = new Blob([arr as BlobPart], { type: mt });
|
|
34
|
-
const url = URL.createObjectURL(blob);
|
|
35
|
-
setObjectUrl(url);
|
|
36
|
-
onCleanup(() => URL.revokeObjectURL(url));
|
|
37
|
-
} else {
|
|
38
|
-
setObjectUrl(undefined);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const src = () => getImageSrc(local.base64, mediaType()) ?? objectUrl();
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<Show
|
|
46
|
-
when={src()}
|
|
47
|
-
fallback={
|
|
48
|
-
<Skeleton
|
|
49
|
-
aria-label={local.alt}
|
|
50
|
-
role="img"
|
|
51
|
-
class={cn('h-auto max-w-full overflow-hidden', local.class)}
|
|
52
|
-
/>
|
|
53
|
-
}
|
|
54
|
-
>
|
|
55
|
-
<img
|
|
56
|
-
src={src()}
|
|
57
|
-
alt={local.alt}
|
|
58
|
-
class={cn('h-auto max-w-full overflow-hidden rounded-md', local.class)}
|
|
59
|
-
role="img"
|
|
60
|
-
/>
|
|
61
|
-
</Show>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export { Image };
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type JSX,
|
|
3
|
-
splitProps,
|
|
4
|
-
createSignal,
|
|
5
|
-
createEffect,
|
|
6
|
-
createMemo,
|
|
7
|
-
on,
|
|
8
|
-
onMount,
|
|
9
|
-
onCleanup,
|
|
10
|
-
Show,
|
|
11
|
-
} from 'solid-js';
|
|
12
|
-
import { cn } from '../utils/cn';
|
|
13
|
-
import { Skeleton } from '../ui/skeleton';
|
|
14
|
-
import { Link as LinkIcon } from 'lucide-solid';
|
|
15
|
-
import type { CardEvent } from '../primitives/card-contract';
|
|
16
|
-
import {
|
|
17
|
-
type LinkPreviewData,
|
|
18
|
-
deriveDomain,
|
|
19
|
-
isRenderableLink,
|
|
20
|
-
hasLinkPreviewFetcher,
|
|
21
|
-
resolveLinkMetadata,
|
|
22
|
-
} from '../primitives/link-preview';
|
|
23
|
-
|
|
24
|
-
export interface LinkPreviewProps {
|
|
25
|
-
/** The card id correlating every emitted event. */
|
|
26
|
-
cardId: string;
|
|
27
|
-
/** The link payload (data-down). */
|
|
28
|
-
data: LinkPreviewData;
|
|
29
|
-
/** Emit a contract CardEvent up (host routes it). */
|
|
30
|
-
onEmit?: (event: CardEvent) => void;
|
|
31
|
-
/** Extra classes for the card root. */
|
|
32
|
-
class?: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** True when the payload already carries renderable metadata (the pure path). */
|
|
36
|
-
function hasMetadata(data: LinkPreviewData): boolean {
|
|
37
|
-
return Boolean(data.title || data.description || data.image);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* `LinkPreview` — a pure, themed, accessible rich link / OG preview. Renders from the
|
|
42
|
-
* supplied metadata; it never fetches the network itself. When the payload is a
|
|
43
|
-
* bare `{ url }` and an app has registered a `configureLinkPreview` fetcher, it
|
|
44
|
-
* shows a skeleton, calls the hook, merges the result, and renders. Activating the
|
|
45
|
-
* card (click / Enter / Space) emits the contract `open` verb (`target:'tab'`); the
|
|
46
|
-
* host policy performs the navigation so it can veto/redirect.
|
|
47
|
-
*/
|
|
48
|
-
export function LinkPreview(props: LinkPreviewProps): JSX.Element {
|
|
49
|
-
const [local] = splitProps(props, ['cardId', 'data', 'onEmit', 'class']);
|
|
50
|
-
|
|
51
|
-
const emit = (event: CardEvent) => local.onEmit?.(event);
|
|
52
|
-
|
|
53
|
-
// Bare-URL resolution state (only used when the payload lacks metadata + a fetcher exists).
|
|
54
|
-
const [fetched, setFetched] = createSignal<Partial<LinkPreviewData> | undefined>();
|
|
55
|
-
const [loading, setLoading] = createSignal(false);
|
|
56
|
-
const [imageBroken, setImageBroken] = createSignal(false);
|
|
57
|
-
|
|
58
|
-
const url = () => local.data.url;
|
|
59
|
-
const valid = createMemo(() => isRenderableLink(url()));
|
|
60
|
-
|
|
61
|
-
// The effective payload = supplied data merged with any fetched metadata.
|
|
62
|
-
const effective = createMemo<LinkPreviewData>(() => ({ ...local.data, ...fetched() }));
|
|
63
|
-
|
|
64
|
-
// Lifecycle `ready` once on mount.
|
|
65
|
-
onMount(() => emit({ kind: 'ready', cardId: local.cardId }));
|
|
66
|
-
|
|
67
|
-
// Invalid URL → emit a single `error` (belt-and-suspenders; host also rejects bad schemes on open).
|
|
68
|
-
createEffect(
|
|
69
|
-
on(valid, (ok) => {
|
|
70
|
-
if (!ok) emit({ kind: 'error', cardId: local.cardId, message: `Invalid link url: ${url()}` });
|
|
71
|
-
}),
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
// Bare-URL path: when there's no metadata AND a fetcher is configured, resolve once.
|
|
75
|
-
createEffect(
|
|
76
|
-
on(
|
|
77
|
-
() => [local.data, valid()] as const,
|
|
78
|
-
([data, ok]) => {
|
|
79
|
-
setImageBroken(false);
|
|
80
|
-
if (!ok || hasMetadata(data) || !hasLinkPreviewFetcher()) return;
|
|
81
|
-
let cancelled = false;
|
|
82
|
-
// Cancel a stale in-flight fetch if `data` changes before it resolves.
|
|
83
|
-
onCleanup(() => {
|
|
84
|
-
cancelled = true;
|
|
85
|
-
});
|
|
86
|
-
setLoading(true);
|
|
87
|
-
resolveLinkMetadata(data.url)
|
|
88
|
-
.then((meta) => {
|
|
89
|
-
if (!cancelled) setFetched(meta);
|
|
90
|
-
})
|
|
91
|
-
.catch(() => {
|
|
92
|
-
// Reject → fall back to the bare link chip; the URL itself is still usable.
|
|
93
|
-
if (!cancelled) setFetched({});
|
|
94
|
-
})
|
|
95
|
-
.finally(() => {
|
|
96
|
-
if (!cancelled) setLoading(false);
|
|
97
|
-
});
|
|
98
|
-
},
|
|
99
|
-
),
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
const domain = createMemo(() => effective().domain ?? deriveDomain(url()) ?? url());
|
|
103
|
-
const heading = createMemo(() => effective().siteName ?? domain());
|
|
104
|
-
const titleText = createMemo(() => effective().title ?? domain());
|
|
105
|
-
const showImage = createMemo(() => Boolean(effective().image) && !imageBroken());
|
|
106
|
-
|
|
107
|
-
const activate = () => {
|
|
108
|
-
if (!valid()) return;
|
|
109
|
-
emit({ kind: 'open', cardId: local.cardId, url: url(), target: 'tab' });
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const onClick = (e: MouseEvent) => {
|
|
113
|
-
// Intercept the anchor's default navigation so it routes through host policy.
|
|
114
|
-
// (Middle-click / cmd-click still open the real href in a new tab — acceptable + safe.)
|
|
115
|
-
e.preventDefault();
|
|
116
|
-
activate();
|
|
117
|
-
};
|
|
118
|
-
const onKeyDown = (e: KeyboardEvent) => {
|
|
119
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
120
|
-
e.preventDefault();
|
|
121
|
-
activate();
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
// --- Invalid-link error chip ------------------------------------------
|
|
126
|
-
return (
|
|
127
|
-
<Show
|
|
128
|
-
when={valid()}
|
|
129
|
-
fallback={
|
|
130
|
-
<div
|
|
131
|
-
role="img"
|
|
132
|
-
aria-label="Invalid link"
|
|
133
|
-
class={cn(
|
|
134
|
-
'flex items-center gap-2 rounded-xl border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive dark:border-red-400/50 dark:bg-destructive/20 dark:text-red-400',
|
|
135
|
-
local.class,
|
|
136
|
-
)}
|
|
137
|
-
>
|
|
138
|
-
<LinkIcon size={16} aria-hidden="true" />
|
|
139
|
-
<span class="truncate">Invalid link</span>
|
|
140
|
-
</div>
|
|
141
|
-
}
|
|
142
|
-
>
|
|
143
|
-
<a
|
|
144
|
-
href={url()}
|
|
145
|
-
rel="noopener noreferrer"
|
|
146
|
-
aria-label={`Open ${titleText()} on ${domain()}`}
|
|
147
|
-
class={cn(
|
|
148
|
-
'group block overflow-hidden rounded-xl border border-border bg-card text-card-foreground no-underline outline-none transition-shadow',
|
|
149
|
-
'cursor-pointer hover:shadow-md focus-visible:ring-2 focus-visible:ring-ring',
|
|
150
|
-
local.class,
|
|
151
|
-
)}
|
|
152
|
-
onClick={onClick}
|
|
153
|
-
onKeyDown={onKeyDown}
|
|
154
|
-
>
|
|
155
|
-
<Show when={loading()}>
|
|
156
|
-
{/* Skeleton while the bare-URL fetcher resolves. */}
|
|
157
|
-
<Skeleton class="aspect-[16/9] w-full rounded-none" />
|
|
158
|
-
<div class="space-y-2 p-3">
|
|
159
|
-
<Skeleton class="h-3 w-1/3" />
|
|
160
|
-
<Skeleton class="h-4 w-2/3" />
|
|
161
|
-
<Skeleton class="h-3 w-full" />
|
|
162
|
-
</div>
|
|
163
|
-
</Show>
|
|
164
|
-
<Show when={!loading()}>
|
|
165
|
-
<Show when={showImage()}>
|
|
166
|
-
<img
|
|
167
|
-
src={effective().image}
|
|
168
|
-
alt={effective().imageAlt ?? ''}
|
|
169
|
-
role="img"
|
|
170
|
-
class="aspect-[16/9] w-full object-cover"
|
|
171
|
-
onError={() => setImageBroken(true)}
|
|
172
|
-
/>
|
|
173
|
-
</Show>
|
|
174
|
-
<div class="space-y-1 p-3">
|
|
175
|
-
<div class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
176
|
-
<Show
|
|
177
|
-
when={effective().favicon}
|
|
178
|
-
fallback={<LinkIcon size={12} class="shrink-0 opacity-70" aria-hidden="true" />}
|
|
179
|
-
>
|
|
180
|
-
<img src={effective().favicon} alt="" class="h-3.5 w-3.5 shrink-0 rounded-sm" />
|
|
181
|
-
</Show>
|
|
182
|
-
<span class="truncate">{heading()}</span>
|
|
183
|
-
</div>
|
|
184
|
-
<div class="line-clamp-2 text-sm font-semibold text-foreground">{titleText()}</div>
|
|
185
|
-
<Show when={effective().description}>
|
|
186
|
-
<div class="line-clamp-3 text-xs text-muted-foreground">{effective().description}</div>
|
|
187
|
-
</Show>
|
|
188
|
-
</div>
|
|
189
|
-
</Show>
|
|
190
|
-
</a>
|
|
191
|
-
</Show>
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export type { LinkPreviewData } from '../primitives/link-preview';
|