perf: 完善黑夜模式的表现效果,工作流编排幕布和节点在黑夜模式正常表现

This commit is contained in:
2026-03-04 19:56:20 +08:00
parent 27376a5f33
commit a79718b03b
33 changed files with 605 additions and 363 deletions

View File

@@ -1,6 +1,6 @@
import {type useSvelteFlow} from '@xyflow/svelte'; import type {useSvelteFlow} from '@xyflow/svelte';
import {componentName} from './consts'; import {componentName} from './consts';
import type {TinyflowData, TinyflowOptions} from './types'; import type {TinyflowData, TinyflowOptions, TinyflowTheme} from './types';
type FlowInstance = ReturnType<typeof useSvelteFlow>; type FlowInstance = ReturnType<typeof useSvelteFlow>;
@@ -8,6 +8,10 @@ export class Tinyflow {
private options!: TinyflowOptions; private options!: TinyflowOptions;
private rootEl!: Element; private rootEl!: Element;
private svelteFlowInstance!: FlowInstance; private svelteFlowInstance!: FlowInstance;
private tinyflowEl!: HTMLElement & {
options: TinyflowOptions;
onInit: (svelteFlowInstance: FlowInstance) => void;
};
constructor(options: TinyflowOptions) { constructor(options: TinyflowOptions) {
if (typeof options.element !== 'string' && !(options.element instanceof Element)) { if (typeof options.element !== 'string' && !(options.element instanceof Element)) {
@@ -38,20 +42,13 @@ export class Tinyflow {
tinyflowEl.style.display = 'block'; tinyflowEl.style.display = 'block';
tinyflowEl.style.width = '100%'; tinyflowEl.style.width = '100%';
tinyflowEl.style.height = '100%'; tinyflowEl.style.height = '100%';
tinyflowEl.classList.add('tf-theme-light'); this._applyThemeClass(tinyflowEl, this.options.theme);
tinyflowEl.options = this.options; tinyflowEl.options = this.options;
tinyflowEl.onInit = (svelteFlowInstance: FlowInstance) => { tinyflowEl.onInit = (svelteFlowInstance: FlowInstance) => {
this.svelteFlowInstance = svelteFlowInstance; this.svelteFlowInstance = svelteFlowInstance;
}; };
return tinyflowEl;
this.rootEl.appendChild(tinyflowEl);
}
private _setOptions(options: TinyflowOptions) {
this.options = {
...options
};
} }
getOptions() { getOptions() {
@@ -62,25 +59,20 @@ export class Tinyflow {
return this.svelteFlowInstance.toObject(); return this.svelteFlowInstance.toObject();
} }
setTheme(theme: TinyflowTheme) {
this.options.theme = theme;
if (this.tinyflowEl) {
this._applyThemeClass(this.tinyflowEl, theme);
}
}
setData(data: TinyflowData) { setData(data: TinyflowData) {
this.options.data = data; this.options.data = data;
const tinyflowEl = document.createElement(componentName) as HTMLElement & { this.tinyflowEl = this._createTinyflowElement();
options: TinyflowOptions;
onInit: (svelteFlowInstance: FlowInstance) => void;
};
tinyflowEl.style.display = 'block';
tinyflowEl.style.width = '100%';
tinyflowEl.style.height = '100%';
tinyflowEl.classList.add('tf-theme-light');
tinyflowEl.options = this.options;
tinyflowEl.onInit = (svelteFlowInstance: FlowInstance) => {
this.svelteFlowInstance = svelteFlowInstance;
};
this.destroy(); this.destroy();
this.rootEl.appendChild(tinyflowEl); this.rootEl.appendChild(this.tinyflowEl);
} }
destroy() { destroy() {

View File

@@ -461,17 +461,18 @@
<style> <style>
.panel-content { .panel-content {
padding: 10px; padding: 10px;
background-color: #fff; background-color: var(--tf-bg-surface);
border-radius: 5px; border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-soft);
width: 200px; width: 200px;
border: 1px solid #efefef; border: 1px solid var(--tf-border-color);
color: var(--tf-text-primary);
} }
.setting-title { .setting-title {
margin: 10px 0; margin: 10px 0;
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
} }
.setting-item { .setting-item {
@@ -487,13 +488,13 @@
.readonly-edge-branch { .readonly-edge-branch {
font-size: 12px; font-size: 12px;
color: #6b7280; color: var(--tf-text-secondary);
margin-bottom: 8px; margin-bottom: 8px;
} }
.readonly-edge-tip { .readonly-edge-tip {
margin-top: 6px; margin-top: 6px;
font-size: 12px; font-size: 12px;
color: #9ca3af; color: var(--tf-text-muted);
} }
</style> </style>

View File

@@ -91,8 +91,8 @@
width: 16px; width: 16px;
height: 16px; height: 16px;
border-radius: 50%; border-radius: 50%;
border: 1px solid #c6cfdd; border: 1px solid var(--tf-border-color-strong);
color: #64748b; color: var(--tf-text-secondary);
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -100,14 +100,14 @@
line-height: 1; line-height: 1;
cursor: default; cursor: default;
user-select: none; user-select: none;
background: #fff; background: var(--tf-bg-surface);
position: relative; position: relative;
} }
.tf-collapse-item-title-help:hover { .tf-collapse-item-title-help:hover {
border-color: #94a3b8; border-color: var(--tf-border-color-strong);
color: #334155; color: var(--tf-text-primary);
background: #f8fafc; background: var(--tf-bg-hover);
} }
.tf-collapse-item-title-help::after { .tf-collapse-item-title-help::after {
@@ -119,13 +119,13 @@
min-width: 260px; min-width: 260px;
max-width: 420px; max-width: 420px;
white-space: pre-line; white-space: pre-line;
background: #0f172a; background: var(--tf-tip-bg);
color: #f8fafc; color: var(--tf-tip-text);
border-radius: 8px; border-radius: 8px;
padding: 10px 12px; padding: 10px 12px;
font-size: 12px; font-size: 12px;
line-height: 1.45; line-height: 1.45;
box-shadow: 0 8px 22px rgba(2, 6, 23, 0.25); box-shadow: var(--tf-shadow-medium);
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
pointer-events: none; pointer-events: none;
@@ -140,7 +140,7 @@
transform: translateY(-50%); transform: translateY(-50%);
border-top: 6px solid transparent; border-top: 6px solid transparent;
border-bottom: 6px solid transparent; border-bottom: 6px solid transparent;
border-right: 6px solid #0f172a; border-right: 6px solid var(--tf-tip-bg);
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
z-index: 121; z-index: 121;

View File

@@ -18,7 +18,7 @@
padding: 3px; padding: 3px;
&:hover { &:hover {
background: #eee; background: var(--tf-bg-hover);
border: 1px solid transparent; border: 1px solid transparent;
} }
} }

View File

@@ -227,8 +227,8 @@
} }
.tf-mixed-ref-box { .tf-mixed-ref-box {
background-color: #ffffff; background-color: var(--tf-bg-input);
border: 1px solid #d1d5db; border: 1px solid var(--tf-border-color-strong);
padding: 0 48px 0 12px; padding: 0 48px 0 12px;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
@@ -236,8 +236,8 @@
} }
.tf-mixed-text-box { .tf-mixed-text-box {
background-color: #ffffff; background-color: var(--tf-bg-input);
border: 1px solid #d1d5db; border: 1px solid var(--tf-border-color-strong);
padding: 0 48px 0 12px; padding: 0 48px 0 12px;
align-items: center; align-items: center;
transition: all 0.2s; transition: all 0.2s;
@@ -247,13 +247,13 @@
.tf-mixed-wrapper.is-focus .tf-mixed-text-box, .tf-mixed-wrapper.is-focus .tf-mixed-text-box,
.tf-mixed-ref-box:hover, .tf-mixed-ref-box:hover,
.tf-mixed-text-box:hover { .tf-mixed-text-box:hover {
border-color: #94a3b8; border-color: var(--tf-border-color-strong);
} }
.tf-mixed-wrapper.is-focus .tf-mixed-ref-box, .tf-mixed-wrapper.is-focus .tf-mixed-ref-box,
.tf-mixed-wrapper.is-focus .tf-mixed-text-box { .tf-mixed-wrapper.is-focus .tf-mixed-text-box {
border-color: #3b82f6; border-color: var(--tf-primary-color);
outline: none; outline: none;
box-shadow: 0 0 0 2px rgba(59,130,246,0.1); box-shadow: var(--tf-focus-shadow);
} }
.tf-mixed-sel-val { .tf-mixed-sel-val {
@@ -272,8 +272,8 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-shrink: 0; flex-shrink: 0;
color: #3474ff; color: var(--tf-icon-color);
background: #cedafb; background: var(--tf-icon-bg);
border-radius: 4px; border-radius: 4px;
padding: 2px; padding: 2px;
box-sizing: border-box; box-sizing: border-box;
@@ -281,9 +281,9 @@
:global(svg) { width: 12px; height: 12px; } :global(svg) { width: 12px; height: 12px; }
} }
.tf-mixed-val-name { color: #111827; font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; user-select: none; } .tf-mixed-val-name { color: var(--tf-text-primary); font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; user-select: none; }
.tf-mixed-placeholder { .tf-mixed-placeholder {
color: #9ca3af; color: var(--tf-text-muted);
font-size: 13px; font-size: 13px;
height: 100%; height: 100%;
display: flex; display: flex;
@@ -301,12 +301,12 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;
color: #94a3b8; color: var(--tf-text-muted);
border-radius: 0 5px 5px 0; border-radius: 0 5px 5px 0;
transition: all 0.2s; transition: all 0.2s;
flex-shrink: 0; flex-shrink: 0;
&:hover { background: rgba(0,0,0,0.04); color: #64748b; } &:hover { background: var(--tf-bg-tag); color: var(--tf-text-secondary); }
} }
/* Keep the trigger in the same visual position in both text/ref modes */ /* Keep the trigger in the same visual position in both text/ref modes */
@@ -330,10 +330,10 @@
height: 20px; height: 20px;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
background: #e2e8f0; background: var(--tf-bg-active);
border: none; border: none;
border-radius: 50%; border-radius: 50%;
color: #64748b; color: var(--tf-text-secondary);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -343,7 +343,7 @@
padding: 3px; padding: 3px;
z-index: 10; z-index: 10;
} }
.tf-mixed-clear-btn:hover { background: #ef4444; color: #fff; } .tf-mixed-clear-btn:hover { background: var(--tf-danger-color); color: var(--tf-bg-surface); }
.tf-mixed-wrapper:hover .tf-mixed-clear-btn { opacity: 1; } .tf-mixed-wrapper:hover .tf-mixed-clear-btn { opacity: 1; }
.tf-mixed-native-input { .tf-mixed-native-input {
@@ -352,7 +352,7 @@
border: none; border: none;
outline: none; outline: none;
background: transparent; background: transparent;
color: #111827; color: var(--tf-text-primary);
font-size: 13px; font-size: 13px;
line-height: 32px; line-height: 32px;
height: 32px; height: 32px;
@@ -363,17 +363,17 @@
} }
.tf-mixed-native-input::placeholder { .tf-mixed-native-input::placeholder {
color: #9ca3af; color: var(--tf-text-muted);
line-height: 32px; line-height: 32px;
} }
/* Dropdown Styles matched perfectly to Select */ /* Dropdown Styles matched perfectly to Select */
.tf-mixed-dropdown { .tf-mixed-dropdown {
display: flex; display: flex;
background: #fff; background: var(--tf-bg-surface);
border-radius: 12px; border-radius: 12px;
box-shadow: 0 10px 25px rgba(0,0,0,0.15); box-shadow: var(--tf-shadow-medium);
border: 1px solid #e5e7eb; border: 1px solid var(--tf-border-color);
overflow: hidden; overflow: hidden;
width: max-content; width: max-content;
box-sizing: border-box; box-sizing: border-box;
@@ -382,9 +382,9 @@
margin-top: 5px; margin-top: 5px;
} }
.tf-mixed-list { display: flex; flex-direction: column; padding: 8px; overflow-y: auto; } .tf-mixed-list { display: flex; flex-direction: column; padding: 8px; overflow-y: auto; }
.tf-mixed-primary-list { width: 100%; flex-shrink: 0; background: #f9fafb; } .tf-mixed-primary-list { width: 100%; flex-shrink: 0; background: var(--tf-bg-surface-alt); }
.tf-mixed-dropdown:has(.tf-mixed-secondary-list) .tf-mixed-primary-list { width: auto; min-width: 180px; } .tf-mixed-dropdown:has(.tf-mixed-secondary-list) .tf-mixed-primary-list { width: auto; min-width: 180px; }
.tf-mixed-secondary-list { min-width: 220px; background: #fff; padding: 12px; border-left: 1px solid #f3f4f6; animation: slideIn 0.2s ease-out; box-sizing: border-box; } .tf-mixed-secondary-list { min-width: 220px; background: var(--tf-bg-surface); padding: 12px; border-left: 1px solid var(--tf-bg-muted); animation: slideIn 0.2s ease-out; box-sizing: border-box; }
@keyframes slideIn { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideIn { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: translateX(0); } }
@@ -398,28 +398,28 @@
cursor: pointer; cursor: pointer;
text-align: left; text-align: left;
font-size: 13px; font-size: 13px;
color: #374151; color: var(--tf-text-primary);
gap: 10px; gap: 10px;
width: 100%; width: 100%;
transition: all 0.15s; transition: all 0.15s;
margin-bottom: 2px; margin-bottom: 2px;
&:hover { background: #f3f4f6; } &:hover { background: var(--tf-bg-muted); }
&.active { background: #eff6ff; color: #2563eb; font-weight: 500; } &.active { background: var(--tf-primary-soft-bg); color: var(--tf-primary-color); font-weight: 500; }
&.has-children { background: #f8fafc; margin-bottom: 4px; &:hover { background: #f1f5f9; } } &.has-children { background: var(--tf-bg-hover); margin-bottom: 4px; &:hover { background: var(--tf-bg-active); } }
} }
.tf-mixed-item-icon { .tf-mixed-item-icon {
width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: #3474ff; background: #cedafb; border-radius: 5px; padding: 3px; box-sizing: border-box; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--tf-icon-color); background: var(--tf-icon-bg); border-radius: 5px; padding: 3px; box-sizing: border-box;
:global(svg) { width: 16px; height: 16px; } :global(svg) { width: 16px; height: 16px; }
} }
.tf-mixed-item-label { flex-grow: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .tf-mixed-item-label { flex-grow: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tf-mixed-item-arrow { width: 14px; height: 14px; color: #9ca3af; } .tf-mixed-item-arrow { width: 14px; height: 14px; color: var(--tf-text-muted); }
.tf-mixed-item-container { position: relative; width: 100%; } .tf-mixed-item-container { position: relative; width: 100%; }
.tf-mixed-item-children { position: relative; width: 100%; &::before { content: ''; position: absolute; left: 8px; top: 0; bottom: 0; width: 1px; background: #f0f0f0; } } .tf-mixed-item-children { position: relative; width: 100%; &::before { content: ''; position: absolute; left: 8px; top: 0; bottom: 0; width: 1px; background: var(--tf-border-color-soft); } }
.tf-mixed-label { display: flex; justify-content: flex-start; align-items: center; width: 100%; gap: 8px; overflow: hidden;} .tf-mixed-label { display: flex; justify-content: flex-start; align-items: center; width: 100%; gap: 8px; overflow: hidden;}
.tf-mixed-name-wrapper { display: flex; align-items: center; gap: 6px; } .tf-mixed-name-wrapper { display: flex; align-items: center; gap: 6px; }
.tf-mixed-expand-icon { width: 12px; height: 12px; color: currentColor; opacity: 0.6; } .tf-mixed-expand-icon { width: 12px; height: 12px; color: currentColor; opacity: 0.6; }
.tf-mixed-name { color: inherit; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .tf-mixed-name { color: inherit; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tf-mixed-type { background: rgba(0,0,0,0.06); color: #6b7280; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 500; white-space: nowrap; } .tf-mixed-type { background: var(--tf-bg-tag); color: var(--tf-text-secondary); padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 500; white-space: nowrap; }
</style> </style>

View File

@@ -309,9 +309,9 @@
.tf-select-default-wrapper { .tf-select-default-wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: #fff; background: var(--tf-bg-surface);
margin-top: 5px; margin-top: 5px;
border: 1px solid #e5e7eb; border: 1px solid var(--tf-border-color);
border-radius: 6px; border-radius: 6px;
padding: 4px; padding: 4px;
width: 100%; width: 100%;
@@ -319,7 +319,7 @@
box-sizing: border-box; box-sizing: border-box;
max-height: 220px; max-height: 220px;
overflow: auto; overflow: auto;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); box-shadow: var(--tf-shadow-soft);
} }
.tf-select-default-item { .tf-select-default-item {
@@ -327,7 +327,7 @@
align-items: center; align-items: center;
padding: 6px 12px; padding: 6px 12px;
border: none; border: none;
background: #fff; background: var(--tf-bg-surface);
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
line-height: 1.5; line-height: 1.5;
@@ -335,10 +335,10 @@
width: 100%; width: 100%;
text-align: left; text-align: left;
font-size: 13px; font-size: 13px;
color: #111827; color: var(--tf-text-primary);
&:hover { &:hover {
background: #f5f5f7; background: var(--tf-bg-hover);
} }
} }
@@ -351,16 +351,16 @@
.tf-select-model-wrapper { .tf-select-model-wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: #fff; background: var(--tf-bg-surface);
margin-top: 5px; margin-top: 5px;
border: 1px solid #e5e7eb; border: 1px solid var(--tf-border-color);
border-radius: 10px; border-radius: 10px;
/* Removed fixed width to allow syncWidth to control it */ /* Removed fixed width to allow syncWidth to control it */
z-index: 99999; z-index: 99999;
box-sizing: border-box; box-sizing: border-box;
max-height: 400px; max-height: 400px;
overflow: hidden; overflow: hidden;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12); box-shadow: var(--tf-shadow-medium);
} }
.tf-select-model-header { .tf-select-model-header {
@@ -368,20 +368,20 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 10px 12px; padding: 10px 12px;
border-bottom: 1px solid #f3f4f6; border-bottom: 1px solid var(--tf-bg-muted);
background: #fff; background: var(--tf-bg-surface);
} }
.tf-select-model-header-title { .tf-select-model-header-title {
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
color: #111827; color: var(--tf-text-primary);
} }
.tf-select-model-header-icon { .tf-select-model-header-icon {
width: 14px; width: 14px;
height: 14px; height: 14px;
color: #6b7280; color: var(--tf-text-secondary);
cursor: pointer; cursor: pointer;
} }
@@ -396,7 +396,7 @@
.tf-select-model-group-title { .tf-select-model-group-title {
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 500;
color: #6b7280; color: var(--tf-text-secondary);
margin-top: 6px; margin-top: 6px;
margin-bottom: 2px; margin-bottom: 2px;
padding-left: 6px; padding-left: 6px;
@@ -438,11 +438,11 @@
} }
.tf-select-model-item:hover { .tf-select-model-item:hover {
background: #f9fafb; background: var(--tf-bg-surface-alt);
} }
.tf-select-model-item.active { .tf-select-model-item.active {
background: #e0e7ff; background: var(--tf-primary-soft-bg);
} }
.tf-select-model-icon { .tf-select-model-icon {
@@ -454,7 +454,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: #f3f4f6; background: var(--tf-bg-muted);
margin-top: 2px; margin-top: 2px;
} }
@@ -467,7 +467,7 @@
.tf-select-model-avatar { .tf-select-model-avatar {
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
color: #9ca3af; color: var(--tf-text-muted);
} }
.tf-select-model-info { .tf-select-model-info {
@@ -481,7 +481,7 @@
.tf-select-model-title { .tf-select-model-title {
font-size: 13px; font-size: 13px;
font-weight: 500; font-weight: 500;
color: #111827; color: var(--tf-text-primary);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -494,8 +494,8 @@
} }
.tf-select-model-tag { .tf-select-model-tag {
background: #f3f4f6; background: var(--tf-bg-muted);
color: #6b7280; color: var(--tf-text-secondary);
font-size: 10px; font-size: 10px;
padding: 1px 6px; padding: 1px 6px;
border-radius: 4px; border-radius: 4px;
@@ -503,7 +503,7 @@
.tf-select-model-desc { .tf-select-model-desc {
font-size: 11px; font-size: 11px;
color: #6b7280; color: var(--tf-text-secondary);
line-height: 1.3; line-height: 1.3;
margin-top: 2px; margin-top: 2px;
display: -webkit-box; display: -webkit-box;
@@ -515,10 +515,10 @@
/* Reference Variant Styles */ /* Reference Variant Styles */
.tf-select-wrapper { .tf-select-wrapper {
display: flex; display: flex;
background: #fff; background: var(--tf-bg-surface);
border-radius: 12px; border-radius: 12px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15); box-shadow: var(--tf-shadow-medium);
border: 1px solid #e5e7eb; border: 1px solid var(--tf-border-color);
overflow: hidden; overflow: hidden;
/* width expands naturally since createFloating sets minWidth, not width */ /* width expands naturally since createFloating sets minWidth, not width */
width: max-content; width: max-content;
@@ -536,7 +536,7 @@
&.tf-select-primary-list { &.tf-select-primary-list {
width: 100%; /* Default fills the wrapper, which is minWidth-constrained by the input */ width: 100%; /* Default fills the wrapper, which is minWidth-constrained by the input */
flex-shrink: 0; flex-shrink: 0;
background: #f9fafb; background: var(--tf-bg-surface-alt);
} }
/* When a secondary list is open, we fix the primary list to 100% of the input's width (done via absolute positioning or just keeping it wide enough) */ /* When a secondary list is open, we fix the primary list to 100% of the input's width (done via absolute positioning or just keeping it wide enough) */
@@ -548,9 +548,9 @@
&.tf-select-secondary-list { &.tf-select-secondary-list {
min-width: 220px; min-width: 220px;
background: #fff; background: var(--tf-bg-surface);
padding: 12px; padding: 12px;
border-left: 1px solid #f3f4f6; border-left: 1px solid var(--tf-bg-muted);
animation: slideIn 0.2s ease-out; animation: slideIn 0.2s ease-out;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -572,7 +572,7 @@
top: 0; top: 0;
bottom: 0; bottom: 0;
width: 1px; width: 1px;
background: #f0f0f0; background: var(--tf-border-color-soft);
} }
} }
@@ -586,27 +586,27 @@
cursor: pointer; cursor: pointer;
text-align: left; text-align: left;
font-size: 13px; font-size: 13px;
color: #374151; color: var(--tf-text-primary);
gap: 10px; gap: 10px;
width: 100%; width: 100%;
transition: all 0.15s; transition: all 0.15s;
margin-bottom: 2px; margin-bottom: 2px;
&:hover { &:hover {
background: #f3f4f6; background: var(--tf-bg-muted);
} }
&.active { &.active {
background: #eff6ff; background: var(--tf-primary-soft-bg);
color: #2563eb; color: var(--tf-primary-color);
font-weight: 500; font-weight: 500;
} }
&.has-children { &.has-children {
background: #f8fafc; background: var(--tf-bg-hover);
margin-bottom: 4px; margin-bottom: 4px;
&:hover { &:hover {
background: #f1f5f9; background: var(--tf-bg-active);
} }
} }
@@ -617,8 +617,8 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-shrink: 0; flex-shrink: 0;
color: #3474ff; color: var(--tf-icon-color);
background: #cedafb; background: var(--tf-icon-bg);
border-radius: 5px; border-radius: 5px;
padding: 3px; padding: 3px;
box-sizing: border-box; box-sizing: border-box;
@@ -639,7 +639,7 @@
&-arrow { &-arrow {
width: 14px; width: 14px;
height: 14px; height: 14px;
color: #9ca3af; color: var(--tf-text-muted);
} }
} }
@@ -656,8 +656,8 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-shrink: 0; flex-shrink: 0;
color: #3474ff; color: var(--tf-icon-color);
background: #cedafb; background: var(--tf-icon-bg);
border-radius: 4px; border-radius: 4px;
padding: 2px; padding: 2px;
box-sizing: border-box; box-sizing: border-box;
@@ -712,8 +712,8 @@
} }
.tf-parameter-type { .tf-parameter-type {
background: rgba(0, 0, 0, 0.06); background: var(--tf-bg-tag);
color: #6b7280; color: var(--tf-text-secondary);
padding: 2px 8px; padding: 2px 8px;
border-radius: 4px; border-radius: 4px;
font-size: 11px; font-size: 11px;

View File

@@ -10,7 +10,12 @@
} from '@codemirror/autocomplete'; } from '@codemirror/autocomplete';
import {defaultKeymap, history, historyKeymap, indentWithTab} from '@codemirror/commands'; import {defaultKeymap, history, historyKeymap, indentWithTab} from '@codemirror/commands';
import {javascript} from '@codemirror/lang-javascript'; import {javascript} from '@codemirror/lang-javascript';
import {defaultHighlightStyle, indentOnInput, indentUnit, syntaxHighlighting} from '@codemirror/language'; import {
defaultHighlightStyle,
indentOnInput,
indentUnit,
syntaxHighlighting
} from '@codemirror/language';
import {python} from '@codemirror/lang-python'; import {python} from '@codemirror/lang-python';
import { import {
Decoration, Decoration,
@@ -25,8 +30,8 @@
import type {Parameter} from '#types'; import type {Parameter} from '#types';
import {flattenParameterCandidates} from '../utils/paramToken'; import {flattenParameterCandidates} from '../utils/paramToken';
import { import {
createBusinessCompletionSource,
type CodeEngine, type CodeEngine,
createBusinessCompletionSource,
normalizeCodeEngine, normalizeCodeEngine,
shouldAutoAppendCallParens shouldAutoAppendCallParens
} from '../utils/codeCompletion'; } from '../utils/codeCompletion';
@@ -230,18 +235,18 @@
function createEditorTheme() { function createEditorTheme() {
return EditorView.theme({ return EditorView.theme({
'&': { '&': {
border: '1px solid #dcdfe6', border: '1px solid var(--tf-border-color)',
borderRadius: '6px', borderRadius: '6px',
backgroundColor: '#fff', backgroundColor: 'var(--tf-bg-surface)',
fontSize: '13px' fontSize: '13px'
}, },
'&.cm-focused': { '&.cm-focused': {
outline: 'none', outline: 'none',
borderColor: '#4c82f7', borderColor: 'var(--tf-primary-color)',
boxShadow: '0 0 0 1px rgba(76, 130, 247, 0.25)' boxShadow: '0 0 0 1px var(--tf-primary-ghost-bg)'
}, },
'&.cm-editor.cm-disabled': { '&.cm-editor.cm-disabled': {
backgroundColor: '#f5f7fa', backgroundColor: 'var(--tf-bg-input-disabled)',
opacity: 0.85 opacity: 0.85
}, },
'.cm-scroller': { '.cm-scroller': {
@@ -252,17 +257,17 @@
}, },
'.cm-content': { '.cm-content': {
padding: '8px 38px 8px 10px', padding: '8px 38px 8px 10px',
caretColor: '#1f2937' caretColor: 'var(--tf-text-primary)'
}, },
'.cm-gutters': { '.cm-gutters': {
border: 'none', border: 'none',
background: 'transparent' background: 'transparent'
}, },
'.cm-activeLine': { '.cm-activeLine': {
background: 'rgba(76, 130, 247, 0.06)' background: 'var(--tf-primary-ghost-bg)'
}, },
'.cm-placeholder': { '.cm-placeholder': {
color: '#c0c4cc' color: 'var(--tf-text-muted)'
} }
}); });
} }
@@ -687,8 +692,9 @@
padding: 0 4px; padding: 0 4px;
font-size: 10px; font-size: 10px;
border-radius: 4px; border-radius: 4px;
color: #666; color: var(--tf-text-secondary);
background: rgba(255, 255, 255, 0.9); background: var(--tf-bg-surface);
border-color: var(--tf-border-color);
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -704,9 +710,9 @@
min-width: 20px; min-width: 20px;
padding: 0 4px; padding: 0 4px;
font-size: 10px; font-size: 10px;
border-color: #d3defd; border-color: var(--tf-primary-soft-border);
color: #1d4ed8; color: var(--tf-primary-color);
background: #f5f8ff; background: var(--tf-primary-soft-bg);
} }
@media (max-width: 900px) { @media (max-width: 900px) {
@@ -719,9 +725,9 @@
} }
:global(.code-script-button:hover) { :global(.code-script-button:hover) {
background: #f0f3ff; background: var(--tf-primary-soft-bg);
color: #2563eb; color: var(--tf-primary-color);
border-color: #d3defd; border-color: var(--tf-primary-soft-border);
} }
.code-script-panel { .code-script-panel {
@@ -729,10 +735,10 @@
max-width: 340px; max-width: 340px;
max-height: 240px; max-height: 240px;
overflow: auto; overflow: auto;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
padding: 6px; padding: 6px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -741,14 +747,14 @@
.code-script-item { .code-script-item {
border: none; border: none;
background: #fff; background: var(--tf-bg-surface);
padding: 6px 8px; padding: 6px 8px;
text-align: left; text-align: left;
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
font-size: 12px; font-size: 12px;
line-height: 1.3; line-height: 1.3;
color: #333; color: var(--tf-text-primary);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -756,13 +762,13 @@
} }
.code-script-item:hover { .code-script-item:hover {
background: #f5f7ff; background: var(--tf-bg-surface-alt);
color: #2563eb; color: var(--tf-primary-color);
} }
.code-script-item.unresolved { .code-script-item.unresolved {
background: #fff8e6; background: var(--tf-warning-soft-bg);
color: #92400e; color: var(--tf-warning-soft-text);
} }
.code-script-item-warn { .code-script-item-warn {
@@ -772,8 +778,8 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-radius: 50%; border-radius: 50%;
background: #d97706; background: var(--tf-warning-icon-color);
color: #fff; color: var(--tf-bg-surface);
font-size: 10px; font-size: 10px;
line-height: 1; line-height: 1;
flex-shrink: 0; flex-shrink: 0;
@@ -782,38 +788,38 @@
.code-script-empty { .code-script-empty {
padding: 8px; padding: 8px;
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
text-align: center; text-align: center;
} }
.code-script-editor :global(.cm-special-result) { .code-script-editor :global(.cm-special-result) {
color: #1d4ed8; color: var(--tf-primary-color);
font-weight: 700; font-weight: 700;
} }
.code-script-editor :global(.cm-template-token-valid) { .code-script-editor :global(.cm-template-token-valid) {
color: #1e4ed8; color: var(--tf-primary-color);
background: rgba(37, 99, 235, 0.12); background: var(--tf-primary-ghost-bg);
border-radius: 4px; border-radius: 4px;
} }
.code-script-editor :global(.cm-template-token-unresolved) { .code-script-editor :global(.cm-template-token-unresolved) {
color: #92400e; color: var(--tf-warning-soft-text);
background: rgba(217, 119, 6, 0.16); background: var(--tf-warning-soft-bg);
border-radius: 4px; border-radius: 4px;
} }
.code-script-editor :global(.cm-template-token-invalid) { .code-script-editor :global(.cm-template-token-invalid) {
color: #b42318; color: var(--tf-danger-soft-text);
background: rgba(217, 45, 32, 0.14); background: var(--tf-danger-soft-bg);
border-radius: 4px; border-radius: 4px;
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete) {
border: 1px solid #e6eaf2; border: 1px solid var(--tf-border-color);
background: #ffffff; background: var(--tf-bg-surface);
border-radius: 10px; border-radius: 10px;
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12); box-shadow: var(--tf-shadow-medium);
padding: 6px; padding: 6px;
min-width: 260px; min-width: 260px;
max-width: 360px; max-width: 360px;
@@ -838,29 +844,29 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
color: #1f2937; color: var(--tf-text-primary);
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]) {
background: #eef4ff; background: var(--tf-primary-soft-bg);
color: #1d4ed8; color: var(--tf-primary-color);
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul > li:hover) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul > li:hover) {
background: #f6f8fc; background: var(--tf-bg-surface-alt);
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionIcon) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionIcon) {
width: 16px; width: 16px;
height: 16px; height: 16px;
color: #6b7280; color: var(--tf-text-secondary);
opacity: 1; opacity: 1;
font-size: 12px; font-size: 12px;
margin-right: 0; margin-right: 0;
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected] .cm-completionIcon) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected] .cm-completionIcon) {
color: #2563eb; color: var(--tf-primary-color);
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionLabel) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionLabel) {
@@ -870,14 +876,14 @@
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionDetail) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionDetail) {
margin-left: auto; margin-left: auto;
color: #94a3b8; color: var(--tf-text-muted);
font-style: normal; font-style: normal;
font-size: 12px; font-size: 12px;
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionMatchedText) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete .cm-completionMatchedText) {
text-decoration: none; text-decoration: none;
color: #2563eb; color: var(--tf-primary-color);
font-weight: 700; font-weight: 700;
} }
@@ -886,7 +892,7 @@
} }
.code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul::-webkit-scrollbar-thumb) { .code-script-editor :global(.cm-tooltip.cm-tooltip-autocomplete > ul::-webkit-scrollbar-thumb) {
background: #d6dce8; background: var(--tf-scrollbar-thumb);
border-radius: 999px; border-radius: 999px;
} }

View File

@@ -158,18 +158,18 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
border-radius: 5px; border-radius: 5px;
width: 200px; width: 200px;
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
.input-more-item { .input-more-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 3px; gap: 3px;
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }

View File

@@ -45,7 +45,7 @@
.none-params { .none-params {
font-size: 12px; font-size: 12px;
background: #f8f8f8; background: var(--tf-bg-muted);
height: 40px; height: 40px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -57,7 +57,7 @@
.input-header { .input-header {
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }

View File

@@ -156,7 +156,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
.input-more-setting { .input-more-setting {
@@ -164,18 +164,18 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
border-radius: 5px; border-radius: 5px;
width: 200px; width: 200px;
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
.input-more-item { .input-more-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 3px; gap: 3px;
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }

View File

@@ -34,7 +34,7 @@
.none-params { .none-params {
font-size: 12px; font-size: 12px;
background: #f8f8f8; background: var(--tf-bg-muted);
height: 40px; height: 40px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -46,7 +46,7 @@
.input-header { .input-header {
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }

View File

@@ -263,9 +263,9 @@
gap: 5px; gap: 5px;
padding: 5px; padding: 5px;
border-radius: 5px; border-radius: 5px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #eee; border: 1px solid var(--tf-border-color);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-soft);
} }
:global(.tf-node-toolbar-item) { :global(.tf-node-toolbar-item) {
@@ -277,25 +277,34 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
border-radius: 5px; border-radius: 5px;
width: 200px; width: 200px;
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
.input-item { .input-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 3px; gap: 3px;
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
.input-item-inline { .input-item-inline {
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
}
input[type='checkbox'] {
width: 14px;
height: 14px;
accent-color: var(--tf-primary-color);
background: var(--tf-bg-input);
border: 1px solid var(--tf-border-color-strong);
border-radius: 3px;
} }
} }
</style> </style>

View File

@@ -205,21 +205,20 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
border-radius: 5px; border-radius: 5px;
width: 200px; width: 200px;
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
.input-more-item { .input-more-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 3px; gap: 3px;
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }
</style> </style>

View File

@@ -55,7 +55,7 @@
.none-params { .none-params {
font-size: 12px; font-size: 12px;
background: #f8f8f8; background: var(--tf-bg-muted);
height: 40px; height: 40px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -67,7 +67,7 @@
.input-header { .input-header {
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }

View File

@@ -4,9 +4,9 @@
import type {Parameter} from '#types'; import type {Parameter} from '#types';
import { import {
escapeHtml, escapeHtml,
flattenParameterCandidates,
findBackspaceTokenRange, findBackspaceTokenRange,
findTokenRangeAtCursor, findTokenRangeAtCursor,
flattenParameterCandidates,
insertTextAtCursor, insertTextAtCursor,
parseTokenParts, parseTokenParts,
splitTokenDisplay splitTokenDisplay
@@ -534,22 +534,22 @@
} }
.hint-item.hint-unresolved { .hint-item.hint-unresolved {
background: #fff8e6; background: var(--tf-warning-soft-bg);
border-color: #f6d99a; border-color: var(--tf-warning-soft-border);
color: #8a5a00; color: var(--tf-warning-soft-text);
.hint-item-icon { .hint-item-icon {
color: #d97706; color: var(--tf-warning-icon-color);
} }
} }
.hint-item.hint-undefined { .hint-item.hint-undefined {
background: #fff1f1; background: var(--tf-danger-soft-bg);
border-color: #f5c7c4; border-color: var(--tf-danger-soft-border);
color: #b42318; color: var(--tf-danger-soft-text);
.hint-item-icon { .hint-item-icon {
color: #d92d20; color: var(--tf-danger-icon-color);
} }
} }
@@ -570,7 +570,7 @@
border-radius: 5px; border-radius: 5px;
padding: 5px 8px; padding: 5px 8px;
box-sizing: border-box; box-sizing: border-box;
color: #333; color: var(--tf-text-primary);
pointer-events: none; pointer-events: none;
z-index: 0; z-index: 0;
font-family: inherit; font-family: inherit;
@@ -598,7 +598,7 @@
z-index: 1; z-index: 1;
background: transparent; background: transparent;
color: transparent; color: transparent;
caret-color: #333; caret-color: var(--tf-text-primary);
padding-right: 36px; padding-right: 36px;
font-family: inherit; font-family: inherit;
font-size: inherit; font-size: inherit;
@@ -609,7 +609,7 @@
.param-token-input::placeholder, .param-token-input::placeholder,
.param-token-textarea::placeholder { .param-token-textarea::placeholder {
color: #ccc; color: var(--tf-text-muted);
} }
.param-token-textarea { .param-token-textarea {
@@ -630,14 +630,15 @@
padding: 0 4px; padding: 0 4px;
font-size: 10px; font-size: 10px;
border-radius: 4px; border-radius: 4px;
color: #666; color: var(--tf-text-secondary);
background: rgba(255, 255, 255, 0.9); background: var(--tf-bg-surface);
border-color: var(--tf-border-color);
} }
:global(.param-token-button:hover) { :global(.param-token-button:hover) {
background: #f0f3ff; background: var(--tf-primary-soft-bg);
color: #2563eb; color: var(--tf-primary-color);
border-color: #d3defd; border-color: var(--tf-primary-soft-border);
} }
.param-token-panel { .param-token-panel {
@@ -645,10 +646,10 @@
max-width: 320px; max-width: 320px;
max-height: 220px; max-height: 220px;
overflow: auto; overflow: auto;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
padding: 6px; padding: 6px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -657,14 +658,14 @@
.param-token-item { .param-token-item {
border: none; border: none;
background: #fff; background: var(--tf-bg-surface);
padding: 6px 8px; padding: 6px 8px;
text-align: left; text-align: left;
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
font-size: 12px; font-size: 12px;
line-height: 1.3; line-height: 1.3;
color: #333; color: var(--tf-text-primary);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -672,13 +673,13 @@
} }
.param-token-item:hover { .param-token-item:hover {
background: #f5f7ff; background: var(--tf-bg-surface-alt);
color: #2563eb; color: var(--tf-primary-color);
} }
.param-token-item.unresolved { .param-token-item.unresolved {
background: #fff8e6; background: var(--tf-warning-soft-bg);
color: #92400e; color: var(--tf-warning-soft-text);
} }
.param-token-item-warn { .param-token-item-warn {
@@ -687,7 +688,7 @@
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: #d97706; color: var(--tf-warning-icon-color);
flex-shrink: 0; flex-shrink: 0;
svg { svg {
@@ -700,7 +701,7 @@
.param-token-empty { .param-token-empty {
padding: 8px; padding: 8px;
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
text-align: center; text-align: center;
} }
@@ -729,20 +730,20 @@
} }
:global(.param-token-valid) { :global(.param-token-valid) {
background: #eaf2ff; background: var(--tf-primary-soft-bg);
color: #1e4ed8; color: var(--tf-primary-color);
box-shadow: inset 0 0 0 1px #c6d8ff; box-shadow: inset 0 0 0 1px var(--tf-primary-soft-border);
} }
:global(.param-token-invalid) { :global(.param-token-invalid) {
background: #fff1f1; background: var(--tf-danger-soft-bg);
color: #b42318; color: var(--tf-danger-soft-text);
box-shadow: inset 0 0 0 1px #f5c7c4; box-shadow: inset 0 0 0 1px var(--tf-danger-soft-border);
} }
:global(.param-token-warning) { :global(.param-token-warning) {
background: #fff8e6; background: var(--tf-warning-soft-bg);
color: #92400e; color: var(--tf-warning-soft-text);
box-shadow: inset 0 0 0 1px #f7d79e; box-shadow: inset 0 0 0 1px var(--tf-warning-soft-border);
} }
</style> </style>

View File

@@ -155,18 +155,18 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
border-radius: 5px; border-radius: 5px;
width: 200px; width: 200px;
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
.input-more-item { .input-more-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 3px; gap: 3px;
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }

View File

@@ -47,7 +47,7 @@
.none-params { .none-params {
font-size: 12px; font-size: 12px;
background: #f8f8f8; background: var(--tf-bg-muted);
height: 40px; height: 40px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -59,7 +59,7 @@
.input-header { .input-header {
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
} }
} }

View File

@@ -3,8 +3,7 @@
import {type NodeProps, useNodesData, useSvelteFlow} from '@xyflow/svelte'; import {type NodeProps, useNodesData, useSvelteFlow} from '@xyflow/svelte';
import {Button, Heading, Select} from '../base'; import {Button, Heading, Select} from '../base';
import RefParameterList from '../core/RefParameterList.svelte'; import RefParameterList from '../core/RefParameterList.svelte';
import {getCurrentNodeId} from '#components/utils/NodeUtils'; import {getCurrentNodeId, getOptions} from '#components/utils/NodeUtils';
import {getOptions} from '#components/utils/NodeUtils';
import {useAddParameter} from '../utils/useAddParameter.svelte'; import {useAddParameter} from '../utils/useAddParameter.svelte';
import OutputDefList from '../core/OutputDefList.svelte'; import OutputDefList from '../core/OutputDefList.svelte';
import {onMount} from 'svelte'; import {onMount} from 'svelte';
@@ -152,7 +151,7 @@
.setting-title { .setting-title {
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
margin-bottom: 4px; margin-bottom: 4px;
margin-top: 10px; margin-top: 10px;
} }

View File

@@ -784,7 +784,7 @@
.condition-rail-title { .condition-rail-title {
font-size: 13px; font-size: 13px;
color: #475569; color: var(--tf-text-secondary);
font-weight: 500; font-weight: 500;
} }
@@ -798,28 +798,28 @@
.condition-branch-row { .condition-branch-row {
position: relative; position: relative;
min-height: 44px; min-height: 44px;
border: 1px solid #e2e8f0; border: 1px solid var(--tf-border-color);
border-radius: 6px; border-radius: 6px;
display: flex; display: flex;
align-items: center; align-items: center;
background: #fff; background: var(--tf-bg-surface);
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
&:hover { &:hover {
border-color: #cbd5e1; border-color: var(--tf-border-color-strong);
background: #f8fafc; background: var(--tf-bg-hover);
} }
&.active { &.active {
border-color: #3b82f6; border-color: var(--tf-primary-color);
box-shadow: 0 0 0 1px #3b82f6; box-shadow: 0 0 0 1px var(--tf-primary-color);
z-index: 10; z-index: 10;
} }
&.default { &.default {
border-style: dashed; border-style: dashed;
background: #f8fafc; background: var(--tf-bg-hover);
cursor: default; /* Disable pointer since default branch is non-selectable */ cursor: default; /* Disable pointer since default branch is non-selectable */
} }
} }
@@ -833,12 +833,12 @@
:global(.condition-branch-row .tf-input) { :global(.condition-branch-row .tf-input) {
font-size: 13px; font-size: 13px;
color: #475569; color: var(--tf-text-secondary);
padding: 0; padding: 0;
} }
:global(.condition-branch-row .tf-input:focus) { :global(.condition-branch-row .tf-input:focus) {
color: #0f172a; color: var(--tf-text-primary);
} }
.condition-branch-prefix { .condition-branch-prefix {
@@ -849,7 +849,7 @@
align-items: center; align-items: center;
padding-left: 12px; padding-left: 12px;
padding-right: 8px; padding-right: 8px;
color: #64748b; color: var(--tf-text-secondary);
font-weight: 600; font-weight: 600;
white-space: nowrap; white-space: nowrap;
} }
@@ -861,7 +861,7 @@
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
font-size: 13px; font-size: 13px;
color: #334155; color: var(--tf-text-primary);
font-weight: 500; font-weight: 500;
} }
@@ -910,9 +910,9 @@
border-radius: 4px; border-radius: 4px;
font-size: 11px; font-size: 11px;
font-weight: 600; font-weight: 600;
color: #475569; color: var(--tf-text-secondary);
background: #f1f5f9; background: var(--tf-bg-muted);
border: 1px solid #cbd5e1; border: 1px solid var(--tf-border-color-strong);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -921,8 +921,8 @@
box-shadow: none; box-shadow: none;
&:hover { &:hover {
background: #e2e8f0; background: var(--tf-border-color);
color: #0f172a; color: var(--tf-text-primary);
} }
} }
@@ -949,9 +949,9 @@
:global(.condition-rule-add-btn) { :global(.condition-rule-add-btn) {
min-width: 140px; min-width: 140px;
background: #f8fafc; background: var(--tf-bg-hover);
border: 1px dashed #cbd5e1; border: 1px dashed var(--tf-border-color-strong);
color: #475569; color: var(--tf-text-secondary);
font-size: 13px; font-size: 13px;
padding: 6px 12px; padding: 6px 12px;
height: 28px; height: 28px;
@@ -961,9 +961,9 @@
transition: all 0.2s; transition: all 0.2s;
&:hover { &:hover {
background: #eff6ff; background: var(--tf-primary-soft-bg);
border-color: #93c5fd; border-color: var(--tf-primary-soft-border);
color: #3b82f6; color: var(--tf-primary-color);
} }
} }
@@ -977,7 +977,7 @@
align-items: center; align-items: center;
gap: 8px; gap: 8px;
/* Added to left-align the OR/AND switches properly above the left select */ /* Added to left-align the OR/AND switches properly above the left select */
color: #94a3b8; color: var(--tf-text-muted);
} }
/* Custom joiner text buttons */ /* Custom joiner text buttons */
@@ -987,25 +987,25 @@
padding: 2px 4px; padding: 2px 4px;
font-size: 12px; font-size: 12px;
font-weight: 600; font-weight: 600;
color: #94a3b8; color: var(--tf-text-muted);
cursor: pointer; cursor: pointer;
transition: all 0.2s; transition: all 0.2s;
border-radius: 4px; border-radius: 4px;
&:hover { &:hover {
color: #64748b; color: var(--tf-text-secondary);
background: #f1f5f9; background: var(--tf-bg-muted);
} }
&.active { &.active {
color: #3b82f6; color: var(--tf-primary-color);
background: #eff6ff; background: var(--tf-primary-soft-bg);
} }
} }
.tf-joiner-divider { .tf-joiner-divider {
font-size: 12px; font-size: 12px;
color: #cbd5e1; color: var(--tf-border-color-strong);
user-select: none; user-select: none;
} }
@@ -1021,7 +1021,7 @@
padding: 0; padding: 0;
border: none; border: none;
background: transparent; background: transparent;
color: #cbd5e1; color: var(--tf-border-color-strong);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -1035,8 +1035,8 @@
} }
&:hover { &:hover {
background: #fee2e2; background: var(--tf-danger-soft-bg);
color: #ef4444; color: var(--tf-danger-color);
} }
} }
@@ -1059,6 +1059,20 @@
min-width: 0; min-width: 0;
} }
:global(.condition-simple-rule-row .tf-select-input),
:global(.condition-simple-rule-row .tf-mixed-input-root),
:global(.condition-simple-rule-row .tf-input),
:global(.condition-simple-rule-row .tf-textarea) {
background: var(--tf-bg-input);
border-color: var(--tf-border-color-strong);
color: var(--tf-text-primary);
}
:global(.condition-simple-rule-row .tf-select-input:hover),
:global(.condition-simple-rule-row .tf-mixed-input-root:hover) {
border-color: var(--tf-border-color-strong);
}
:global(.condition-icon-btn) { :global(.condition-icon-btn) {
width: 26px; width: 26px;
height: 26px; height: 26px;
@@ -1066,7 +1080,7 @@
border-color: transparent; border-color: transparent;
border-radius: 4px; border-radius: 4px;
background: transparent; background: transparent;
color: #64748b; color: var(--tf-text-secondary);
padding: 0; padding: 0;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -1081,33 +1095,33 @@
} }
:global(.condition-icon-btn:hover:not(:disabled)) { :global(.condition-icon-btn:hover:not(:disabled)) {
background: #cbd5e1; background: var(--tf-border-color-strong);
color: #0f172a; color: var(--tf-text-primary);
} }
:global(.condition-icon-btn.danger) { :global(.condition-icon-btn.danger) {
color: #ef4444; color: var(--tf-danger-color);
} }
:global(.condition-icon-btn.danger:hover:not(:disabled)) { :global(.condition-icon-btn.danger:hover:not(:disabled)) {
background: #fee2e2; background: var(--tf-danger-soft-bg);
color: #b91c1c; color: var(--tf-danger-hover);
} }
:global(.condition-icon-btn:disabled), :global(.condition-icon-btn:disabled),
:global(.condition-icon-btn[disabled]) { :global(.condition-icon-btn[disabled]) {
color: #cbd5e1; color: var(--tf-border-color-strong);
background: transparent; background: transparent;
cursor: not-allowed; cursor: not-allowed;
} }
.condition-default-tip { .condition-default-tip {
color: #64748b; color: var(--tf-text-secondary);
font-size: 12px; font-size: 12px;
padding: 8px 10px; padding: 8px 10px;
border-radius: 6px; border-radius: 6px;
background: #f1f5f9; background: var(--tf-bg-muted);
border: 1px dashed #cbd5e1; border: 1px dashed var(--tf-border-color-strong);
text-align: center; text-align: center;
} }
@@ -1126,18 +1140,18 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #e2e8f0; border: 1px solid var(--tf-border-color);
border-radius: 6px; border-radius: 6px;
width: 180px; width: 180px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); box-shadow: var(--tf-shadow-medium);
.input-more-item { .input-more-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
font-size: 12px; font-size: 12px;
color: #64748b; color: var(--tf-text-secondary);
} }
} }

View File

@@ -113,7 +113,7 @@
.setting-title { .setting-title {
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
margin-bottom: 4px; margin-bottom: 4px;
margin-top: 10px; margin-top: 10px;
} }

View File

@@ -232,7 +232,7 @@
.setting-title { .setting-title {
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
margin-bottom: 4px; margin-bottom: 4px;
margin-top: 10px; margin-top: 10px;
} }
@@ -255,7 +255,7 @@
.slider-container span { .slider-container span {
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@@ -264,7 +264,7 @@
input[type="range"] { input[type="range"] {
width: 100%; width: 100%;
height: 4px; height: 4px;
background: #ddd; background: var(--tf-slider-track-bg);
border-radius: 2px; border-radius: 2px;
outline: none; outline: none;
-webkit-appearance: none; -webkit-appearance: none;
@@ -274,7 +274,7 @@
-webkit-appearance: none; -webkit-appearance: none;
width: 14px; width: 14px;
height: 14px; height: 14px;
background: #007bff; background: var(--tf-slider-thumb-bg);
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
} }

View File

@@ -271,15 +271,15 @@
.http-section { .http-section {
margin: 10px 0; margin: 10px 0;
padding: 10px; padding: 10px;
border: 1px solid #e6eaf2; border: 1px solid var(--tf-border-color);
border-radius: 8px; border-radius: 8px;
background: #fafcff; background: var(--tf-bg-surface-alt);
} }
.section-title { .section-title {
font-size: 12px; font-size: 12px;
line-height: 1.3; line-height: 1.3;
color: #6b7280; color: var(--tf-text-secondary);
font-weight: 600; font-weight: 600;
margin-bottom: 8px; margin-bottom: 8px;
} }
@@ -314,17 +314,17 @@
box-sizing: border-box; box-sizing: border-box;
padding: 5px 10px; padding: 5px 10px;
border-radius: 999px; border-radius: 999px;
border: 1px solid #dbe3f3; border: 1px solid var(--tf-border-color-strong);
background: #fff; background: var(--tf-bg-surface);
color: #4b5563; color: var(--tf-text-secondary);
cursor: pointer; cursor: pointer;
transition: all 0.15s ease; transition: all 0.15s ease;
} }
label.active { label.active {
background: #eef4ff; background: var(--tf-primary-soft-bg);
border-color: #c7d8ff; border-color: var(--tf-primary-soft-border);
color: #1d4ed8; color: var(--tf-primary-color);
} }
:global(input[type='radio']) { :global(input[type='radio']) {

View File

@@ -170,7 +170,7 @@
.setting-title { .setting-title {
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
margin-bottom: 4px; margin-bottom: 4px;
margin-top: 10px; margin-top: 10px;
} }

View File

@@ -285,7 +285,7 @@
.setting-title { .setting-title {
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
margin-bottom: 4px; margin-bottom: 4px;
margin-top: 10px; margin-top: 10px;
} }
@@ -308,7 +308,7 @@
.slider-container span { .slider-container span {
font-size: 12px; font-size: 12px;
color: #666; color: var(--tf-text-secondary);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@@ -316,18 +316,18 @@
.llm-setting { .llm-setting {
width: 200px; width: 200px;
background: #fff; background: var(--tf-bg-surface);
padding: 10px; padding: 10px;
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-medium);
border: 1px solid #ddd; border: 1px solid var(--tf-border-color-strong);
} }
input[type="range"] { input[type="range"] {
width: 100%; width: 100%;
height: 4px; height: 4px;
background: #ddd; background: var(--tf-slider-track-bg);
border-radius: 2px; border-radius: 2px;
outline: none; outline: none;
-webkit-appearance: none; -webkit-appearance: none;
@@ -337,9 +337,8 @@
-webkit-appearance: none; -webkit-appearance: none;
width: 14px; width: 14px;
height: 14px; height: 14px;
background: #007bff; background: var(--tf-slider-thumb-bg);
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
} }
</style> </style>

View File

@@ -81,15 +81,15 @@
content: '循环体'; content: '循环体';
width: 100px; width: 100px;
height: 20px; height: 20px;
background: #000; background: var(--tf-bg-surface-alt);
color: #fff; color: var(--tf-loop-handle-text);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
border: 1px solid var(--tf-border-color-strong);
border-radius: 4px;
} }
} }
</style> </style>

View File

@@ -156,7 +156,7 @@
.setting-title { .setting-title {
font-size: 12px; font-size: 12px;
color: #999; color: var(--tf-text-muted);
margin-bottom: 4px; margin-bottom: 4px;
margin-top: 10px; margin-top: 10px;
} }

View File

@@ -50,10 +50,9 @@
padding: 3px; padding: 3px;
&:hover { &:hover {
background: #eee; background: var(--tf-bg-hover);
border: 1px solid transparent; border: 1px solid transparent;
} }
} }
</style> </style>

