Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script setup lang="ts">
import { ref } from "vue";

const expanded = ref(true);
const destroyOnHidden = ref(true);
</script>

<template>
<a-space direction="vertical" :size="16">
<a-space>
<a-button @click="expanded = !expanded">
{{ expanded ? "Collapse" : "Expand" }}
</a-button>
<a-switch
v-model:checked="destroyOnHidden"
checked-children="destroyOnHidden"
un-checked-children="keep"
/>
</a-space>
<ax-think
title="Deep Thinking"
:expanded="expanded"
:destroy-on-hidden="destroyOnHidden"
@expand="expanded = $event"
>
This content will be removed from DOM when collapsed and
destroyOnHidden is true.
</ax-think>
</a-space>
</template>

<docs lang="zh-CN">
通过外部按钮控制展开状态,并切换 `destroyOnHidden` 对折叠内容的处理方式。
</docs>

<docs lang="en-US">
Control the expanded state externally and switch how collapsed content is handled with `destroyOnHidden`.
</docs>
26 changes: 14 additions & 12 deletions packages/docs/src/pages/components/think/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,25 @@ Used to show deep thinking process.
<demo src="./demo/status.vue">Status</demo>
<demo src="./demo/expand.vue">Expand</demo>
<demo src="./demo/slot.vue">Slots</demo>
<demo src="./demo/destroy-on-hidden.vue">Destroy On Hidden</demo>

## API

### ThinkProps

