feat(ui): scaffold @langgenius/dify-ui and migrate design tokens (#35256)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
yyh 2026-04-15 21:11:20 +08:00 committed by GitHub
parent dbceb3067e
commit af7d5e60b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
990 changed files with 3065 additions and 5786 deletions

View File

@ -0,0 +1,27 @@
# @langgenius/dify-ui
This package provides shared design tokens (colors, shadows, typography), the `cn()` utility, and a Tailwind CSS preset consumed by `web/`.
## Border Radius: Figma Token → Tailwind Class Mapping
The Figma design system uses `--radius/*` tokens whose scale is **offset by one step** from Tailwind CSS v4 defaults. When translating Figma specs to code, always use this mapping — never use `radius-*` as a CSS class, and never extend `borderRadius` in the preset.
| Figma Token | Value | Tailwind Class |
|---|---|---|
| `--radius/2xs` | 2px | `rounded-xs` |
| `--radius/xs` | 4px | `rounded-sm` |
| `--radius/sm` | 6px | `rounded-md` |
| `--radius/md` | 8px | `rounded-lg` |
| `--radius/lg` | 10px | `rounded-[10px]` |
| `--radius/xl` | 12px | `rounded-xl` |
| `--radius/2xl` | 16px | `rounded-2xl` |
| `--radius/3xl` | 20px | `rounded-[20px]` |
| `--radius/6xl` | 28px | `rounded-[28px]` |
| `--radius/full` | 999px | `rounded-full` |
### Rules
- **Do not** add custom `borderRadius` values to `tailwind-preset.ts`. We use Tailwind v4 defaults and arbitrary values (`rounded-[Npx]`) for sizes without a standard equivalent.
- **Do not** use `radius-*` as CSS class names. The old `@utility radius-*` definitions have been removed.
- When the Figma MCP returns `rounded-[var(--radius/sm, 6px)]`, convert it to the standard Tailwind class from the table above (e.g. `rounded-md`).
- For values without a standard Tailwind equivalent (10px, 20px, 28px), use arbitrary values like `rounded-[10px]`.

View File

@ -0,0 +1,24 @@
{
"name": "@langgenius/dify-ui",
"version": "0.0.1",
"private": true,
"type": "module",
"exports": {
"./styles.css": "./src/styles/styles.css",
"./tailwind-preset": {
"import": "./src/tailwind-preset.ts",
"types": "./src/tailwind-preset.ts"
},
"./cn": {
"import": "./src/cn.ts",
"types": "./src/cn.ts"
}
},
"dependencies": {
"clsx": "catalog:",
"tailwind-merge": "catalog:"
},
"devDependencies": {
"tailwindcss": "catalog:"
}
}

View File

@ -0,0 +1,3 @@
@import '../themes/light.css' layer(base);
@import '../themes/dark.css' layer(base);
@import './utilities.css';

View File

@ -0,0 +1,272 @@
@utility system-kbd {
font-size: 12px;
font-weight: 500;
line-height: 16px;
}
@utility system-2xs-regular-uppercase {
font-size: 10px;
font-weight: 400;
text-transform: uppercase;
line-height: 12px;
}
@utility system-2xs-regular {
font-size: 10px;
font-weight: 400;
line-height: 12px;
}
@utility system-2xs-medium {
font-size: 10px;
font-weight: 500;
line-height: 12px;
}
@utility system-2xs-medium-uppercase {
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
line-height: 12px;
}
@utility system-2xs-semibold-uppercase {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
line-height: 12px;
}
@utility system-xs-regular {
font-size: 12px;
font-weight: 400;
line-height: 16px;
}
@utility system-xs-regular-uppercase {
font-size: 12px;
font-weight: 400;
text-transform: uppercase;
line-height: 16px;
}
@utility system-xs-medium {
font-size: 12px;
font-weight: 500;
line-height: 16px;
}
@utility system-xs-medium-uppercase {
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
line-height: 16px;
}
@utility system-xs-semibold {
font-size: 12px;
font-weight: 600;
line-height: 16px;
}
@utility system-xs-semibold-uppercase {
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
line-height: 16px;
}
@utility system-sm-regular {
font-size: 13px;
font-weight: 400;
line-height: 16px;
}
@utility system-sm-medium {
font-size: 13px;
font-weight: 500;
line-height: 16px;
}
@utility system-sm-medium-uppercase {
font-size: 13px;
font-weight: 500;
text-transform: uppercase;
line-height: 16px;
}
@utility system-sm-semibold {
font-size: 13px;
font-weight: 600;
line-height: 16px;
}
@utility system-sm-semibold-uppercase {
font-size: 13px;
font-weight: 600;
text-transform: uppercase;
line-height: 16px;
}
@utility system-md-regular {
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
@utility system-md-medium {
font-size: 14px;
font-weight: 500;
line-height: 20px;
}
@utility system-md-semibold {
font-size: 14px;
font-weight: 600;
line-height: 20px;
}
@utility system-md-semibold-uppercase {
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
line-height: 20px;
}
@utility system-xl-medium {
font-size: 16px;
font-weight: 500;
line-height: 24px;
}
@utility system-xl-semibold {
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
@utility code-xs-regular {
font-size: 12px;
font-weight: 400;
line-height: 1.5;
}
@utility code-sm-regular {
font-size: 13px;
font-weight: 400;
line-height: 1.5;
}
@utility code-sm-semibold {
font-size: 13px;
font-weight: 600;
line-height: 1.5;
}
@utility body-xs-regular {
font-size: 12px;
font-weight: 400;
line-height: 16px;
}
@utility body-xs-medium {
font-size: 12px;
font-weight: 500;
line-height: 16px;
}
@utility body-sm-regular {
font-size: 13px;
font-weight: 400;
line-height: 16px;
}
@utility body-sm-medium {
font-size: 13px;
font-weight: 500;
line-height: 16px;
}
@utility body-md-regular {
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
@utility body-md-medium {
font-size: 14px;
font-weight: 500;
line-height: 20px;
}
@utility body-lg-regular {
font-size: 15px;
font-weight: 400;
line-height: 20px;
}
@utility body-2xl-regular {
font-size: 18px;
font-weight: 400;
line-height: 1.5;
}
@utility title-xs-semi-bold {
font-size: 12px;
font-weight: 600;
line-height: 16px;
}
@utility title-sm-semi-bold {
font-size: 13px;
font-weight: 600;
line-height: 16px;
}
@utility title-md-semi-bold {
font-size: 14px;
font-weight: 600;
line-height: 20px;
}
@utility title-lg-bold {
font-size: 15px;
font-weight: 700;
line-height: 1.2;
}
@utility title-xl-semi-bold {
font-size: 16px;
font-weight: 600;
line-height: 1.2;
}
@utility title-2xl-semi-bold {
font-size: 18px;
font-weight: 600;
line-height: 1.2;
}
@utility title-3xl-semi-bold {
font-size: 20px;
font-weight: 600;
line-height: 1.2;
}
@utility title-3xl-bold {
font-size: 20px;
font-weight: 700;
line-height: 1.2;
}
@utility title-4xl-semi-bold {
font-size: 24px;
font-weight: 600;
line-height: 1.2;
}
@utility title-5xl-bold {
font-size: 30px;
font-weight: 700;
line-height: 1.2;
}

View File

@ -0,0 +1,87 @@
import tailwindThemeVarDefine from './themes/tailwind-theme-var-define'
const difyUIPreset = {
theme: {
extend: {
colors: {
gray: {
25: '#fcfcfd',
50: '#f9fafb',
100: '#f2f4f7',
200: '#eaecf0',
300: '#d0d5dd',
400: '#98a2b3',
500: '#667085',
600: '#344054',
700: '#475467',
800: '#1d2939',
900: '#101828',
},
primary: {
25: '#f5f8ff',
50: '#eff4ff',
100: '#d1e0ff',
200: '#b2ccff',
300: '#84adff',
400: '#528bff',
500: '#2970ff',
600: '#155eef',
700: '#004eeb',
800: '#0040c1',
900: '#00359e',
},
blue: {
500: '#E1EFFE',
},
green: {
50: '#F3FAF7',
100: '#DEF7EC',
800: '#03543F',
},
yellow: {
100: '#FDF6B2',
800: '#723B13',
},
purple: {
50: '#F6F5FF',
200: '#DCD7FE',
},
indigo: {
25: '#F5F8FF',
50: '#EEF4FF',
100: '#E0EAFF',
300: '#A4BCFD',
400: '#8098F9',
600: '#444CE7',
800: '#2D31A6',
},
...tailwindThemeVarDefine,
},
boxShadow: {
'xs': '0px 1px 2px 0px rgba(16, 24, 40, 0.05)',
'sm': '0px 1px 2px 0px rgba(16, 24, 40, 0.06), 0px 1px 3px 0px rgba(16, 24, 40, 0.10)',
'sm-no-bottom': '0px -1px 2px 0px rgba(16, 24, 40, 0.06), 0px -1px 3px 0px rgba(16, 24, 40, 0.10)',
'md': '0px 2px 4px -2px rgba(16, 24, 40, 0.06), 0px 4px 8px -2px rgba(16, 24, 40, 0.10)',
'lg': '0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08)',
'xl': '0px 8px 8px -4px rgba(16, 24, 40, 0.03), 0px 20px 24px -4px rgba(16, 24, 40, 0.08)',
'2xl': '0px 24px 48px -12px rgba(16, 24, 40, 0.18)',
'3xl': '0px 32px 64px -12px rgba(16, 24, 40, 0.14)',
'status-indicator-green-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-success-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-warning-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-warning-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-red-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-error-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-blue-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-normal-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-gray-shadow': '0px 1px 2px 0px var(--color-components-badge-status-light-disabled-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
},
opacity: {
2: '0.02',
8: '0.08',
},
fontSize: {
'2xs': '0.625rem',
},
},
},
plugins: [],
}
export default difyUIPreset

View File

@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "dist",
"rootDir": "src",
"isolatedModules": true,
"verbatimModuleSyntax": true
},
"include": ["src"]
}

85
pnpm-lock.yaml generated
View File

@ -599,6 +599,19 @@ importers:
specifier: 'catalog:'
version: 0.1.16(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.6.0)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.1)(tsx@4.21.0)(typescript@6.0.2)(yaml@2.8.3))(happy-dom@20.9.0)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.1)(tsx@4.21.0)(typescript@6.0.2)(yaml@2.8.3)
packages/dify-ui:
dependencies:
clsx:
specifier: 'catalog:'
version: 2.1.1
tailwind-merge:
specifier: 'catalog:'
version: 3.5.0
devDependencies:
tailwindcss:
specifier: 'catalog:'
version: 4.2.2
packages/iconify-collections:
devDependencies:
iconify-import-svg:
@ -739,9 +752,6 @@ importers:
client-only:
specifier: 'catalog:'
version: 0.0.1
clsx:
specifier: 'catalog:'
version: 2.1.1
cmdk:
specifier: 'catalog:'
version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
@ -922,9 +932,6 @@ importers:
string-ts:
specifier: 'catalog:'
version: 2.3.1
tailwind-merge:
specifier: 'catalog:'
version: 3.5.0
tldts:
specifier: 'catalog:'
version: 7.0.28
@ -971,6 +978,9 @@ importers:
'@iconify-json/ri':
specifier: 'catalog:'
version: 1.2.10
'@langgenius/dify-ui':
specifier: workspace:*
version: link:../packages/dify-ui
'@mdx-js/loader':
specifier: 'catalog:'
version: 3.1.1(webpack@5.105.4(uglify-js@3.19.3))
@ -1126,7 +1136,7 @@ importers:
version: 4.12.12
knip:
specifier: 'catalog:'
version: 6.4.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)
version: 6.4.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
postcss:
specifier: 'catalog:'
version: 8.5.9
@ -1553,14 +1563,17 @@ packages:
peerDependencies:
tailwindcss: '*'
'@emnapi/core@1.9.1':
resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==}
'@emnapi/core@1.9.2':
resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==}
'@emnapi/runtime@1.9.1':
resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==}
'@emnapi/wasi-threads@1.2.0':
resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==}
'@emnapi/runtime@1.9.2':
resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==}
'@emnapi/wasi-threads@1.2.1':
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
'@emoji-mart/data@1.2.1':
resolution: {integrity: sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==}
@ -8007,6 +8020,10 @@ packages:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
tinyglobby@0.2.16:
resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
engines: {node: '>=12.0.0'}
tinypool@2.1.0:
resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==}
engines: {node: ^20.0.0 || >=22.0.0}
@ -9153,9 +9170,9 @@ snapshots:
'@iconify/utils': 3.1.0
tailwindcss: 4.2.2
'@emnapi/core@1.9.1':
'@emnapi/core@1.9.2':
dependencies:
'@emnapi/wasi-threads': 1.2.0
'@emnapi/wasi-threads': 1.2.1
tslib: 2.8.1
optional: true
@ -9164,7 +9181,12 @@ snapshots:
tslib: 2.8.1
optional: true
'@emnapi/wasi-threads@1.2.0':
'@emnapi/runtime@1.9.2':
dependencies:
tslib: 2.8.1
optional: true
'@emnapi/wasi-threads@1.2.1':
dependencies:
tslib: 2.8.1
optional: true
@ -9944,10 +9966,10 @@ snapshots:
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
'@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)':
'@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
dependencies:
'@emnapi/core': 1.9.1
'@emnapi/runtime': 1.9.1
'@emnapi/core': 1.9.2
'@emnapi/runtime': 1.9.2
'@tybys/wasm-util': 0.10.1
optional: true
@ -10120,9 +10142,9 @@ snapshots:
'@oxc-parser/binding-openharmony-arm64@0.121.0':
optional: true
'@oxc-parser/binding-wasm32-wasi@0.121.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)':
'@oxc-parser/binding-wasm32-wasi@0.121.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
dependencies:
'@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)
'@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
transitivePeerDependencies:
- '@emnapi/core'
- '@emnapi/runtime'
@ -10191,9 +10213,9 @@ snapshots:
'@oxc-resolver/binding-openharmony-arm64@11.19.1':
optional: true
'@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)':
'@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
dependencies:
'@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)
'@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
transitivePeerDependencies:
- '@emnapi/core'
- '@emnapi/runtime'
@ -11758,7 +11780,7 @@ snapshots:
debug: 4.4.3(supports-color@8.1.1)
minimatch: 10.2.4
semver: 7.7.4
tinyglobby: 0.2.15
tinyglobby: 0.2.16
ts-api-utils: 2.5.0(typescript@6.0.2)
typescript: 6.0.2
transitivePeerDependencies:
@ -14140,7 +14162,7 @@ snapshots:
khroma@2.1.0: {}
knip@6.4.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1):
knip@6.4.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2):
dependencies:
'@nodelib/fs.walk': 1.2.8
fast-glob: 3.3.3
@ -14148,8 +14170,8 @@ snapshots:
get-tsconfig: 4.13.7
jiti: 2.6.1
minimist: 1.2.8
oxc-parser: 0.121.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)
oxc-resolver: 11.19.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)
oxc-parser: 0.121.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
oxc-resolver: 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
picocolors: 1.1.1
picomatch: 4.0.4
smol-toml: 1.6.1
@ -15056,7 +15078,7 @@ snapshots:
type-check: 0.4.0
word-wrap: 1.2.5
oxc-parser@0.121.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1):
oxc-parser@0.121.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2):
dependencies:
'@oxc-project/types': 0.121.0
optionalDependencies:
@ -15076,7 +15098,7 @@ snapshots:
'@oxc-parser/binding-linux-x64-gnu': 0.121.0
'@oxc-parser/binding-linux-x64-musl': 0.121.0
'@oxc-parser/binding-openharmony-arm64': 0.121.0
'@oxc-parser/binding-wasm32-wasi': 0.121.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)
'@oxc-parser/binding-wasm32-wasi': 0.121.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
'@oxc-parser/binding-win32-arm64-msvc': 0.121.0
'@oxc-parser/binding-win32-ia32-msvc': 0.121.0
'@oxc-parser/binding-win32-x64-msvc': 0.121.0
@ -15084,7 +15106,7 @@ snapshots:
- '@emnapi/core'
- '@emnapi/runtime'
oxc-resolver@11.19.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1):
oxc-resolver@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2):
optionalDependencies:
'@oxc-resolver/binding-android-arm-eabi': 11.19.1
'@oxc-resolver/binding-android-arm64': 11.19.1
@ -15102,7 +15124,7 @@ snapshots:
'@oxc-resolver/binding-linux-x64-gnu': 11.19.1
'@oxc-resolver/binding-linux-x64-musl': 11.19.1
'@oxc-resolver/binding-openharmony-arm64': 11.19.1
'@oxc-resolver/binding-wasm32-wasi': 11.19.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)
'@oxc-resolver/binding-wasm32-wasi': 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
'@oxc-resolver/binding-win32-arm64-msvc': 11.19.1
'@oxc-resolver/binding-win32-ia32-msvc': 11.19.1
'@oxc-resolver/binding-win32-x64-msvc': 11.19.1
@ -16241,6 +16263,11 @@ snapshots:
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
tinyglobby@0.2.16:
dependencies:
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
tinypool@2.1.0: {}
tinyrainbow@2.0.0: {}