View File

@@ -3,8 +3,9 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 2px; gap: 2px;
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #ccc; border: 1px solid var(--tf-border-color-strong);
color: var(--tf-text-primary);
cursor: pointer; cursor: pointer;
border-radius: 5px; border-radius: 5px;
padding: 5px; padding: 5px;
@@ -25,11 +26,11 @@
.tf-btn.tf-btn-primary { .tf-btn.tf-btn-primary {
background: var(--tf-primary-color); background: var(--tf-primary-color);
color: #fff; color: var(--tf-loop-handle-text);
&:hover { &:hover {
border: 1px solid #ccc; border: 1px solid var(--tf-border-color-strong);
background: #3a6fe3; background: var(--tf-primary-color-hover);
} }
} }
@@ -37,7 +38,9 @@
.tf-input, .tf-textarea { .tf-input, .tf-textarea {
display: flex; display: flex;
border-radius: 5px; border-radius: 5px;
border: 1px solid #ccc; border: 1px solid var(--tf-border-color-strong);
background: var(--tf-bg-input);
color: var(--tf-text-primary);
padding: 5px 8px; padding: 5px 8px;
box-sizing: border-box; box-sizing: border-box;
resize: vertical; resize: vertical;
@@ -46,21 +49,21 @@
overflow-y: hidden; overflow-y: hidden;
&::placeholder { &::placeholder {
color: #ccc; color: var(--tf-text-muted);
font-size: 12px; font-size: 12px;
} }
// 获得焦点时的样式 // 获得焦点时的样式
&:focus { &:focus {
border-color: var(--tf-primary-color); border-color: var(--tf-primary-color);
box-shadow: 0 0 5px rgba(81, 203, 238, .2); box-shadow: var(--tf-focus-shadow);
} }
// 禁用时的样式 // 禁用时的样式
&[disabled] { &[disabled] {
background-color: #f0f0f0; background-color: var(--tf-bg-input-disabled);
cursor: not-allowed; cursor: not-allowed;
color: #aaa; color: var(--tf-text-disabled);
} }
} }
@@ -68,26 +71,26 @@
.tf-select { .tf-select {
&-input { &-input {
display: flex; display: flex;
border: 1px solid #e5e7eb; border: 1px solid var(--tf-border-color);
padding: 4px 10px; padding: 4px 10px;
border-radius: 6px; border-radius: 6px;
font-size: 13px; font-size: 13px;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
background: #fff; background: var(--tf-bg-input);
height: 32px; height: 32px;
transition: all 0.2s; transition: all 0.2s;
width: 100%; width: 100%;
color: #111827; color: var(--tf-text-primary);
&:hover { &:hover {
border-color: #d1d5db; border-color: var(--tf-border-color-strong);
} }
&:focus, &.active { &:focus, &.active {
border-color: #2563eb; border-color: var(--tf-primary-color);
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.1); box-shadow: var(--tf-focus-shadow);
} }
&-value { &-value {
@@ -105,13 +108,13 @@
display: flex; display: flex;
width: 16px; width: 16px;
height: 16px; height: 16px;
color: #6b7280; color: var(--tf-text-secondary);
flex-shrink: 0; flex-shrink: 0;
margin-left: 4px; margin-left: 4px;
} }
&-placeholder { &-placeholder {
color: #9ca3af; color: var(--tf-text-muted);
} }
} }
@@ -133,7 +136,7 @@
padding: 5px; padding: 5px;
border-radius: 5px; border-radius: 5px;
border: none; border: none;
background: #F4F4F5; background: var(--tf-bg-muted);
.tf-tabs-item { .tf-tabs-item {
flex-grow: 1; flex-grow: 1;
@@ -144,14 +147,14 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 14px; font-size: 14px;
color: #808088; color: var(--tf-text-secondary);
} }
.tf-tabs-item.active { .tf-tabs-item.active {
background: #fff; background: var(--tf-bg-surface);
color: #333; color: var(--tf-text-primary);
font-weight: 500; font-weight: 500;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.15); box-shadow: var(--tf-shadow-soft);
} }
} }
@@ -160,7 +163,7 @@ h3.tf-heading {
font-size: 14px; font-size: 14px;
margin-top: 2px; margin-top: 2px;
margin-bottom: 3px; margin-bottom: 3px;
color: #333; color: var(--tf-text-primary);
} }
@@ -181,8 +184,8 @@ h3.tf-heading {
display: flex; display: flex;
width: 26px; width: 26px;
height: 26px; height: 26px;
color: #2563EB; color: var(--tf-icon-color);
background: #cedafb; background: var(--tf-icon-bg);
border-radius: 5px; border-radius: 5px;
padding: 3px; padding: 3px;
justify-content: center; justify-content: center;
@@ -192,7 +195,7 @@ h3.tf-heading {
svg { svg {
width: 22px; width: 22px;
height: 22px; height: 22px;
color: #3474ff; color: var(--tf-icon-color);
} }
} }
@@ -208,7 +211,7 @@ h3.tf-heading {
&-description { &-description {
font-size: 12px; font-size: 12px;
margin: 10px 0; margin: 10px 0;
color: #999; color: var(--tf-text-muted);
} }
} }
} }