| Property | Description | Type | Default | Version |
| ------------------ | ---------------------------- | ----------------------------------------------------- | ------- | ------- |
| classes | Semantic DOM class | [Record\<SemanticDOM, string\>](#semantic-dom) | - | - |
| styles | Semantic DOM style | [Record\<SemanticDOM, CSSProperties\>](#semantic-dom) | - | - |
| default | Content (default slot) | `VNodeChild` | - | - |
| title | Text of status | `VNodeChild` | - | - |
| icon | Show icon | `VNodeChild` | - | - |
| loading | Loading | `boolean \| VNodeChild` | `false` | - |
| defaultExpanded | Default Expand state | `boolean` | `true` | - |
| expanded (v-model) | Expand state | `boolean` | - | - |
| onExpand | Callback when expand changes | `(expand: boolean) => void` | - | - |
| blink | Blink mode | `boolean` | - | - |
| Property | Description | Type | Default | Version |
| ------------------ | -------------------------------------------------- | ----------------------------------------------------- | ------- | ------- |
| classes | Semantic DOM class | [Record\<SemanticDOM, string\>](#semantic-dom) | - | - |
| styles | Semantic DOM style | [Record\<SemanticDOM, CSSProperties\>](#semantic-dom) | - | - |
| default | Content (default slot) | `VNodeChild` | - | - |
| title | Text of status | `VNodeChild` | - | - |
| icon | Show icon | `VNodeChild` | - | - |
| loading | Loading | `boolean \| VNodeChild` | `false` | - |
| defaultExpanded | Default Expand state | `boolean` | `true` | - |
| expanded (v-model) | Expand state | `boolean` | - | - |
| onExpand | Callback when expand changes | `(expand: boolean) => void` | - | - |
| blink | Blink mode | `boolean` | - | - |
| destroyOnHidden | Whether to destroy the content node when collapsed | `boolean` | `true` | - |

### Think Slots

Expand Down
26 changes: 14 additions & 12 deletions packages/docs/src/pages/components/think/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,25 @@ description: 展示大模型深度思考过程。
<demo src="./demo/status.vue">设置状态</demo>
<demo src="./demo/expand.vue">是否展开</demo>
<demo src="./demo/slot.vue">插槽用法</demo>
<demo src="./demo/destroy-on-hidden.vue">折叠时销毁内容</demo>

## API

### ThinkProps

| 属性 | 说明 | 类型 | 默认值 | 版本 |
| ------------------ | ---------------- | --------------------------------------------------- | ------- | ---- |
| classes | 语义化结构类名 | [Record\<SemanticDOM, string\>](#语义化-dom) | - | - |
| styles | 语义化结构样式 | [Record\<SemanticDOM, CSSProperties\>](#语义化-dom) | - | - |
| default | 内容(默认插槽) | `VNodeChild` | - | - |
| title | 状态文本 | `VNodeChild` | - | - |
| icon | 状态图标 | `VNodeChild` | - | - |
| loading | 加载中 | `boolean \| VNodeChild` | `false` | - |
| defaultExpanded | 默认是否展开 | `boolean` | `true` | - |
| expanded (v-model) | 是否展开 | `boolean` | - | - |
| onExpand | 展开事件 | `(expand: boolean) => void` | - | - |
| blink | 闪动模式 | `boolean` | - | - |
| 属性 | 说明 | 类型 | 默认值 | 版本 |
| ------------------ | ---------------------- | --------------------------------------------------- | ------- | ---- |
| classes | 语义化结构类名 | [Record\<SemanticDOM, string\>](#语义化-dom) | - | - |
| styles | 语义化结构样式 | [Record\<SemanticDOM, CSSProperties\>](#语义化-dom) | - | - |
| default | 内容(默认插槽) | `VNodeChild` | - | - |
| title | 状态文本 | `VNodeChild` | - | - |
| icon | 状态图标 | `VNodeChild` | - | - |
| loading | 加载中 | `boolean \| VNodeChild` | `false` | - |
| defaultExpanded | 默认是否展开 | `boolean` | `true` | - |
| expanded (v-model) | 是否展开 | `boolean` | - | - |
| onExpand | 展开事件 | `(expand: boolean) => void` | - | - |
| blink | 闪动模式 | `boolean` | - | - |
| destroyOnHidden | 折叠时是否销毁内容节点 | `boolean` | `true` | - |

### Think 插槽

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script setup lang="ts">
import type { ThoughtChainProps } from "@antdv-next/x";

import { computed, onBeforeUnmount, ref } from "vue";

const destroyOnHidden = ref(false);
const seconds = ref(0);

const timer = setInterval(() => {
seconds.value += 1;
}, 1000);

onBeforeUnmount(() => clearInterval(timer));

const items = computed<ThoughtChainProps["items"]>(() => [
{
key: "keep_alive",
title: "Streaming Node",
description: "Collapse and expand to compare the two behaviors",
collapsible: true,
status: "loading",
destroyOnHidden: destroyOnHidden.value,
},
]);
</script>

<template>
<a-card :style="{ width: '500px' }">
<a-switch
v-model:checked="destroyOnHidden"
checked-children="destroyOnHidden: true"
un-checked-children="destroyOnHidden: false"
/>
<br />
<br />
<ax-thought-chain :default-expanded-keys="['keep_alive']" :items="items">
<template #content>
<a-flex gap="small" vertical>
<a-typography-text type="secondary">
Streaming for {{ seconds }}s.
</a-typography-text>
<a-input placeholder="Type something, then collapse" />
</a-flex>
</template>
</ax-thought-chain>
</a-card>
</template>

<docs lang="zh-CN">
节点的 `destroyOnHidden` 默认为 `true`,折叠时销毁内容节点。设为 `false` 时内容节点保留在 DOM 中,仅隐藏,可以保留流式输出与内部组件状态(例如上面输入框中已输入的内容)。
</docs>

<docs lang="en-US">
The node level `destroyOnHidden` defaults to `true`, which destroys the content node on collapse. Set it to `false` to keep the node mounted and merely hidden, preserving streaming output and inner component state (such as the text typed into the input above).
</docs>
24 changes: 13 additions & 11 deletions packages/docs/src/pages/components/thought-chain/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ description: The ThoughtChain component is used to visualize and track the call
<demo src="./demo/slot.vue">Slots</demo>
<demo src="./demo/nested.vue">Nested Usage</demo>
<demo src="./demo/single-row.vue">Single Row</demo>
<demo src="./demo/destroy-on-hidden.vue">Destroy On Hidden</demo>

## API

Expand Down Expand Up @@ -50,17 +51,18 @@ description: The ThoughtChain component is used to visualize and track the call

### ThoughtChainItemType

| Property | Description | Type | Default | Version |
| ----------- | ---------------------------------------------------- | ---------------------------------------------- | ----------- | ------- |
| content | Content of the thought node | `VNodeChild` | - | - |
| description | Description of the thought node | `VNodeChild` | - | - |
| footer | Footer of the thought node | `VNodeChild` | - | - |
| icon | Icon of the thought node, not displayed when `false` | `false \| VNodeChild` | DefaultIcon | - |
| key | Unique identifier for the thought node | `string` | - | - |
| status | Status of the thought node | `'loading' \| 'success' \| 'error' \| 'abort'` | - | - |
| title | Title of the thought node | `VNodeChild` | - | - |
| collapsible | Whether the thought node is collapsible | `boolean` | `false` | - |
| blink | Blink mode | `boolean` | - | - |
| Property | Description | Type | Default | Version |
| --------------- | ---------------------------------------------------- | ---------------------------------------------- | ----------- | ------- |
| content | Content of the thought node | `VNodeChild` | - | - |
| description | Description of the thought node | `VNodeChild` | - | - |
| footer | Footer of the thought node | `VNodeChild` | - | - |
| icon | Icon of the thought node, not displayed when `false` | `false \| VNodeChild` | DefaultIcon | - |
| key | Unique identifier for the thought node | `string` | - | - |
| status | Status of the thought node | `'loading' \| 'success' \| 'error' \| 'abort'` | - | - |
| title | Title of the thought node | `VNodeChild` | - | - |
| collapsible | Whether the thought node is collapsible | `boolean` | `false` | - |
| blink | Blink mode | `boolean` | - | - |
| destroyOnHidden | Whether to destroy the content node when collapsed | `boolean` | `true` | - |

### ThoughtChain.Item

Expand Down
24 changes: 13 additions & 11 deletions packages/docs/src/pages/components/thought-chain/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ description: 思维链组件用于可视化和追踪 Agent 对 Actions 和 Tools
<demo src="./demo/slot.vue">插槽自定义</demo>
<demo src="./demo/nested.vue">嵌套使用</demo>
<demo src="./demo/single-row.vue">单行折叠</demo>
<demo src="./demo/destroy-on-hidden.vue">折叠时销毁内容</demo>

## API

Expand Down Expand Up @@ -51,17 +52,18 @@ description: 思维链组件用于可视化和追踪 Agent 对 Actions 和 Tools

### ThoughtChainItemType

| 属性 | 说明 | 类型 | 默认值 | 版本 |
| ----------- | --------------------------------- | ---------------------------------------------- | ----------- | ---- |
| content | 思维节点内容 | `VNodeChild` | - | - |
| description | 思维节点描述 | `VNodeChild` | - | - |
| footer | 思维节点脚注 | `VNodeChild` | - | - |
| icon | 思维节点图标,为 `false` 时不展示 | `false \| VNodeChild` | DefaultIcon | - |
| key | 思维节点唯一标识符 | `string` | - | - |
| status | 思维节点状态 | `'loading' \| 'success' \| 'error' \| 'abort'` | - | - |
| title | 思维节点标题 | `VNodeChild` | - | - |
| collapsible | 思维节点是否可折叠 | `boolean` | `false` | - |
| blink | 闪动效果 | `boolean` | - | - |
| 属性 | 说明 | 类型 | 默认值 | 版本 |
| --------------- | --------------------------------- | ---------------------------------------------- | ----------- | ---- |
| content | 思维节点内容 | `VNodeChild` | - | - |
| description | 思维节点描述 | `VNodeChild` | - | - |
| footer | 思维节点脚注 | `VNodeChild` | - | - |
| icon | 思维节点图标,为 `false` 时不展示 | `false \| VNodeChild` | DefaultIcon | - |
| key | 思维节点唯一标识符 | `string` | - | - |
| status | 思维节点状态 | `'loading' \| 'success' \| 'error' \| 'abort'` | - | - |
| title | 思维节点标题 | `VNodeChild` | - | - |
| collapsible | 思维节点是否可折叠 | `boolean` | `false` | - |
| blink | 闪动效果 | `boolean` | - | - |
| destroyOnHidden | 折叠时是否销毁内容节点 | `boolean` | `true` | - |

### ThoughtChain.Item

Expand Down
53 changes: 36 additions & 17 deletions packages/x/components/think/Think.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
defineComponent,
ref,
useAttrs,
vShow,
watch,
withDirectives,
} from "vue";

import type { SemanticType, ThinkProps, ThinkRef } from "./interface";
Expand Down Expand Up @@ -69,6 +71,10 @@ export const XThink = defineComponent({
type: Boolean,
default: false,
},
destroyOnHidden: {
type: Boolean,
default: true,
},
},
emits: ["update:expanded", "expand"],
setup(props, { slots, emit, expose }) {
Expand Down Expand Up @@ -163,6 +169,32 @@ export const XThink = defineComponent({

const prefixCls = computed(() => props.prefixCls);

// Content is kept mounted and only toggled with `v-show` when
// `destroyOnHidden` is false, so streaming output and inner component
// state survive a collapse. Keep `vShow` attached in both modes so changing
// `destroyOnHidden` at runtime does not reset the directive lifecycle.
function renderContent() {
const node = (
<div ref={contentRef}>
<div
class={[
`${prefixCls.value}-content`,
contextConfig.value.classes?.content,
props.classes?.content,
]}
style={[
contextConfig.value.styles?.content,
props.styles?.content,
]}
>
{slots.default?.()}
</div>
</div>
);

return withDirectives(node, [[vShow, mergedExpanded.value]]);
}

expose<ThinkRef>({
get nativeElement() {
return rootRef.value as HTMLDivElement;
Expand Down Expand Up @@ -230,30 +262,17 @@ export const XThink = defineComponent({
{/* Collapsible content */}
<Transition
name={`${prefixCls.value}-collapse`}
persisted={!props.destroyOnHidden}
onBeforeEnter={onBeforeEnter}
onEnter={onEnter}
onAfterEnter={onAfterEnter}
onBeforeLeave={onBeforeLeave}
onLeave={onLeave}
onAfterLeave={onAfterLeave}
>
{mergedExpanded.value ? (
<div ref={contentRef}>
<div
class={[
`${prefixCls.value}-content`,
contextConfig.value.classes?.content,
props.classes?.content,
]}
style={[
contextConfig.value.styles?.content,
props.styles?.content,
]}
>
{slots.default?.()}
</div>
</div>
) : null}
{props.destroyOnHidden && !mergedExpanded.value
? null
: renderContent()}
</Transition>
</div>
);
Expand Down
Loading
Loading