View File

@ -1,57 +1,22 @@
catalogMode: prefer
trustPolicy: no-downgrade
trustPolicyExclude:
- chokidar@4.0.3
- reselect@5.1.1
- semver@6.3.1
blockExoticSubdeps: true
strictDepBuilds: true
allowBuilds:
"@parcel/watcher": false
canvas: false
esbuild: false
sharp: false
packages:
- web
- e2e
- sdks/nodejs-client
- packages/*
overrides:
"@lexical/code": npm:lexical-code-no-prism@0.41.0
"@monaco-editor/loader": 1.7.0
brace-expansion@>=2.0.0 <2.0.3: 2.0.3
canvas: ^3.2.2
dompurify@>=3.1.3 <=3.3.1: 3.3.2
esbuild@<0.27.2: 0.27.2
flatted@<=3.4.1: 3.4.2
glob@>=10.2.0 <10.5.0: 11.1.0
is-core-module: npm:@nolyfill/is-core-module@^1.0.39
lodash@>=4.0.0 <= 4.17.23: 4.18.0
lodash-es@>=4.0.0 <= 4.17.23: 4.18.0
picomatch@<2.3.2: 2.3.2
picomatch@>=4.0.0 <4.0.4: 4.0.4
rollup@>=4.0.0 <4.59.0: 4.59.0
safe-buffer: ^5.2.1
safer-buffer: npm:@nolyfill/safer-buffer@^1.0.44
side-channel: npm:@nolyfill/side-channel@^1.0.44
smol-toml@<1.6.1: 1.6.1
solid-js: 1.9.11
string-width: ~8.2.0
svgo@>=3.0.0 <3.3.3: 3.3.3
tar@<=7.5.10: 7.5.11
undici@>=7.0.0 <7.24.0: 7.24.0
vite: npm:@voidzero-dev/vite-plus-core@0.1.16
vitest: npm:@voidzero-dev/vite-plus-test@0.1.16
yaml@>=2.0.0 <2.8.3: 2.8.3
yauzl@<3.2.1: 3.2.1
allowBuilds:
"@parcel/watcher": false
canvas: false
esbuild: false
sharp: false
blockExoticSubdeps: true
catalog:
"@amplitude/analytics-browser": 2.39.0
"@amplitude/plugin-session-replay-browser": 1.27.7
"@antfu/eslint-config": 8.2.0
"@base-ui/react": 1.4.0
"@date-fns/tz": 1.4.1
"@chromatic-com/storybook": 5.1.2
"@cucumber/cucumber": 12.8.0
"@date-fns/tz": 1.4.1
"@egoist/tailwindcss-icons": 1.9.2
"@emoji-mart/data": 1.2.1
"@eslint-react/eslint-plugin": 3.0.0
@ -107,6 +72,7 @@ catalog:
"@testing-library/jest-dom": 6.9.1
"@testing-library/react": 16.3.2
"@testing-library/user-event": 14.6.1
'@tsdown/css': 0.21.8
"@tsslint/cli": 3.0.3
"@tsslint/compat-eslint": 3.0.3
"@tsslint/config": 3.0.3
@ -230,3 +196,38 @@ catalog:
zod: 4.3.6
zundo: 2.3.0
zustand: 5.0.12
catalogMode: prefer
overrides:
"@lexical/code": npm:lexical-code-no-prism@0.41.0
"@monaco-editor/loader": 1.7.0
brace-expansion@>=2.0.0 <2.0.3: 2.0.3
canvas: ^3.2.2
dompurify@>=3.1.3 <=3.3.1: 3.3.2
esbuild@<0.27.2: 0.27.2
flatted@<=3.4.1: 3.4.2
glob@>=10.2.0 <10.5.0: 11.1.0
is-core-module: npm:@nolyfill/is-core-module@^1.0.39
lodash-es@>=4.0.0 <= 4.17.23: 4.18.0
lodash@>=4.0.0 <= 4.17.23: 4.18.0
picomatch@<2.3.2: 2.3.2
picomatch@>=4.0.0 <4.0.4: 4.0.4
rollup@>=4.0.0 <4.59.0: 4.59.0
safe-buffer: ^5.2.1
safer-buffer: npm:@nolyfill/safer-buffer@^1.0.44
side-channel: npm:@nolyfill/side-channel@^1.0.44
smol-toml@<1.6.1: 1.6.1
solid-js: 1.9.11
string-width: ~8.2.0
svgo@>=3.0.0 <3.3.3: 3.3.3
tar@<=7.5.10: 7.5.11
undici@>=7.0.0 <7.24.0: 7.24.0
vite: npm:@voidzero-dev/vite-plus-core@0.1.16
vitest: npm:@voidzero-dev/vite-plus-test@0.1.16
yaml@>=2.0.0 <2.8.3: 2.8.3
yauzl@<3.2.1: 3.2.1
strictDepBuilds: true
trustPolicy: no-downgrade
trustPolicyExclude:
- chokidar@4.0.3
- reselect@5.1.1
- semver@6.3.1

View File

@ -12,6 +12,10 @@
- `frontend-query-mutation` is the source of truth for Dify frontend contracts, query and mutation call-site patterns, conditional queries, invalidation, and mutation error handling.
## Design Token Mapping
- When translating Figma designs to code, read `../packages/dify-ui/AGENTS.md` for the Figma `--radius/*` token to Tailwind `rounded-*` class mapping. The two scales are offset by one step.
## Automated Test Generation
- Use `./docs/test.md` as the canonical instruction set for generating frontend automated tests.

View File

@ -136,7 +136,6 @@ pnpm -C web test
If you are not familiar with writing tests, refer to:
- [classnames.spec.ts] - Utility function test example
- [index.spec.tsx] - Component test example
### Analyze Component Complexity
@ -166,7 +165,6 @@ The Dify community can be found on [Discord community], where you can ask questi
[Storybook]: https://storybook.js.org
[Vite+]: https://viteplus.dev
[Vitest]: https://vitest.dev
[classnames.spec.ts]: ./utils/classnames.spec.ts
[index.spec.tsx]: ./app/components/base/button/index.spec.tsx
[pnpm]: https://pnpm.io
[vinext]: https://github.com/cloudflare/vinext

View File

@ -31,7 +31,7 @@ vi.mock('@/context/app-context', () => ({
}),
}))
vi.mock('@/utils/classnames', () => ({
vi.mock('@langgenius/dify-ui/cn', () => ({
cn: (...args: unknown[]) => args.filter(Boolean).join(' '),
}))

View File

@ -32,7 +32,7 @@ vi.mock('@/types/app', async () => {
return vi.importActual<typeof import('@/types/app')>('@/types/app')
})
vi.mock('@/utils/classnames', () => ({
vi.mock('@langgenius/dify-ui/cn', () => ({
cn: (...args: unknown[]) => args.filter(a => typeof a === 'string' && a).join(' '),
}))

View File

@ -226,7 +226,7 @@ vi.mock('@/app/components/tools/mcp', () => ({
default: () => <div data-testid="mcp-list">MCP List</div>,
}))
vi.mock('@/utils/classnames', () => ({
vi.mock('@langgenius/dify-ui/cn', () => ({
cn: (...args: unknown[]) => args.filter(Boolean).join(' '),
}))

View File

@ -112,7 +112,7 @@ vi.mock('@/service/use-tools', () => ({
useInvalidateAllWorkflowTools: () => vi.fn(),
}))
vi.mock('@/utils/classnames', () => ({
vi.mock('@langgenius/dify-ui/cn', () => ({
cn: (...args: unknown[]) => args.filter(Boolean).join(' '),
}))

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { NavIcon } from '@/app/components/app-sidebar/nav-link'
import type { App } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiDashboard2Fill,
RiDashboard2Line,
@ -28,7 +29,6 @@ import dynamic from '@/next/dynamic'
import { usePathname, useRouter } from '@/next/navigation'
import { fetchAppDetailDirect } from '@/service/apps'
import { AppModeEnum } from '@/types/app'
import { cn } from '@/utils/classnames'
import s from './style.module.css'
const TagManagementModal = dynamic(() => import('@/app/components/base/tag-management'), {

View File

@ -2,6 +2,7 @@
import type { Dayjs } from 'dayjs'
import type { FC } from 'react'
import type { TriggerProps } from '@/app/components/base/date-and-time-picker/types'
import { cn } from '@langgenius/dify-ui/cn'
import { RiCalendarLine } from '@remixicon/react'
import dayjs from 'dayjs'
import { noop } from 'es-toolkit/function'
@ -9,7 +10,6 @@ import * as React from 'react'
import { useCallback } from 'react'
import Picker from '@/app/components/base/date-and-time-picker/date-picker'
import { useLocale } from '@/context/i18n'
import { cn } from '@/utils/classnames'
import { formatToLocalTime } from '@/utils/format'
type Props = {
@ -30,7 +30,7 @@ const DatePicker: FC<Props> = ({
const renderDate = useCallback(({ value, handleClickTrigger, isOpen }: TriggerProps) => {
return (
<div className={cn('system-sm-regular flex h-7 cursor-pointer items-center rounded-lg px-1 text-components-input-text-filled hover:bg-state-base-hover', isOpen && 'bg-state-base-hover')} onClick={handleClickTrigger}>
<div className={cn('flex h-7 cursor-pointer items-center rounded-lg px-1 system-sm-regular text-components-input-text-filled hover:bg-state-base-hover', isOpen && 'bg-state-base-hover')} onClick={handleClickTrigger}>
{value ? formatToLocalTime(value, locale, 'MMM D') : ''}
</div>
)

View File

@ -3,13 +3,13 @@ import type { FC } from 'react'
import type { PeriodParamsWithTimeRange, TimeRange } from '@/app/components/app/overview/app-chart'
import type { Item } from '@/app/components/base/select'
import type { I18nKeysByPrefix } from '@/types/i18n'
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowDownSLine, RiCheckLine } from '@remixicon/react'
import dayjs from 'dayjs'
import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { SimpleSelect } from '@/app/components/base/select'
import { cn } from '@/utils/classnames'
const today = dayjs()
@ -44,7 +44,7 @@ const RangeSelector: FC<Props> = ({
const renderTrigger = useCallback((item: Item | null, isOpen: boolean) => {
return (
<div className={cn('flex h-8 cursor-pointer items-center space-x-1.5 rounded-lg bg-components-input-bg-normal pl-3 pr-2', isOpen && 'bg-state-base-hover-alt')}>
<div className={cn('flex h-8 cursor-pointer items-center space-x-1.5 rounded-lg bg-components-input-bg-normal pr-2 pl-3', isOpen && 'bg-state-base-hover-alt')}>
<div className="system-sm-regular text-components-input-text-filled">{isCustomRange ? t('filter.period.custom', { ns: 'appLog' }) : item?.name}</div>
<RiArrowDownSLine className={cn('size-4 text-text-quaternary', isOpen && 'text-text-secondary')} />
</div>
@ -57,13 +57,13 @@ const RangeSelector: FC<Props> = ({
{selected && (
<span
className={cn(
'absolute left-2 top-[9px] flex items-center text-text-accent',
'absolute top-[9px] left-2 flex items-center text-text-accent',
)}
>
<RiCheckLine className="h-4 w-4" aria-hidden="true" />
</span>
)}
<span className={cn('system-md-regular block truncate')}>{item.name}</span>
<span className={cn('block truncate system-md-regular')}>{item.name}</span>
</>
)
}, [])

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { PopupProps } from './config-popup'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useCallback, useRef, useState } from 'react'
import {
@ -9,7 +10,6 @@ import {
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { cn } from '@/utils/classnames'
import ConfigPopup from './config-popup'
type Props = {

View File

@ -1,6 +1,7 @@
'use client'
import type { FC, JSX } from 'react'
import type { AliyunConfig, ArizeConfig, DatabricksConfig, LangFuseConfig, LangSmithConfig, MLflowConfig, OpikConfig, PhoenixConfig, TencentConfig, WeaveConfig } from './type'
import { cn } from '@langgenius/dify-ui/cn'
import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useCallback, useState } from 'react'
@ -9,7 +10,6 @@ import Divider from '@/app/components/base/divider'
import Switch from '@/app/components/base/switch'
import Tooltip from '@/app/components/base/tooltip'
import Indicator from '@/app/components/header/indicator'
import { cn } from '@/utils/classnames'
import ProviderConfigModal from './provider-config-modal'
import ProviderPanel from './provider-panel'
import TracingIcon from './tracing-icon'
@ -331,7 +331,7 @@ const ConfigPopup: FC<PopupProps> = ({
</div>
<div className="flex items-center">
<Indicator color={enabled ? 'green' : 'gray'} />
<div className={cn('system-xs-semibold-uppercase ml-1 text-text-tertiary', enabled && 'text-util-colors-green-green-600')}>
<div className={cn('ml-1 system-xs-semibold-uppercase text-text-tertiary', enabled && 'text-util-colors-green-green-600')}>
{t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`, { ns: 'app' })}
</div>
{!readOnly && (
@ -350,7 +350,7 @@ const ConfigPopup: FC<PopupProps> = ({
</div>
</div>
<div className="system-xs-regular mt-2 text-text-tertiary">
<div className="mt-2 system-xs-regular text-text-tertiary">
{t(`${I18N_PREFIX}.tracingDescription`, { ns: 'app' })}
</div>
<Divider className="my-3" />
@ -379,7 +379,7 @@ const ConfigPopup: FC<PopupProps> = ({
<div className="mt-2 max-h-40 space-y-2 overflow-y-auto">
{configuredProviderPanel()}
</div>
<div className="system-xs-medium-uppercase mt-3 text-text-tertiary">{t(`${I18N_PREFIX}.configProviderTitle.moreProvider`, { ns: 'app' })}</div>
<div className="mt-3 system-xs-medium-uppercase text-text-tertiary">{t(`${I18N_PREFIX}.configProviderTitle.moreProvider`, { ns: 'app' })}</div>
<div className="mt-2 max-h-40 space-y-2 overflow-y-auto">
{moreProviderPanel()}
</div>

View File

@ -1,8 +1,8 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import Input from '@/app/components/base/input'
import { cn } from '@/utils/classnames'
type Props = {
className?: string

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { AliyunConfig, ArizeConfig, DatabricksConfig, LangFuseConfig, LangSmithConfig, MLflowConfig, OpikConfig, PhoenixConfig, TencentConfig, WeaveConfig } from './type'
import type { TracingStatus } from '@/models/app'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiArrowDownDoubleLine,
RiEqualizer2Line,
@ -18,7 +19,6 @@ import Indicator from '@/app/components/header/indicator'
import { useAppContext } from '@/context/app-context'
import { usePathname } from '@/next/navigation'
import { fetchTracingConfig as doFetchTracingConfig, fetchTracingStatus, updateTracingStatus } from '@/service/apps'
import { cn } from '@/utils/classnames'
import ConfigButton from './config-button'
import TracingIcon from './tracing-icon'
import { TracingProvider } from './type'
@ -247,11 +247,11 @@ const Panel: FC = () => {
>
<div
className={cn(
'flex cursor-pointer select-none items-center rounded-xl border-l-[0.5px] border-t border-effects-highlight bg-background-default-dodge p-2 shadow-xs hover:border-effects-highlight-lightmode-off hover:bg-background-default-lighter',
'flex cursor-pointer items-center rounded-xl border-t border-l-[0.5px] border-effects-highlight bg-background-default-dodge p-2 shadow-xs select-none hover:border-effects-highlight-lightmode-off hover:bg-background-default-lighter',
)}
>
<TracingIcon size="md" />
<div className="system-sm-semibold mx-2 text-text-secondary">{t(`${I18N_PREFIX}.title`, { ns: 'app' })}</div>
<div className="mx-2 system-sm-semibold text-text-secondary">{t(`${I18N_PREFIX}.title`, { ns: 'app' })}</div>
<div className="rounded-md p-1">
<RiEqualizer2Line className="h-4 w-4 text-text-tertiary" />
</div>
@ -286,12 +286,12 @@ const Panel: FC = () => {
>
<div
className={cn(
'flex cursor-pointer select-none items-center rounded-xl border-l-[0.5px] border-t border-effects-highlight bg-background-default-dodge p-2 shadow-xs hover:border-effects-highlight-lightmode-off hover:bg-background-default-lighter',
'flex cursor-pointer items-center rounded-xl border-t border-l-[0.5px] border-effects-highlight bg-background-default-dodge p-2 shadow-xs select-none hover:border-effects-highlight-lightmode-off hover:bg-background-default-lighter',
)}
>
<div className="ml-4 mr-1 flex items-center">
<div className="mr-1 ml-4 flex items-center">
<Indicator color={enabled ? 'green' : 'gray'} />
<div className="system-xs-semibold-uppercase ml-1.5 text-text-tertiary">
<div className="ml-1.5 system-xs-semibold-uppercase text-text-tertiary">
{t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`, { ns: 'app' })}
</div>
</div>

View File

@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiEqualizer2Line,
} from '@remixicon/react'
@ -8,7 +9,6 @@ import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { AliyunIconBig, ArizeIconBig, DatabricksIconBig, LangfuseIconBig, LangsmithIconBig, MlflowIconBig, OpikIconBig, PhoenixIconBig, TencentIconBig, WeaveIconBig } from '@/app/components/base/icons/src/public/tracing'
import { Eye as View } from '@/app/components/base/icons/src/vender/solid/general'
import { cn } from '@/utils/classnames'
import { TracingProvider } from './type'
const I18N_PREFIX = 'tracing'
@ -82,7 +82,7 @@ const ProviderPanel: FC<Props> = ({
<div className="flex items-center justify-between space-x-1">
<div className="flex items-center">
<Icon className="h-6" />
{isChosen && <div className="system-2xs-medium-uppercase ml-1 flex h-4 items-center radius-xs border border-text-accent-secondary px-1 text-text-accent-secondary">{t(`${I18N_PREFIX}.inUse`, { ns: 'app' })}</div>}
{isChosen && <div className="ml-1 flex h-4 items-center rounded-sm border border-text-accent-secondary px-1 system-2xs-medium-uppercase text-text-accent-secondary">{t(`${I18N_PREFIX}.inUse`, { ns: 'app' })}</div>}
</div>
{!readOnly && (
<div className="flex items-center justify-between space-x-1">
@ -102,7 +102,7 @@ const ProviderPanel: FC<Props> = ({
</div>
)}
</div>
<div className="system-xs-regular mt-2 text-text-tertiary">
<div className="mt-2 system-xs-regular text-text-tertiary">
{t(`${I18N_PREFIX}.${type}.description`, { ns: 'app' })}
</div>
</div>

View File

@ -1,8 +1,8 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { TracingIcon as Icon } from '@/app/components/base/icons/src/public/tracing'
import { cn } from '@/utils/classnames'
type Props = {
className?: string
@ -10,7 +10,7 @@ type Props = {
}
const sizeClassMap = {
lg: 'w-9 h-9 p-2 radius-lg',
lg: 'w-9 h-9 p-2 rounded-[10px]',
md: 'w-6 h-6 p-1 rounded-lg',
}

View File

@ -1,6 +1,7 @@
'use client'
import type { RemixiconComponentType } from '@remixicon/react'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiEqualizer2Fill,
RiEqualizer2Line,
@ -24,7 +25,6 @@ import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import useDocumentTitle from '@/hooks/use-document-title'
import { usePathname } from '@/next/navigation'
import { useDatasetDetail, useDatasetRelatedApps } from '@/service/knowledge/use-dataset'
import { cn } from '@/utils/classnames'
type IAppDetailLayoutProps = {
children: React.ReactNode

View File

@ -3,6 +3,7 @@ import type { ButtonProps } from '@/app/components/base/ui/button'
import type { FormInputItem, UserAction } from '@/app/components/workflow/nodes/human-input/types'
import type { SiteInfo } from '@/models/share'
import type { HumanInputFormError } from '@/service/use-share'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiCheckboxCircleFill,
RiErrorWarningFill,
@ -22,7 +23,6 @@ import { Button } from '@/app/components/base/ui/button'
import useDocumentTitle from '@/hooks/use-document-title'
import { useParams } from '@/next/navigation'
import { useGetHumanInputForm, useSubmitHumanInputForm } from '@/service/use-share'
import { cn } from '@/utils/classnames'
export type FormData = {
site: { site: SiteInfo }
@ -101,7 +101,7 @@ const FormContent = () => {
return (
<div className={cn('flex h-full w-full flex-col items-center justify-center')}>
<div className="max-w-[640px] min-w-[480px]">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 radius-3xl border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 rounded-[20px] border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="h-[56px] w-[56px] shrink-0 rounded-2xl border border-components-panel-border-subtle bg-background-default-dodge p-3">
<RiCheckboxCircleFill className="h-8 w-8 text-text-success" />
</div>
@ -129,7 +129,7 @@ const FormContent = () => {
return (
<div className={cn('flex h-full w-full flex-col items-center justify-center')}>
<div className="max-w-[640px] min-w-[480px]">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 radius-3xl border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 rounded-[20px] border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl border border-components-panel-border-subtle bg-background-default-dodge p-3">
<RiInformation2Fill className="h-8 w-8 text-text-accent" />
</div>
@ -157,7 +157,7 @@ const FormContent = () => {
return (
<div className={cn('flex h-full w-full flex-col items-center justify-center')}>
<div className="max-w-[640px] min-w-[480px]">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 radius-3xl border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 rounded-[20px] border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl border border-components-panel-border-subtle bg-background-default-dodge p-3">
<RiInformation2Fill className="h-8 w-8 text-text-accent" />
</div>
@ -185,7 +185,7 @@ const FormContent = () => {
return (
<div className={cn('flex h-full w-full flex-col items-center justify-center')}>
<div className="max-w-[640px] min-w-[480px]">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 radius-3xl border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 rounded-[20px] border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl border border-components-panel-border-subtle bg-background-default-dodge p-3">
<RiErrorWarningFill className="h-8 w-8 text-text-destructive" />
</div>
@ -211,7 +211,7 @@ const FormContent = () => {
return (
<div className={cn('flex h-full w-full flex-col items-center justify-center')}>
<div className="max-w-[640px] min-w-[480px]">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 radius-3xl border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="border-components-divider-subtle flex h-[320px] flex-col gap-4 rounded-[20px] border bg-chat-bubble-bg p-10 pb-9 shadow-lg backdrop-blur-xs">
<div className="flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl border border-components-panel-border-subtle bg-background-default-dodge p-3">
<RiErrorWarningFill className="h-8 w-8 text-text-destructive" />
</div>
@ -248,7 +248,7 @@ const FormContent = () => {
<div className="grow system-xl-semibold text-text-primary">{site.title}</div>
</div>
<div className="h-0 w-full grow overflow-y-auto">
<div className="border-components-divider-subtle radius-3xl border bg-chat-bubble-bg p-4 shadow-lg backdrop-blur-xs">
<div className="border-components-divider-subtle rounded-[20px] border bg-chat-bubble-bg p-4 shadow-lg backdrop-blur-xs">
{contentList.map((content, index) => (
<ContentItem
key={index}

View File

@ -1,8 +1,8 @@
'use client'
import Header from '@/app/signin/_header'
import { cn } from '@langgenius/dify-ui/cn'
import Header from '@/app/signin/_header'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { cn } from '@/utils/classnames'
export default function SignInLayout({ children }: any) {
const { systemFeatures } = useGlobalPublicStore()
@ -24,7 +24,7 @@ export default function SignInLayout({ children }: any) {
</div>
</div>
{!systemFeatures.branding.enabled && (
<div className="system-xs-regular px-8 py-6 text-text-tertiary">
<div className="px-8 py-6 system-xs-regular text-text-tertiary">
©
{' '}
{new Date().getFullYear()}

View File

@ -1,4 +1,5 @@
'use client'
import { cn } from '@langgenius/dify-ui/cn'
import { RiCheckboxCircleFill } from '@remixicon/react'
import { useCountDown } from 'ahooks'
import { useCallback, useState } from 'react'
@ -9,7 +10,6 @@ import { toast } from '@/app/components/base/ui/toast'
import { validPassword } from '@/config'
import { useRouter, useSearchParams } from '@/next/navigation'
import { changeWebAppPasswordWithToken } from '@/service/common'
import { cn } from '@/utils/classnames'
const ChangePasswordForm = () => {
const { t } = useTranslation()

View File

@ -1,10 +1,10 @@
'use client'
import type { PropsWithChildren } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { useTranslation } from 'react-i18next'
import { useGlobalPublicStore } from '@/context/global-public-context'
import useDocumentTitle from '@/hooks/use-document-title'
import { cn } from '@/utils/classnames'
export default function SignInLayout({ children }: PropsWithChildren) {
const { t } = useTranslation()
@ -21,7 +21,7 @@ export default function SignInLayout({ children }: PropsWithChildren) {
</div>
</div>
{systemFeatures.branding.enabled === false && (
<div className="system-xs-regular px-8 py-6 text-text-tertiary">
<div className="px-8 py-6 system-xs-regular text-text-tertiary">
©
{' '}
{new Date().getFullYear()}

View File

@ -1,4 +1,5 @@
'use client'
import { cn } from '@langgenius/dify-ui/cn'
import { RiContractLine, RiDoorLockLine, RiErrorWarningFill } from '@remixicon/react'
import * as React from 'react'
import { useCallback, useEffect, useState } from 'react'
@ -8,7 +9,6 @@ import { IS_CE_EDITION } from '@/config'
import { useGlobalPublicStore } from '@/context/global-public-context'
import Link from '@/next/link'
import { LicenseStatus } from '@/types/feature'
import { cn } from '@/utils/classnames'
import MailAndCodeAuth from './components/mail-and-code-auth'
import MailAndPasswordAuth from './components/mail-and-password-auth'
import SSOAuth from './components/sso-auth'
@ -58,10 +58,10 @@ const NormalForm = () => {
<div className="rounded-lg bg-linear-to-r from-workflow-workflow-progress-bg-1 to-workflow-workflow-progress-bg-2 p-4">
<div className="shadows-shadow-lg relative mb-2 flex h-10 w-10 items-center justify-center rounded-xl bg-components-card-bg shadow">
<RiContractLine className="h-5 w-5" />
<RiErrorWarningFill className="absolute -right-1 -top-1 h-4 w-4 text-text-warning-secondary" />
<RiErrorWarningFill className="absolute -top-1 -right-1 h-4 w-4 text-text-warning-secondary" />
</div>
<p className="system-sm-medium text-text-primary">{t('licenseLost', { ns: 'login' })}</p>
<p className="system-xs-regular mt-1 text-text-tertiary">{t('licenseLostTip', { ns: 'login' })}</p>
<p className="mt-1 system-xs-regular text-text-tertiary">{t('licenseLostTip', { ns: 'login' })}</p>
</div>
</div>
</div>
@ -74,10 +74,10 @@ const NormalForm = () => {
<div className="rounded-lg bg-linear-to-r from-workflow-workflow-progress-bg-1 to-workflow-workflow-progress-bg-2 p-4">
<div className="shadows-shadow-lg relative mb-2 flex h-10 w-10 items-center justify-center rounded-xl bg-components-card-bg shadow">
<RiContractLine className="h-5 w-5" />
<RiErrorWarningFill className="absolute -right-1 -top-1 h-4 w-4 text-text-warning-secondary" />
<RiErrorWarningFill className="absolute -top-1 -right-1 h-4 w-4 text-text-warning-secondary" />
</div>
<p className="system-sm-medium text-text-primary">{t('licenseExpired', { ns: 'login' })}</p>
<p className="system-xs-regular mt-1 text-text-tertiary">{t('licenseExpiredTip', { ns: 'login' })}</p>
<p className="mt-1 system-xs-regular text-text-tertiary">{t('licenseExpiredTip', { ns: 'login' })}</p>
</div>
</div>
</div>
@ -90,10 +90,10 @@ const NormalForm = () => {
<div className="rounded-lg bg-linear-to-r from-workflow-workflow-progress-bg-1 to-workflow-workflow-progress-bg-2 p-4">
<div className="shadows-shadow-lg relative mb-2 flex h-10 w-10 items-center justify-center rounded-xl bg-components-card-bg shadow">
<RiContractLine className="h-5 w-5" />
<RiErrorWarningFill className="absolute -right-1 -top-1 h-4 w-4 text-text-warning-secondary" />
<RiErrorWarningFill className="absolute -top-1 -right-1 h-4 w-4 text-text-warning-secondary" />
</div>
<p className="system-sm-medium text-text-primary">{t('licenseInactive', { ns: 'login' })}</p>
<p className="system-xs-regular mt-1 text-text-tertiary">{t('licenseInactiveTip', { ns: 'login' })}</p>
<p className="mt-1 system-xs-regular text-text-tertiary">{t('licenseInactiveTip', { ns: 'login' })}</p>
</div>
</div>
</div>
@ -105,7 +105,7 @@ const NormalForm = () => {
<div className="mx-auto mt-8 w-full">
<div className="mx-auto w-full">
<h2 className="title-4xl-semi-bold text-text-primary">{systemFeatures.branding.enabled ? t('pageTitleForE', { ns: 'login' }) : t('pageTitle', { ns: 'login' })}</h2>
<p className="body-md-regular mt-2 text-text-tertiary">{t('welcome', { ns: 'login' })}</p>
<p className="mt-2 body-md-regular text-text-tertiary">{t('welcome', { ns: 'login' })}</p>
</div>
<div className="relative">
<div className="mt-6 flex flex-col gap-3">
@ -122,7 +122,7 @@ const NormalForm = () => {
<div className="h-px w-full bg-linear-to-r from-background-gradient-mask-transparent via-divider-regular to-background-gradient-mask-transparent"></div>
</div>
<div className="relative flex justify-center">
<span className="system-xs-medium-uppercase px-2 text-text-tertiary">{t('or', { ns: 'login' })}</span>
<span className="px-2 system-xs-medium-uppercase text-text-tertiary">{t('or', { ns: 'login' })}</span>
</div>
</div>
)}
@ -159,7 +159,7 @@ const NormalForm = () => {
<RiDoorLockLine className="h-5 w-5" />
</div>
<p className="system-sm-medium text-text-primary">{t('noLoginMethod', { ns: 'login' })}</p>
<p className="system-xs-regular mt-1 text-text-tertiary">{t('noLoginMethodTip', { ns: 'login' })}</p>
<p className="mt-1 system-xs-regular text-text-tertiary">{t('noLoginMethodTip', { ns: 'login' })}</p>
</div>
<div className="relative my-2 py-2">
<div className="absolute inset-0 flex items-center" aria-hidden="true">
@ -170,7 +170,7 @@ const NormalForm = () => {
)}
{!systemFeatures.branding.enabled && (
<>
<div className="system-xs-regular mt-2 block w-full text-text-tertiary">
<div className="mt-2 block w-full system-xs-regular text-text-tertiary">
{t('tosDesc', { ns: 'login' })}
&nbsp;
<Link
@ -192,7 +192,7 @@ const NormalForm = () => {
</Link>
</div>
{IS_CE_EDITION && (
<div className="w-hull system-xs-regular mt-2 block text-text-tertiary">
<div className="w-hull mt-2 block system-xs-regular text-text-tertiary">
{t('goToInit', { ns: 'login' })}
&nbsp;
<Link

View File

@ -44,7 +44,7 @@ export default function AppSelector() {
<MenuButton
className={`
p-1x inline-flex
items-center radius-3xl text-sm
items-center rounded-[20px] text-sm
text-text-primary
mobile:px-1
${open && 'bg-components-panel-bg-blur'}
@ -64,7 +64,7 @@ export default function AppSelector() {
>
<MenuItems
className="
absolute -right-2 -top-1 w-60 max-w-80
absolute -top-1 -right-2 w-60 max-w-80
origin-top-right divide-y divide-divider-subtle rounded-lg bg-components-panel-bg-blur
shadow-lg
"

View File

@ -1,12 +1,12 @@
'use client'
import Loading from '@/app/components/base/loading'
import { cn } from '@langgenius/dify-ui/cn'
import Loading from '@/app/components/base/loading'
import Header from '@/app/signin/_header'
import { AppContextProvider } from '@/context/app-context-provider'
import { useGlobalPublicStore } from '@/context/global-public-context'
import useDocumentTitle from '@/hooks/use-document-title'
import { useIsLogin } from '@/service/use-common'
import { cn } from '@/utils/classnames'
export default function SignInLayout({ children }: any) {
const { systemFeatures } = useGlobalPublicStore()
@ -38,7 +38,7 @@ export default function SignInLayout({ children }: any) {
</div>
</div>
{systemFeatures.branding.enabled === false && (
<div className="px-8 py-6 text-text-tertiary system-xs-regular">
<div className="px-8 py-6 system-xs-regular text-text-tertiary">
©
{' '}
{new Date().getFullYear()}

View File

@ -1,13 +1,13 @@
'use client'
import { cn } from '@langgenius/dify-ui/cn'
import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { Button } from '@/app/components/base/ui/button'
import useDocumentTitle from '@/hooks/use-document-title'
import useDocumentTitle from '@/hooks/use-document-title'
import { useRouter, useSearchParams } from '@/next/navigation'
import { useInvitationCheck } from '@/service/use-common'
import { cn } from '@/utils/classnames'
const ActivateForm = () => {
useDocumentTitle('')
@ -55,7 +55,7 @@ const ActivateForm = () => {
{checkRes && !checkRes.is_valid && (
<div className="flex flex-col md:w-[400px]">
<div className="mx-auto w-full">
<div className="mb-3 flex h-20 w-20 items-center justify-center radius-3xl border border-divider-regular bg-components-option-card-option-bg p-5 text-[40px] font-bold shadow-lg">🤷</div>
<div className="mb-3 flex h-20 w-20 items-center justify-center rounded-[20px] border border-divider-regular bg-components-option-card-option-bg p-5 text-[40px] font-bold shadow-lg">🤷</div>
<h2 className="text-[32px] font-bold text-text-primary">{t('invalid', { ns: 'login' })}</h2>
</div>
<div className="mx-auto mt-6 w-full">

View File

@ -1,7 +1,7 @@
'use client'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { cn } from '@/utils/classnames'
import Header from '../signin/_header'
import ActivateForm from './activateForm'

View File

@ -12,7 +12,7 @@ vi.mock('@/next/navigation', () => ({
}))
// Mock classnames utility
vi.mock('@/utils/classnames', () => ({
vi.mock('@langgenius/dify-ui/cn', () => ({
default: (...classes: unknown[]) => classes.filter(Boolean).join(' '),
}))

View File

@ -1,8 +1,8 @@
import type { App, AppSSO } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import { RiEqualizer2Line } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
import AppIcon from '../../base/app-icon'
import { getAppModeLabel } from './app-mode-labels'
@ -52,9 +52,9 @@ const AppInfoTrigger = ({ appDetail, expand, onClick }: AppInfoTriggerProps) =>
{expand && (
<div className="flex flex-col items-start gap-1">
<div className="flex w-full">
<div className="truncate whitespace-nowrap text-text-secondary system-md-semibold">{appDetail.name}</div>
<div className="truncate system-md-semibold whitespace-nowrap text-text-secondary">{appDetail.name}</div>
</div>
<div className="whitespace-nowrap text-text-tertiary system-2xs-medium-uppercase">
<div className="system-2xs-medium-uppercase whitespace-nowrap text-text-tertiary">
{getAppModeLabel(appDetail.mode, t)}
</div>
</div>

View File

@ -188,7 +188,7 @@ const AppOperations = ({
</Button>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className="z-30">
<div className="flex min-w-[264px] flex-col radius-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg backdrop-blur-[5px]">
<div className="flex min-w-[264px] flex-col rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg backdrop-blur-[5px]">
{moreOperations.map(item => item.type === 'divider'
? (
<div key={item.id} className="my-1 h-px bg-divider-subtle" />

View File

@ -1,4 +1,5 @@
import type { NavIcon } from './nav-link'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiEqualizer2Line,
RiMenuLine,
@ -13,7 +14,6 @@ import {
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { useAppContext } from '@/context/app-context'
import { cn } from '@/utils/classnames'
import AppIcon from '../base/app-icon'
import Divider from '../base/divider'
import AppInfo from './app-info'
@ -50,7 +50,7 @@ const AppSidebarDropdown = ({ navigation }: Props) => {
return (
<>
<div className="fixed left-2 top-2 z-20">
<div className="fixed top-2 left-2 z-20">
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
@ -60,7 +60,7 @@ const AppSidebarDropdown = ({ navigation }: Props) => {
}}
>
<PortalToFollowElemTrigger onClick={handleTrigger}>
<div className={cn('flex cursor-pointer items-center radius-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-1 shadow-lg backdrop-blur-xs hover:bg-background-default-hover', open && 'bg-background-default-hover')}>
<div className={cn('flex cursor-pointer items-center rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-1 shadow-lg backdrop-blur-xs hover:bg-background-default-hover', open && 'bg-background-default-hover')}>
<AppIcon
size="small"
iconType={appDetail.icon_type}
@ -97,16 +97,16 @@ const AppSidebarDropdown = ({ navigation }: Props) => {
</div>
<div className="flex flex-col items-start gap-1">
<div className="flex w-full">
<div className="truncate text-text-secondary system-md-semibold">{appDetail.name}</div>
<div className="truncate system-md-semibold text-text-secondary">{appDetail.name}</div>
</div>
<div className="text-text-tertiary system-2xs-medium-uppercase">{getAppModeLabel(appDetail.mode, t)}</div>
<div className="system-2xs-medium-uppercase text-text-tertiary">{getAppModeLabel(appDetail.mode, t)}</div>
</div>
</div>
</div>
<div className="px-4">
<Divider bgStyle="gradient" />
</div>
<nav className="space-y-0.5 px-3 pb-6 pt-4">
<nav className="space-y-0.5 px-3 pt-4 pb-6">
{navigation.map((item, index) => {
return (
<NavLink key={index} mode="expand" iconMap={{ selected: item.selectedIcon, normal: item.icon }} name={item.name} href={item.href} />

View File

@ -1,4 +1,5 @@
import type { DataSet } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
import { RiMoreFill } from '@remixicon/react'
import * as React from 'react'
import { useCallback, useState } from 'react'
@ -11,7 +12,6 @@ import { checkIsUsedInApp, deleteDataset } from '@/service/datasets'
import { datasetDetailQueryKeyPrefix, useInvalidDatasetList } from '@/service/knowledge/use-dataset'
import { useInvalid } from '@/service/use-base'
import { useExportPipelineDSL } from '@/service/use-pipeline'
import { cn } from '@/utils/classnames'
import { downloadBlob } from '@/utils/download'
import ActionButton from '../../base/action-button'
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '../../base/portal-to-follow-elem'

View File

@ -1,13 +1,13 @@
'use client'
import type { FC } from 'react'
import type { DataSet } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { useKnowledge } from '@/hooks/use-knowledge'
import { DOC_FORM_TEXT } from '@/models/datasets'
import { cn } from '@/utils/classnames'
import AppIcon from '../../base/app-icon'
import Effect from '../../base/effect'
import Dropdown from './dropdown'
@ -36,7 +36,7 @@ const DatasetInfo: FC<DatasetInfoProps> = ({
return (
<div className={cn('relative flex flex-col', expand ? '' : 'p-1')}>
{expand && (
<Effect className="-left-5 top-[-22px] opacity-15" />
<Effect className="top-[-22px] -left-5 opacity-15" />
)}
<div className="flex flex-col gap-2 p-2">
@ -57,19 +57,19 @@ const DatasetInfo: FC<DatasetInfoProps> = ({
)}
</div>
{!expand && (
<div className="-mb-2 -mt-1 flex items-center justify-center">
<div className="-mt-1 -mb-2 flex items-center justify-center">
<Dropdown expand={false} />
</div>
)}
{expand && (
<div className="flex flex-col gap-y-1 pb-0.5">
<div
className="truncate text-text-secondary system-md-semibold"
className="truncate system-md-semibold text-text-secondary"
title={dataset.name}
>
{dataset.name}
</div>
<div className="text-text-tertiary system-2xs-medium-uppercase">
<div className="system-2xs-medium-uppercase text-text-tertiary">
{isExternalProvider && t('externalTag', { ns: 'dataset' })}
{!!(!isExternalProvider && isPipelinePublished && dataset.doc_form && dataset.indexing_technique) && (
<div className="flex items-center gap-x-2">
@ -79,7 +79,7 @@ const DatasetInfo: FC<DatasetInfoProps> = ({
)}
</div>
{!!dataset.description && (
<p className="line-clamp-3 text-text-tertiary system-xs-regular first-letter:capitalize">
<p className="line-clamp-3 system-xs-regular text-text-tertiary first-letter:capitalize">
{dataset.description}
</p>
)}

View File

@ -1,5 +1,6 @@
import type { NavIcon } from './nav-link'
import type { DataSet } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiMenuLine,
} from '@remixicon/react'
@ -15,7 +16,6 @@ import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { useKnowledge } from '@/hooks/use-knowledge'
import { DOC_FORM_TEXT } from '@/models/datasets'
import { useDatasetRelatedApps } from '@/service/knowledge/use-dataset'
import { cn } from '@/utils/classnames'
import AppIcon from '../base/app-icon'
import Divider from '../base/divider'
import Effect from '../base/effect'
@ -65,7 +65,7 @@ const DatasetSidebarDropdown = ({
return (
<>
<div className="fixed left-2 top-2 z-20">
<div className="fixed top-2 left-2 z-20">
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
@ -77,7 +77,7 @@ const DatasetSidebarDropdown = ({
<PortalToFollowElemTrigger onClick={handleTrigger}>
<div
className={cn(
'flex cursor-pointer items-center radius-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-1 shadow-lg backdrop-blur-xs hover:bg-background-default-hover',
'flex cursor-pointer items-center rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-1 shadow-lg backdrop-blur-xs hover:bg-background-default-hover',
open && 'bg-background-default-hover',
)}
>
@ -93,7 +93,7 @@ const DatasetSidebarDropdown = ({
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className="z-50">
<div className="relative w-[216px] rounded-xl border-[0.5px] border-components-panel-border bg-background-default-subtle shadow-lg">
<Effect className="-left-5 top-[-22px] opacity-15" />
<Effect className="top-[-22px] -left-5 opacity-15" />
<div className="flex flex-col gap-y-2 p-4">
<div className="flex items-center justify-between">
<AppIcon
@ -107,12 +107,12 @@ const DatasetSidebarDropdown = ({
</div>
<div className="flex flex-col gap-y-1 pb-0.5">
<div
className="truncate text-text-secondary system-md-semibold"
className="truncate system-md-semibold text-text-secondary"
title={dataset.name}
>
{dataset.name}
</div>
<div className="text-text-tertiary system-2xs-medium-uppercase">
<div className="system-2xs-medium-uppercase text-text-tertiary">
{isExternalProvider && t('externalTag', { ns: 'dataset' })}
{!!(!isExternalProvider && dataset.doc_form && dataset.indexing_technique) && (
<div className="flex items-center gap-x-2">
@ -123,7 +123,7 @@ const DatasetSidebarDropdown = ({
</div>
</div>
{!!dataset.description && (
<p className="line-clamp-3 text-text-tertiary system-xs-regular first-letter:capitalize">
<p className="line-clamp-3 system-xs-regular text-text-tertiary first-letter:capitalize">
{dataset.description}
</p>
)}

View File

@ -1,4 +1,5 @@
import type { NavIcon } from './nav-link'
import { cn } from '@langgenius/dify-ui/cn'
import { useHover, useKeyPress } from 'ahooks'
import * as React from 'react'
import { useCallback, useEffect, useState } from 'react'
@ -7,7 +8,6 @@ import { useStore as useAppStore } from '@/app/components/app/store'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { usePathname } from '@/next/navigation'
import { cn } from '@/utils/classnames'
import Divider from '../base/divider'
import { getKeyboardKeyCodeBySystem } from '../workflow/utils'
import AppInfo from './app-info'
@ -124,7 +124,7 @@ const AppDetailNav = ({
/>
{!isMobile && isHoveringSidebar && (
<ToggleButton
className="absolute -right-3 top-[-3.5px] z-20"
className="absolute top-[-3.5px] -right-3 z-20"
expand={expand}
handleToggle={handleToggle}
/>

View File

@ -1,9 +1,9 @@
'use client'
import type { RemixiconComponentType } from '@remixicon/react'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import Link from '@/next/link'
import { useSelectedLayoutSegment } from '@/next/navigation'
import { cn } from '@/utils/classnames'
export type NavIcon = React.ComponentType<
React.PropsWithoutRef<React.ComponentProps<'svg'>> & {
@ -54,7 +54,7 @@ const NavLink = ({
key={name}
type="button"
disabled
className={cn('flex h-8 cursor-not-allowed items-center rounded-lg text-components-menu-item-text opacity-30 system-sm-medium hover:bg-components-menu-item-bg-hover', 'pl-3 pr-1')}
className={cn('flex h-8 cursor-not-allowed items-center rounded-lg system-sm-medium text-components-menu-item-text opacity-30 hover:bg-components-menu-item-bg-hover', 'pr-1 pl-3')}
title={mode === 'collapse' ? name : ''}
aria-disabled
>
@ -75,8 +75,8 @@ const NavLink = ({
key={name}
href={href}
className={cn(isActive
? 'border-b-[0.25px] border-l-[0.75px] border-r-[0.25px] border-t-[0.75px] border-effects-highlight-lightmode-off bg-components-menu-item-bg-active text-text-accent-light-mode-only system-sm-semibold'
: 'text-components-menu-item-text system-sm-medium hover:bg-components-menu-item-bg-hover hover:text-components-menu-item-text-hover', 'flex h-8 items-center rounded-lg pl-3 pr-1')}
? 'border-t-[0.75px] border-r-[0.25px] border-b-[0.25px] border-l-[0.75px] border-effects-highlight-lightmode-off bg-components-menu-item-bg-active system-sm-semibold text-text-accent-light-mode-only'
: 'system-sm-medium text-components-menu-item-text hover:bg-components-menu-item-bg-hover hover:text-components-menu-item-text-hover', 'flex h-8 items-center rounded-lg pr-1 pl-3')}
title={mode === 'collapse' ? name : ''}
>
{renderIcon()}

View File

@ -1,8 +1,8 @@
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowLeftSLine, RiArrowRightSLine } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/app/components/base/ui/button'
import { cn } from '@/utils/classnames'
import Tooltip from '../base/tooltip'
import ShortcutsName from '../workflow/shortcuts-name'

View File

@ -1,4 +1,5 @@
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiDeleteBinLine } from '@remixicon/react'
import { useBoolean } from 'ahooks'
import * as React from 'react'
@ -12,7 +13,6 @@ import {
AlertDialogContent,
AlertDialogTitle,
} from '@/app/components/base/ui/alert-dialog'
import { cn } from '@/utils/classnames'
const i18nPrefix = 'batchAction'
@ -47,7 +47,7 @@ const BatchAction: FC<IBatchActionProps> = ({
}
return (
<div className={cn('pointer-events-none flex w-full justify-center', className)}>
<div className="pointer-events-auto flex items-center gap-x-1 radius-lg border border-components-actionbar-border-accent bg-components-actionbar-bg-accent p-1 shadow-xl shadow-shadow-shadow-5 backdrop-blur-[5px]">
<div className="pointer-events-auto flex items-center gap-x-1 rounded-[10px] border border-components-actionbar-border-accent bg-components-actionbar-bg-accent p-1 shadow-xl shadow-shadow-shadow-5 backdrop-blur-[5px]">
<div className="inline-flex items-center gap-x-2 py-1 pr-3 pl-2">
<span className="flex h-5 w-5 items-center justify-center rounded-md bg-text-accent px-1 py-0.5 text-xs font-medium text-text-primary-on-surface">
{selectedIds.length}

View File

@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiDeleteBinLine } from '@remixicon/react'
import * as React from 'react'
import { useEffect, useRef, useState } from 'react'
@ -7,7 +8,6 @@ import { useTranslation } from 'react-i18next'
import { Csv as CSVIcon } from '@/app/components/base/icons/src/public/files'
import { Button } from '@/app/components/base/ui/button'
import { toast } from '@/app/components/base/ui/toast'
import { cn } from '@/utils/classnames'
export type Props = {
file: File | undefined

View File

@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiDeleteBinLine, RiEditFill, RiEditLine } from '@remixicon/react'
import * as React from 'react'
import { useEffect, useState } from 'react'
@ -7,7 +8,6 @@ import { useTranslation } from 'react-i18next'
import { Robot, User } from '@/app/components/base/icons/src/public/avatar'
import Textarea from '@/app/components/base/textarea'
import { Button } from '@/app/components/base/ui/button'
import { cn } from '@/utils/classnames'
export enum EditItemType {
Query = 'query',

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { AnnotationItemBasic } from '../type'
import { Menu, MenuButton, MenuItems, Transition } from '@headlessui/react'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiAddLine,
RiDeleteBinLine,
@ -18,10 +19,9 @@ import { FileDownload02, FilePlus02 } from '@/app/components/base/icons/src/vend
import CustomPopover from '@/app/components/base/popover'
import { Button } from '@/app/components/base/ui/button'
import { useLocale } from '@/context/i18n'
import { LanguagesSupported } from '@/i18n-config/language'
import { LanguagesSupported } from '@/i18n-config/language'
import { clearAllAnnotations, fetchExportAnnotationList } from '@/service/annotation'
import { cn } from '@/utils/classnames'
import { downloadBlob } from '@/utils/download'
import AddAnnotationModal from '../add-annotation-modal'
import BatchAddModal from '../batch-add-annotation-modal'

View File

@ -4,6 +4,7 @@ import type { QueryParam } from './filter'
import type { AnnotationItem, AnnotationItemBasic } from './type'
import type { AnnotationReplyConfig } from '@/models/debug'
import type { App } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import { RiEqualizer2Line } from '@remixicon/react'
import { useDebounce } from 'ahooks'
import * as React from 'react'
@ -22,7 +23,6 @@ import { useProviderContext } from '@/context/provider-context'
import { addAnnotation, delAnnotation, delAnnotations, fetchAnnotationConfig as doFetchAnnotationConfig, editAnnotation, fetchAnnotationList, queryAnnotationJobStatus, updateAnnotationScore, updateAnnotationStatus } from '@/service/annotation'
import { AppModeEnum } from '@/types/app'
import { sleep } from '@/utils'
import { cn } from '@/utils/classnames'
import EmptyElement from './empty-element'
import Filter from './filter'
import HeaderOpts from './header-opts'
@ -144,7 +144,7 @@ const Annotation: FC<Props> = (props) => {
return (
<div className="flex h-full flex-col">
<p className="text-text-tertiary system-sm-regular">{t('description', { ns: 'appLog' })}</p>
<p className="system-sm-regular text-text-tertiary">{t('description', { ns: 'appLog' })}</p>
<div className="relative flex h-full flex-1 flex-col py-4">
<Filter appId={appDetail.id} queryParams={queryParams} setQueryParams={setQueryParams}>
<div className="flex items-center space-x-2">
@ -152,7 +152,7 @@ const Annotation: FC<Props> = (props) => {
<>
<div className={cn(!annotationConfig?.enabled && 'pr-2', 'flex h-7 items-center space-x-1 rounded-lg border border-components-panel-border bg-components-panel-bg-blur pl-2')}>
<MessageFast className="h-4 w-4 text-util-colors-indigo-indigo-600" />
<div className="text-text-primary system-sm-medium">{t('name', { ns: 'appAnnotation' })}</div>
<div className="system-sm-medium text-text-primary">{t('name', { ns: 'appAnnotation' })}</div>
<Switch
key={controlRefreshSwitch}
value={annotationConfig?.enabled ?? false}

View File

@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { AnnotationItem } from './type'
import { cn } from '@langgenius/dify-ui/cn'
import { RiDeleteBinLine, RiEditLine } from '@remixicon/react'
import * as React from 'react'
import { useCallback, useMemo } from 'react'
@ -8,7 +9,6 @@ import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import Checkbox from '@/app/components/base/checkbox'
import useTimestamp from '@/hooks/use-timestamp'
import { cn } from '@/utils/classnames'
import BatchAction from './batch-action'
import RemoveAnnotationConfirmModal from './remove-annotation-confirm-modal'
@ -60,7 +60,7 @@ const List: FC<Props> = ({
<table className={cn('w-full min-w-[440px] border-collapse border-0')}>
<thead className="system-xs-medium-uppercase text-text-tertiary">
<tr>
<td className="w-12 whitespace-nowrap rounded-l-lg bg-background-section-burn px-2">
<td className="w-12 rounded-l-lg bg-background-section-burn px-2 whitespace-nowrap">
<Checkbox
className="mr-2"
checked={isAllSelected}
@ -68,11 +68,11 @@ const List: FC<Props> = ({
onCheck={handleSelectAll}
/>
</td>
<td className="w-5 whitespace-nowrap bg-background-section-burn pl-2 pr-1">{t('table.header.question', { ns: 'appAnnotation' })}</td>
<td className="whitespace-nowrap bg-background-section-burn py-1.5 pl-3">{t('table.header.answer', { ns: 'appAnnotation' })}</td>
<td className="whitespace-nowrap bg-background-section-burn py-1.5 pl-3">{t('table.header.createdAt', { ns: 'appAnnotation' })}</td>
<td className="whitespace-nowrap bg-background-section-burn py-1.5 pl-3">{t('table.header.hits', { ns: 'appAnnotation' })}</td>
<td className="w-[96px] whitespace-nowrap rounded-r-lg bg-background-section-burn py-1.5 pl-3">{t('table.header.actions', { ns: 'appAnnotation' })}</td>
<td className="w-5 bg-background-section-burn pr-1 pl-2 whitespace-nowrap">{t('table.header.question', { ns: 'appAnnotation' })}</td>
<td className="bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('table.header.answer', { ns: 'appAnnotation' })}</td>
<td className="bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('table.header.createdAt', { ns: 'appAnnotation' })}</td>
<td className="bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('table.header.hits', { ns: 'appAnnotation' })}</td>
<td className="w-[96px] rounded-r-lg bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('table.header.actions', { ns: 'appAnnotation' })}</td>
</tr>
</thead>
<tbody className="system-sm-regular text-text-secondary">
@ -99,13 +99,13 @@ const List: FC<Props> = ({
/>
</td>
<td
className="max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2"
className="max-w-[250px] overflow-hidden p-3 pr-2 text-ellipsis whitespace-nowrap"
title={item.question}
>
{item.question}
</td>
<td
className="max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2"
className="max-w-[250px] overflow-hidden p-3 pr-2 text-ellipsis whitespace-nowrap"
title={item.answer}
>
{item.answer}

View File

@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { AnnotationItem, HitHistoryItem } from '../type'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -20,7 +21,6 @@ import {
import { APP_PAGE_LIMIT } from '@/config'
import useTimestamp from '@/hooks/use-timestamp'
import { fetchHitHistoryList } from '@/service/annotation'
import { cn } from '@/utils/classnames'
import EditItem, { EditItemType } from '../edit-annotation-modal/edit-item'
import HitHistoryNoData from './hit-history-no-data'
@ -146,12 +146,12 @@ const ViewAnnotationModal: FC<Props> = ({
<table className={cn('w-full min-w-[440px] border-collapse border-0')}>
<thead className="system-xs-medium-uppercase text-text-tertiary">
<tr>
<td className="w-5 whitespace-nowrap rounded-l-lg bg-background-section-burn pl-2 pr-1">{t('hitHistoryTable.query', { ns: 'appAnnotation' })}</td>
<td className="whitespace-nowrap bg-background-section-burn py-1.5 pl-3">{t('hitHistoryTable.match', { ns: 'appAnnotation' })}</td>
<td className="whitespace-nowrap bg-background-section-burn py-1.5 pl-3">{t('hitHistoryTable.response', { ns: 'appAnnotation' })}</td>
<td className="whitespace-nowrap bg-background-section-burn py-1.5 pl-3">{t('hitHistoryTable.source', { ns: 'appAnnotation' })}</td>
<td className="whitespace-nowrap bg-background-section-burn py-1.5 pl-3">{t('hitHistoryTable.score', { ns: 'appAnnotation' })}</td>
<td className="w-[160px] whitespace-nowrap rounded-r-lg bg-background-section-burn py-1.5 pl-3">{t('hitHistoryTable.time', { ns: 'appAnnotation' })}</td>
<td className="w-5 rounded-l-lg bg-background-section-burn pr-1 pl-2 whitespace-nowrap">{t('hitHistoryTable.query', { ns: 'appAnnotation' })}</td>
<td className="bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('hitHistoryTable.match', { ns: 'appAnnotation' })}</td>
<td className="bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('hitHistoryTable.response', { ns: 'appAnnotation' })}</td>
<td className="bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('hitHistoryTable.source', { ns: 'appAnnotation' })}</td>
<td className="bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('hitHistoryTable.score', { ns: 'appAnnotation' })}</td>
<td className="w-[160px] rounded-r-lg bg-background-section-burn py-1.5 pl-3 whitespace-nowrap">{t('hitHistoryTable.time', { ns: 'appAnnotation' })}</td>
</tr>
</thead>
<tbody className="system-sm-regular text-text-secondary">
@ -161,19 +161,19 @@ const ViewAnnotationModal: FC<Props> = ({
className="cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover"
>
<td
className="max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2"
className="max-w-[250px] overflow-hidden p-3 pr-2 text-ellipsis whitespace-nowrap"
title={item.question}
>
{item.question}
</td>
<td
className="max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2"
className="max-w-[250px] overflow-hidden p-3 pr-2 text-ellipsis whitespace-nowrap"
title={item.match}
>
{item.match}
</td>
<td
className="max-w-[250px] overflow-hidden text-ellipsis whitespace-nowrap p-3 pr-2"
className="max-w-[250px] overflow-hidden p-3 pr-2 text-ellipsis whitespace-nowrap"
title={item.response}
>
{item.response}
@ -250,7 +250,7 @@ const ViewAnnotationModal: FC<Props> = ({
)}
foot={id
? (
<div className="system-sm-medium flex h-16 items-center justify-between rounded-bl-xl rounded-br-xl border-t border-divider-subtle bg-background-section-burn px-4 text-text-tertiary">
<div className="flex h-16 items-center justify-between rounded-br-xl rounded-bl-xl border-t border-divider-subtle bg-background-section-burn px-4 system-sm-medium text-text-tertiary">
<div
className="flex cursor-pointer items-center space-x-2 pl-3"
onClick={() => setShowModal(true)}

View File

@ -1,8 +1,8 @@
import type { ReactNode } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiCloseLine } from '@remixicon/react'
import { Fragment, useCallback } from 'react'
import { cn } from '@/utils/classnames'
type DialogProps = {
className?: string
@ -46,7 +46,7 @@ const AccessControlDialog = ({
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className={cn('relative h-auto min-h-[323px] w-[600px] overflow-y-auto rounded-2xl bg-components-panel-bg p-0 shadow-xl transition-all', className)}>
<div onClick={() => close()} className="absolute right-5 top-5 z-10 flex h-8 w-8 cursor-pointer items-center justify-center">
<div onClick={() => close()} className="absolute top-5 right-5 z-10 flex h-8 w-8 cursor-pointer items-center justify-center">
<RiCloseLine className="h-5 w-5 text-text-tertiary" />
</div>
{children}

View File

@ -13,7 +13,7 @@ const AccessControlItem: FC<AccessControlItemProps> = ({ type, children }) => {
if (currentMenu !== type) {
return (
<div
className="cursor-pointer radius-lg border
className="cursor-pointer rounded-[10px] border
border-components-option-card-option-border bg-components-option-card-option-bg
hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover"
onClick={() => setCurrentMenu(type)}
@ -24,7 +24,7 @@ const AccessControlItem: FC<AccessControlItemProps> = ({ type, children }) => {
}
return (
<div className="radius-lg border-[1.5px]
<div className="rounded-[10px] border-[1.5px]
border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg shadow-sm"
>
{children}

View File

@ -1,6 +1,7 @@
'use client'
import type { AccessControlAccount, AccessControlGroup, Subject, SubjectAccount, SubjectGroup } from '@/models/access-control'
import { FloatingOverlay } from '@floating-ui/react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiAddCircleFill, RiArrowRightSLine, RiOrganizationChart } from '@remixicon/react'
import { useDebounce } from 'ahooks'
import { useCallback, useEffect, useRef, useState } from 'react'
@ -10,7 +11,6 @@ import { Button } from '@/app/components/base/ui/button'
import { useSelector } from '@/context/app-context'
import { SubjectType } from '@/models/access-control'
import { useSearchForWhiteListCandidates } from '@/service/access-control'
import { cn } from '@/utils/classnames'
import useAccessControlStore from '../../../../context/access-control-store'
import Checkbox from '../../base/checkbox'
import Input from '../../base/input'

View File

@ -1,6 +1,6 @@
import type { HTMLProps, PropsWithChildren } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowRightUpLine } from '@remixicon/react'
import { cn } from '@/utils/classnames'
type SuggestedActionProps = PropsWithChildren<HTMLProps<HTMLAnchorElement> & {
icon?: React.ReactNode
@ -24,7 +24,7 @@ const SuggestedAction = ({ icon, link, disabled, children, className, onClick, .
{...props}
>
<div className="relative h-4 w-4">{icon}</div>
<div className="system-sm-medium shrink grow basis-0">{children}</div>
<div className="shrink grow basis-0 system-sm-medium">{children}</div>
<RiArrowRightUpLine className="h-3.5 w-3.5" />
</a>
)

View File

@ -1,7 +1,7 @@
'use client'
import type { FC, ReactNode } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { cn } from '@/utils/classnames'
type IFeaturePanelProps = {
className?: string
@ -23,7 +23,7 @@ const FeaturePanel: FC<IFeaturePanelProps> = ({
children,
}) => {
return (
<div className={cn('rounded-xl border-l-[0.5px] border-t-[0.5px] border-effects-highlight bg-background-section-burn pb-3', noBodySpacing && 'pb-0', className)}>
<div className={cn('rounded-xl border-t-[0.5px] border-l-[0.5px] border-effects-highlight bg-background-section-burn pb-3', noBodySpacing && 'pb-0', className)}>
{/* Header */}
<div className={cn('px-3 pt-2', hasHeaderBottomBorder && 'border-b border-divider-subtle')} data-testid="feature-panel-header">
<div className="flex h-8 items-center justify-between">