View File

@@ -18,7 +18,7 @@
&::after { &::after {
content: ' '; content: ' ';
background: #2563EB; background: var(--tf-primary-color);
width: 8px; width: 8px;
height: 8px; height: 8px;
border-radius: 100%; border-radius: 100%;
@@ -36,12 +36,12 @@
div.loop_handle_wrapper { div.loop_handle_wrapper {
&::after { &::after {
content: '循环体'; content: '循环体';
background: #2563EB; background: var(--tf-primary-color);
width: 100px; width: 100px;
height: 20px; height: 20px;
border-radius: 0; border-radius: 0;
display: flex; display: flex;
color: #fff; color: var(--tf-loop-handle-text);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
@@ -60,17 +60,17 @@
border-radius: 5px; border-radius: 5px;
top: -2px; top: -2px;
left: -2px; left: -2px;
border: 1px solid #ccc; border: 1px solid var(--tf-node-outline-color);
height: calc(100% + 2px); height: calc(100% + 2px);
width: calc(100% + 2px); width: calc(100% + 2px);
} }
&:hover { &:hover {
border: 3px solid #bacaef7d; border: 3px solid var(--tf-node-hover-border);
} }
&.selectable.selected { &.selectable.selected {
border: 3px solid #bacaef7d; border: 3px solid var(--tf-node-hover-border);
box-shadow: var(--xy-node-boxshadow-selected); box-shadow: var(--xy-node-boxshadow-selected);
} }
@@ -88,7 +88,7 @@
.tf-node-wrapper { .tf-node-wrapper {
border-radius: 5px; border-radius: 5px;
min-width: 300px; min-width: 300px;
background: #fff; background: var(--tf-bg-surface);
&-body { &-body {
padding: 10px; padding: 10px;
@@ -114,10 +114,10 @@
} }
&-container { &-container {
background: #fff; background: var(--tf-bg-surface);
border: 1px solid #eee; border: 1px solid var(--tf-border-color);
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); box-shadow: var(--tf-shadow-soft);
padding: 10px; padding: 10px;
width: fit-content; width: fit-content;
@@ -147,11 +147,11 @@
svg { svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: #2563EB; fill: var(--tf-primary-color);
} }
&:hover { &:hover {
background: #f1f1f1; background: var(--tf-bg-hover);
} }
} }
} }

View File

@@ -1,14 +1,144 @@
:root, :root,
:root .tf-theme-light { :root .tf-theme-light {
--tf-primary-color: #2563EB; --tf-primary-color: #2563eb;
--tf-primary-color-hover: #3a6fe3;
--tf-primary-soft-bg: #eff6ff;
--tf-primary-soft-border: #bfdbfe;
--tf-primary-ghost-bg: rgba(37, 99, 235, 0.08);
--tf-danger-color: #ef4444;
--tf-danger-hover: #dc2626;
--tf-danger-soft-bg: #fff1f1;
--tf-danger-soft-border: #f5c7c4;
--tf-danger-soft-text: #b42318;
--tf-danger-icon-color: #d92d20;
--tf-warning-soft-bg: #fff8e6;
--tf-warning-soft-border: #f7d79e;
--tf-warning-soft-text: #92400e;
--tf-warning-icon-color: #d97706;
--tf-bg-canvas: #f8fafc;
--tf-bg-surface: #ffffff;
--tf-bg-surface-alt: #f9fafb;
--tf-bg-muted: #f3f4f6;
--tf-bg-hover: #f1f5f9;
--tf-bg-active: #e2e8f0;
--tf-bg-input: #ffffff;
--tf-bg-input-disabled: #f3f4f6;
--tf-bg-tag: rgba(0, 0, 0, 0.06);
--tf-border-color: #e5e7eb;
--tf-border-color-strong: #d1d5db;
--tf-border-color-soft: #f3f4f6;
--tf-node-outline-color: #d1d5db;
--tf-node-hover-border: rgba(186, 202, 239, 0.49);
--tf-text-primary: #111827;
--tf-text-secondary: #6b7280;
--tf-text-muted: #9ca3af;
--tf-text-disabled: #9ca3af;
--tf-icon-bg: #cedafb;
--tf-icon-color: #3474ff;
--tf-loop-handle-text: #ffffff;
--tf-shadow-soft: 0 2px 4px rgba(0, 0, 0, 0.08);
--tf-shadow-medium: 0 10px 25px rgba(0, 0, 0, 0.15);
--tf-focus-shadow: 0 0 0 2px rgba(37, 99, 235, 0.12);
--tf-tip-bg: #0f172a;
--tf-tip-text: #f8fafc;
--tf-scrollbar-thumb: #d6dce8;
--tf-slider-track-bg: #d1d5db;
--tf-slider-thumb-bg: var(--tf-primary-color);
--xy-node-boxshadow-selected: 0 0 0 1px var(--tf-primary-color); --xy-node-boxshadow-selected: 0 0 0 1px var(--tf-primary-color);
--xy-handle-background-color: var(--tf-primary-color); --xy-handle-background-color: var(--tf-primary-color);
--xy-handle-border-color: var(--tf-bg-surface);
--xy-background-color: var(--tf-bg-canvas);
--xy-background-pattern-dots-color: #d1d5db;
--xy-background-pattern-lines-color: #e5e7eb;
--xy-background-pattern-cross-color: #e2e8f0;
--xy-edge-stroke: #94a3b8;
--xy-edge-stroke-selected: var(--tf-primary-color);
--xy-controls-button-background-color: var(--tf-bg-surface);
--xy-controls-button-background-color-hover: var(--tf-bg-hover);
--xy-controls-button-color: var(--tf-text-secondary);
--xy-controls-button-color-hover: var(--tf-text-primary);
--xy-controls-button-border-color: var(--tf-border-color);
--xy-minimap-background-color: var(--tf-bg-surface);
--xy-minimap-mask-background-color: rgba(241, 245, 249, 0.68);
--xy-minimap-node-background-color: #cbd5e1;
--xy-edge-label-background-color: var(--tf-bg-surface);
--xy-edge-label-color: var(--tf-text-primary);
} }
//the dark theme variables
:root .tf-theme-dark { :root .tf-theme-dark {
--tf-primary-color: #60a5fa;
--tf-primary-color-hover: #93c5fd;
--tf-primary-soft-bg: rgba(96, 165, 250, 0.18);
--tf-primary-soft-border: rgba(96, 165, 250, 0.35);
--tf-primary-ghost-bg: rgba(96, 165, 250, 0.12);
--tf-danger-color: #f87171;
--tf-danger-hover: #ef4444;
--tf-danger-soft-bg: rgba(248, 113, 113, 0.16);
--tf-danger-soft-border: rgba(248, 113, 113, 0.28);
--tf-danger-soft-text: #fca5a5;
--tf-danger-icon-color: #f87171;
--tf-warning-soft-bg: rgba(217, 119, 6, 0.2);
--tf-warning-soft-border: rgba(217, 119, 6, 0.35);
--tf-warning-soft-text: #fbbf24;
--tf-warning-icon-color: #f59e0b;
--tf-bg-canvas: #0b1220;
--tf-bg-surface: #111827;
--tf-bg-surface-alt: #1f2937;
--tf-bg-muted: #273449;
--tf-bg-hover: #334155;
--tf-bg-active: #3b4b63;
--tf-bg-input: #0f172a;
--tf-bg-input-disabled: #0b1324;
--tf-bg-tag: rgba(148, 163, 184, 0.2);
--tf-border-color: #334155;
--tf-border-color-strong: #475569;
--tf-border-color-soft: #263449;
--tf-node-outline-color: #475569;
--tf-node-hover-border: rgba(96, 165, 250, 0.38);
--tf-text-primary: #e5e7eb;
--tf-text-secondary: #cbd5e1;
--tf-text-muted: #94a3b8;
--tf-text-disabled: #64748b;
--tf-icon-bg: rgba(96, 165, 250, 0.2);
--tf-icon-color: #93c5fd;
--tf-loop-handle-text: #f8fafc;
--tf-shadow-soft: 0 2px 8px rgba(2, 6, 23, 0.35);
--tf-shadow-medium: 0 10px 25px rgba(2, 6, 23, 0.48);
--tf-focus-shadow: 0 0 0 2px rgba(96, 165, 250, 0.2);
--tf-tip-bg: #020617;
--tf-tip-text: #e2e8f0;
--tf-scrollbar-thumb: #475569;
--tf-slider-track-bg: #475569;
--tf-slider-thumb-bg: #93c5fd;
--xy-node-boxshadow-selected: 0 0 0 1px var(--tf-primary-color);
--xy-handle-background-color: var(--tf-primary-color);
--xy-handle-border-color: var(--tf-bg-canvas);
--xy-background-color: var(--tf-bg-canvas);
--xy-background-pattern-dots-color: #334155;
--xy-background-pattern-lines-color: #334155;
--xy-background-pattern-cross-color: #334155;
--xy-edge-stroke: #64748b;
--xy-edge-stroke-selected: #93c5fd;
--xy-controls-button-background-color: var(--tf-bg-surface);
--xy-controls-button-background-color-hover: var(--tf-bg-hover);
--xy-controls-button-color: var(--tf-text-secondary);
--xy-controls-button-color-hover: var(--tf-text-primary);
--xy-controls-button-border-color: var(--tf-border-color);
--xy-minimap-background-color: var(--tf-bg-surface);
--xy-minimap-mask-background-color: rgba(15, 23, 42, 0.7);
--xy-minimap-node-background-color: #475569;
--xy-edge-label-background-color: var(--tf-bg-surface);
--xy-edge-label-color: var(--tf-text-primary);
} }

View File

@@ -0,0 +1,70 @@
import {beforeEach, describe, expect, it} from 'vitest';
import {componentName} from './consts';
import {Tinyflow} from './Tinyflow';
describe('tinyflow theme', () => {
beforeEach(() => {
document.body.innerHTML = '';
});
it('should use light theme by default', () => {
const container = document.createElement('div');
document.body.append(container);
const tinyflow = new Tinyflow({
element: container
});
const tinyflowEl = container.querySelector(componentName);
expect(tinyflowEl).toBeTruthy();
expect(tinyflowEl?.classList.contains('tf-theme-light')).toBe(true);
expect(tinyflowEl?.classList.contains('tf-theme-dark')).toBe(false);
tinyflow.destroy();
});
it('should toggle theme class without remount', () => {
const container = document.createElement('div');
document.body.append(container);
const tinyflow = new Tinyflow({
element: container,
theme: 'dark'
});
const tinyflowEl = container.querySelector(componentName);
expect(tinyflowEl?.classList.contains('tf-theme-dark')).toBe(true);
tinyflow.setTheme('light');
expect(tinyflowEl?.classList.contains('tf-theme-light')).toBe(true);
expect(tinyflowEl?.classList.contains('tf-theme-dark')).toBe(false);
tinyflow.destroy();
});
it('should keep theme when data is reset', () => {
const container = document.createElement('div');
document.body.append(container);
const tinyflow = new Tinyflow({
element: container,
theme: 'dark'
});
const firstRenderEl = container.querySelector(componentName);
tinyflow.setData({
nodes: [],
edges: []
});
const secondRenderEl = container.querySelector(componentName);
expect(firstRenderEl).toBeTruthy();
expect(secondRenderEl).toBeTruthy();
expect(secondRenderEl).not.toBe(firstRenderEl);
expect(secondRenderEl?.classList.contains('tf-theme-dark')).toBe(true);
tinyflow.destroy();
});
});

View File

@@ -2,6 +2,7 @@ import type {Snippet} from 'svelte';
import type {Node, useSvelteFlow} from '@xyflow/svelte'; import type {Node, useSvelteFlow} from '@xyflow/svelte';
export type TinyflowData = Partial<ReturnType<ReturnType<typeof useSvelteFlow>['toObject']>>; export type TinyflowData = Partial<ReturnType<ReturnType<typeof useSvelteFlow>['toObject']>>;
export type TinyflowTheme = 'light' | 'dark';
export type SelectItem = { export type SelectItem = {
value: number | string; value: number | string;
@@ -82,6 +83,7 @@ export type CustomNode = {
export type TinyflowOptions = { export type TinyflowOptions = {
element: string | Element; element: string | Element;
theme?: TinyflowTheme;
data?: TinyflowData | string; data?: TinyflowData | string;
provider?: { provider?: {
llm?: () => SelectItem[] | Promise<SelectItem[]>; llm?: () => SelectItem[] | Promise<SelectItem[]>;

View File

@@ -5,7 +5,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {Tinyflow as TinyflowNative, TinyflowOptions} from '@tinyflow-ai/ui'; import {Tinyflow as TinyflowNative, TinyflowOptions} from '@tinyflow-ai/ui';
import '@tinyflow-ai/ui/dist/index.css'; import '@tinyflow-ai/ui/dist/index.css';
import {onMounted, onUnmounted, ref} from 'vue'; import {onMounted, onUnmounted, ref, watch} from 'vue';
const props = defineProps< const props = defineProps<
{ {
@@ -55,6 +55,15 @@ onUnmounted(() => {
} }
}); });
watch(
() => props.theme,
(theme) => {
if (tinyflow) {
tinyflow.setTheme(theme || 'light');
}
}
);
const getData = () => { const getData = () => {
if (tinyflow) { if (tinyflow) {
return tinyflow.getData(); return tinyflow.getData();
@@ -71,8 +80,17 @@ const getInstance = () => {
return null; return null;
}; };
const focusNode = async (nodeId: string, options?: { duration?: number; zoom?: number }) => {
if (tinyflow) {
return tinyflow.focusNode(nodeId, options);
}
console.warn('Tinyflow instance is not initialized');
return false;
};
defineExpose({ defineExpose({
getData, getData,
getInstance getInstance,
focusNode
}); });
</script> </script>