mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-07-27 16:37:43 +00:00
Compare commits
13 Commits
v1.8.0-bet
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ffda3ddd5 | ||
|
|
a0b5702330 | ||
|
|
e6cf694a03 | ||
|
|
be7b38f97e | ||
|
|
dec4ebfa20 | ||
|
|
596d86f2ab | ||
|
|
b564c9e4aa | ||
|
|
b5abf31066 | ||
|
|
bf8df74864 | ||
|
|
a37e0487c6 | ||
|
|
329cd947e1 | ||
|
|
0e1986c819 | ||
|
|
d0a22315c0 |
21
CHANGELOG.md
21
CHANGELOG.md
@ -1,3 +1,24 @@
|
||||
# [1.8.0-beta.17](https://github.com/Tencent/tmagic-editor/compare/v1.8.0-beta.16...v1.8.0-beta.17) (2026-07-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** 修复 collectIdle 批次结算与中断时 Promise 挂起问题 ([b5abf31](https://github.com/Tencent/tmagic-editor/commit/b5abf310663f0bc34bd2c51c2e1a28de0bdf6ab9))
|
||||
* **editor:** 切换动作类型时清空关联配置字段 ([b564c9e](https://github.com/Tencent/tmagic-editor/commit/b564c9e4aacd215dd46c4b839cf0033ceedc8047))
|
||||
* **form,table:** groupList分界线、空状态、actions只存在一个 ([dec4ebf](https://github.com/Tencent/tmagic-editor/commit/dec4ebfa20483f699a676e41e0541d23ebe24d81))
|
||||
* **form:** 完善 mountFormInstance 清理逻辑,避免临时表单实例泄漏 ([bf8df74](https://github.com/Tencent/tmagic-editor/commit/bf8df74864b78891a8820462062624702a1d33d3))
|
||||
* **table:** 列操作点击后关闭popover ([596d86f](https://github.com/Tencent/tmagic-editor/commit/596d86f2ab08d3d4e6548b5e4bd5759d18e4493d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **editor,stage:** 新增 containerHighlightAddOnly 配置 ([e6cf694](https://github.com/Tencent/tmagic-editor/commit/e6cf694a032652e4f2c05efbab4a07a252e2ffa1))
|
||||
# [1.8.0-beta.16](https://github.com/Tencent/tmagic-editor/compare/v1.8.0-beta.15...v1.8.0-beta.16) (2026-07-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 参考建议可选值最多展示个数由 5 调整为 20 ([0e1986c](https://github.com/Tencent/tmagic-editor/commit/0e1986c81998e50461c294c1a27a8139e8ae9a13))
|
||||
# [1.8.0-beta.15](https://github.com/Tencent/tmagic-editor/compare/v1.8.0-beta.14...v1.8.0-beta.15) (2026-07-23)
|
||||
|
||||
|
||||
|
||||
@ -1019,6 +1019,18 @@ alt: 按住alt键启动识别
|
||||
|
||||
|
||||
- **类型:** `'default' | 'alt' | ''`
|
||||
|
||||
## containerHighlightAddOnly
|
||||
|
||||
- **详情:**
|
||||
|
||||
是否只有新增组件(从组件列表拖入新组件)时才启用识别容器
|
||||
|
||||
开启后,在画布中拖动已有组件时不再识别容器,即已有组件不能通过拖动加入其他容器;新增组件仍然按 [containerHighlightType](#containerHighlightType) 配置的方式识别
|
||||
|
||||
- **默认值:** `false`
|
||||
|
||||
- **类型:** `boolean`
|
||||
|
||||
## stageRect
|
||||
|
||||
|
||||
@ -69,10 +69,11 @@
|
||||
|
||||
## delayedMarkContainer
|
||||
|
||||
- **类型**:`(event: MouseEvent, excludeElList?: Element[]) => NodeJS.Timeout | undefined`
|
||||
- **类型**:`(event: MouseEvent, excludeElList?: Element[], isAdd?: boolean) => NodeJS.Timeout | undefined`
|
||||
- **参数**:
|
||||
- `event`:鼠标事件
|
||||
- `excludeElList`:计算鼠标所在容器时要排除的元素列表
|
||||
- `isAdd`:当前操作是否为新增组件(从组件列表拖入新组件),`containerHighlightType` 为 `addOnly` 时只有新增才会标记容器
|
||||
- **详情**:
|
||||
|
||||
鼠标拖拽着元素,在容器上方悬停,延迟一段时间后,对容器进行标记,如果悬停时间够长将标记成功,悬停时间短,调用方通过返回的timeoutId取消标记
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "tmagic",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/cli",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/core",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/data-source",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/dep",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/design",
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<component :is="uiComponent" :class="['tmagic-design-card', { 'tmagic-design-card--flat': isFlat }]" v-bind="uiProps">
|
||||
<component
|
||||
:is="uiComponent"
|
||||
:class="['tmagic-design-card', { 'tmagic-design-card--flat': isFlat, 'm-flat-hide-body': isHideBody }]"
|
||||
v-bind="uiProps"
|
||||
>
|
||||
<template #header v-if="$slots.header">
|
||||
<slot name="header" class="header"></slot>
|
||||
</template>
|
||||
@ -30,7 +34,7 @@ const uiComponent = ui?.component || 'el-card';
|
||||
// 当祖先 `<MEditor>` / `<MForm>` 的 theme 是 `magic-admin` 时,整套设计语言默认走「无卡片感」,
|
||||
// 因此这里自动等价于 `flat=true`;调用方仍可显式传 `flat` 强制开启。
|
||||
const isFlat = computed(() => !!props.flat || isGlobalFlat.value);
|
||||
|
||||
const isHideBody = computed(() => isFlat.value && props.bodyStyle?.display === 'none');
|
||||
// 把 `flat` 从转发给底层 UI 库(el-card / t-card 等)的 props 中剥离:
|
||||
// 它仅作用于本组件的视觉修饰类,不需要也不应该作为属性落到底层组件 / DOM 上。
|
||||
const uiProps = computed<CardProps>(() => {
|
||||
|
||||
@ -11,7 +11,11 @@
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
border-bottom: 0;
|
||||
|
||||
&.m-flat-hide-body {
|
||||
.el-card__header {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
&.m-fields-group-list-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@ -21,7 +25,7 @@
|
||||
|
||||
.el-card__header {
|
||||
border-bottom: none;
|
||||
padding: 16px;
|
||||
padding: 8px 16px;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
@ -29,11 +33,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.m-fields-group-list-footer {
|
||||
margin-bottom: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.el-card__body {
|
||||
padding: 0 16px 0 16px;
|
||||
// 这里每个form-item应该要有一个16px间距,但是除了tbody中的form-item
|
||||
.tmagic-design-form-item:not(tbody .tmagic-design-form-item) {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
> .m-container-row {
|
||||
overflow-x: hidden;
|
||||
@ -61,7 +69,7 @@
|
||||
}
|
||||
> .el-card__body {
|
||||
background-color: #fff;
|
||||
padding-top: 16px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/editor",
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
|
||||
@ -218,6 +218,7 @@ const stageOptions: StageOptions = {
|
||||
containerHighlightClassName: props.containerHighlightClassName,
|
||||
containerHighlightDuration: props.containerHighlightDuration,
|
||||
containerHighlightType: props.containerHighlightType,
|
||||
containerHighlightAddOnly: props.containerHighlightAddOnly,
|
||||
disabledDragStart: props.disabledDragStart,
|
||||
renderType: props.renderType,
|
||||
guidesOptions: props.guidesOptions,
|
||||
|
||||
@ -82,6 +82,11 @@ export interface EditorProps {
|
||||
containerHighlightDuration?: number;
|
||||
/** 拖入画布中容器时,识别容器的操作类型 */
|
||||
containerHighlightType?: ContainerHighlightType;
|
||||
/**
|
||||
* 是否仅在新增组件(从组件列表拖入新组件)时才启用识别容器,
|
||||
* 开启后在画布中拖动已有组件不会识别容器,默认 false
|
||||
*/
|
||||
containerHighlightAddOnly?: boolean;
|
||||
/** 画布大小 */
|
||||
stageRect?: StageRect;
|
||||
/** monaco editor 的配置 */
|
||||
@ -163,6 +168,7 @@ export const defaultEditorProps = {
|
||||
containerHighlightClassName: CONTAINER_HIGHLIGHT_CLASS_NAME,
|
||||
containerHighlightDuration: 800,
|
||||
containerHighlightType: ContainerHighlightType.DEFAULT,
|
||||
containerHighlightAddOnly: false,
|
||||
disabledShowSrc: false,
|
||||
disabledDataSource: false,
|
||||
disabledCodeBlock: false,
|
||||
|
||||
@ -37,13 +37,12 @@
|
||||
:model="entry.cardItem"
|
||||
:last-values="entry.lastCardItem"
|
||||
:is-compare="isCompareMode"
|
||||
:hide-expand="true"
|
||||
:hide-expand="false"
|
||||
:label-width="config.labelWidth || '100px'"
|
||||
@change="onChangeHandler"
|
||||
>
|
||||
<template #header>
|
||||
<div class="event-item-header">
|
||||
<div class="event-item-title">事件{{ Number(entry.index) + 1 }}</div>
|
||||
<MFormContainer
|
||||
class="fullWidth"
|
||||
:config="eventNameConfig"
|
||||
@ -210,6 +209,12 @@ const actionTypeConfig = computed(() => {
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
onChange: (_mForm: FormState, _v: string, { setModel }: any) => {
|
||||
setModel('to', '');
|
||||
setModel('method', '');
|
||||
setModel('codeId', '');
|
||||
setModel('dataSourceMethod', []);
|
||||
},
|
||||
};
|
||||
return { ...defaultActionTypeConfig, ...props.config.actionTypeConfig };
|
||||
});
|
||||
@ -222,7 +227,7 @@ const targetCompConfig = computed(() => {
|
||||
type: 'ui-select',
|
||||
labelPosition: 'left',
|
||||
display: (_mForm, { model }) => model.actionType === ActionType.COMP,
|
||||
onChange: (_MForm, _v, { setModel }) => {
|
||||
onChange: (_mForm, _v, { setModel }) => {
|
||||
setModel('method', '');
|
||||
},
|
||||
rules: [
|
||||
|
||||
@ -28,6 +28,7 @@ export const useStage = (stageOptions: StageOptions) => {
|
||||
containerHighlightClassName: stageOptions.containerHighlightClassName,
|
||||
containerHighlightDuration: stageOptions.containerHighlightDuration,
|
||||
containerHighlightType: stageOptions.containerHighlightType,
|
||||
containerHighlightAddOnly: stageOptions.containerHighlightAddOnly,
|
||||
disabledDragStart: stageOptions.disabledDragStart,
|
||||
renderType: stageOptions.renderType,
|
||||
canSelect: (el, event, stop) => {
|
||||
|
||||
@ -333,11 +333,11 @@ export const initServiceEvents = (
|
||||
Promise.all(
|
||||
nodes.map((node) => {
|
||||
if (node.type === NodeType.ROOT) {
|
||||
return Promise.resolve();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
return depService.collectIdle([node], { pageId: getPageIdByNode(node) }, deep, type);
|
||||
}),
|
||||
);
|
||||
).then((results) => results.every(Boolean));
|
||||
|
||||
watch(
|
||||
() => editorService.get('stage'),
|
||||
@ -351,7 +351,7 @@ export const initServiceEvents = (
|
||||
|
||||
if (!node) return;
|
||||
|
||||
await collectIdle([node], true, DepTargetType.DATA_SOURCE);
|
||||
if (!(await collectIdle([node], true, DepTargetType.DATA_SOURCE))) return;
|
||||
updateStageNode(node);
|
||||
});
|
||||
},
|
||||
@ -494,8 +494,10 @@ export const initServiceEvents = (
|
||||
|
||||
// 新增节点,收集依赖
|
||||
const nodeAddHandler = (nodes: MComponent[]) => {
|
||||
collectIdle(nodes, true).then(() => {
|
||||
updateStageNodes(nodes);
|
||||
collectIdle(nodes, true).then((completed) => {
|
||||
if (completed) {
|
||||
updateStageNodes(nodes);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -549,8 +551,8 @@ export const initServiceEvents = (
|
||||
if (needRecollectNodes.length) {
|
||||
// 有数据源依赖,需要等依赖重新收集完才更新stage
|
||||
const handler = async () => {
|
||||
await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE);
|
||||
await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE_COND);
|
||||
if (!(await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE))) return;
|
||||
if (!(await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE_COND))) return;
|
||||
updateStageNodes(needRecollectNodes);
|
||||
};
|
||||
handler();
|
||||
@ -572,8 +574,10 @@ export const initServiceEvents = (
|
||||
|
||||
// 历史记录变化时,需要重新收集依赖
|
||||
const historyChangeHandler = (page: MPage | MPageFragment) => {
|
||||
collectIdle([page], true).then(() => {
|
||||
updateStageNode(page);
|
||||
collectIdle([page], true).then((completed) => {
|
||||
if (completed) {
|
||||
updateStageNode(page);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -654,7 +658,7 @@ export const initServiceEvents = (
|
||||
if (Array.isArray(root?.items)) {
|
||||
depService.clearIdleTasks();
|
||||
|
||||
let collectIdlePromises: Promise<void[]>[] = [];
|
||||
let collectIdlePromises: Promise<boolean>[] = [];
|
||||
if (isModifyField) {
|
||||
depService.removeTarget(config.id, DepTargetType.DATA_SOURCE);
|
||||
depService.removeTarget(config.id, DepTargetType.DATA_SOURCE_COND);
|
||||
@ -679,10 +683,15 @@ export const initServiceEvents = (
|
||||
|
||||
collectIdlePromises = [collectIdle(root.items, true, DepTargetType.DATA_SOURCE_METHOD)];
|
||||
}
|
||||
Promise.all(collectIdlePromises)
|
||||
.then(() => updateDataSourceSchema())
|
||||
.then(() => updateDsData())
|
||||
.then(() => updateStageNodes(root.items));
|
||||
const handler = async () => {
|
||||
const results = await Promise.all(collectIdlePromises);
|
||||
if (!results.every(Boolean)) return;
|
||||
|
||||
updateDataSourceSchema();
|
||||
await updateDsData();
|
||||
updateStageNodes(root.items);
|
||||
};
|
||||
handler();
|
||||
}
|
||||
} else if (root?.dataSources) {
|
||||
updateDsData();
|
||||
@ -706,11 +715,12 @@ export const initServiceEvents = (
|
||||
const nodeIds = Object.keys(root.dataSourceDeps?.[id] || {});
|
||||
const nodes = getNodes(nodeIds, root.items);
|
||||
|
||||
await Promise.all([
|
||||
const results = await Promise.all([
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE),
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE_COND),
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE_METHOD),
|
||||
]);
|
||||
if (!results.every(Boolean)) return;
|
||||
|
||||
updateDataSourceSchema();
|
||||
|
||||
|
||||
@ -49,14 +49,13 @@ import { Document as DocumentIcon } from '@element-plus/icons-vue';
|
||||
|
||||
import { TMagicButton, tMagicMessage, TMagicScrollbar } from '@tmagic/design';
|
||||
import type { ContainerChangeEventData, FormConfig, FormState, FormValue } from '@tmagic/form';
|
||||
import { MForm } from '@tmagic/form';
|
||||
import { MForm, validateForm } from '@tmagic/form';
|
||||
import { filterXSS } from '@tmagic/utils';
|
||||
|
||||
import MIcon from '@editor/components/Icon.vue';
|
||||
import { ENABLE_PROPS_FORM_VALIDATE } from '@editor/editorProps';
|
||||
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import { validatePropsForm } from '@editor/utils/props';
|
||||
|
||||
import CodeEditor from '../CodeEditor.vue';
|
||||
|
||||
@ -162,14 +161,19 @@ const saveCode = async (values: any) => {
|
||||
// 做一次静默校验(不复用、也不污染页面上正在展示的表单),并将校验结果(错误信息)随提交
|
||||
// 一并抛给上层记录,使源码保存的错误状态与表单编辑保持一致。
|
||||
try {
|
||||
const error = await validatePropsForm({
|
||||
const error = await validateForm({
|
||||
config: props.config,
|
||||
values: newValues,
|
||||
appContext: internalInstance?.appContext ?? null,
|
||||
services,
|
||||
stage: stage.value,
|
||||
typeMatchValid: true,
|
||||
extendState: props.extendState,
|
||||
initValues: newValues,
|
||||
// 将当前组件实例的 provides(含 Editor 顶层的 services / codeOptions 等组件级 provide)
|
||||
// 合入 appContext,使临时 MForm 中的编辑器字段组件(DataSourceInput 等)能正常 inject
|
||||
appContext: internalInstance?.appContext ? { ...internalInstance?.appContext, provides: { services } } : null,
|
||||
extendState: (state) => {
|
||||
if (configFormRef.value?.formState) {
|
||||
return { ...(configFormRef.value?.formState || {}) };
|
||||
}
|
||||
return props.extendState?.(state) || {};
|
||||
},
|
||||
});
|
||||
|
||||
if (error) {
|
||||
|
||||
@ -145,6 +145,6 @@ const dragHandler = (e: DragEvent) => {
|
||||
|
||||
if (timeout || !stage.value) return;
|
||||
|
||||
timeout = stage.value.delayedMarkContainer(e);
|
||||
timeout = stage.value.delayedMarkContainer(e, [], true);
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -42,6 +42,21 @@ interface State {
|
||||
|
||||
type StateKey = keyof State;
|
||||
|
||||
/**
|
||||
* 一次 collectIdle 调用对应一个批次。批次自行统计入队/完成的任务数,在自身任务全部完成或被中断时
|
||||
* 结算对应的 Promise,避免多次快速触发时共用 idleTask 的 finish 事件造成的串扰、提前 resolve,
|
||||
* 以及 clearTasks 后 Promise 永不 resolve(collecting 卡死、监听器泄漏)。
|
||||
*/
|
||||
interface CollectBatch {
|
||||
nodes: MNode[];
|
||||
deep: boolean;
|
||||
pending: number;
|
||||
dsPending: number;
|
||||
collectedEmitted: boolean;
|
||||
dsSettled: boolean;
|
||||
resolve: (completed: boolean) => void;
|
||||
}
|
||||
|
||||
class Dep extends BaseService {
|
||||
private state = shallowReactive<State>({
|
||||
collecting: false,
|
||||
@ -54,6 +69,12 @@ class Dep extends BaseService {
|
||||
|
||||
private waitingWorker?: Promise<void>;
|
||||
|
||||
private resolveWaitingWorker?: () => void;
|
||||
|
||||
private workerGeneration = 0;
|
||||
|
||||
private activeBatches = new Set<CollectBatch>();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@ -137,38 +158,44 @@ class Dep extends BaseService {
|
||||
await this.waitingWorker;
|
||||
}
|
||||
|
||||
this.set('collecting', true);
|
||||
let startTask = false;
|
||||
this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
|
||||
startTask = true;
|
||||
const batch: CollectBatch = {
|
||||
nodes,
|
||||
deep,
|
||||
pending: 0,
|
||||
dsPending: 0,
|
||||
collectedEmitted: false,
|
||||
dsSettled: false,
|
||||
resolve: () => {},
|
||||
};
|
||||
|
||||
this.enqueueTask(node, target, depExtendedData, deep);
|
||||
this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
|
||||
this.enqueueTask(node, target, depExtendedData, deep, batch);
|
||||
});
|
||||
|
||||
return new Promise<void>((resolve) => {
|
||||
if (!startTask) {
|
||||
this.emit('collected', nodes, deep);
|
||||
this.set('collecting', false);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
this.idleTask.once('finish', () => {
|
||||
this.emit('collected', nodes, deep);
|
||||
this.set('collecting', false);
|
||||
});
|
||||
this.idleTask.once('hight-level-finish', () => {
|
||||
this.emit('ds-collected', nodes, deep);
|
||||
resolve();
|
||||
});
|
||||
// 没有命中任何 target,无需收集,直接完成
|
||||
if (batch.pending === 0) {
|
||||
this.emit('collected', nodes, deep);
|
||||
this.updateCollectingState();
|
||||
return true;
|
||||
}
|
||||
|
||||
this.activeBatches.add(batch);
|
||||
this.set('collecting', true);
|
||||
|
||||
return new Promise<boolean>((resolve) => {
|
||||
batch.resolve = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
public collectByWorker(dsl: MApp) {
|
||||
this.set('collecting', true);
|
||||
this.workerGeneration += 1;
|
||||
const generation = this.workerGeneration;
|
||||
|
||||
const { promise, resolve: waitingResolve } = Promise.withResolvers<void>();
|
||||
|
||||
this.waitingWorker = promise;
|
||||
this.resolveWaitingWorker = waitingResolve;
|
||||
|
||||
return new Promise<Record<string, Record<string, DepData>>>((resolve) => {
|
||||
const worker = new Work();
|
||||
@ -182,6 +209,11 @@ class Dep extends BaseService {
|
||||
resolve({});
|
||||
};
|
||||
}).then((depsData) => {
|
||||
if (generation !== this.workerGeneration) {
|
||||
waitingResolve();
|
||||
return depsData;
|
||||
}
|
||||
|
||||
traverseTarget(this.watcher.getTargetsList(), (target) => {
|
||||
if (depsData[target.type]?.[target.id]) {
|
||||
target.deps = reactive(depsData[target.type][target.id]);
|
||||
@ -200,6 +232,10 @@ class Dep extends BaseService {
|
||||
this.emit('collected', dsl.items, true);
|
||||
this.emit('ds-collected', dsl.items, true);
|
||||
waitingResolve();
|
||||
if (this.waitingWorker === promise) {
|
||||
this.waitingWorker = undefined;
|
||||
this.resolveWaitingWorker = undefined;
|
||||
}
|
||||
|
||||
return depsData;
|
||||
});
|
||||
@ -233,6 +269,7 @@ class Dep extends BaseService {
|
||||
}
|
||||
|
||||
public clearIdleTasks() {
|
||||
this.abortActiveBatches();
|
||||
this.idleTask.clearTasks();
|
||||
}
|
||||
|
||||
@ -251,6 +288,11 @@ class Dep extends BaseService {
|
||||
}
|
||||
|
||||
public reset() {
|
||||
this.abortActiveBatches();
|
||||
this.workerGeneration += 1;
|
||||
this.resolveWaitingWorker?.();
|
||||
this.resolveWaitingWorker = undefined;
|
||||
this.waitingWorker = undefined;
|
||||
this.idleTask.clearTasks();
|
||||
|
||||
for (const type of Object.keys(this.watcher.getTargetsList())) {
|
||||
@ -286,25 +328,99 @@ class Dep extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
private enqueueTask(node: MNode, target: Target, depExtendedData: DepExtendedData, deep: boolean) {
|
||||
private enqueueTask(
|
||||
node: MNode,
|
||||
target: Target,
|
||||
depExtendedData: DepExtendedData,
|
||||
deep: boolean,
|
||||
batch: CollectBatch,
|
||||
) {
|
||||
const isDataSource = target.type === DepTargetType.DATA_SOURCE;
|
||||
|
||||
batch.pending += 1;
|
||||
if (isDataSource) {
|
||||
batch.dsPending += 1;
|
||||
}
|
||||
|
||||
this.idleTask.enqueueTask(
|
||||
({ node, deep, target }) => {
|
||||
this.collectNode(node, target, depExtendedData, deep);
|
||||
try {
|
||||
this.collectNode(node, target, depExtendedData, deep);
|
||||
} finally {
|
||||
this.onBatchTaskDone(batch, isDataSource);
|
||||
}
|
||||
},
|
||||
{
|
||||
node,
|
||||
deep: false,
|
||||
target,
|
||||
},
|
||||
target.type === DepTargetType.DATA_SOURCE,
|
||||
isDataSource,
|
||||
);
|
||||
|
||||
if (deep && Array.isArray(node.items) && node.items.length) {
|
||||
node.items.forEach((item) => {
|
||||
this.enqueueTask(item, target, depExtendedData, deep);
|
||||
this.enqueueTask(item, target, depExtendedData, deep, batch);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onBatchTaskDone(batch: CollectBatch, isDataSource: boolean) {
|
||||
if (isDataSource) {
|
||||
batch.dsPending -= 1;
|
||||
// 数据源依赖收集完先 resolve,让 stage 尽快更新,其余依赖继续在后台收集
|
||||
if (batch.dsPending === 0) {
|
||||
this.settleBatchDs(batch);
|
||||
}
|
||||
}
|
||||
|
||||
batch.pending -= 1;
|
||||
if (batch.pending === 0) {
|
||||
this.finishBatch(batch);
|
||||
}
|
||||
}
|
||||
|
||||
private settleBatchDs(batch: CollectBatch) {
|
||||
if (batch.dsSettled) return;
|
||||
batch.dsSettled = true;
|
||||
this.emit('ds-collected', batch.nodes, batch.deep);
|
||||
batch.resolve(true);
|
||||
}
|
||||
|
||||
private finishBatch(batch: CollectBatch) {
|
||||
if (!batch.collectedEmitted) {
|
||||
batch.collectedEmitted = true;
|
||||
this.emit('collected', batch.nodes, batch.deep);
|
||||
}
|
||||
// 没有数据源任务的批次在此结算 Promise
|
||||
this.settleBatchDs(batch);
|
||||
this.activeBatches.delete(batch);
|
||||
this.updateCollectingState();
|
||||
}
|
||||
|
||||
/**
|
||||
* idleTask 被清空时,在途批次的任务不会再执行,必须主动结算,
|
||||
* 否则对应的 collectIdle Promise 永远不会 resolve(collecting 卡在 true、once 监听器泄漏)。
|
||||
* 收集被中断(通常紧跟一次全量重新收集),因此不再 emit collected/ds-collected,仅结算 Promise。
|
||||
*/
|
||||
private abortActiveBatches() {
|
||||
if (!this.activeBatches.size) {
|
||||
return;
|
||||
}
|
||||
|
||||
const batches = [...this.activeBatches];
|
||||
this.activeBatches.clear();
|
||||
|
||||
for (const batch of batches) {
|
||||
batch.resolve(false);
|
||||
}
|
||||
|
||||
this.updateCollectingState();
|
||||
}
|
||||
|
||||
private updateCollectingState() {
|
||||
this.set('collecting', this.activeBatches.size > 0);
|
||||
}
|
||||
}
|
||||
|
||||
export type DepService = Dep;
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
> .m-fields-group-list {
|
||||
> .tmagic-design-card--flat {
|
||||
> .el-card__header {
|
||||
padding: 16px 0;
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,7 +34,7 @@
|
||||
.create-button {
|
||||
&.fullWidth {
|
||||
width: 100%;
|
||||
margin: 0 0 16px 0;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
.m-fields-event-select {
|
||||
width: 100%;
|
||||
.fullWidth {
|
||||
width: 100%;
|
||||
width: calc(100% - 32px);
|
||||
box-sizing: border-box;
|
||||
&.create-button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.event-select-container {
|
||||
padding: 0 16px;
|
||||
@ -11,7 +14,7 @@
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
> .el-card__body {
|
||||
padding-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
.m-fields-group-list-footer {
|
||||
div {
|
||||
justify-content: flex-start !important;
|
||||
@ -19,7 +22,7 @@
|
||||
}
|
||||
.el-card.tmagic-design-card--flat {
|
||||
> .el-card__header {
|
||||
padding: 16px 0;
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -76,17 +79,18 @@
|
||||
.event-item-header {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.event-item-title {
|
||||
color: #0f1113;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.event-item-delete-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: #0f1113;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
|
||||
@ -178,6 +178,11 @@ export interface StageOptions {
|
||||
containerHighlightClassName?: string;
|
||||
containerHighlightDuration?: number;
|
||||
containerHighlightType?: ContainerHighlightType;
|
||||
/**
|
||||
* 是否仅在新增组件(从组件列表拖入新组件)时才启用识别容器,
|
||||
* 开启后在画布中拖动已有组件不会识别容器,默认 false
|
||||
*/
|
||||
containerHighlightAddOnly?: boolean;
|
||||
disabledDragStart?: boolean;
|
||||
render?: (stage: StageCore) => HTMLDivElement | void | Promise<HTMLDivElement | void>;
|
||||
moveableOptions?: CustomizeMoveableOptions;
|
||||
|
||||
@ -25,6 +25,12 @@ globalThis.requestIdleCallback =
|
||||
}, 1);
|
||||
};
|
||||
|
||||
globalThis.cancelIdleCallback =
|
||||
globalThis.cancelIdleCallback ||
|
||||
function (handle) {
|
||||
clearTimeout(handle as unknown as ReturnType<typeof setTimeout>);
|
||||
};
|
||||
|
||||
export class IdleTask<T = any> extends EventEmitter {
|
||||
private taskList: TaskList<T> = [];
|
||||
|
||||
|
||||
@ -16,9 +16,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { AppContext } from 'vue';
|
||||
|
||||
import {
|
||||
HookType,
|
||||
NODE_CONDS_KEY,
|
||||
@ -27,18 +24,7 @@ import {
|
||||
NODE_DISABLE_DATA_SOURCE_KEY,
|
||||
} from '@tmagic/core';
|
||||
import { tMagicMessage } from '@tmagic/design';
|
||||
import type {
|
||||
ChildConfig,
|
||||
DisplayCondsConfig,
|
||||
FormConfig,
|
||||
FormState,
|
||||
FormValue,
|
||||
TabConfig,
|
||||
TabPaneConfig,
|
||||
} from '@tmagic/form';
|
||||
import { validateForm } from '@tmagic/form';
|
||||
|
||||
import type { Services } from '@editor/type';
|
||||
import type { ChildConfig, DisplayCondsConfig, FormConfig, TabConfig, TabPaneConfig } from '@tmagic/form';
|
||||
|
||||
export const arrayOptions = [
|
||||
{ text: '包含', value: 'include' },
|
||||
@ -403,86 +389,3 @@ export const removeStyleDisplayConfig = (formConfig: FormConfig): FormConfig =>
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
// #region ValidatePropsFormOptions
|
||||
/**
|
||||
* validatePropsForm 参数
|
||||
*/
|
||||
export interface ValidatePropsFormOptions {
|
||||
/** 组件属性表单配置 */
|
||||
config: FormConfig;
|
||||
/** 待校验的表单值 */
|
||||
values: FormValue;
|
||||
/**
|
||||
* 当前组件实例的 appContext(通常为 `getCurrentInstance()?.appContext`)。
|
||||
* 会与 services 一并合入临时 MForm 的 appContext,使编辑器字段组件(DataSourceInput 等)能正常 inject。
|
||||
*/
|
||||
appContext?: AppContext | null;
|
||||
/** 编辑器服务集合,注入到临时表单的 formState */
|
||||
services?: Services;
|
||||
/** stage 实例,注入到临时表单的 formState */
|
||||
stage?: any;
|
||||
/** 外部扩展的 formState */
|
||||
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
||||
/**
|
||||
* 调试模式,默认 `true`:以弹层形式可见地渲染表单,点击「确定」才触发校验。
|
||||
* 置为 `false` 时静默挂载后自动校验。
|
||||
*/
|
||||
debug?: boolean;
|
||||
typeMatchValid?: boolean;
|
||||
}
|
||||
// #endregion ValidatePropsFormOptions
|
||||
|
||||
/**
|
||||
* 对一份「组件属性表单配置 + 值」做一次独立的校验,**不复用也不污染页面上正在展示的表单**。
|
||||
*
|
||||
* 内部基于 `@tmagic/form` 的 `validateForm` 另建一个独立的 MForm 实例完成校验,并统一处理
|
||||
* 编辑器场景所需的上下文注入:将当前组件实例的 provides 合入 appContext,并向 formState 注入
|
||||
* stage / services 及外部扩展状态,保证校验规则依赖的上下文可用。
|
||||
*
|
||||
* 常用于源码编辑器保存后,对最新配置做一次校验,并将校验结果(错误信息)随提交一并抛给上层记录,
|
||||
* 使源码保存的错误状态与表单编辑保持一致。
|
||||
*
|
||||
* @returns 校验通过返回空字符串 `''`,否则返回以 `<br>` 拼接的错误文案。
|
||||
* 仅在初始化超时或挂载失败等异常情况下才会 reject。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const error = await validatePropsForm({
|
||||
* config,
|
||||
* values,
|
||||
* appContext: getCurrentInstance()?.appContext,
|
||||
* services,
|
||||
* stage: editorService.get('stage'),
|
||||
* extendState,
|
||||
* });
|
||||
* if (error) {
|
||||
* // 配置不合法,error 为错误文案
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export const validatePropsForm = ({
|
||||
config,
|
||||
values,
|
||||
appContext = null,
|
||||
services,
|
||||
stage,
|
||||
extendState,
|
||||
debug,
|
||||
typeMatchValid,
|
||||
}: ValidatePropsFormOptions): Promise<string> =>
|
||||
validateForm({
|
||||
config,
|
||||
debug,
|
||||
typeMatchValid,
|
||||
initValues: values,
|
||||
// 将当前组件实例的 provides(含 Editor 顶层的 services / codeOptions 等组件级 provide)
|
||||
// 合入 appContext,使临时 MForm 中的编辑器字段组件(DataSourceInput 等)能正常 inject
|
||||
appContext: appContext ? { ...appContext, provides: { services } } : null,
|
||||
// 与页面表单保持一致:注入 stage/services 及外部扩展状态,保证校验规则依赖的上下文可用
|
||||
extendState: async (state) => ({
|
||||
...((await extendState?.(state)) || {}),
|
||||
stage,
|
||||
services,
|
||||
}),
|
||||
});
|
||||
|
||||
@ -58,7 +58,7 @@ const stringifyExampleValue = (value: any): string => {
|
||||
};
|
||||
|
||||
// 参考建议中最多展示的可选值个数,超出以「等」省略。
|
||||
const MAX_SUGGESTION_OPTIONS = 5;
|
||||
const MAX_SUGGESTION_OPTIONS = 20;
|
||||
|
||||
/**
|
||||
* 生成「请使用以下某一个值:xxx;xxx」形式的参考建议;无可选值时返回空字符串(不追加建议)。
|
||||
|
||||
@ -21,6 +21,7 @@ describe('defaultEditorProps', () => {
|
||||
test('containerHighlight 默认值', () => {
|
||||
expect(defaultEditorProps.containerHighlightDuration).toBe(800);
|
||||
expect(typeof defaultEditorProps.containerHighlightClassName).toBe('string');
|
||||
expect(defaultEditorProps.containerHighlightAddOnly).toBe(false);
|
||||
});
|
||||
|
||||
test('数组/对象工厂函数返回空值', () => {
|
||||
|
||||
@ -91,7 +91,7 @@ const mkServices = () => {
|
||||
clear: vi.fn(),
|
||||
clearTargets: vi.fn(),
|
||||
clearIdleTasks: vi.fn(),
|
||||
collectIdle: vi.fn(async () => undefined),
|
||||
collectIdle: vi.fn(async () => true),
|
||||
collectByWorker: vi.fn(async () => undefined),
|
||||
reset: vi.fn(),
|
||||
};
|
||||
|
||||
@ -135,6 +135,6 @@ describe('ComponentListPanel', () => {
|
||||
const item = wrapper.find('.component-item');
|
||||
await item.trigger('drag', { clientX: 0, clientY: 0 });
|
||||
await item.trigger('drag', { clientX: 0, clientY: 0 });
|
||||
expect(stage.delayedMarkContainer).toHaveBeenCalled();
|
||||
expect(stage.delayedMarkContainer).toHaveBeenCalledWith(expect.anything(), [], true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -13,16 +13,17 @@ vi.mock('@editor/utils/dep/worker.ts?worker&inline', () => ({
|
||||
default: class FakeWorker {
|
||||
public static nextData: Record<string, any> = {};
|
||||
public static nextError = false;
|
||||
public static nextDelay = 0;
|
||||
public onmessage: ((e: any) => void) | null = null;
|
||||
public onerror: (() => void) | null = null;
|
||||
public postMessage() {
|
||||
setTimeout(() => {
|
||||
if (FakeWorker.nextError) {
|
||||
this.onerror?.(new Event('error'));
|
||||
this.onerror?.();
|
||||
return;
|
||||
}
|
||||
this.onmessage?.({ data: FakeWorker.nextData });
|
||||
}, 0);
|
||||
}, FakeWorker.nextDelay);
|
||||
}
|
||||
},
|
||||
}));
|
||||
@ -121,7 +122,7 @@ describe('Dep service', () => {
|
||||
test('collectIdle - 没有命中时立即 resolve 并 emit collected', async () => {
|
||||
const fn = vi.fn();
|
||||
depService.on('collected', fn);
|
||||
await depService.collectIdle([{ id: 'n1', type: 'text' }] as any);
|
||||
await expect(depService.collectIdle([{ id: 'n1', type: 'text' }] as any)).resolves.toBe(true);
|
||||
expect(fn).toHaveBeenCalled();
|
||||
depService.off('collected', fn);
|
||||
});
|
||||
@ -219,6 +220,83 @@ describe('Dep service', () => {
|
||||
fakeWorker.nextData = {};
|
||||
});
|
||||
|
||||
test('collectIdle 命中 target 时最终 resolve 并按批次 emit collected/ds-collected', async () => {
|
||||
depService.addTarget(makeTarget('ds1', DepTargetType.DATA_SOURCE));
|
||||
const collected = vi.fn();
|
||||
const dsCollected = vi.fn();
|
||||
depService.on('collected', collected);
|
||||
depService.on('ds-collected', dsCollected);
|
||||
|
||||
const nodes = [{ id: 'n1', type: 'text' }] as any;
|
||||
await expect(depService.collectIdle(nodes, {}, false, DepTargetType.DATA_SOURCE)).resolves.toBe(true);
|
||||
|
||||
expect(dsCollected).toHaveBeenCalledWith(nodes, false);
|
||||
expect(collected).toHaveBeenCalledWith(nodes, false);
|
||||
expect(depService.get('collecting')).toBe(false);
|
||||
|
||||
depService.off('collected', collected);
|
||||
depService.off('ds-collected', dsCollected);
|
||||
});
|
||||
|
||||
test('clearIdleTasks 会结算在途 collectIdle,避免 Promise 永久挂起且 collecting 复位', async () => {
|
||||
depService.addTarget(makeTarget('ds1', DepTargetType.DATA_SOURCE));
|
||||
|
||||
const promise = depService.collectIdle([{ id: 'n1', type: 'text' }] as any, {}, false, DepTargetType.DATA_SOURCE);
|
||||
expect(depService.get('collecting')).toBe(true);
|
||||
|
||||
// 快速触发:任务尚未执行就清空队列,批次应被主动结算而不是永久挂起
|
||||
depService.clearIdleTasks();
|
||||
|
||||
await expect(promise).resolves.toBe(false);
|
||||
expect(depService.get('collecting')).toBe(false);
|
||||
});
|
||||
|
||||
test('reset 会结算在途 collectIdle', async () => {
|
||||
depService.addTarget(makeTarget('ds1', DepTargetType.DATA_SOURCE));
|
||||
|
||||
const promise = depService.collectIdle([{ id: 'n1', type: 'text' }] as any, {}, false, DepTargetType.DATA_SOURCE);
|
||||
depService.reset();
|
||||
|
||||
await expect(promise).resolves.toBe(false);
|
||||
expect(depService.get('collecting')).toBe(false);
|
||||
});
|
||||
|
||||
test('reset 会忽略在途 worker 的过期结果,避免覆盖新依赖', async () => {
|
||||
const fakeWorker = (await import('@editor/utils/dep/worker.ts?worker&inline')).default as any;
|
||||
fakeWorker.nextDelay = 20;
|
||||
fakeWorker.nextData = {
|
||||
[DepTargetType.DATA_SOURCE]: { ds1: { n1: { data: {} } } },
|
||||
};
|
||||
|
||||
const workerPromise = depService.collectByWorker({ items: [], id: 'app', type: 'app' } as any);
|
||||
depService.reset();
|
||||
|
||||
const target = makeTarget('ds1', DepTargetType.DATA_SOURCE);
|
||||
depService.addTarget(target);
|
||||
const idlePromise = depService.collectIdle(
|
||||
[{ id: 'n1', type: 'text' }] as any,
|
||||
{},
|
||||
false,
|
||||
DepTargetType.DATA_SOURCE,
|
||||
);
|
||||
|
||||
await Promise.all([workerPromise, idlePromise]);
|
||||
expect(target.deps.n1).toBeUndefined();
|
||||
|
||||
fakeWorker.nextDelay = 0;
|
||||
fakeWorker.nextData = {};
|
||||
});
|
||||
|
||||
test('多个批次并发时各自独立 resolve,全部完成后 collecting 复位', async () => {
|
||||
depService.addTarget(makeTarget('ds1', DepTargetType.DATA_SOURCE));
|
||||
|
||||
const p1 = depService.collectIdle([{ id: 'n1', type: 'text' }] as any, {}, false, DepTargetType.DATA_SOURCE);
|
||||
const p2 = depService.collectIdle([{ id: 'n2', type: 'text' }] as any, {}, false, DepTargetType.DATA_SOURCE);
|
||||
|
||||
await Promise.all([p1, p2]);
|
||||
expect(depService.get('collecting')).toBe(false);
|
||||
});
|
||||
|
||||
test('destroy 会 reset 并移除监听', () => {
|
||||
depService.addTarget(makeTarget('destroy-me'));
|
||||
expect(() => depService.destroy()).not.toThrow();
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
*
|
||||
* Copyright (C) 2025 Tencent.
|
||||
*/
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import { NODE_CONDS_RESULT_KEY } from '@tmagic/core';
|
||||
import { validateForm } from '@tmagic/form';
|
||||
|
||||
import {
|
||||
advancedTabConfig,
|
||||
@ -20,7 +19,6 @@ import {
|
||||
numberOptions,
|
||||
removeStyleDisplayConfig,
|
||||
styleTabConfig,
|
||||
validatePropsForm,
|
||||
} from '@editor/utils/props';
|
||||
|
||||
vi.mock('@tmagic/design', () => ({
|
||||
@ -172,59 +170,6 @@ describe('fillConfig', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('validatePropsForm', () => {
|
||||
beforeEach(() => {
|
||||
vi.mocked(validateForm).mockReset();
|
||||
});
|
||||
|
||||
test('合入 appContext.provides、注入 stage/services 并合并外部 extendState,debug 默认 undefined', async () => {
|
||||
vi.mocked(validateForm).mockResolvedValue('err-text');
|
||||
|
||||
const services = { uiService: {} } as any;
|
||||
const stage = { id: 'stage' };
|
||||
const appContext = { app: {}, provides: { foo: 1 } } as any;
|
||||
|
||||
const result = await validatePropsForm({
|
||||
config: [],
|
||||
values: { a: 1 },
|
||||
appContext,
|
||||
services,
|
||||
stage,
|
||||
extendState: async () => ({ extra: true }),
|
||||
});
|
||||
|
||||
// 直接返回 validateForm 的结果
|
||||
expect(result).toBe('err-text');
|
||||
|
||||
const arg = vi.mocked(validateForm).mock.calls[0][0];
|
||||
expect(arg.config).toEqual([]);
|
||||
expect(arg.debug).toBeUndefined();
|
||||
expect(arg.initValues).toEqual({ a: 1 });
|
||||
// appContext 保留原字段,但 provides 被替换为 { services }
|
||||
expect(arg.appContext).toEqual({ app: {}, provides: { services } });
|
||||
|
||||
// extendState 合并外部返回并注入 stage/services
|
||||
const state = await arg.extendState!({} as any);
|
||||
expect(state).toEqual({ extra: true, stage, services });
|
||||
});
|
||||
|
||||
test('appContext 缺省为 null,extendState 缺省时仍注入 stage/services,可覆盖 debug', async () => {
|
||||
vi.mocked(validateForm).mockResolvedValue('');
|
||||
|
||||
const services = {} as any;
|
||||
const stage = {};
|
||||
|
||||
await validatePropsForm({ config: [], values: {}, services, stage, debug: false });
|
||||
|
||||
const arg = vi.mocked(validateForm).mock.calls[0][0];
|
||||
expect(arg.appContext).toBeNull();
|
||||
expect(arg.debug).toBe(false);
|
||||
|
||||
const state = await arg.extendState!({} as any);
|
||||
expect(state).toEqual({ stage, services });
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeStyleDisplayConfig', () => {
|
||||
test('将 tab 内「样式」pane 的 display 置为 true', () => {
|
||||
const config = [
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/element-plus-adapter",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/form-schema",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/form",
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
|
||||
@ -261,6 +261,18 @@ const formState: FormState = reactive<FormState>({
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* formState 的内置 key 快照(keyProp / values / $emit / fields / post 等)。
|
||||
*
|
||||
* 在 `extendState` 首次合并前捕获,`applyExtendState` 会据此禁止 `extendState`
|
||||
* 覆盖这些已有字段(只能新增字段),避免表单核心状态被外部意外改写。
|
||||
*
|
||||
* 之所以在此处(effect 之外)捕获而不是在 `applyExtendState` 内动态取:
|
||||
* `watchEffect` 会在依赖变化时重跑,若动态取,`extendState` 自己新增的字段在第二次
|
||||
* 合并时也会被当成「已有 key」而拒绝刷新;这里只锁定内置字段即可规避该问题。
|
||||
*/
|
||||
const reservedStateKeys = new Set<string | symbol>(Reflect.ownKeys(formState));
|
||||
|
||||
/**
|
||||
* `extendState` 的同步段(直到第一个 `await` 之前)所访问的任何响应式数据,
|
||||
* 都会被 `watchEffect` 自动跟踪。这样可以兼容历史用法 ——
|
||||
@ -299,7 +311,7 @@ watchEffect(async (onCleanup) => {
|
||||
}
|
||||
if (stale) return;
|
||||
|
||||
applyExtendState(formState, state);
|
||||
applyExtendState(formState, state, reservedStateKeys);
|
||||
});
|
||||
|
||||
provide('mForm', formState);
|
||||
|
||||
@ -87,6 +87,11 @@ export interface SubmitFormOptions {
|
||||
*/
|
||||
debug?: boolean;
|
||||
typeMatchValid?: boolean;
|
||||
/**
|
||||
* 外部中断信号。abort 时会立即以 `signal.reason` reject 并卸载临时表单实例、移除容器。
|
||||
* 主要用于 `debug` 模式(无超时兜底)下取消一个被放弃的表单弹层,避免其无限驻留在页面上。
|
||||
*/
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
// #endregion SubmitFormOptions
|
||||
|
||||
@ -127,7 +132,7 @@ interface MountFormInstanceOptions<T> {
|
||||
formProps: Record<string, any>;
|
||||
/** 父级应用上下文,用于继承全局组件、指令、provide 等 */
|
||||
appContext?: AppContext | null;
|
||||
/** 等待表单初始化的最长时间(毫秒),<=0 表示不注册超时 */
|
||||
/** 等待表单初始化的最长时间(毫秒),<=0 时回退到默认超时以保证兜底清理生效 */
|
||||
timeout: number;
|
||||
/** 超时 reject 的错误文案 */
|
||||
timeoutMessage: string;
|
||||
@ -135,10 +140,15 @@ interface MountFormInstanceOptions<T> {
|
||||
hidden?: boolean;
|
||||
/** 是否跳过超时注册。调试模式等待人工操作,应传 `true` */
|
||||
skipTimeout?: boolean;
|
||||
/** 外部中断信号:abort 时会 reject 并卸载实例、移除容器,用于取消无超时(如 debug)的挂载 */
|
||||
signal?: AbortSignal;
|
||||
/** 构造 wrapper 组件 */
|
||||
createWrapper: FormWrapperFactory<T>;
|
||||
}
|
||||
|
||||
/** 未指定或传入非正数 timeout 时的兜底超时(毫秒),保证非 debug 挂载始终能被清理 */
|
||||
const DEFAULT_MOUNT_TIMEOUT = 10000;
|
||||
|
||||
/**
|
||||
* submitForm / validateForm 的公共脚手架:
|
||||
*
|
||||
@ -149,20 +159,36 @@ interface MountFormInstanceOptions<T> {
|
||||
* 容器创建、卸载、超时、上下文注入等模板代码在此统一收口。
|
||||
*/
|
||||
const mountFormInstance = <T>(options: MountFormInstanceOptions<T>): Promise<T> => {
|
||||
const { formProps, appContext, timeout, timeoutMessage, hidden = true, skipTimeout = false, createWrapper } = options;
|
||||
const {
|
||||
formProps,
|
||||
appContext,
|
||||
timeout,
|
||||
timeoutMessage,
|
||||
hidden = true,
|
||||
skipTimeout = false,
|
||||
signal,
|
||||
createWrapper,
|
||||
} = options;
|
||||
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
// 已中断则直接 reject,不创建任何容器/实例
|
||||
if (signal?.aborted) {
|
||||
reject(signal.reason ?? new Error('mountFormInstance aborted'));
|
||||
return;
|
||||
}
|
||||
|
||||
let cleaned = false;
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
let onAbort: (() => void) | null = null;
|
||||
// 用 holder 持有 app,使 cleanup 可在 app 创建之前定义(const app + 无 TDZ / 无 use-before-define)
|
||||
const instance: { app: ReturnType<typeof createApp> | null } = { app: null };
|
||||
|
||||
const container = document.createElement('div');
|
||||
if (hidden) {
|
||||
container.style.display = 'none';
|
||||
}
|
||||
document.body.appendChild(container);
|
||||
|
||||
let cleaned = false;
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
// 用 holder 持有 app,使 cleanup 可在 app 创建之前定义(const app + 无 TDZ / 无 use-before-define)
|
||||
const instance: { app: ReturnType<typeof createApp> | null } = { app: null };
|
||||
|
||||
const cleanup = () => {
|
||||
if (cleaned) return;
|
||||
cleaned = true;
|
||||
@ -170,6 +196,10 @@ const mountFormInstance = <T>(options: MountFormInstanceOptions<T>): Promise<T>
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
if (signal && onAbort) {
|
||||
signal.removeEventListener('abort', onAbort);
|
||||
onAbort = null;
|
||||
}
|
||||
try {
|
||||
instance.app?.unmount();
|
||||
} catch {
|
||||
@ -178,81 +208,101 @@ const mountFormInstance = <T>(options: MountFormInstanceOptions<T>): Promise<T>
|
||||
container.parentNode?.removeChild(container);
|
||||
};
|
||||
|
||||
const formRef = ref<any>(null);
|
||||
// 支持外部通过 AbortSignal 主动中断:debug 模式无超时兜底,若调用方放弃了该 Promise,
|
||||
// 可通过 abort 卸载实例、移除遮罩/容器,避免无限驻留在 DOM 中。
|
||||
if (signal) {
|
||||
onAbort = () => {
|
||||
if (cleaned) return;
|
||||
reject(signal.reason ?? new Error('mountFormInstance aborted'));
|
||||
cleanup();
|
||||
};
|
||||
signal.addEventListener('abort', onAbort);
|
||||
}
|
||||
|
||||
// 将 extendState 从 formProps 中剥离:不由 Form.vue 的 async watchEffect 异步应用,
|
||||
// 而是在 wrapper 中通过 sync watch 在 formRef 就绪后直接写入 formState,
|
||||
// 避免 display 等 filterFunction 在首次渲染时读到 undefined。
|
||||
// 与 CompareForm / FormPanel 中「formRef.value.formState.services = ...」的做法一致。
|
||||
const { extendState, ...restFormProps } = formProps;
|
||||
// 从容器创建到 mount 的全流程统一 try/catch:任一步骤(createWrapper/createApp/上下文合并/mount)
|
||||
// 抛错都会走到 cleanup,避免已插入 body 的 container 及未挂载的 app 残留导致泄漏。
|
||||
try {
|
||||
const formRef = ref<any>(null);
|
||||
|
||||
const userWrapper = createWrapper({ formRef, formProps: restFormProps, cleanup, resolve, reject });
|
||||
// 将 extendState 从 formProps 中剥离:不由 Form.vue 的 async watchEffect 异步应用,
|
||||
// 而是在 wrapper 中通过 sync watch 在 formRef 就绪后直接写入 formState,
|
||||
// 避免 display 等 filterFunction 在首次渲染时读到 undefined。
|
||||
// 与 CompareForm / FormPanel 中「formRef.value.formState.services = ...」的做法一致。
|
||||
const { extendState, ...restFormProps } = formProps;
|
||||
|
||||
const wrapperComponent =
|
||||
typeof extendState === 'function'
|
||||
const userWrapper = createWrapper({ formRef, formProps: restFormProps, cleanup, resolve, reject });
|
||||
|
||||
const wrapperComponent =
|
||||
typeof extendState === 'function'
|
||||
? defineComponent({
|
||||
name: 'MFormExtendStateInjector',
|
||||
setup() {
|
||||
watch(
|
||||
() => formRef.value,
|
||||
(form) => {
|
||||
if (!form) return;
|
||||
let result: any;
|
||||
try {
|
||||
result = extendState(form.formState);
|
||||
} catch (e) {
|
||||
console.error('[MForm] extendState failed:', e);
|
||||
return;
|
||||
}
|
||||
// formState 的内置 key 快照:在 extendState 合并前捕获,
|
||||
// 供 applyExtendState 禁止 extendState 覆盖这些已有字段(只能新增),
|
||||
// 与 Form.vue 中 reservedStateKeys 的语义保持一致。
|
||||
const reservedStateKeys = new Set<string | symbol>(Reflect.ownKeys(form.formState));
|
||||
// 合并逻辑收口在 applyExtendState:props 派生的只读 getter 字段
|
||||
// (keyProp 等)以普通字段形式返回时会被跳过并告警,避免 proxy set 抛错
|
||||
const apply = (state: Record<string, any> | null | undefined) =>
|
||||
applyExtendState(form.formState, state, reservedStateKeys);
|
||||
if (result && typeof result.then === 'function') {
|
||||
result.then(apply, (e: any) => console.error('[MForm] extendState failed:', e));
|
||||
} else {
|
||||
apply(result);
|
||||
}
|
||||
},
|
||||
{ flush: 'sync', immediate: true },
|
||||
);
|
||||
return () => h(userWrapper);
|
||||
},
|
||||
})
|
||||
: userWrapper;
|
||||
|
||||
// 静默(隐藏挂载)模式下注入静默标记:vs-code 等重型字段组件可据此跳过自身渲染,
|
||||
// 校验/取值依赖 FormItem 与 model 值,与叶子 UI 组件无关(见 FORM_SILENT_MODE_KEY 注释)。
|
||||
// 用组件级 provide 而非 app.provide:appContext 合并后 app._context.provides 与父级应用
|
||||
// 共享引用,app.provide 会把标记泄漏到父级应用。
|
||||
const rootComponent = hidden
|
||||
? defineComponent({
|
||||
name: 'MFormExtendStateInjector',
|
||||
name: 'MFormSilentProvider',
|
||||
setup() {
|
||||
watch(
|
||||
() => formRef.value,
|
||||
(form) => {
|
||||
if (!form) return;
|
||||
let result: any;
|
||||
try {
|
||||
result = extendState(form.formState);
|
||||
} catch (e) {
|
||||
console.error('[MForm] extendState failed:', e);
|
||||
return;
|
||||
}
|
||||
// 合并逻辑收口在 applyExtendState:props 派生的只读 getter 字段
|
||||
// (keyProp 等)以普通字段形式返回时会被跳过并告警,避免 proxy set 抛错
|
||||
const apply = (state: Record<string, any> | null | undefined) =>
|
||||
applyExtendState(form.formState, state);
|
||||
if (result && typeof result.then === 'function') {
|
||||
result.then(apply, (e: any) => console.error('[MForm] extendState failed:', e));
|
||||
} else {
|
||||
apply(result);
|
||||
}
|
||||
},
|
||||
{ flush: 'sync', immediate: true },
|
||||
);
|
||||
return () => h(userWrapper);
|
||||
provide(FORM_SILENT_MODE_KEY, true);
|
||||
return () => h(wrapperComponent);
|
||||
},
|
||||
})
|
||||
: userWrapper;
|
||||
: wrapperComponent;
|
||||
|
||||
// 静默(隐藏挂载)模式下注入静默标记:vs-code 等重型字段组件可据此跳过自身渲染,
|
||||
// 校验/取值依赖 FormItem 与 model 值,与叶子 UI 组件无关(见 FORM_SILENT_MODE_KEY 注释)。
|
||||
// 用组件级 provide 而非 app.provide:appContext 合并后 app._context.provides 与父级应用
|
||||
// 共享引用,app.provide 会把标记泄漏到父级应用。
|
||||
const rootComponent = hidden
|
||||
? defineComponent({
|
||||
name: 'MFormSilentProvider',
|
||||
setup() {
|
||||
provide(FORM_SILENT_MODE_KEY, true);
|
||||
return () => h(wrapperComponent);
|
||||
},
|
||||
})
|
||||
: wrapperComponent;
|
||||
const app = createApp(rootComponent);
|
||||
instance.app = app;
|
||||
|
||||
const app = createApp(rootComponent);
|
||||
instance.app = app;
|
||||
// 继承父级应用上下文(components / directives / provides / config 等)
|
||||
if (appContext) {
|
||||
Object.assign(app._context, appContext);
|
||||
}
|
||||
|
||||
// 继承父级应用上下文(components / directives / provides / config 等)
|
||||
if (appContext) {
|
||||
Object.assign(app._context, appContext);
|
||||
}
|
||||
// 非 debug(未跳过超时)场景始终注册超时兜底:timeout 为非正数时回退到默认值,
|
||||
// 避免表单永不初始化时实例/容器/watcher 无限驻留而泄漏。
|
||||
if (!skipTimeout) {
|
||||
const effectiveTimeout = timeout > 0 ? timeout : DEFAULT_MOUNT_TIMEOUT;
|
||||
timer = setTimeout(() => {
|
||||
if (!cleaned) {
|
||||
reject(new Error(timeoutMessage));
|
||||
cleanup();
|
||||
}
|
||||
}, effectiveTimeout);
|
||||
}
|
||||
|
||||
if (timeout > 0 && !skipTimeout) {
|
||||
timer = setTimeout(() => {
|
||||
if (!cleaned) {
|
||||
reject(new Error(timeoutMessage));
|
||||
cleanup();
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
try {
|
||||
app.mount(container);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
@ -450,12 +500,13 @@ const createDebugWrapper = (options: DebugWrapperOptions): Component => {
|
||||
* ```
|
||||
*/
|
||||
export const submitForm = (options: SubmitFormOptions): Promise<any> => {
|
||||
const { native, appContext, timeout = 10000, returnChangeRecords, debug = false, ...formProps } = options;
|
||||
const { native, appContext, timeout = 10000, returnChangeRecords, debug = false, signal, ...formProps } = options;
|
||||
|
||||
return mountFormInstance<any>({
|
||||
formProps,
|
||||
appContext,
|
||||
timeout,
|
||||
signal,
|
||||
// 调试模式需把表单展示出来;普通模式隐藏挂载
|
||||
hidden: !debug,
|
||||
// 调试模式等待人工操作,不应用超时
|
||||
@ -559,6 +610,11 @@ export interface ValidateFormOptions {
|
||||
*/
|
||||
debug?: boolean;
|
||||
typeMatchValid?: boolean;
|
||||
/**
|
||||
* 外部中断信号。abort 时会立即以 `signal.reason` reject 并卸载临时表单实例、移除容器。
|
||||
* 主要用于 `debug` 模式(无超时兜底)下取消一个被放弃的表单弹层,避免其无限驻留在页面上。
|
||||
*/
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
// #endregion ValidateFormOptions
|
||||
|
||||
@ -654,7 +710,7 @@ export const stripTabItemsLazy = (config: FormConfig): FormConfig => {
|
||||
* ```
|
||||
*/
|
||||
export const validateForm = (options: ValidateFormOptions): Promise<string> => {
|
||||
const { appContext, timeout = 10000, debug = false, config, ...rest } = options;
|
||||
const { appContext, timeout = 10000, debug = false, config, signal, ...rest } = options;
|
||||
|
||||
// 去掉 tab 容器各标签页的 lazy,确保懒加载标签页内的字段也参与校验
|
||||
const formProps = { ...rest, config: stripTabItemsLazy(config) };
|
||||
@ -663,6 +719,7 @@ export const validateForm = (options: ValidateFormOptions): Promise<string> => {
|
||||
formProps,
|
||||
appContext,
|
||||
timeout,
|
||||
signal,
|
||||
// 调试模式需把表单展示出来;普通模式隐藏挂载
|
||||
hidden: !debug,
|
||||
// 调试模式等待人工操作,不应用超时
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
.m-fields-group-list-item.tmagic-design-card--flat:last-child {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.el-button--text {
|
||||
padding: 0;
|
||||
margin-bottom: 7px;
|
||||
@ -32,9 +31,19 @@
|
||||
}
|
||||
|
||||
.m-fields-group-list-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/** 最外层的groupList需要每个item需要增加空白区域界限时,增加outer-gorup_list可以实现 */
|
||||
.m-container-group-list {
|
||||
&.outer-gorup_list {
|
||||
> .m-fields-group-list {
|
||||
> .m-fields-group-list-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,4 +92,15 @@
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.m-fields-group-list {
|
||||
.el-table__empty-block {
|
||||
.el-table__empty-text {
|
||||
width: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
margin-top: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,16 +449,27 @@ export const sortChange = (data: any[], { prop, order }: SortProp) => {
|
||||
* - accessor 描述符(`{ get stage() { return ... } }`)按原样 defineProperty,调用方
|
||||
* 可控制读时求值;强制 `configurable: true` 以便下一次合并可再 define。
|
||||
*
|
||||
* 注意:formState 上由 props 派生的字段(keyProp / popperClass / config / initValues /
|
||||
* isCompare / lastValues / parentValues)是只读 getter(无 setter),extendState 若以
|
||||
* 普通字段形式返回同名 key,直接赋值会让 proxy 的 set trap 失败并抛出
|
||||
* `TypeError: 'set' on proxy: trap returned falsish`,这里统一跳过并告警;
|
||||
* 如确需覆盖,可在 extendState 中以 get 访问器形式返回。
|
||||
* 注意:extendState 只能向 formState「新增」字段,不允许覆盖其已有 key。
|
||||
* 调用方可通过 `reservedKeys` 传入合并前已存在的内置 key 快照(keyProp / popperClass /
|
||||
* config / initValues / isCompare / lastValues / parentValues / values / $emit / fields /
|
||||
* post 等),命中这些 key 时统一跳过并告警。
|
||||
*
|
||||
* 兜底:未传 `reservedKeys` 时,仍会拦截 props 派生的只读 getter 字段(无 setter),
|
||||
* 否则以普通字段形式赋值会让 proxy 的 set trap 抛出
|
||||
* `TypeError: 'set' on proxy: trap returned falsish`。
|
||||
*/
|
||||
export const applyExtendState = (formState: FormState, state: Record<string, any> | null | undefined): void => {
|
||||
export const applyExtendState = (
|
||||
formState: FormState,
|
||||
state: Record<string, any> | null | undefined,
|
||||
reservedKeys?: Set<string | symbol>,
|
||||
): void => {
|
||||
if (!state) return;
|
||||
|
||||
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(state))) {
|
||||
if (reservedKeys?.has(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!('value' in descriptor)) {
|
||||
descriptor.configurable = true;
|
||||
Object.defineProperty(formState, key, descriptor);
|
||||
|
||||
@ -142,7 +142,7 @@ const stringifyExampleValue = (value: any): string => {
|
||||
};
|
||||
|
||||
// 参考建议中最多展示的可选值个数,超出以「等」省略。
|
||||
const MAX_SUGGESTION_OPTIONS = 5;
|
||||
const MAX_SUGGESTION_OPTIONS = 20;
|
||||
|
||||
/**
|
||||
* 生成「请使用以下某一个值:xxx;xxx」形式的参考建议;无可选值时返回空字符串(不追加建议)。
|
||||
|
||||
@ -189,9 +189,7 @@ describe('Form.vue —— extendState', () => {
|
||||
expect(v2).toMatch(/^stage-/);
|
||||
});
|
||||
|
||||
test('extendState 以普通字段返回 props 派生的只读字段时跳过并告警,不抛错', async () => {
|
||||
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
test('extendState 以普通字段返回内置保留字段时静默跳过,其余字段正常合并', async () => {
|
||||
const wrapper = mountForm({
|
||||
keyProp: 'id',
|
||||
extendState: () => ({ keyProp: 'custom', config: [], extra: 'ok' }),
|
||||
@ -201,18 +199,15 @@ describe('Form.vue —— extendState', () => {
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
|
||||
// 只读派生字段保持 props 值,未被覆盖
|
||||
// 内置保留字段(keyProp / config)未被 extendState 覆盖
|
||||
expect((wrapper.vm.formState as any).keyProp).toBe('id');
|
||||
expect(Array.isArray((wrapper.vm.formState as any).config)).toBe(true);
|
||||
// 其他字段正常合并
|
||||
// 非保留字段正常合并
|
||||
expect((wrapper.vm.formState as any).extra).toBe('ok');
|
||||
expect(warnSpy).toHaveBeenCalled();
|
||||
expect(wrapper.find('.m-form').exists()).toBe(true);
|
||||
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
test('extendState 以 get 访问器返回只读字段同名 key 时允许显式覆盖', async () => {
|
||||
test('extendState 以 get 访问器返回内置保留字段同名 key 时仍被拦截,无法覆盖', async () => {
|
||||
const wrapper = mountForm({
|
||||
keyProp: 'id',
|
||||
extendState: () =>
|
||||
@ -228,7 +223,8 @@ describe('Form.vue —— extendState', () => {
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect((wrapper.vm.formState as any).keyProp).toBe('custom-key');
|
||||
// keyProp 属于内置保留字段,即使以访问器形式返回也不允许覆盖
|
||||
expect((wrapper.vm.formState as any).keyProp).toBe('id');
|
||||
});
|
||||
|
||||
test('extendState 同步段读到的响应式数据变化时会重跑', async () => {
|
||||
|
||||
@ -90,9 +90,7 @@ describe('submitForm', () => {
|
||||
expect(extendState).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('extendState 返回 keyProp 等只读派生字段时不抛错且正常 resolve', async () => {
|
||||
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
test('extendState 返回 keyProp 等内置保留字段时静默跳过且正常 resolve', async () => {
|
||||
const values = await submitForm({
|
||||
config: [{ type: 'text', name: 'text', text: 'text' }],
|
||||
initValues: { text: 'foo' },
|
||||
@ -100,10 +98,8 @@ describe('submitForm', () => {
|
||||
appContext,
|
||||
});
|
||||
|
||||
// keyProp 属于内置保留字段,被静默跳过,不污染最终 values
|
||||
expect(values).toEqual({ text: 'foo' });
|
||||
expect(warnSpy).toHaveBeenCalled();
|
||||
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
test('在嵌套 items 配置下也能正确 resolve', async () => {
|
||||
|
||||
@ -16,9 +16,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
import type { FormState } from '@form/index';
|
||||
import {
|
||||
applyExtendState,
|
||||
createObjectProp,
|
||||
createValues,
|
||||
datetimeFormatter,
|
||||
@ -1014,3 +1015,130 @@ describe('createObjectProp', () => {
|
||||
expect(createObjectProp('a.b.c', 'newKey', 'c')).toBe('a.b.newKey');
|
||||
});
|
||||
});
|
||||
|
||||
describe('applyExtendState', () => {
|
||||
test('state 为 null 或 undefined 时不修改 formState', () => {
|
||||
const formState = { a: 1 } as any;
|
||||
|
||||
applyExtendState(formState, null);
|
||||
applyExtendState(formState, undefined);
|
||||
|
||||
expect(formState).toEqual({ a: 1 });
|
||||
});
|
||||
|
||||
test('普通字段(data descriptor)以新增字段形式合并进 formState', () => {
|
||||
const formState = {} as any;
|
||||
|
||||
applyExtendState(formState, { foo: 'bar', num: 1 });
|
||||
|
||||
expect(formState.foo).toBe('bar');
|
||||
expect(formState.num).toBe(1);
|
||||
});
|
||||
|
||||
test('accessor descriptor 按原样 define 且读时求值', () => {
|
||||
const formState = {} as any;
|
||||
let count = 0;
|
||||
const state = {};
|
||||
Object.defineProperty(state, 'stage', {
|
||||
get() {
|
||||
count += 1;
|
||||
return 'stageValue';
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
applyExtendState(formState, state);
|
||||
|
||||
// 读时才求值
|
||||
expect(count).toBe(0);
|
||||
expect(formState.stage).toBe('stageValue');
|
||||
expect(count).toBe(1);
|
||||
});
|
||||
|
||||
test('accessor descriptor 强制 configurable=true,可再次 define 不报错', () => {
|
||||
const formState = {} as any;
|
||||
const state = {};
|
||||
// 原始描述符 configurable 为 false
|
||||
Object.defineProperty(state, 'stage', {
|
||||
get: () => 'v',
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
});
|
||||
|
||||
applyExtendState(formState, state);
|
||||
|
||||
const descriptor = Object.getOwnPropertyDescriptor(formState, 'stage');
|
||||
expect(descriptor?.configurable).toBe(true);
|
||||
// 再次合并(重新 define)不应抛出
|
||||
expect(() => applyExtendState(formState, state)).not.toThrow();
|
||||
});
|
||||
|
||||
test('reservedKeys 命中的 key 被跳过,不覆盖已有内置字段', () => {
|
||||
const formState = { values: { origin: true } } as any;
|
||||
const reservedKeys = new Set<string | symbol>(['values']);
|
||||
|
||||
applyExtendState(formState, { values: { changed: true }, extra: 1 }, reservedKeys);
|
||||
|
||||
// reserved key 未被覆盖
|
||||
expect(formState.values).toEqual({ origin: true });
|
||||
// 非 reserved 的新字段正常新增
|
||||
expect(formState.extra).toBe(1);
|
||||
});
|
||||
|
||||
test('reservedKeys 对 accessor 形式的同名 key 同样跳过', () => {
|
||||
const formState = { keyProp: 'origin' } as any;
|
||||
const reservedKeys = new Set<string | symbol>(['keyProp']);
|
||||
const state = {};
|
||||
Object.defineProperty(state, 'keyProp', {
|
||||
get: () => 'override',
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
applyExtendState(formState, state, reservedKeys);
|
||||
|
||||
expect(formState.keyProp).toBe('origin');
|
||||
});
|
||||
|
||||
test('未传 reservedKeys 时,只读 getter 字段被跳过并告警', () => {
|
||||
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
const formState = {} as any;
|
||||
Object.defineProperty(formState, 'keyProp', {
|
||||
get: () => 'readonly',
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
applyExtendState(formState, { keyProp: 'newValue' });
|
||||
|
||||
expect(formState.keyProp).toBe('readonly');
|
||||
expect(warnSpy).toHaveBeenCalled();
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
test('未传 reservedKeys 时,存在 setter 的字段可被赋值', () => {
|
||||
let inner = 'old';
|
||||
const formState = {} as any;
|
||||
Object.defineProperty(formState, 'writable', {
|
||||
get: () => inner,
|
||||
set: (v: string) => {
|
||||
inner = v;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
applyExtendState(formState, { writable: 'new' });
|
||||
|
||||
expect(formState.writable).toBe('new');
|
||||
});
|
||||
|
||||
test('未传 reservedKeys 时,普通可写字段正常覆盖赋值', () => {
|
||||
const formState = { editable: 'old' } as any;
|
||||
|
||||
applyExtendState(formState, { editable: 'new' });
|
||||
|
||||
expect(formState.editable).toBe('new');
|
||||
});
|
||||
});
|
||||
|
||||
@ -196,13 +196,14 @@ describe('validateTypeMatch', () => {
|
||||
expect(validateTypeMatch(3, mForm, propsOf(config))).toBe('3 不在可选项中\n\n请使用以下某一个值:1;2');
|
||||
});
|
||||
|
||||
test('可选项超过 5 个时建议仅展示前 5 个并以「等」省略', () => {
|
||||
test('可选项超过 20 个时建议仅展示前 20 个并以「等」省略', () => {
|
||||
const values = Array.from({ length: 21 }, (_, i) => i + 1);
|
||||
const config = {
|
||||
type: 'select',
|
||||
options: [1, 2, 3, 4, 5, 6, 7].map((v) => ({ text: `${v}`, value: v })),
|
||||
options: values.map((v) => ({ text: `${v}`, value: v })),
|
||||
};
|
||||
expect(validateTypeMatch(99, mForm, propsOf(config))).toBe(
|
||||
'99 不在可选项中\n\n请使用以下某一个值:1;2;3;4;5 等',
|
||||
`99 不在可选项中\n\n请使用以下某一个值:${values.slice(0, 20).join(';')} 等`,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/schema",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/stage",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -84,6 +84,8 @@ export default class ActionManager extends EventEmitter {
|
||||
private containerHighlightDuration: number;
|
||||
/** 将组件加入容器的操作方式 */
|
||||
private containerHighlightType?: ContainerHighlightType;
|
||||
/** 是否仅在新增组件时才启用将组件加入容器 */
|
||||
private containerHighlightAddOnly = false;
|
||||
private isAltKeydown = false;
|
||||
private getTargetElement: GetTargetElement;
|
||||
private getElementsFromPoint: GetElementsFromPoint;
|
||||
@ -124,6 +126,7 @@ export default class ActionManager extends EventEmitter {
|
||||
this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS_NAME;
|
||||
this.containerHighlightDuration = config.containerHighlightDuration || defaultContainerHighlightDuration;
|
||||
this.containerHighlightType = config.containerHighlightType;
|
||||
this.containerHighlightAddOnly = config.containerHighlightAddOnly ?? false;
|
||||
this.disabledMultiSelect = config.disabledMultiSelect ?? false;
|
||||
this.alwaysMultiSelect = config.alwaysMultiSelect ?? false;
|
||||
this.getTargetElement = config.getTargetElement;
|
||||
@ -428,10 +431,15 @@ export default class ActionManager extends EventEmitter {
|
||||
* 标记的作用:1、高亮容器,给用户一个加入容器的交互感知;2、释放鼠标后,通过标记的标志找到要加入的容器
|
||||
* @param event 鼠标事件
|
||||
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
||||
* @param isAdd 当前操作是否为新增组件(从组件列表拖入),开启 containerHighlightAddOnly 时只有新增才会标记
|
||||
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
||||
*/
|
||||
public delayedMarkContainer(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout | undefined {
|
||||
if (this.canAddToContainer()) {
|
||||
public delayedMarkContainer(
|
||||
event: MouseEvent,
|
||||
excludeElList: Element[] = [],
|
||||
isAdd = false,
|
||||
): NodeJS.Timeout | undefined {
|
||||
if (this.canAddToContainer(isAdd)) {
|
||||
return globalThis.setTimeout(() => {
|
||||
this.addContainerHighlightClassName(event, excludeElList);
|
||||
}, this.containerHighlightDuration);
|
||||
@ -609,9 +617,13 @@ export default class ActionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前状态下能否将组件加入容器,默认是鼠标悬停一段时间加入,alt模式则是按住alt+鼠标悬停一段时间加入
|
||||
* 当前状态下能否将组件加入容器,默认是鼠标悬停一段时间加入,alt模式则是按住alt+鼠标悬停一段时间加入;
|
||||
* 开启containerHighlightAddOnly时,画布中拖动已有组件不能加入容器
|
||||
* @param isAdd 当前操作是否为新增组件
|
||||
*/
|
||||
private canAddToContainer(): boolean {
|
||||
private canAddToContainer(isAdd = false): boolean {
|
||||
if (this.containerHighlightAddOnly && !isAdd) return false;
|
||||
|
||||
return (
|
||||
this.containerHighlightType === ContainerHighlightType.DEFAULT ||
|
||||
(this.containerHighlightType === ContainerHighlightType.ALT && this.isAltKeydown)
|
||||
@ -624,10 +636,10 @@ export default class ActionManager extends EventEmitter {
|
||||
*/
|
||||
private markContainerEnd(): HTMLElement | null {
|
||||
const doc = this.getRenderDocument();
|
||||
if (doc && this.canAddToContainer()) {
|
||||
return removeClassNameByClassName(doc, this.containerHighlightClassName);
|
||||
}
|
||||
return null;
|
||||
if (!doc) return null;
|
||||
|
||||
const markedContainer = removeClassNameByClassName(doc, this.containerHighlightClassName);
|
||||
return this.canAddToContainer() ? markedContainer : null;
|
||||
}
|
||||
|
||||
private initMouseEvent(): void {
|
||||
|
||||
@ -263,10 +263,15 @@ export default class StageCore extends EventEmitter {
|
||||
* 标记的作用:1、高亮容器,给用户一个加入容器的交互感知;2、释放鼠标后,通过标记的标志找到要加入的容器
|
||||
* @param event 鼠标事件
|
||||
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
||||
* @param isAdd 当前操作是否为新增组件(从组件列表拖入),开启 containerHighlightAddOnly 时只有新增才会标记
|
||||
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
||||
*/
|
||||
public delayedMarkContainer(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout | undefined {
|
||||
return this.actionManager?.delayedMarkContainer(event, excludeElList);
|
||||
public delayedMarkContainer(
|
||||
event: MouseEvent,
|
||||
excludeElList: Element[] = [],
|
||||
isAdd = false,
|
||||
): NodeJS.Timeout | undefined {
|
||||
return this.actionManager?.delayedMarkContainer(event, excludeElList, isAdd);
|
||||
}
|
||||
|
||||
public getMoveableOption<K extends keyof MoveableOptions>(key: K): MoveableOptions[K] | undefined {
|
||||
@ -368,6 +373,7 @@ export default class StageCore extends EventEmitter {
|
||||
containerHighlightClassName: config.containerHighlightClassName,
|
||||
containerHighlightDuration: config.containerHighlightDuration,
|
||||
containerHighlightType: config.containerHighlightType,
|
||||
containerHighlightAddOnly: config.containerHighlightAddOnly,
|
||||
moveableOptions: config.moveableOptions,
|
||||
container: this.mask!.content,
|
||||
disabledDragStart: config.disabledDragStart,
|
||||
|
||||
@ -53,7 +53,11 @@ export type GetTargetElement = (id: Id) => HTMLElement | null;
|
||||
/** render提供的接口,通过坐标获得坐标下所有HTML元素数组 */
|
||||
export type GetElementsFromPoint = (point: Point) => HTMLElement[];
|
||||
export type GetRenderDocument = () => Document | undefined;
|
||||
export type DelayedMarkContainer = (event: MouseEvent, exclude: Element[]) => NodeJS.Timeout | undefined;
|
||||
export type DelayedMarkContainer = (
|
||||
event: MouseEvent,
|
||||
exclude?: Element[],
|
||||
isAdd?: boolean,
|
||||
) => NodeJS.Timeout | undefined;
|
||||
export type MarkContainerEnd = () => HTMLElement | null;
|
||||
export type GetRootContainer = () => HTMLDivElement | undefined;
|
||||
|
||||
@ -74,6 +78,11 @@ export interface StageCoreConfig {
|
||||
containerHighlightClassName?: string;
|
||||
containerHighlightDuration?: number;
|
||||
containerHighlightType?: ContainerHighlightType;
|
||||
/**
|
||||
* 是否仅在新增组件(从组件列表拖入新组件)时才启用将组件拖入容器,
|
||||
* 开启后在画布中拖动已有组件不会识别容器,默认 false
|
||||
*/
|
||||
containerHighlightAddOnly?: boolean;
|
||||
moveableOptions?: CustomizeMoveableOptions;
|
||||
/** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
|
||||
runtimeUrl?: string;
|
||||
@ -102,6 +111,8 @@ export interface ActionManagerConfig {
|
||||
containerHighlightClassName?: string;
|
||||
containerHighlightDuration?: number;
|
||||
containerHighlightType?: ContainerHighlightType;
|
||||
/** 见 StageCoreConfig.containerHighlightAddOnly */
|
||||
containerHighlightAddOnly?: boolean;
|
||||
moveableOptions?: CustomizeMoveableOptions;
|
||||
disabledDragStart?: boolean;
|
||||
disabledMultiSelect?: boolean;
|
||||
|
||||
@ -275,6 +275,84 @@ describe('ActionManager - 交互与事件', () => {
|
||||
expect(containerEl.classList.contains('tmagic-stage-container-highlight')).toBe(true);
|
||||
});
|
||||
|
||||
test('delayedMarkContainer 未配置 containerHighlightType 时不标记容器', () => {
|
||||
am = new ActionManager(createConfig({ isContainer: async () => true }));
|
||||
expect(am.delayedMarkContainer(mouseAtOrigin())).toBeUndefined();
|
||||
});
|
||||
|
||||
test('delayedMarkContainer alt 模式下需按住 alt 才标记容器', () => {
|
||||
am = new ActionManager(
|
||||
createConfig({
|
||||
containerHighlightType: ContainerHighlightType.ALT,
|
||||
isContainer: async () => true,
|
||||
}),
|
||||
);
|
||||
expect(am.delayedMarkContainer(mouseAtOrigin())).toBeUndefined();
|
||||
(am as any).isAltKeydown = true;
|
||||
expect(am.delayedMarkContainer(mouseAtOrigin())).toBeDefined();
|
||||
});
|
||||
|
||||
test('containerHighlightAddOnly 开启时拖动已有组件不标记容器', () => {
|
||||
const containerEl = globalThis.document.createElement('div');
|
||||
containerEl.dataset.tmagicId = 'container_1';
|
||||
am = new ActionManager(
|
||||
createConfig({
|
||||
containerHighlightType: ContainerHighlightType.DEFAULT,
|
||||
containerHighlightAddOnly: true,
|
||||
getElementsFromPoint: () => [containerEl],
|
||||
isContainer: async () => true,
|
||||
}),
|
||||
);
|
||||
expect(am.delayedMarkContainer(mouseAtOrigin(), [globalThis.document.createElement('div')])).toBeUndefined();
|
||||
vi.advanceTimersByTime(900);
|
||||
expect(containerEl.classList.contains('tmagic-stage-container-highlight')).toBe(false);
|
||||
});
|
||||
|
||||
test('containerHighlightAddOnly 开启时新增组件仍按 containerHighlightType 标记容器', async () => {
|
||||
const containerEl = globalThis.document.createElement('div');
|
||||
containerEl.dataset.tmagicId = 'container_1';
|
||||
am = new ActionManager(
|
||||
createConfig({
|
||||
containerHighlightType: ContainerHighlightType.DEFAULT,
|
||||
containerHighlightAddOnly: true,
|
||||
getElementsFromPoint: () => [containerEl],
|
||||
isContainer: async () => true,
|
||||
}),
|
||||
);
|
||||
expect(am.delayedMarkContainer(mouseAtOrigin(), [], true)).toBeDefined();
|
||||
vi.advanceTimersByTime(900);
|
||||
await Promise.resolve();
|
||||
expect(containerEl.classList.contains('tmagic-stage-container-highlight')).toBe(true);
|
||||
});
|
||||
|
||||
test('containerHighlightAddOnly 开启且 containerHighlightType 为 alt 时新增组件也需按住 alt', () => {
|
||||
am = new ActionManager(
|
||||
createConfig({
|
||||
containerHighlightType: ContainerHighlightType.ALT,
|
||||
containerHighlightAddOnly: true,
|
||||
isContainer: async () => true,
|
||||
}),
|
||||
);
|
||||
expect(am.delayedMarkContainer(mouseAtOrigin(), [], true)).toBeUndefined();
|
||||
(am as any).isAltKeydown = true;
|
||||
expect(am.delayedMarkContainer(mouseAtOrigin(), [], true)).toBeDefined();
|
||||
});
|
||||
|
||||
test('containerHighlightAddOnly 开启时结束标记仍清理高亮但不返回容器', () => {
|
||||
const containerEl = globalThis.document.createElement('div');
|
||||
containerEl.classList.add('tmagic-stage-container-highlight');
|
||||
globalThis.document.body.appendChild(containerEl);
|
||||
am = new ActionManager(
|
||||
createConfig({
|
||||
containerHighlightType: ContainerHighlightType.DEFAULT,
|
||||
containerHighlightAddOnly: true,
|
||||
}),
|
||||
);
|
||||
|
||||
expect((am as any).markContainerEnd()).toBeNull();
|
||||
expect(containerEl.classList.contains('tmagic-stage-container-highlight')).toBe(false);
|
||||
});
|
||||
|
||||
test('updateMoveableOptions / getDragStatus 可调用', () => {
|
||||
am = new ActionManager(createConfig());
|
||||
expect(() => am.updateMoveableOptions()).not.toThrow();
|
||||
|
||||
@ -181,6 +181,16 @@ describe('StageCore', () => {
|
||||
stage.destroy();
|
||||
});
|
||||
|
||||
test('delayedMarkContainer 将新增标识透传给 actionManager', async () => {
|
||||
const { host, stage } = createStage();
|
||||
await stage.mount(host);
|
||||
const spy = vi.spyOn(stage.actionManager!, 'delayedMarkContainer');
|
||||
const event = mouseAtOrigin();
|
||||
stage.delayedMarkContainer(event, [], true);
|
||||
expect(spy).toHaveBeenCalledWith(event, [], true);
|
||||
stage.destroy();
|
||||
});
|
||||
|
||||
test('autoScrollIntoView 选中时调用 mask.observerIntersection', async () => {
|
||||
const host = globalThis.document.createElement('div');
|
||||
globalThis.document.body.appendChild(host);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/table",
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
:width="action.subActionConfig?.popoverWidth"
|
||||
:popper-class="action.subActionConfig?.popoverClass"
|
||||
:destroy-on-close="action.subActionConfig?.popoverDestroyOnClose ?? true"
|
||||
@clickoutside="popoverVisible = false"
|
||||
>
|
||||
<template #reference>
|
||||
<TMagicButton
|
||||
@ -84,8 +85,15 @@
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
// 所有行共享:同一时间仅允许一个 sub-actions 气泡展开,激活新的会自动关闭上一个
|
||||
const activePopoverId = ref<symbol | null>(null);
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch } from 'vue';
|
||||
import { ArrowDown, ArrowRight } from '@element-plus/icons-vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
@ -117,7 +125,23 @@ const props = withDefaults(
|
||||
},
|
||||
);
|
||||
|
||||
const popoverId = Symbol('sub-actions-popover');
|
||||
const popoverVisible = ref(false);
|
||||
|
||||
watch(popoverVisible, (visible) => {
|
||||
if (visible) {
|
||||
activePopoverId.value = popoverId;
|
||||
} else if (activePopoverId.value === popoverId) {
|
||||
activePopoverId.value = null;
|
||||
}
|
||||
});
|
||||
|
||||
watch(activePopoverId, (id) => {
|
||||
if (id !== popoverId && popoverVisible.value) {
|
||||
popoverVisible.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
const togglePopover = () => {
|
||||
popoverVisible.value = !popoverVisible.value;
|
||||
};
|
||||
@ -134,7 +158,8 @@ const actionHandler = async (action: ColumnActionConfig, row: any, index: number
|
||||
} else {
|
||||
await action.handler?.(row, index);
|
||||
}
|
||||
action.after?.(row, index);
|
||||
await action.after?.(row, index);
|
||||
popoverVisible.value = false;
|
||||
};
|
||||
|
||||
const save = async (index: number, config: ColumnConfig) => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/tdesign-vue-next-adapter",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"name": "@tmagic/utils",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tmagic-playground",
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@ -12,11 +12,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@tmagic/core": "1.8.0-beta.15",
|
||||
"@tmagic/design": "1.8.0-beta.15",
|
||||
"@tmagic/editor": "1.8.0-beta.15",
|
||||
"@tmagic/element-plus-adapter": "1.8.0-beta.15",
|
||||
"@tmagic/tdesign-vue-next-adapter": "1.8.0-beta.15",
|
||||
"@tmagic/core": "1.8.0-beta.17",
|
||||
"@tmagic/design": "1.8.0-beta.17",
|
||||
"@tmagic/editor": "1.8.0-beta.17",
|
||||
"@tmagic/element-plus-adapter": "1.8.0-beta.17",
|
||||
"@tmagic/tdesign-vue-next-adapter": "1.8.0-beta.17",
|
||||
"@tmagic/tmagic-form-runtime": "1.1.3",
|
||||
"element-plus": "^2.14.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
|
||||
228
pnpm-lock.yaml
generated
228
pnpm-lock.yaml
generated
@ -564,23 +564,23 @@ importers:
|
||||
specifier: ^2.3.2
|
||||
version: 2.3.2(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/core':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(typescript@6.0.3)
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/design':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/editor':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/element-plus-adapter':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/tdesign-vue-next-adapter':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(tdesign-vue-next@1.17.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(tdesign-vue-next@1.17.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/tmagic-form-runtime':
|
||||
specifier: 1.1.3
|
||||
version: 1.1.3(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/editor@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
version: 1.1.3(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/editor@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
element-plus:
|
||||
specifier: ^2.14.3
|
||||
version: 2.14.3(vue@3.5.40(typescript@6.0.3))
|
||||
@ -920,14 +920,14 @@ importers:
|
||||
runtime/react:
|
||||
dependencies:
|
||||
'@tmagic/core':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(typescript@6.0.3)
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/react-runtime-help':
|
||||
specifier: 0.2.2
|
||||
version: 0.2.2(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(lodash-es@4.18.1)(react@18.3.1)(typescript@6.0.3)
|
||||
version: 0.2.2(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(lodash-es@4.18.1)(react@18.3.1)(typescript@6.0.3)
|
||||
'@tmagic/stage':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
axios:
|
||||
specifier: ^1.13.2
|
||||
version: 1.13.2
|
||||
@ -942,8 +942,8 @@ importers:
|
||||
version: 18.3.1(react@18.3.1)
|
||||
devDependencies:
|
||||
'@tmagic/cli':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(typescript@6.0.3)
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@types/fs-extra':
|
||||
specifier: ^11.0.4
|
||||
version: 11.0.4
|
||||
@ -1018,14 +1018,14 @@ importers:
|
||||
runtime/vue:
|
||||
dependencies:
|
||||
'@tmagic/core':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(typescript@6.0.3)
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/stage':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/vue-runtime-help':
|
||||
specifier: ^2.0.4
|
||||
version: 2.0.4(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
version: 2.0.4(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
axios:
|
||||
specifier: ^1.13.2
|
||||
version: 1.13.2
|
||||
@ -1034,8 +1034,8 @@ importers:
|
||||
version: 3.5.40(typescript@6.0.3)
|
||||
devDependencies:
|
||||
'@tmagic/cli':
|
||||
specifier: 1.8.0-beta.15
|
||||
version: 1.8.0-beta.15(typescript@6.0.3)
|
||||
specifier: 1.8.0-beta.17
|
||||
version: 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@types/fs-extra':
|
||||
specifier: ^11.0.4
|
||||
version: 11.0.4
|
||||
@ -2997,8 +2997,8 @@ packages:
|
||||
'@sxzz/popperjs-es@2.11.8':
|
||||
resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==}
|
||||
|
||||
'@tmagic/cli@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-SXheOCY5pcl+UbJmsoeOIcNkHVvfrwd2/Tp3wlm8n4HuBF13kElbhaBaT79fvkH7govXaO3LyIIGnh+DG+6jBg==}
|
||||
'@tmagic/cli@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-M2HORy79DarjNTaB08huag0TIhkD0vTctZEltH/YrPrenCvv5izD3PQK3/QacnDZqgXC7TFepw0fZvHcUnlwPw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@ -3025,8 +3025,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/core@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-nN5C1/tVyV9vOb9BTQvdVpM2UmQOBw6Xjrzj7NFusPyC8HCKgYAdWqoIciODPqoM9V6uPGuM450Y5E6zXsm1bA==}
|
||||
'@tmagic/core@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-VmtY2lM5eMYwjXUaUh+r1cFVq075rKuXeo5sPOfUKVaGeIhEYO5L7X4IEEv21TcAD91vUabbZUKVwYN4SVO7Cw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
typescript: ^6.0.3
|
||||
@ -3054,11 +3054,11 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/data-source@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-2Me1wbdyd7+Vo7EUKYnKu36mGSBcdK5GwMpuRm6RX+3NEgxW/tg+PHdSnxhyXe57eyjeQsBE6PNjkuYWc36knQ==}
|
||||
'@tmagic/data-source@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-Gw+VrNF4WgHe+H5pgzFjpeoymkQjZ/hM50irxeAmUGF4NZdkPULzig+NHxbLt4wzwLsS6JAvHvlfitajv5NW9w==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/core': 1.8.0-beta.15
|
||||
'@tmagic/core': 1.8.0-beta.17
|
||||
typescript: ^6.0.3
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
@ -3086,12 +3086,12 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/dep@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-9y4RDPUpyyMbG94x2rkvriI7KHg29nn7xykDPGy2PtF4eZECtj9fgf5oDqVo21kT/n/nDn1WpMoEX56jO/2tmw==}
|
||||
'@tmagic/dep@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-22yQTbWcKwvByGBfjzGNlnfKqbv+aPJ34bC6weYRZV5vFLZS8QitdQLgM74TT+7nagzeV8uWZVPCGtrr6JUtEw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/schema': 1.8.0-beta.15
|
||||
'@tmagic/utils': 1.8.0-beta.15
|
||||
'@tmagic/schema': 1.8.0-beta.17
|
||||
'@tmagic/utils': 1.8.0-beta.17
|
||||
typescript: ^6.0.3
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
@ -3107,8 +3107,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/design@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-vh7fNy3gs63FzVILojstTx2xYszE2RKdeijAHDGMkWmnrTpWj1QhuEd+lq8ipu41fjGZsz/9EeAImJ0PWaRCPA==}
|
||||
'@tmagic/design@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-9ZxLqd+WrqEBRbxQd8daDaMmiuDDHl/Pbq8jib1bgX84iVO+AbFQxV0WFIzcqygFj2aE3KoszjIeZzjlSja6Kg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
typescript: ^6.0.3
|
||||
@ -3129,11 +3129,11 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/editor@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-B34YITY0QHu5j6/ZD/JhF6ft/GPpWeV4c7SpxTRkTQGwxaB0xyJ1M2W+p2pGtDM+mlAswJ7h5MXlfmpOYGne/w==}
|
||||
'@tmagic/editor@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-T9gDbIk/o1UKgd5ioFrJHssFp/P2VbRNHGGjAouH4ujMw7WkNtL8CFdpOMTWG8krCaWxkJ4IUQg/WhVDjotLHg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/core': 1.8.0-beta.15
|
||||
'@tmagic/core': 1.8.0-beta.17
|
||||
monaco-editor: '^0.55.1 '
|
||||
type-fest: ^5.2.0
|
||||
typescript: ^6.0.3
|
||||
@ -3144,11 +3144,11 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/element-plus-adapter@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-UyBnS3mskpg6foWftGcVyIhF3yiLvVVgOxJDNhUhEWO5X3M09XWFmIFb+759fomCDvMhRIX3VJuos2sQIFRjTQ==}
|
||||
'@tmagic/element-plus-adapter@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-szV/jaxbW6DEkI90sDeqscobnu5QNn8yx+3JyfonY0tsJ4HEzaNE0xMUTaGeDNtjj6xAYIX8ld/uz6tChmgajA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/design': 1.8.0-beta.15
|
||||
'@tmagic/design': 1.8.0-beta.17
|
||||
element-plus: ^2.14.3
|
||||
typescript: ^6.0.3
|
||||
vue: ^3.5.40
|
||||
@ -3165,8 +3165,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/form-schema@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-a1cAcoW/FrCcm0Mw2yYa/PbIH8hT4pGxBrV9wt5mF6u+7eQ3wP4b9vKcnwTj142sfR11H2zgS5hu4rxF7mDJJQ==}
|
||||
'@tmagic/form-schema@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-fESNNvRQFsJcNv1y1wuA9vXvJnOxi5qdRf2I8Ph5O7cCPjPltoFWI2m/otEws1iPiMRhjHLQJrLupPkILd1Kwg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
typescript: ^6.0.3
|
||||
@ -3187,13 +3187,13 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/form@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-cx8JmiZi9kGwt/mEqwX7RHm4B+NvHbjZs70ogpzwVgkLNefylYNOg8JGdiyjUSRhP3bU+D+epGo9o53l4Pzz0g==}
|
||||
'@tmagic/form@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-ttol7h4U69ypS+Q7pslvNO3XwdCa3XnC9vIEsH1aSfoIHPRBRp7GC3IJ80orkUkxeTciXmDZtrxO0Jy5epMIMA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/design': 1.8.0-beta.15
|
||||
'@tmagic/form-schema': 1.8.0-beta.15
|
||||
'@tmagic/utils': 1.8.0-beta.15
|
||||
'@tmagic/design': 1.8.0-beta.17
|
||||
'@tmagic/form-schema': 1.8.0-beta.17
|
||||
'@tmagic/utils': 1.8.0-beta.17
|
||||
typescript: ^6.0.3
|
||||
vue: ^3.5.40
|
||||
peerDependenciesMeta:
|
||||
@ -3235,8 +3235,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/schema@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-ehlSOGQh6RYg0CCNHiWsq6WlHIcMsnI3XitmRISyslEBJDI+0BS08ElLIb9BlhyE+hhL+1mhAOXVdiKfE2Lj/Q==}
|
||||
'@tmagic/schema@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-9BXKkhXuZtmp9xp5fKxZ2noMs7lC4YKxtehmv7Q3YEWFklbQBuIhYbpl/BTpdy7eYM7zvOQQN3ow2PdCdGwfOw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
typescript: ^6.0.3
|
||||
@ -3264,11 +3264,11 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/stage@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-3YsKf7PFRqwzeHQcCmdgAKmFHEL1kbHkCXjj/5fLs0d3Dca0FT+zkcIM+lRlBocIeFz11I7JasQ83iJwA6qTtg==}
|
||||
'@tmagic/stage@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-fmI9VPRDv6rSzjfB6s/6B/6NO8IwHrIGqy5poN345okBIp3g+Mi1vdRDRWUl/Fyan8em5uVzDhseAa5qVTi88Q==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/core': 1.8.0-beta.15
|
||||
'@tmagic/core': 1.8.0-beta.17
|
||||
typescript: ^6.0.3
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
@ -3286,24 +3286,24 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/table@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-iuzWL/5oIWJ1/w8n8oLOXlVwk2KHg+DaHLZB4ux2DlreXuq6/EDkRjeR1YJxY1XQcBOA2lTp6x/cHUMWtZFs7g==}
|
||||
'@tmagic/table@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-Vk+ZU2ibXFuZ+7JfFl4XlVIJrFu+u2j+WgXGE8Tp91pfE+I8588D2PywLJnw2X2LJE1rlivhyHrkE7PsVSc51Q==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/design': 1.8.0-beta.15
|
||||
'@tmagic/form': 1.8.0-beta.15
|
||||
'@tmagic/utils': 1.8.0-beta.15
|
||||
'@tmagic/design': 1.8.0-beta.17
|
||||
'@tmagic/form': 1.8.0-beta.17
|
||||
'@tmagic/utils': 1.8.0-beta.17
|
||||
typescript: ^6.0.3
|
||||
vue: ^3.5.40
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/tdesign-vue-next-adapter@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-1IMYlV36O7cpR0U2Vo2hL+7Jruz6szZYYw8glVB/kGd1Ou4A0dwmzZoIQdTTBGfHTJHVudye4+22BAXh7oELPA==}
|
||||
'@tmagic/tdesign-vue-next-adapter@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-nvOfCFrimeIQfUX16gIE/jEI8Qo9YKhGOm7aH3uFHxz5QJoK1DWLgHFm34s55ZJwtt+z+w6tHO0Oe2zsbs4YWw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/design': 1.8.0-beta.15
|
||||
'@tmagic/design': 1.8.0-beta.17
|
||||
tdesign-vue-next: ^1.17.1
|
||||
typescript: ^6.0.3
|
||||
vue: ^3.5.40
|
||||
@ -3346,11 +3346,11 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tmagic/utils@1.8.0-beta.15':
|
||||
resolution: {integrity: sha512-MmUHz9K7VnsqeyvuxBECIsHcDglaiOwGyaEZoEs6zCw3UfZE2pFKAxWs5YZqDpEWsEqOlk99gAXt77zgb727VQ==}
|
||||
'@tmagic/utils@1.8.0-beta.17':
|
||||
resolution: {integrity: sha512-2rHDYffWbIYa++kYmTarD1DD6lgHJtRFNzXuhO3dZlzFE/KG5XK4v5/IOa4CNbuLyJhwWm10UdywqlYK1P6o0A==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@tmagic/schema': 1.8.0-beta.15
|
||||
'@tmagic/schema': 1.8.0-beta.17
|
||||
typescript: ^6.0.3
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
@ -8737,7 +8737,7 @@ snapshots:
|
||||
|
||||
'@sxzz/popperjs-es@2.11.8': {}
|
||||
|
||||
'@tmagic/cli@1.8.0-beta.15(typescript@6.0.3)':
|
||||
'@tmagic/cli@1.8.0-beta.17(typescript@6.0.3)':
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
chokidar: 3.6.0
|
||||
@ -8772,12 +8772,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/core@1.8.0-beta.15(typescript@6.0.3)':
|
||||
'@tmagic/core@1.8.0-beta.17(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@tmagic/data-source': 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/dep': 1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/schema': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/utils': 1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/data-source': 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/dep': 1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/schema': 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/utils': 1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
events: 3.3.0
|
||||
lodash-es: 4.18.1
|
||||
optionalDependencies:
|
||||
@ -8801,9 +8801,9 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/data-source@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)':
|
||||
'@tmagic/data-source@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@tmagic/core': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/core': 1.8.0-beta.17(typescript@6.0.3)
|
||||
deep-state-observer: 5.5.14
|
||||
events: 3.3.0
|
||||
lodash-es: 4.18.1
|
||||
@ -8824,10 +8824,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/dep@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)':
|
||||
'@tmagic/dep@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@tmagic/schema': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/utils': 1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/schema': 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/utils': 1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
@ -8838,7 +8838,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
'@popperjs/core': 2.11.8
|
||||
vue: 3.5.40(typescript@6.0.3)
|
||||
@ -8872,15 +8872,15 @@ snapshots:
|
||||
- '@tmagic/form-schema'
|
||||
- '@tmagic/schema'
|
||||
|
||||
'@tmagic/editor@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/editor@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
'@element-plus/icons-vue': 2.3.2(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/core': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/design': 1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/form': 1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/stage': 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/table': 1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form@1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/utils': 1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/core': 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/design': 1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/form': 1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/stage': 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/table': 1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form@1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/utils': 1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
buffer: 6.0.3
|
||||
deep-object-diff: 1.1.9
|
||||
emmet-monaco-es: 5.7.0(monaco-editor@0.55.1)
|
||||
@ -8900,9 +8900,9 @@ snapshots:
|
||||
- '@tmagic/form-schema'
|
||||
- '@tmagic/schema'
|
||||
|
||||
'@tmagic/element-plus-adapter@1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/element-plus-adapter@1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
'@tmagic/design': 1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/design': 1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
element-plus: 2.14.3(vue@3.5.40(typescript@6.0.3))
|
||||
vue: 3.5.40(typescript@6.0.3)
|
||||
optionalDependencies:
|
||||
@ -8914,9 +8914,9 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3)':
|
||||
'@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@tmagic/schema': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/schema': 1.8.0-beta.17(typescript@6.0.3)
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
@ -8934,13 +8934,13 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/form@1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/form@1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
'@element-plus/icons-vue': 2.3.2(vue@3.5.40(typescript@6.0.3))
|
||||
'@popperjs/core': 2.11.8
|
||||
'@tmagic/design': 1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/form-schema': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/utils': 1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/design': 1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/form-schema': 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/utils': 1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
dayjs: 1.11.21
|
||||
lodash-es: 4.18.1
|
||||
sortablejs: 1.15.6
|
||||
@ -8948,13 +8948,13 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/react-runtime-help@0.2.2(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(lodash-es@4.18.1)(react@18.3.1)(typescript@6.0.3)':
|
||||
'@tmagic/react-runtime-help@0.2.2(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(lodash-es@4.18.1)(react@18.3.1)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
lodash-es: 4.18.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@tmagic/core': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/stage': 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/core': 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/stage': 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/schema@1.7.0(typescript@6.0.3)':
|
||||
@ -8965,7 +8965,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/schema@1.8.0-beta.15(typescript@6.0.3)':
|
||||
'@tmagic/schema@1.8.0-beta.17(typescript@6.0.3)':
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
@ -8995,10 +8995,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/stage@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)':
|
||||
'@tmagic/stage@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@scena/guides': 0.29.2
|
||||
'@tmagic/core': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/core': 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@zumer/snapdom': 2.8.0
|
||||
events: 3.3.0
|
||||
keycon: 1.4.0
|
||||
@ -9018,32 +9018,32 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/table@1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form@1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/table@1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form@1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
'@element-plus/icons-vue': 2.3.2(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/design': 1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/form': 1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/utils': 1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/design': 1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/form': 1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/utils': 1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
lodash-es: 4.18.1
|
||||
vue: 3.5.40(typescript@6.0.3)
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/tdesign-vue-next-adapter@1.8.0-beta.15(@tmagic/design@1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(tdesign-vue-next@1.17.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/tdesign-vue-next-adapter@1.8.0-beta.17(@tmagic/design@1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(tdesign-vue-next@1.17.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
'@tmagic/design': 1.8.0-beta.15(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/design': 1.8.0-beta.17(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
tdesign-vue-next: 1.17.3(vue@3.5.40(typescript@6.0.3))
|
||||
vue: 3.5.40(typescript@6.0.3)
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/tmagic-form-runtime@1.1.3(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/editor@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/tmagic-form-runtime@1.1.3(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/editor@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3)))(element-plus@2.14.3(vue@3.5.40(typescript@6.0.3)))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
'@tmagic/editor': 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.15(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
'@tmagic/editor': 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/form-schema@1.8.0-beta.17(typescript@6.0.3))(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(monaco-editor@0.55.1)(type-fest@5.2.0)(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))
|
||||
element-plus: 2.14.3(vue@3.5.40(typescript@6.0.3))
|
||||
vue: 3.5.40(typescript@6.0.3)
|
||||
optionalDependencies:
|
||||
'@tmagic/core': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/core': 1.8.0-beta.17(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/utils@1.7.0(@tmagic/schema@1.7.0(typescript@6.0.3))(typescript@6.0.3)':
|
||||
@ -9060,19 +9060,19 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/utils@1.8.0-beta.15(@tmagic/schema@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)':
|
||||
'@tmagic/utils@1.8.0-beta.17(@tmagic/schema@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@tmagic/schema': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/schema': 1.8.0-beta.17(typescript@6.0.3)
|
||||
lodash-es: 4.18.1
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tmagic/vue-runtime-help@2.0.4(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
'@tmagic/vue-runtime-help@2.0.4(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(@tmagic/stage@1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3))(typescript@6.0.3)(vue@3.5.40(typescript@6.0.3))':
|
||||
dependencies:
|
||||
vue: 3.5.40(typescript@6.0.3)
|
||||
optionalDependencies:
|
||||
'@tmagic/core': 1.8.0-beta.15(typescript@6.0.3)
|
||||
'@tmagic/stage': 1.8.0-beta.15(@tmagic/core@1.8.0-beta.15(typescript@6.0.3))(typescript@6.0.3)
|
||||
'@tmagic/core': 1.8.0-beta.17(typescript@6.0.3)
|
||||
'@tmagic/stage': 1.8.0-beta.17(@tmagic/core@1.8.0-beta.17(typescript@6.0.3))(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
|
||||
'@tybys/wasm-util@0.10.3':
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "runtime-react",
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"engines": {
|
||||
@ -16,16 +16,16 @@
|
||||
"build:playground": "node scripts/build.mjs --type=playground"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tmagic/core": "1.8.0-beta.15",
|
||||
"@tmagic/core": "1.8.0-beta.17",
|
||||
"@tmagic/react-runtime-help": "0.2.2",
|
||||
"@tmagic/stage": "1.8.0-beta.15",
|
||||
"@tmagic/stage": "1.8.0-beta.17",
|
||||
"axios": "^1.13.2",
|
||||
"qrcode": "^1.5.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tmagic/cli": "1.8.0-beta.15",
|
||||
"@tmagic/cli": "1.8.0-beta.17",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "runtime-vue",
|
||||
"version": "1.8.0-beta.15",
|
||||
"version": "1.8.0-beta.17",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"engines": {
|
||||
@ -16,14 +16,14 @@
|
||||
"build:playground": "node scripts/build.mjs --type=playground"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tmagic/core": "1.8.0-beta.15",
|
||||
"@tmagic/stage": "1.8.0-beta.15",
|
||||
"@tmagic/core": "1.8.0-beta.17",
|
||||
"@tmagic/stage": "1.8.0-beta.17",
|
||||
"@tmagic/vue-runtime-help": "^2.0.4",
|
||||
"axios": "^1.13.2",
|
||||
"vue": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tmagic/cli": "1.8.0-beta.15",
|
||||
"@tmagic/cli": "1.8.0-beta.17",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/node": "^24.0.10",
|
||||
"@vitejs/plugin-legacy": "^8.0.1",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user