View File

@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiAddLine,
RiEditLine,
@ -7,7 +8,6 @@ import {
import { noop } from 'es-toolkit/function'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
type IOperationBtnProps = {
className?: string
@ -30,7 +30,7 @@ const OperationBtn: FC<IOperationBtnProps> = ({
const { t } = useTranslation()
return (
<div
className={cn('flex h-7 cursor-pointer select-none items-center space-x-1 rounded-md px-3 text-text-secondary hover:bg-state-base-hover', className)}
className={cn('flex h-7 cursor-pointer items-center space-x-1 rounded-md px-3 text-text-secondary select-none hover:bg-state-base-hover', className)}
onClick={onClick}
>
<div>

View File

@ -15,21 +15,21 @@ const HasNotSetAPI: FC<IHasNotSetAPIProps> = ({
return (
<div className="flex grow flex-col items-center justify-center pb-[120px]">
<div className="flex w-full max-w-[400px] flex-col gap-2 px-4 py-4">
<div className="flex h-10 w-10 items-center justify-center radius-lg">
<div className="flex h-full w-full items-center justify-center overflow-hidden radius-lg border-[0.5px] border-components-card-border bg-components-card-bg p-1 shadow-lg backdrop-blur-[5px]">
<div className="flex h-10 w-10 items-center justify-center rounded-[10px]">
<div className="flex h-full w-full items-center justify-center overflow-hidden rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg p-1 shadow-lg backdrop-blur-[5px]">
<span className="i-ri-brain-2-line h-5 w-5 text-text-tertiary" />
</div>
</div>
<div className="flex flex-col gap-1">
<div className="text-text-secondary system-md-semibold">{t('noModelProviderConfigured', { ns: 'appDebug' })}</div>
<div className="text-text-tertiary system-xs-regular">{t('noModelProviderConfiguredTip', { ns: 'appDebug' })}</div>
<div className="system-md-semibold text-text-secondary">{t('noModelProviderConfigured', { ns: 'appDebug' })}</div>
<div className="system-xs-regular text-text-tertiary">{t('noModelProviderConfiguredTip', { ns: 'appDebug' })}</div>
</div>
<button
type="button"
className="flex w-fit items-center gap-1 rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-3 py-2 shadow-xs backdrop-blur-[5px]"
onClick={onSetting}
>
<span className="text-components-button-secondary-accent-text system-sm-medium">{t('manageModels', { ns: 'appDebug' })}</span>
<span className="system-sm-medium text-components-button-secondary-accent-text">{t('manageModels', { ns: 'appDebug' })}</span>
<span className="i-ri-arrow-right-line h-4 w-4 text-components-button-secondary-accent-text" />
</button>
</div>

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { ExternalDataTool } from '@/models/common'
import type { PromptRole, PromptVariable } from '@/models/debug'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiDeleteBinLine,
RiErrorWarningFill,
@ -30,7 +31,6 @@ import ConfigContext from '@/context/debug-configuration'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useModalContext } from '@/context/modal-context'
import { AppModeEnum } from '@/types/app'
import { cn } from '@/utils/classnames'
import { getNewVar, getVars } from '@/utils/var'
import ConfirmAddVar from './confirm-add-var'
import MessageTypeSelector from './message-type-selector'

View File

@ -1,10 +1,10 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { useBoolean, useClickAway } from 'ahooks'
import * as React from 'react'
import { ChevronSelectorVertical } from '@/app/components/base/icons/src/vender/line/arrows'
import { PromptRole } from '@/models/debug'
import { cn } from '@/utils/classnames'
type Props = {
value: PromptRole
@ -25,10 +25,10 @@ const MessageTypeSelector: FC<Props> = ({
<div className="relative left-[-8px]" ref={ref}>
<div
onClick={toggleShow}
className={cn(showOption && 'bg-indigo-100', 'flex h-7 cursor-pointer items-center space-x-0.5 rounded-lg pl-1.5 pr-1 text-indigo-800')}
className={cn(showOption && 'bg-indigo-100', 'flex h-7 cursor-pointer items-center space-x-0.5 rounded-lg pr-1 pl-1.5 text-indigo-800')}
>
<div className="text-sm font-semibold uppercase">{value}</div>
<ChevronSelectorVertical className="h-3 w-3 " />
<ChevronSelectorVertical className="h-3 w-3" />
</div>
{showOption && (
<div className="absolute top-[30px] z-10 rounded-lg border border-components-panel-border bg-components-panel-bg p-1 shadow-lg">
@ -39,7 +39,7 @@ const MessageTypeSelector: FC<Props> = ({
setHide()
onChange(type)
}}
className="flex h-9 min-w-[44px] cursor-pointer items-center rounded-lg px-3 text-sm font-medium uppercase text-text-secondary hover:bg-state-base-hover"
className="flex h-9 min-w-[44px] cursor-pointer items-center rounded-lg px-3 text-sm font-medium text-text-secondary uppercase hover:bg-state-base-hover"
>
{type}
</div>

View File

@ -1,9 +1,9 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { useDebounceFn } from 'ahooks'
import * as React from 'react'
import { useCallback, useEffect, useState } from 'react'
import { cn } from '@/utils/classnames'
type Props = {
className?: string

View File

@ -3,6 +3,7 @@ import type { FC } from 'react'
import type { ExternalDataTool } from '@/models/common'
import type { PromptVariable } from '@/models/debug'
import type { GenRes } from '@/service/debug'
import { cn } from '@langgenius/dify-ui/cn'
import { useBoolean } from 'ahooks'
import { noop } from 'es-toolkit/function'
import { produce } from 'immer'
@ -28,7 +29,6 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useModalContext } from '@/context/modal-context'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { AppModeEnum } from '@/types/app'
import { cn } from '@/utils/classnames'
import { getNewVar, getVars } from '@/utils/var'
import ConfirmAddVar from './confirm-add-var'
import PromptEditorHeightResizeWrap from './prompt-editor-height-resize-wrap'
@ -179,14 +179,14 @@ const Prompt: FC<ISimplePromptInput> = ({
<div className={cn('relative rounded-xl bg-linear-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2 p-0.5 shadow-xs')}>
<div className="rounded-xl bg-background-section-burn">
{!noTitle && (
<div className="flex h-11 items-center justify-between pl-3 pr-2.5">
<div className="flex h-11 items-center justify-between pr-2.5 pl-3">
<div className="flex items-center space-x-1">
<div className="h2 text-text-secondary system-sm-semibold-uppercase">{mode !== AppModeEnum.COMPLETION ? t('chatSubTitle', { ns: 'appDebug' }) : t('completionSubTitle', { ns: 'appDebug' })}</div>
<div className="system-sm-semibold-uppercase text-text-secondary">{mode !== AppModeEnum.COMPLETION ? t('chatSubTitle', { ns: 'appDebug' }) : t('completionSubTitle', { ns: 'appDebug' })}</div>
{!readonly && (
<Tooltip>
<TooltipTrigger
render={(
<span className="i-ri-question-line ml-1 h-4 w-4 shrink-0 text-text-quaternary" />
<span className="ml-1 i-ri-question-line h-4 w-4 shrink-0 text-text-quaternary" />
)}
/>
<TooltipContent>

View File

@ -1,8 +1,8 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
type Props = {
className?: string
@ -20,10 +20,10 @@ const Field: FC<Props> = ({
const { t } = useTranslation()
return (
<div className={cn(className)}>
<div className="leading-8! text-text-secondary system-sm-semibold">
<div className="system-sm-semibold leading-8! text-text-secondary">
{title}
{isOptional && (
<span className="ml-1 text-text-tertiary system-xs-regular">
<span className="ml-1 system-xs-regular text-text-tertiary">
(
{t('variableConfig.optional', { ns: 'appDebug' })}
)

View File

@ -206,7 +206,7 @@ const ConfigModalFormFields: FC<ConfigModalFormFieldsProps> = ({
value={jsonSchemaStr}
onChange={onJSONSchemaChange}
noWrapper
className="h-[80px] overflow-y-auto radius-lg bg-components-input-bg-normal p-1"
className="h-[80px] overflow-y-auto rounded-[10px] bg-components-input-bg-normal p-1"
placeholder={<div className="whitespace-pre">{jsonConfigPlaceHolder}</div>}
/>
</Field>

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { InputVarType } from '@/app/components/workflow/types'
import { ChevronDownIcon } from '@heroicons/react/20/solid'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useState } from 'react'
import Badge from '@/app/components/base/badge'
@ -12,7 +13,6 @@ import {
} from '@/app/components/base/portal-to-follow-elem'
import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon'
import { inputVarTypeToVarType } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { cn } from '@/utils/classnames'
export type Item = {
value: InputVarType

View File

@ -1,11 +1,11 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiAddLine, RiDeleteBinLine, RiDraggable } from '@remixicon/react'
import * as React from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ReactSortable } from 'react-sortablejs'
import { cn } from '@/utils/classnames'
export type Options = string[]
type IConfigSelectProps = {
@ -63,13 +63,13 @@ const ConfigSelect: FC<IConfigSelectProps> = ({
return item
}))
}}
className="h-9 w-full grow cursor-pointer overflow-x-auto rounded-lg border-0 bg-transparent pl-1.5 pr-8 text-sm leading-9 text-text-secondary focus:outline-hidden"
className="h-9 w-full grow cursor-pointer overflow-x-auto rounded-lg border-0 bg-transparent pr-8 pl-1.5 text-sm leading-9 text-text-secondary focus:outline-hidden"
onFocus={() => setFocusID(index)}
onBlur={() => setFocusID(null)}
/>
<div
role="button"
className="absolute right-1.5 top-1/2 block translate-y-[-50%] cursor-pointer rounded-md p-1 text-text-tertiary hover:bg-state-destructive-hover hover:text-text-destructive"
className="absolute top-1/2 right-1.5 block translate-y-[-50%] cursor-pointer rounded-md p-1 text-text-tertiary hover:bg-state-destructive-hover hover:text-text-destructive"
onClick={() => {
onChange(options.filter((_, i) => index !== i))
setDeletingID(null)
@ -87,7 +87,7 @@ const ConfigSelect: FC<IConfigSelectProps> = ({
<div
onClick={() => { onChange([...options, '']) }}
className="mt-1 flex h-9 cursor-pointer items-center gap-2 rounded-lg bg-components-button-tertiary-bg px-3 text-components-button-tertiary-text hover:bg-components-button-tertiary-bg-hover"
className="mt-1 flex h-9 cursor-pointer items-center gap-2 rounded-lg bg-components-button-tertiary-bg px-3 text-components-button-tertiary-text hover:bg-components-button-tertiary-bg-hover"
>
<RiAddLine className="h-4 w-4" />
<div className="system-sm-medium text-[13px]">{t('variableConfig.addOption', { ns: 'appDebug' })}</div>

View File

@ -4,6 +4,7 @@ import type { InputVar } from '@/app/components/workflow/types'
import type { ExternalDataTool } from '@/models/common'
import type { PromptVariable } from '@/models/debug'
import type { I18nKeysByPrefix } from '@/types/i18n'
import { cn } from '@langgenius/dify-ui/cn'
import { useBoolean } from 'ahooks'
import { produce } from 'immer'
import * as React from 'react'
@ -27,7 +28,6 @@ import ConfigContext from '@/context/debug-configuration'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useModalContext } from '@/context/modal-context'
import { AppModeEnum } from '@/types/app'
import { cn } from '@/utils/classnames'
import { getNewVar, hasDuplicateStr } from '@/utils/var'
import Panel from '../base/feature-panel'
import EditModal from './config-modal'

View File

@ -2,10 +2,10 @@
import type { FC } from 'react'
import type { InputVarType } from '@/app/components/workflow/types'
import type { I18nKeysByPrefix } from '@/types/i18n'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon'
import { cn } from '@/utils/classnames'
type ISelectTypeItemProps = {
type: InputVarType
@ -33,7 +33,7 @@ const SelectTypeItem: FC<ISelectTypeItemProps> = ({
<div
className={cn(
'flex h-[58px] flex-col items-center justify-center space-y-1 rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary',
selected ? 'system-xs-medium border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg shadow-xs' : ' system-xs-regular cursor-pointer hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs',
selected ? 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg system-xs-medium shadow-xs' : 'cursor-pointer system-xs-regular hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs',
)}
onClick={onClick}
>

View File

@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { IInputTypeIconProps } from './input-type-icon'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiDeleteBinLine,
RiDraggable,
@ -10,7 +11,6 @@ import * as React from 'react'
import { useState } from 'react'
import Badge from '@/app/components/base/badge'
import { BracketsX as VarIcon } from '@/app/components/base/icons/src/vender/line/development'
import { cn } from '@/utils/classnames'
import IconTypeIcon from './input-type-icon'
type ItemProps = {
@ -39,22 +39,22 @@ const VarItem: FC<ItemProps> = ({
const [isDeleting, setIsDeleting] = useState(false)
return (
<div className={cn('group relative mb-1 flex h-[34px] w-full items-center rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg pl-2.5 pr-3 shadow-xs last-of-type:mb-0 hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm', isDeleting && 'border-state-destructive-border hover:bg-state-destructive-hover', readonly && 'cursor-not-allowed', className)}>
<div className={cn('group relative mb-1 flex h-[34px] w-full items-center rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg pr-3 pl-2.5 shadow-xs last-of-type:mb-0 hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm', isDeleting && 'border-state-destructive-border hover:bg-state-destructive-hover', readonly && 'cursor-not-allowed', className)}>
<VarIcon className={cn('mr-1 h-4 w-4 shrink-0 text-text-accent', canDrag && 'group-hover:opacity-0')} />
{canDrag && (
<RiDraggable className="absolute left-3 top-3 hidden h-3 w-3 cursor-pointer text-text-tertiary group-hover:block" />
<RiDraggable className="absolute top-3 left-3 hidden h-3 w-3 cursor-pointer text-text-tertiary group-hover:block" />
)}
<div className="flex w-0 grow items-center">
<div className="truncate" title={`${name} · ${label}`}>
<span className="system-sm-medium text-text-secondary">{name}</span>
<span className="system-xs-regular px-1 text-text-quaternary">·</span>
<span className="px-1 system-xs-regular text-text-quaternary">·</span>
<span className="system-xs-medium text-text-tertiary">{label}</span>
</div>
</div>
<div className="shrink-0">
<div className={cn('flex items-center', !readonly && 'group-hover:hidden')}>
{required && <Badge text="required" />}
<span className="system-xs-regular pl-2 pr-1 text-text-tertiary">{type}</span>
<span className="pr-1 pl-2 system-xs-regular text-text-tertiary">{type}</span>
<IconTypeIcon type={type as IInputTypeIconProps['type']} className="text-text-tertiary" />
</div>
<div className={cn('hidden items-center justify-end rounded-lg', !readonly && 'group-hover:flex')}>
@ -66,7 +66,7 @@ const VarItem: FC<ItemProps> = ({
</div>
<div
data-testid="var-item-delete-btn"
className="flex h-6 w-6 cursor-pointer items-center justify-center text-text-tertiary hover:text-text-destructive"
className="flex h-6 w-6 cursor-pointer items-center justify-center text-text-tertiary hover:text-text-destructive"
onClick={onRemove}
onMouseOver={() => setIsDeleting(true)}
onMouseLeave={() => setIsDeleting(false)}

View File

@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { noop } from 'es-toolkit/function'
import { produce } from 'immer'
import * as React from 'react'
@ -16,7 +17,6 @@ import { SupportUploadFileTypes } from '@/app/components/workflow/types'
// import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
import ConfigContext from '@/context/debug-configuration'
import { Resolution } from '@/types/app'
import { cn } from '@/utils/classnames'
import ParamConfig from './param-config'
const ConfigVision: FC = () => {
@ -62,14 +62,14 @@ const ConfigVision: FC = () => {
return null
return (
<div className="mt-2 flex items-center gap-2 rounded-xl border-l-[0.5px] border-t-[0.5px] border-effects-highlight bg-background-section-burn p-2">
<div className="mt-2 flex items-center gap-2 rounded-xl border-t-[0.5px] border-l-[0.5px] border-effects-highlight bg-background-section-burn p-2">
<div className="shrink-0 p-1">
<div className="rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-indigo-indigo-600 p-1 shadow-xs">
<Vision className="h-4 w-4 text-text-primary-on-surface" />
</div>
</div>
<div className="flex grow items-center">
<div className="system-sm-semibold mr-1 text-text-secondary">{t('vision.name', { ns: 'appDebug' })}</div>
<div className="mr-1 system-sm-semibold text-text-secondary">{t('vision.name', { ns: 'appDebug' })}</div>
<Tooltip
popupContent={(
<div className="w-[180px]">
@ -100,7 +100,7 @@ const ConfigVision: FC = () => {
selected={file?.image?.detail === Resolution.high}
onSelect={noop}
className={cn(
'cursor-not-allowed rounded-lg px-3 hover:shadow-none',
'cursor-not-allowed rounded-lg px-3 hover:shadow-none',
file?.image?.detail !== Resolution.high && 'hover:border-components-option-card-option-border',
)}
/>
@ -109,7 +109,7 @@ const ConfigVision: FC = () => {
selected={file?.image?.detail === Resolution.low}
onSelect={noop}
className={cn(
'cursor-not-allowed rounded-lg px-3 hover:shadow-none',
'cursor-not-allowed rounded-lg px-3 hover:shadow-none',
file?.image?.detail !== Resolution.low && 'hover:border-components-option-card-option-border',
)}
/>
@ -119,7 +119,7 @@ const ConfigVision: FC = () => {
: (
<>
<ParamConfig />
<div className="ml-1 mr-3 h-3.5 w-px bg-divider-regular"></div>
<div className="mr-3 ml-1 h-3.5 w-px bg-divider-regular"></div>
<Switch
value={isImageEnabled}
onChange={handleChange}

View File

@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiSettings2Line } from '@remixicon/react'
import { memo, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -9,7 +10,6 @@ import {
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { Button } from '@/app/components/base/ui/button'
import { cn } from '@/utils/classnames'
import ParamConfigContent from './param-config-content'
const ParamsConfig: FC = () => {

View File

@ -1,8 +1,8 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import Tooltip from '@/app/components/base/tooltip'
import { cn } from '@/utils/classnames'
type Props = {
className?: string
@ -23,7 +23,7 @@ const ItemPanel: FC<Props> = ({
<div className={cn(className, 'flex h-12 items-center justify-between rounded-lg bg-background-section-burn px-3')}>
<div className="flex items-center">
{icon}
<div className="ml-3 mr-1 text-sm font-semibold leading-6 text-text-secondary">{name}</div>
<div className="mr-1 ml-3 text-sm leading-6 font-semibold text-text-secondary">{name}</div>
<Tooltip
popupContent={(
<div className="w-[180px]">

View File

@ -4,6 +4,7 @@ import type { Collection } from '@/app/components/tools/types'
import type { ToolDefaultValue, ToolValue } from '@/app/components/workflow/block-selector/types'
import type { ToolWithProvider } from '@/app/components/workflow/types'
import type { AgentTool } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiDeleteBinLine,
RiEqualizer2Line,
@ -32,7 +33,6 @@ import ConfigContext from '@/context/debug-configuration'
import { useMittContextSelector } from '@/context/mitt-context'
import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools } from '@/service/use-tools'
import { canFindTool } from '@/utils'
import { cn } from '@/utils/classnames'
import { useFormattingChangedDispatcher } from '../../../debug/hooks'
import SettingBuiltInTool from './setting-built-in-tool'

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { Collection, Tool } from '@/app/components/tools/types'
import type { ToolWithProvider } from '@/app/components/workflow/types'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiArrowLeftLine,
RiCloseLine,
@ -28,7 +29,6 @@ import { toolParametersToFormSchemas } from '@/app/components/tools/utils/to-for
import { useLocale } from '@/context/i18n'
import { getLanguage } from '@/i18n-config/language'
import { fetchBuiltInToolList, fetchCustomToolList, fetchModelToolList, fetchWorkflowToolList } from '@/service/tools'
import { cn } from '@/utils/classnames'
type Props = {
showBackButton?: boolean

View File

@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { AgentConfig } from '@/models/debug'
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowDownSLine } from '@remixicon/react'
import * as React from 'react'
import { useState } from 'react'
@ -15,7 +16,6 @@ import {
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import Radio from '@/app/components/base/radio/ui'
import { cn } from '@/utils/classnames'
import AgentSetting from '../agent/agent-setting'
type Props = {
@ -45,15 +45,15 @@ const SelectItem: FC<ItemProps> = ({ text, value, Icon, isChecked, description,
onClick={() => !disabled && onClick(value)}
>
<div className="flex items-center justify-between">
<div className="flex items-center ">
<div className="flex items-center">
<div className="mr-3 rounded-lg bg-indigo-50 p-1">
<Icon className="h-4 w-4 text-indigo-600" />
</div>
<div className="text-sm font-medium leading-5 text-gray-900">{text}</div>
<div className="text-sm leading-5 font-medium text-gray-900">{text}</div>
</div>
<Radio isChecked={isChecked} />
</div>
<div className="ml-9 text-xs font-normal leading-[18px] text-gray-500">{description}</div>
<div className="ml-9 text-xs leading-[18px] font-normal text-gray-500">{description}</div>
</div>
)
}
@ -84,7 +84,7 @@ const AssistantTypePicker: FC<Props> = ({
<>
<div className="my-4 h-px bg-gray-100"></div>
<div
className={cn(isAgent ? 'group cursor-pointer hover:bg-primary-50' : 'opacity-30', 'rounded-xl bg-gray-50 p-3 pr-4 ')}
className={cn(isAgent ? 'group cursor-pointer hover:bg-primary-50' : 'opacity-30', 'rounded-xl bg-gray-50 p-3 pr-4')}
onClick={() => {
if (isAgent) {
setOpen(false)
@ -93,15 +93,15 @@ const AssistantTypePicker: FC<Props> = ({
}}
>
<div className="flex items-center justify-between">
<div className="flex items-center ">
<div className="flex items-center">
<div className="mr-3 rounded-lg bg-gray-200 p-1 group-hover:bg-white">
<Settings04 className="h-4 w-4 text-gray-600 group-hover:text-[#155EEF]" />
</div>
<div className="text-sm font-medium leading-5 text-gray-900 group-hover:text-[#155EEF]">{t('agent.setting.name', { ns: 'appDebug' })}</div>
<div className="text-sm leading-5 font-medium text-gray-900 group-hover:text-[#155EEF]">{t('agent.setting.name', { ns: 'appDebug' })}</div>
</div>
<ArrowUpRight className="h-4 w-4 text-gray-500 group-hover:text-[#155EEF]" />
</div>
<div className="ml-9 text-xs font-normal leading-[18px] text-gray-500">{t('agent.setting.description', { ns: 'appDebug' })}</div>
<div className="ml-9 text-xs leading-[18px] font-normal text-gray-500">{t('agent.setting.description', { ns: 'appDebug' })}</div>
</div>
</>
)
@ -117,7 +117,7 @@ const AssistantTypePicker: FC<Props> = ({
}}
>
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
<div className={cn(open && 'bg-gray-50', 'flex h-8 cursor-pointer select-none items-center space-x-1 rounded-lg border border-black/5 px-3 text-indigo-600')}>
<div className={cn(open && 'bg-gray-50', 'flex h-8 cursor-pointer items-center space-x-1 rounded-lg border border-black/5 px-3 text-indigo-600 select-none')}>
{isAgent ? <BubbleText className="h-3 w-3" /> : <CuteRobot className="h-3 w-3" />}
<div className="text-xs font-medium">{t(`assistantType.${isAgent ? 'agentAssistant' : 'chatAssistant'}.name`, { ns: 'appDebug' })}</div>
<RiArrowDownSLine className="h-3 w-3" />
@ -125,7 +125,7 @@ const AssistantTypePicker: FC<Props> = ({
</PortalToFollowElemTrigger>
<PortalToFollowElemContent style={{ zIndex: 1000 }}>
<div className="relative left-0.5 w-[480px] rounded-xl border border-black/8 bg-white p-6 shadow-lg">
<div className="mb-2 text-sm font-semibold leading-5 text-gray-900">{t('assistantType.name', { ns: 'appDebug' })}</div>
<div className="mb-2 text-sm leading-5 font-semibold text-gray-900">{t('assistantType.name', { ns: 'appDebug' })}</div>
<SelectItem
Icon={BubbleText}
value="chat"

View File

@ -1,11 +1,11 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { ArrowDownRoundFill } from '@/app/components/base/icons/src/vender/solid/general'
import Textarea from '@/app/components/base/textarea'
import { cn } from '@/utils/classnames'
const i18nPrefix = 'generate'
@ -27,10 +27,10 @@ const IdeaOutput: FC<Props> = ({
return (
<div className="mt-4 text-[0px]">
<div
className="mb-1.5 flex cursor-pointer items-center text-sm font-medium leading-5 text-text-primary"
className="mb-1.5 flex cursor-pointer items-center text-sm leading-5 font-medium text-text-primary"
onClick={toggleFoldIdeaOutput}
>
<div className="system-sm-semibold-uppercase mr-1 text-text-secondary">{t(`${i18nPrefix}.idealOutput`, { ns: 'appDebug' })}</div>
<div className="mr-1 system-sm-semibold-uppercase text-text-secondary">{t(`${i18nPrefix}.idealOutput`, { ns: 'appDebug' })}</div>
<div className="system-xs-regular text-text-tertiary">
(
{t(`${i18nPrefix}.optional`, { ns: 'appDebug' })}

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { GeneratorType } from './types'
import type { Node, NodeOutPutVar, ValueSelector } from '@/app/components/workflow/types'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import PromptEditor from '@/app/components/base/prompt-editor'
@ -9,7 +10,6 @@ import { PROMPT_EDITOR_INSERT_QUICKLY } from '@/app/components/base/prompt-edito
import { Type } from '@/app/components/workflow/nodes/llm/types'
import { BlockEnum } from '@/app/components/workflow/types'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { cn } from '@/utils/classnames'
type Props = {
editorKey: string
@ -45,7 +45,7 @@ const InstructionEditor: FC<Props> = ({
const isCode = generatorType === 'code'
const placeholder = isCode
? (
<div className="system-sm-regular whitespace-break-spaces leading-6! text-text-placeholder">
<div className="system-sm-regular leading-6! whitespace-break-spaces text-text-placeholder">
{t(`${i18nPrefix}.codeGenInstructionPlaceHolderLine`, { ns: 'appDebug' })}
</div>
)
@ -67,7 +67,7 @@ const InstructionEditor: FC<Props> = ({
return (
<div className="relative">
<PromptEditor
wrapperClassName="border border-components-input-bg-normal! bg-components-input-bg-normal hover:border-components-input-bg-hover! radius-lg px-4 pt-3"
wrapperClassName="border border-components-input-bg-normal! bg-components-input-bg-normal hover:border-components-input-bg-hover! rounded-[10px] px-4 pt-3"
key={editorKey}
instanceId={editorKey}
placeholder={placeholder}
@ -109,9 +109,9 @@ const InstructionEditor: FC<Props> = ({
editable
isSupportFileVar={false}
/>
<div className="system-xs-regular absolute bottom-0 left-4 flex h-8 items-center space-x-0.5 text-components-input-text-placeholder">
<div className="absolute bottom-0 left-4 flex h-8 items-center space-x-0.5 system-xs-regular text-components-input-text-placeholder">
<span>{t('generate.press', { ns: 'appDebug' })}</span>
<span className="system-kbd flex h-4 w-3.5 items-center justify-center radius-xs bg-components-kbd-bg-gray text-text-placeholder">/</span>
<span className="flex h-4 w-3.5 items-center justify-center rounded-sm bg-components-kbd-bg-gray system-kbd text-text-placeholder">/</span>
<span>{t('generate.to', { ns: 'appDebug' })}</span>
<span onClick={handleInsertVariable} className="ml-1! cursor-pointer hover:border-b hover:border-dotted hover:border-text-tertiary hover:text-text-tertiary">{t('generate.insertContext', { ns: 'appDebug' })}</span>
</div>

View File

@ -1,9 +1,9 @@
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowDownSLine, RiSparklingFill } from '@remixicon/react'
import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { Markdown } from '@/app/components/base/markdown'
import { cn } from '@/utils/classnames'
import s from './style.module.css'
type Props = {
@ -43,7 +43,7 @@ const PromptToast = ({
<RiArrowDownSLine className={cn('size-4 cursor-pointer text-text-tertiary', isFold && '-rotate-90')} onClick={toggleFold} />
</div>
{!isFold && (
<div className="pb-4 pr-4">
<div className="pr-4 pb-4">
<Markdown className="text-sm!" content={message} />
</div>
)}

View File

@ -1,10 +1,10 @@
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowDownSLine, RiCheckLine } from '@remixicon/react'
import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
import { cn } from '@/utils/classnames'
type VersionSelectorProps = {
versionLen: number
@ -52,14 +52,14 @@ const VersionSelector: React.FC<VersionSelectorProps> = ({ versionLen, value, on
asChild
>
<div className={cn('system-xs-medium flex items-center text-text-tertiary', isOpen && 'text-text-secondary', moreThanOneVersion && 'cursor-pointer')}>
<div className={cn('flex items-center system-xs-medium text-text-tertiary', isOpen && 'text-text-secondary', moreThanOneVersion && 'cursor-pointer')}>
<div>
{t('generate.version', { ns: 'appDebug' })}
{' '}
{value + 1}
{isLatest && ` · ${t('generate.latest', { ns: 'appDebug' })}`}
</div>
{moreThanOneVersion && <RiArrowDownSLine className="size-3 " />}
{moreThanOneVersion && <RiArrowDownSLine className="size-3" />}
</div>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className={cn(
@ -71,7 +71,7 @@ const VersionSelector: React.FC<VersionSelectorProps> = ({ versionLen, value, on
'w-[208px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg',
)}
>
<div className={cn('system-xs-medium-uppercase flex h-[22px] items-center px-3 pl-3 text-text-tertiary')}>
<div className={cn('flex h-[22px] items-center px-3 pl-3 system-xs-medium-uppercase text-text-tertiary')}>
{t('generate.versions', { ns: 'appDebug' })}
</div>
{
@ -79,7 +79,7 @@ const VersionSelector: React.FC<VersionSelectorProps> = ({ versionLen, value, on
<div
key={option.value}
className={cn(
'system-sm-medium flex h-7 cursor-pointer items-center rounded-lg px-2 text-text-secondary hover:bg-state-base-hover',
'flex h-7 cursor-pointer items-center rounded-lg px-2 system-sm-medium text-text-secondary hover:bg-state-base-hover',
)}
title={option.label}
onClick={() => {

View File

@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { DataSet } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiDeleteBinLine,
RiEditLine,
@ -14,7 +15,6 @@ import Badge from '@/app/components/base/badge'
import Drawer from '@/app/components/base/drawer'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { useKnowledge } from '@/hooks/use-knowledge'
import { cn } from '@/utils/classnames'
import SettingsModal from '../settings-modal'
type ItemProps = {
@ -68,7 +68,7 @@ const Item: FC<ItemProps> = ({
background={iconInfo.icon_type === 'image' ? undefined : iconInfo.icon_background}
imageUrl={iconInfo.icon_type === 'image' ? iconInfo.icon_url : undefined}
/>
<div className="system-sm-medium w-0 grow truncate text-text-secondary" title={config.name}>{config.name}</div>
<div className="w-0 grow truncate system-sm-medium text-text-secondary" title={config.name}>{config.name}</div>
</div>
<div className="ml-2 hidden shrink-0 items-center space-x-1 group-hover:flex">
{

View File

@ -1,11 +1,11 @@
'use client'
import type { FC } from 'react'
import type { Props } from './var-picker'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { BracketsX } from '@/app/components/base/icons/src/vender/line/development'
import Tooltip from '@/app/components/base/tooltip'
import { cn } from '@/utils/classnames'
import VarPicker from './var-picker'
const ContextVar: FC<Props> = (props) => {
@ -14,7 +14,7 @@ const ContextVar: FC<Props> = (props) => {
const currItem = options.find(item => item.value === value)
const notSetVar = !currItem
return (
<div className={cn(notSetVar ? 'rounded-bl-xl rounded-br-xl border-[#FEF0C7] bg-[#FEF0C7]' : 'border-components-panel-border-subtle', 'flex h-12 items-center justify-between border-t px-3 ')}>
<div className={cn(notSetVar ? 'rounded-br-xl rounded-bl-xl border-[#FEF0C7] bg-[#FEF0C7]' : 'border-components-panel-border-subtle', 'flex h-12 items-center justify-between border-t px-3')}>
<div className="flex shrink-0 items-center space-x-1">
<div className="p-1">
<BracketsX className="h-4 w-4 text-text-accent" />

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { IInputTypeIconProps } from '@/app/components/app/configuration/config-var/input-type-icon'
import { ChevronDownIcon } from '@heroicons/react/24/outline'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -11,7 +12,6 @@ import {
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { cn } from '@/utils/classnames'
type Option = { name: string, value: string, type: string }
export type Props = {
@ -57,11 +57,11 @@ const VarPicker: FC<Props> = ({
<PortalToFollowElemTrigger className={cn(triggerClassName)} onClick={() => setOpen(v => !v)}>
<div className={cn(
className,
notSetVar ? 'border-[#FEDF89] bg-[#FFFCF5] text-[#DC6803]' : ' border-components-button-secondary-border text-text-accent hover:bg-components-button-secondary-bg',
notSetVar ? 'border-[#FEDF89] bg-[#FFFCF5] text-[#DC6803]' : 'border-components-button-secondary-border text-text-accent hover:bg-components-button-secondary-bg',
open ? 'bg-components-button-secondary-bg' : 'bg-transparent',
`
flex h-8 cursor-pointer items-center justify-center space-x-1 rounded-lg border px-2 text-[13px]
font-medium shadow-xs
flex h-8 cursor-pointer items-center justify-center space-x-1 rounded-lg border px-2 text-[13px]
font-medium shadow-xs
`,
)}
>
@ -82,7 +82,7 @@ const VarPicker: FC<Props> = ({
<PortalToFollowElemContent style={{ zIndex: 1000 }}>
{options.length > 0
? (
<div className="max-h-[50vh] w-[240px] overflow-y-auto rounded-lg border border-components-panel-border bg-components-panel-bg p-1 shadow-lg">
<div className="max-h-[50vh] w-[240px] overflow-y-auto rounded-lg border border-components-panel-border bg-components-panel-bg p-1 shadow-lg">
{options.map(({ name, value, type }, index) => (
<div
key={index}

View File

@ -8,6 +8,7 @@ import type {
MetadataFilteringModeEnum,
} from '@/app/components/workflow/nodes/knowledge-retrieval/types'
import type { DataSet } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
import { intersectionBy } from 'es-toolkit/compat'
import { produce } from 'immer'
import * as React from 'react'
@ -30,7 +31,6 @@ import {
import { useSelector as useAppContextSelector } from '@/context/app-context'
import ConfigContext from '@/context/debug-configuration'
import { AppModeEnum } from '@/types/app'
import { cn } from '@/utils/classnames'
import { hasEditPermissionForDataset } from '@/utils/permission'
import FeaturePanel from '../base/feature-panel'
import OperationBtn from '../base/operation-btn'
@ -291,7 +291,7 @@ const DatasetConfig: FC<Props> = ({ readonly, hideMetadataFilter }) => {
)
: (
<div className="mt-1 px-3 pb-3">
<div className="pb-1 pt-2 text-xs text-text-tertiary">{t('feature.dataSet.noData', { ns: 'appDebug' })}</div>
<div className="pt-2 pb-1 text-xs text-text-tertiary">{t('feature.dataSet.noData', { ns: 'appDebug' })}</div>
</div>
)}

View File

@ -9,6 +9,7 @@ import type {
import type {
DatasetConfigs,
} from '@/models/debug'
import { cn } from '@langgenius/dify-ui/cn'
import { memo, useCallback, useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Divider from '@/app/components/base/divider'
@ -24,7 +25,6 @@ import ModelSelector from '@/app/components/header/account-setting/model-provide
import { useSelectedDatasetsMode } from '@/app/components/workflow/nodes/knowledge-retrieval/hooks'
import { RerankingModeEnum } from '@/models/datasets'
import { RETRIEVE_TYPE } from '@/types/app'
import { cn } from '@/utils/classnames'
import WeightedScore from './weighted-score'
type Props = {
@ -188,14 +188,14 @@ const ConfigContent: FC<Props> = ({
return (
<div>
<div className="text-text-primary system-xl-semibold">{t('retrievalSettings', { ns: 'dataset' })}</div>
<div className="text-text-tertiary system-xs-regular">
<div className="system-xl-semibold text-text-primary">{t('retrievalSettings', { ns: 'dataset' })}</div>
<div className="system-xs-regular text-text-tertiary">
{t('defaultRetrievalTip', { ns: 'dataset' })}
</div>
{type === RETRIEVE_TYPE.multiWay && (
<>
<div className="my-2 flex flex-col items-center py-1">
<div className="mb-2 mr-2 shrink-0 text-text-secondary system-xs-semibold-uppercase">
<div className="mr-2 mb-2 shrink-0 system-xs-semibold-uppercase text-text-secondary">
{t('rerankSettings', { ns: 'dataset' })}
</div>
<Divider bgStyle="gradient" className="m-0 h-px!" />
@ -203,21 +203,21 @@ const ConfigContent: FC<Props> = ({
{
selectedDatasetsMode.inconsistentEmbeddingModel
&& (
<div className="mt-4 text-text-warning system-xs-medium">
<div className="mt-4 system-xs-medium text-text-warning">
{t('inconsistentEmbeddingModelTip', { ns: 'dataset' })}
</div>
)
}
{
selectedDatasetsMode.mixtureInternalAndExternal && (
<div className="mt-4 text-text-warning system-xs-medium">
<div className="mt-4 system-xs-medium text-text-warning">
{t('mixtureInternalAndExternalTip', { ns: 'dataset' })}
</div>
)
}
{
selectedDatasetsMode.allExternal && (
<div className="mt-4 text-text-warning system-xs-medium">
<div className="mt-4 system-xs-medium text-text-warning">
{t('allExternalTip', { ns: 'dataset' })}
</div>
)
@ -225,7 +225,7 @@ const ConfigContent: FC<Props> = ({
{
selectedDatasetsMode.mixtureHighQualityAndEconomic
&& (
<div className="mt-4 text-text-warning system-xs-medium">
<div className="mt-4 system-xs-medium text-text-warning">
{t('mixtureHighQualityAndEconomicTip', { ns: 'dataset' })}
</div>
)
@ -238,7 +238,7 @@ const ConfigContent: FC<Props> = ({
<div
key={option.value}
className={cn(
'flex h-8 w-[calc((100%-8px)/2)] cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary system-sm-medium',
'flex h-8 w-[calc((100%-8px)/2)] cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg system-sm-medium text-text-secondary',
selectedRerankMode === option.value && 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary',
)}
onClick={() => handleRerankModeChange(option.value)}
@ -272,7 +272,7 @@ const ConfigContent: FC<Props> = ({
/>
)
}
<div className="ml-1 leading-[32px] text-text-secondary system-sm-semibold">{t('modelProvider.rerankModel.key', { ns: 'common' })}</div>
<div className="ml-1 system-sm-semibold leading-[32px] text-text-secondary">{t('modelProvider.rerankModel.key', { ns: 'common' })}</div>
<Tooltip
popupContent={(
<div className="w-[200px]">
@ -362,7 +362,7 @@ const ConfigContent: FC<Props> = ({
{isInWorkflow && type === RETRIEVE_TYPE.oneWay && (
<div className="mt-4">
<div className="flex items-center space-x-0.5">
<div className="text-[13px] font-medium leading-[32px] text-text-primary">{t('modelProvider.systemReasoningModel.key', { ns: 'common' })}</div>
<div className="text-[13px] leading-[32px] font-medium text-text-primary">{t('modelProvider.systemReasoningModel.key', { ns: 'common' })}</div>
<Tooltip
popupContent={t('modelProvider.systemReasoningModel.tip', { ns: 'common' })}
/>

View File

@ -1,6 +1,7 @@
'use client'
import type { DataSet } from '@/models/datasets'
import type { DatasetConfigs } from '@/models/debug'
import { cn } from '@langgenius/dify-ui/cn'
import { RiEqualizer2Line } from '@remixicon/react'
import { memo, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -16,7 +17,6 @@ import {
import ConfigContext from '@/context/debug-configuration'
import { RerankingModeEnum } from '@/models/datasets'
import { RETRIEVE_TYPE } from '@/types/app'
import { cn } from '@/utils/classnames'
import ConfigContent from './config-content'
type ParamsConfigProps = {

View File

@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import type { DataSet } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
import { useInfiniteScroll } from 'ahooks'
import * as React from 'react'
import { useMemo, useRef, useState } from 'react'
@ -15,7 +16,6 @@ import FeatureIcon from '@/app/components/header/account-setting/model-provider-
import { useKnowledge } from '@/hooks/use-knowledge'
import Link from '@/next/link'
import { useInfiniteDatasets } from '@/service/knowledge/use-dataset'
import { cn } from '@/utils/classnames'
type ISelectDataSetProps = {
isShow: boolean

View File

@ -2,6 +2,7 @@ import type { FC } from 'react'
import type { Member } from '@/models/common'
import type { DataSet } from '@/models/datasets'
import type { RetrievalConfig } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import { RiCloseLine } from '@remixicon/react'
import { isEqual } from 'es-toolkit/predicate'
import { useEffect, useMemo, useRef, useState } from 'react'
@ -25,7 +26,6 @@ import { useModalContext } from '@/context/modal-context'
import { DatasetPermission } from '@/models/datasets'
import { updateDatasetSetting } from '@/service/datasets'
import { useMembers } from '@/service/use-common'
import { cn } from '@/utils/classnames'
import { RetrievalChangeTip, RetrievalSection } from './retrieval-section'
type SettingsModalProps = {

View File

@ -2,6 +2,7 @@ import type { FC } from 'react'
import type { DataSet } from '@/models/datasets'
import type { RetrievalConfig } from '@/types/app'
import type { DocPathWithoutLang } from '@/types/doc-paths'
import { cn } from '@langgenius/dify-ui/cn'
import { RiCloseLine } from '@remixicon/react'
import Divider from '@/app/components/base/divider'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
@ -10,7 +11,6 @@ import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/ec
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
import { IndexingType } from '@/app/components/datasets/create/step-two'
import RetrievalSettings from '@/app/components/datasets/external-knowledge-base/create/RetrievalSettings'
import { cn } from '@/utils/classnames'
type CommonSectionProps = {
rowClass: string
@ -58,7 +58,7 @@ const ExternalRetrievalSection: FC<ExternalRetrievalSectionProps> = ({
<div className="w-full max-w-[480px]">
<div className="flex h-full items-center gap-1 rounded-lg bg-components-input-bg-normal px-3 py-2">
<ApiConnectionMod className="h-4 w-4 text-text-secondary" />
<div className="system-sm-medium overflow-hidden text-ellipsis text-text-secondary">
<div className="overflow-hidden system-sm-medium text-ellipsis text-text-secondary">
{currentDataset?.external_knowledge_info.external_knowledge_api_name}
</div>
<div className="system-xs-regular text-text-tertiary">·</div>
@ -102,7 +102,7 @@ const InternalRetrievalSection: FC<InternalRetrievalSectionProps> = ({
<div className={cn(labelClass, 'w-auto min-w-[168px]')}>
<div>
<div className="system-sm-semibold text-text-secondary">{t('form.retrievalSetting.title', { ns: 'datasetSettings' })}</div>
<div className="text-xs font-normal leading-[18px] text-text-tertiary">
<div className="text-xs leading-[18px] font-normal text-text-tertiary">
<a target="_blank" rel="noopener noreferrer" href={docLink('/use-dify/knowledge/create-knowledge/setting-indexing-methods')} className="text-text-accent">{t('form.retrievalSetting.learnMore', { ns: 'datasetSettings' })}</a>
{t('form.retrievalSetting.description', { ns: 'datasetSettings' })}
</div>
@ -198,10 +198,10 @@ export const RetrievalChangeTip: FC<RetrievalChangeTipProps> = ({
return null
return (
<div className="absolute bottom-[76px] left-[30px] right-[30px] z-10 flex h-10 items-center justify-between rounded-lg border border-[#FEF0C7] bg-[#FFFAEB] px-3 shadow-lg">
<div className="absolute right-[30px] bottom-[76px] left-[30px] z-10 flex h-10 items-center justify-between rounded-lg border border-[#FEF0C7] bg-[#FFFAEB] px-3 shadow-lg">
<div className="flex items-center">
<AlertTriangle className="mr-1 h-3 w-3 text-[#F79009]" />
<div className="text-xs font-medium leading-[18px] text-gray-700">{message}</div>
<div className="text-xs leading-[18px] font-medium text-gray-700">{message}</div>
</div>
<button
type="button"

View File

@ -1,4 +1,5 @@
import type { Inputs } from '@/models/debug'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
@ -8,7 +9,6 @@ import Select from '@/app/components/base/select'
import Textarea from '@/app/components/base/textarea'
import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input'
import ConfigContext from '@/context/debug-configuration'
import { cn } from '@/utils/classnames'
type Props = {
inputs: Inputs
@ -67,7 +67,7 @@ const ChatUserInput = ({
return (
<div className={cn('z-1 rounded-xl border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg shadow-xs')}>
<div className="px-4 pb-4 pt-3">
<div className="px-4 pt-3 pb-4">
{promptVariables.map(({ key, name, type, options, max_length, required }, index) => (
<div
key={key}
@ -75,7 +75,7 @@ const ChatUserInput = ({
>
<div>
{type !== 'checkbox' && (
<div className="system-sm-semibold mb-1 flex h-6 items-center gap-1 text-text-secondary">
<div className="mb-1 flex h-6 items-center gap-1 system-sm-semibold text-text-secondary">
<div className="truncate">{name || key}</div>
{!required && <span className="system-xs-regular text-text-tertiary">{t('panel.optional', { ns: 'workflow' })}</span>}
</div>

View File

@ -511,8 +511,8 @@ const Debug: FC<IDebug> = ({
{modelConfig.provider && isAPIKeySet && !modelConfig.model_id && (
<div className="flex grow flex-col items-center justify-center pb-[120px]">
<div className="flex w-full max-w-[400px] flex-col gap-2 px-4 py-4">
<div className="flex h-10 w-10 items-center justify-center radius-lg">
<div className="flex h-full w-full items-center justify-center overflow-hidden radius-lg border-[0.5px] border-components-card-border bg-components-card-bg p-1 shadow-lg backdrop-blur-[5px]">
<div className="flex h-10 w-10 items-center justify-center rounded-[10px]">
<div className="flex h-full w-full items-center justify-center overflow-hidden rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg p-1 shadow-lg backdrop-blur-[5px]">
<span className="i-ri-brain-2-line h-5 w-5 text-text-tertiary" />
</div>
</div>

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { Inputs } from '@/models/debug'
import type { VisionFile, VisionSettings } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiArrowDownSLine,
RiArrowRightSLine,
@ -22,7 +23,6 @@ import { Button } from '@/app/components/base/ui/button'
import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input'
import ConfigContext from '@/context/debug-configuration'
import { AppModeEnum, ModelModeType } from '@/types/app'
import { cn } from '@/utils/classnames'
export type IPromptValuePanelProps = {
appType: AppModeEnum

View File

@ -1,6 +1,7 @@
'use client'
import type { App } from '@/models/explore'
import { PlusIcon } from '@heroicons/react/20/solid'
import { cn } from '@langgenius/dify-ui/cn'
import { RiInformation2Line } from '@remixicon/react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
@ -9,7 +10,6 @@ import AppIcon from '@/app/components/base/app-icon'
import { Button } from '@/app/components/base/ui/button'
import AppListContext from '@/context/app-list-context'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { cn } from '@/utils/classnames'
import { AppTypeIcon, AppTypeLabel } from '../../type-selector'
type AppCardProps = {
@ -45,7 +45,7 @@ const AppCard = ({
imageUrl={appBasicInfo.icon_url}
/>
<AppTypeIcon
wrapperClassName="absolute -bottom-0.5 -right-0.5 w-4 h-4 radius-xs border border-divider-regular outline-solid outline-components-panel-on-panel-item-bg"
wrapperClassName="absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-sm border border-divider-regular outline-solid outline-components-panel-on-panel-item-bg"
className="h-3 w-3"
type={appBasicInfo.mode}
/>

View File

@ -2,6 +2,7 @@
import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal'
import type { App } from '@/models/explore'
import { cn } from '@langgenius/dify-ui/cn'
import { RiRobot2Line } from '@remixicon/react'
import { useDebounceFn } from 'ahooks'
import * as React from 'react'
@ -23,7 +24,6 @@ import { fetchAppDetail } from '@/service/explore'
import { useExploreAppList } from '@/service/use-explore'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { cn } from '@/utils/classnames'
import { trackCreateApp } from '@/utils/create-app-tracking'
import AppCard from '../app-card'
import Sidebar, { AppCategories, AppCategoryLabel } from './sidebar'
@ -183,7 +183,7 @@ const Apps = ({
<div className="h-full flex-1 shrink-0 grow overflow-auto border-l border-divider-burn p-6 pt-2">
{searchFilteredList && searchFilteredList.length > 0 && (
<>
<div className="pb-1 pt-4">
<div className="pt-4 pb-1">
{searchKeywords
? <p className="title-md-semi-bold text-text-tertiary">{searchFilteredList.length > 1 ? t('newApp.foundResults', { ns: 'app', count: searchFilteredList.length }) : t('newApp.foundResult', { ns: 'app', count: searchFilteredList.length })}</p>
: (
@ -194,7 +194,7 @@ const Apps = ({
</div>
<div
className={cn(
'grid shrink-0 grid-cols-1 content-start gap-3 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6',
'grid shrink-0 grid-cols-1 content-start gap-3 2k:grid-cols-6 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5',
)}
>
{searchFilteredList.map(app => (

View File

@ -1,8 +1,8 @@
'use client'
import { cn } from '@langgenius/dify-ui/cn'
import { RiStickyNoteAddLine, RiThumbUpLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import Divider from '@/app/components/base/divider'
import { cn } from '@/utils/classnames'
export enum AppCategories {
RECOMMENDED = 'Recommended',
@ -22,7 +22,7 @@ export default function Sidebar({ current, categories, onClick, onCreateFromBlan
<ul className="pt-0.5">
<CategoryItem category={AppCategories.RECOMMENDED} active={current === AppCategories.RECOMMENDED} onClick={onClick} />
</ul>
<div className="system-xs-medium-uppercase mb-0.5 mt-3 px-3 pb-1 pt-2 text-text-tertiary">{t('newAppFromTemplate.byCategories', { ns: 'app' })}</div>
<div className="mt-3 mb-0.5 px-3 pt-2 pb-1 system-xs-medium-uppercase text-text-tertiary">{t('newAppFromTemplate.byCategories', { ns: 'app' })}</div>
<ul className="flex grow flex-col gap-0.5">
{categories.map(category => (<CategoryItem key={category} category={category} active={current === category} onClick={onClick} />))}
</ul>

View File

@ -1,8 +1,9 @@
'use client'
import type { AppIconSelection } from '../../base/app-icon-picker'
import { RiArrowRightLine, RiArrowRightSLine, RiExchange2Fill } from '@remixicon/react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowRightLine, RiArrowRightSLine, RiExchange2Fill } from '@remixicon/react'
import { useDebounceFn, useKeyPress } from 'ahooks'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -23,7 +24,6 @@ import { useRouter } from '@/next/navigation'
import { createApp } from '@/service/apps'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { cn } from '@/utils/classnames'
import { trackCreateApp } from '@/utils/create-app-tracking'
import { basePath } from '@/utils/var'
import AppIconPicker from '../../base/app-icon-picker'

View File

@ -1,6 +1,7 @@
'use client'
import type { MouseEventHandler } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { RiCloseLine } from '@remixicon/react'
import { useDebounceFn, useKeyPress } from 'ahooks'
import { noop } from 'es-toolkit/function'
@ -25,7 +26,6 @@ import {
importDSLConfirm,
} from '@/service/apps'
import { getRedirection } from '@/utils/app-redirection'
import { cn } from '@/utils/classnames'
import { trackCreateApp } from '@/utils/create-app-tracking'
import ShortcutsName from '../../workflow/shortcuts-name'
import Uploader from './uploader'

View File

@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import {
RiDeleteBinLine,
RiUploadCloud2Line,
@ -10,7 +11,6 @@ import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import { Yaml as YamlIcon } from '@/app/components/base/icons/src/public/files'
import { toast } from '@/app/components/base/ui/toast'
import { cn } from '@/utils/classnames'
import { formatFileSize } from '@/utils/format'
type Props = {
@ -107,7 +107,7 @@ const Uploader: FC<Props> = ({
/>
<div ref={dropRef}>
{!file && (
<div className={cn('flex h-12 items-center radius-lg border border-dashed border-components-dropzone-border bg-components-dropzone-bg text-sm font-normal', dragging && 'border-components-dropzone-border-accent bg-components-dropzone-bg-accent')}>
<div className={cn('flex h-12 items-center rounded-[10px] border border-dashed border-components-dropzone-border bg-components-dropzone-bg text-sm font-normal', dragging && 'border-components-dropzone-border-accent bg-components-dropzone-bg-accent')}>
<div className="flex w-full items-center justify-center space-x-2">
<RiUploadCloud2Line className="h-6 w-6 text-text-tertiary" />
<div className="text-text-tertiary">
@ -115,7 +115,7 @@ const Uploader: FC<Props> = ({
<span className="cursor-pointer pl-1 text-text-accent" onClick={selectHandle}>{t('dslUploader.browse', { ns: 'app' })}</span>
</div>
</div>
{dragging && <div ref={dragRef} className="absolute left-0 top-0 h-full w-full" />}
{dragging && <div ref={dragRef} className="absolute top-0 left-0 h-full w-full" />}
</div>
)}
{file && (
@ -124,8 +124,8 @@ const Uploader: FC<Props> = ({
<YamlIcon className="h-6 w-6 shrink-0" />
</div>
<div className="flex grow flex-col items-start gap-0.5 py-1 pr-2">
<span className="font-inter max-w-[calc(100%-30px)] overflow-hidden text-ellipsis whitespace-nowrap text-[12px] font-medium leading-4 text-text-secondary">{file.name}</span>
<div className="font-inter flex h-3 items-center gap-1 self-stretch text-[10px] font-medium uppercase leading-3 text-text-tertiary">
<span className="font-inter max-w-[calc(100%-30px)] overflow-hidden text-[12px] leading-4 font-medium text-ellipsis whitespace-nowrap text-text-secondary">{file.name}</span>
<div className="font-inter flex h-3 items-center gap-1 self-stretch text-[10px] leading-3 font-medium text-text-tertiary uppercase">
<span>{displayName}</span>
<span className="text-text-quaternary">·</span>
<span>{formatFileSize(file.size)}</span>

Some files were not shown because too many files have changed in this diff Show More