Compare commits

..

13 Commits

Author SHA1 Message Date
Vben
ccaa32125a fix: enablePreferences does not meet expectations (#4031) 2024-08-04 06:01:09 +08:00
Li Kui
0619faf61e fix: typo in tabbar preferences (#4027) 2024-08-04 05:52:50 +08:00
Vben
b6415fad2d perf: optimize for some details and comments (#4030)
* perf: optimize for some details and comments

* fix: test case

* chore: update ci
2024-08-04 05:42:59 +08:00
vben
d3ed6757ac fix: unbuild version reduced to 2.0 2024-08-03 10:12:45 +08:00
Vben
27ffc9e71b fix: compatibility of fs-extra with esm (#4017) 2024-08-03 09:49:46 +08:00
Vben
bf8a5ffb5d chore(@vben/docs): update docs [deploy] (#4015) 2024-08-03 08:21:07 +08:00
vben
8ed2adb916 chore: update codeowners 2024-08-03 07:54:30 +08:00
dependabot[bot]
43224a4643 chore(deps): bump the non-breaking-changes group with 3 updates (#4013)
Bumps the non-breaking-changes group with 3 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) and [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next).


Updates `@types/node` from 22.0.3 to 22.1.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint-plugin-perfectionist` from 3.0.0 to 3.1.0
- [Release notes](https://github.com/azat-io/eslint-plugin-perfectionist/releases)
- [Changelog](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/changelog.md)
- [Commits](https://github.com/azat-io/eslint-plugin-perfectionist/compare/v3.0.0...v3.1.0)

Updates `lucide-vue-next` from 0.419.0 to 0.424.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.424.0/packages/lucide-vue-next)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: eslint-plugin-perfectionist
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
- dependency-name: lucide-vue-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-breaking-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-03 04:41:47 +08:00
Vben
f13fda408b fix: global scss injection error problem (#4014) 2024-08-03 04:40:06 +08:00
Vben
530159140c fix: Upgrade unbuild to resolve console warning issues and also deal with post-upgrade compatibility issues (#4009) 2024-08-02 22:18:46 +08:00
苗大
e544119aa3 perf: 全局搜索框打开后自动聚焦输入框 (#4006) 2024-08-02 21:56:47 +08:00
Li Kui
8313be8e08 fix: The menu background color is incorrect when toggling the dark menu (#4008)
* fix: the menu background color is incorrect when activating the dark menu light theme

* chore: update active-color & active-background-color
2024-08-02 21:36:36 +08:00
Donny Wang
d5f355120a chore: vscode-eslint已默认启用flat config (#4002)
* chore: vscode eslint已默认启用flat

* chore: delete invalid comments
2024-08-02 21:35:29 +08:00
81 changed files with 493 additions and 525 deletions

15
.github/CODEOWNERS vendored
View File

@@ -1,7 +1,14 @@
# default onwer
* anncwb@126.com
* anncwb@126.com vince292007@gmail.com
# vben core onwer
/packages/@core/ anncwb@126.com
/internal/ anncwb@126.com
/scripts/ anncwb@126.com
/.github/ anncwb@126.com vince292007@gmail.com
/.vscode/ anncwb@126.com vince292007@gmail.com
/packages/ anncwb@126.com vince292007@gmail.com
/packages/@core/ anncwb@126.com vince292007@gmail.com
/internal/ anncwb@126.com vince292007@gmail.com
/scripts/ anncwb@126.com vince292007@gmail.com
# vben team onwer
apps/ anncwb@126.com vince292007@gmail.com @vbenjs/team-v5
docs/ anncwb@126.com vince292007@gmail.com @vbenjs/team-v5

View File

@@ -14,8 +14,8 @@ body:
label: Version
description: What version of our software are you running?
options:
- Vben Admin Pro
- Vben Admin
- Vben Admin V5
- Vben Admin V2
default: 0
validations:
required: true

View File

@@ -1,4 +1,5 @@
name: Dependabot post-update
# name: Dependabot post-update
name: Build detection
on:
pull_request_target:
types: [opened, synchronize, reopened]
@@ -14,7 +15,7 @@ concurrency:
jobs:
post-update:
if: ${{ github.actor == 'dependabot[bot]' }}
# if: ${{ github.actor == 'dependabot[bot]' }}
runs-on: ubuntu-latest
strategy:
matrix:
@@ -43,7 +44,6 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Test and Build
- name: Build
run: |
pnpm run test:unit
pnpm run build

View File

@@ -5,7 +5,6 @@ on:
push:
branches:
- main
- master
- "releases/*"
permissions:
@@ -25,8 +24,8 @@ jobs:
node-version: [20]
os:
- ubuntu-latest
# - macos-latest
# - windows-latest
- macos-latest
- windows-latest
timeout-minutes: 20
steps:
- name: Checkout code

View File

@@ -24,7 +24,14 @@ jobs:
shell: bash
run: |
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-antd/.env.production
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-antd/.env.production
cat ./apps/web-antd/.env.production
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-ele/.env.production
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-ele/.env.production
cat ./apps/web-ele/.env.production
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-naive/.env.production
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-naive/.env.production
cat ./apps/web-naive/.env.production
- name: Install pnpm
uses: pnpm/action-setup@v4

View File

@@ -9,17 +9,18 @@ on:
jobs:
main:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-latest
name: Semantic Pull Request
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5
with:
wip: true
subjectPattern: ^(?![A-Z]).+$
subjectPatternError: |
The subject "{subject}" found in the pull request title "{title}"
didn't match the configured pattern. Please ensure that the subject
doesn't start with an uppercase character.
requireScope: false
env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}

View File

@@ -1 +1,20 @@
export { default } from '@vben/lint-staged-config';
export default {
'*.{js,jsx,ts,tsx}': [
'prettier --cache --ignore-unknown --write',
'eslint --cache --fix',
],
'*.{scss,less,styl,html,vue,css}': [
'prettier --cache --ignore-unknown --write',
'stylelint --fix --allow-empty-input',
],
'*.md': ['prettier --cache --ignore-unknown --write'],
'*.vue': [
'prettier --write',
'eslint --cache --fix',
'stylelint --fix --allow-empty-input',
],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [
'prettier --cache --write--parser json',
],
'package.json': ['prettier --cache --write'],
};

1
.npmrc
View File

@@ -3,7 +3,6 @@ public-hoist-pattern[]=husky
public-hoist-pattern[]=eslint
public-hoist-pattern[]=prettier
public-hoist-pattern[]=prettier-plugin-tailwindcss
public-hoist-pattern[]=lint-staged
public-hoist-pattern[]=stylelint
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=@commitlint/*

View File

@@ -139,8 +139,6 @@
"typescript.preferences.preferTypeOnlyAutoImports": true,
"typescript.preferences.includePackageJsonAutoImports": "on",
// Enable the ESlint flat config support
"eslint.experimental.useFlatConfig": true,
"eslint.validate": [
"javascript",
"typescript",

View File

@@ -21,7 +21,7 @@ RUN echo "Builder Success 🎉"
FROM nginx:stable-alpine as production
RUN echo "types { application/javascript js mjs; }" > /etc/nginx/conf.d/mjs.conf
COPY --from=builder /app/apps/antd-view/dist /usr/share/nginx/html
COPY --from=builder /app/apps/web-antd/dist /usr/share/nginx/html
COPY ./deploy/nginx.conf /etc/nginx/nginx.conf

View File

@@ -25,7 +25,7 @@ function warning() {
}
function success() {
ElMessage.success(
"'Cause you walked hand in hand With another man in my place",
'Cause you walked hand in hand With another man in my place',
);
}

View File

@@ -3,7 +3,7 @@
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
LOG_FILE=${SCRIPT_DIR}/build-local-docker-image.log
ERROR=""
IMAGE_NAME="vben-admin-pro-local"
IMAGE_NAME="vben-admin-local"
function stop_and_remove_container() {
# Stop and remove the existing container

View File

@@ -40,6 +40,7 @@
"nocheck",
"prefixs",
"vitepress",
"antdv",
"ependencies",
"vite",
"echarts",

View File

@@ -72,7 +72,7 @@ const { b, e, is } = useNamespace('menu');
</template>
<style lang="scss" scoped>
// 如果你在应用内使用,这行代码可以省略,已经在所有的应用内全局引入了
@import (reference) '@vben/styles/global';
@import '@vben/styles/global';
@include b('menu') {
color: black;

View File

@@ -6,7 +6,7 @@
## 原理
`vite-plugin-inject-app-loading` 插件实现,插件会在每个页面的注入一个全局的 loading html。
`vite-plugin-inject-app-loading` 插件实现,插件会在每个应用的注入一个全局的 `loading html`
## 关闭

View File

@@ -14,3 +14,4 @@
6. 自行适配组件库的主题,与 `Vben Admin` 契合。
7. 调整 `.env` 内的应用名
8. 在大仓根目录增加 `dev:xxx` 脚本
9. 执行 `pnpm install` 安装依赖

View File

@@ -25,36 +25,52 @@ features:
- icon: 🚀
title: 最新技术栈
details: 基于 Vue3、Pinia、Vue Router、TypeScript、等最新技术栈。
link: /guide/introduction/quick-start
linkText: 快速开始
- icon: 🦄
title: 丰富的配置
details: 企业级中后台前端解决方案,提供丰富的组件和模板以及 N 种偏好设置组合方案。
# link: /
# linkText: x
link: /guide/essentials/settings
linkText: 配置文档
- icon: 🎨
title: 主题定制
details: 通过简单的配置,即可实现各种主题切换,满足个性化需求。
link: /guide/in-depth/theme
linkText: 主题文档
- icon: 🌐
title: 国际化
details: 内置国际化方案,支持多语言切换,满足国际化需求。
link: /guide/in-depth/locale
linkText: 国际化文档
- icon: 🔐
title: 权限管理
details: 内置权限管理方案,支持多种权限控制方式,满足各种权限需求。
link: /guide/in-depth/access
linkText: 权限文档
- title: Vite
icon:
src: /logos/vite.svg
details: 现代化的前端构建工具,快速冷启动,瞬间热更新。
link: https://vitejs.dev/
linkText: 官方站点
- title: Shadcn UI
icon:
src: /logos/shadcn-ui.svg
details: 核心基于 Shadcn UI + Tailwindcss业务可支持任意的 UI 框架。
link: https://www.shadcn-vue.com/
linkText: 官方站点
- title: Turbo Repo
icon:
src: /logos/turborepo.svg
details: 规范且标准的大仓架构,使用 pnpm + monorepo + turbo 工程管理模式,提供企业级开发规范。
link: https://turbo.build/
linkText: 官方站点
- title: Nitro Mock Server
icon:
src: /logos/nitro.svg
details: 内置 Nitro Mock 服务,让你的 mock 服务更加强大。
link: https://nitro.unjs.io/
linkText: 官方站点
---
<!-- <script setup>

View File

@@ -1,7 +0,0 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
declaration: true,
entries: ['src/index'],
});

View File

@@ -1,5 +1,3 @@
import type { UserConfig } from 'cz-git';
import { execSync } from 'node:child_process';
import { getPackagesSync } from '@vben/node-utils';
@@ -27,7 +25,10 @@ const scopeComplete = execSync('git status --porcelain || true')
?.match(/src%%((\w|-)*)/)?.[1]
?.replace(/s$/, '');
const userConfig: UserConfig = {
/**
* @type {import('cz-git').UserConfig}
*/
const userConfig = {
extends: ['@commitlint/config-conventional'],
plugins: ['commitlint-plugin-function-rules'],
prompt: {
@@ -46,7 +47,6 @@ const userConfig: UserConfig = {
defaultScope: scopeComplete,
// English
typesAppend: [
{ name: 'wip: work in process', value: 'wip' },
{ name: 'workflow: workflow improvements', value: 'workflow' },
{ name: 'types: type definition file changes', value: 'types' },
],
@@ -106,7 +106,7 @@ const userConfig: UserConfig = {
'function-rules/scope-enum': [
2, // level: error
'always',
(parsed: { scope: string }) => {
(parsed) => {
if (!parsed.scope || allowedScopes.includes(parsed.scope)) {
return [true];
}

View File

@@ -11,20 +11,15 @@
},
"license": "MIT",
"type": "module",
"scripts": {
"stub": "pnpm unbuild --stub"
},
"files": [
"dist"
],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"main": "./index.mjs",
"module": "./index.mjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.mjs"
"import": "./index.mjs",
"default": "./index.mjs"
}
},
"dependencies": {

View File

@@ -1,6 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/node.json",
"include": ["src"],
"exclude": ["node_modules"]
}

View File

@@ -43,7 +43,7 @@
"eslint-plugin-jsonc": "^2.16.0",
"eslint-plugin-n": "^17.10.1",
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint-plugin-perfectionist": "^3.0.0",
"eslint-plugin-perfectionist": "^3.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-regexp": "^2.6.0",
"eslint-plugin-unicorn": "^55.0.0",

View File

@@ -1,9 +1,11 @@
import type { Linter } from 'eslint';
export async function comments(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function comments(): Promise<Linter.Config[]> {
const [pluginComments] = await Promise.all([
// @ts-expect-error - no types
import('eslint-plugin-eslint-comments'),
interopDefault(import('eslint-plugin-eslint-comments')),
] as const);
return [

View File

@@ -1,6 +1,6 @@
import type { Linter } from 'eslint';
export async function disableds(): Promise<Linter.FlatConfig[]> {
export async function disableds(): Promise<Linter.Config[]> {
return [
{
files: ['**/__tests__/**/*.?([cm])[jt]s?(x)'],

View File

@@ -1,6 +1,6 @@
import type { Linter } from 'eslint';
export async function ignores(): Promise<Linter.FlatConfig[]> {
export async function ignores(): Promise<Linter.Config[]> {
return [
{
ignores: [

View File

@@ -6,7 +6,7 @@ import js from '@eslint/js';
import pluginUnusedImports from 'eslint-plugin-unused-imports';
import globals from 'globals';
export async function javascript(): Promise<Linter.FlatConfig[]> {
export async function javascript(): Promise<Linter.Config[]> {
return [
{
languageOptions: {

View File

@@ -1,14 +1,15 @@
import type { Linter } from 'eslint';
export async function jsdoc(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function jsdoc(): Promise<Linter.Config[]> {
const [pluginJsdoc] = await Promise.all([
import('eslint-plugin-jsdoc'),
interopDefault(import('eslint-plugin-jsdoc')),
] as const);
return [
{
plugins: {
// @ts-expect-error - no types
jsdoc: pluginJsdoc,
},
rules: {

View File

@@ -1,9 +1,11 @@
import type { Linter } from 'eslint';
export async function jsonc(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function jsonc(): Promise<Linter.Config[]> {
const [pluginJsonc, parserJsonc] = await Promise.all([
import('eslint-plugin-jsonc'),
import('jsonc-eslint-parser'),
interopDefault(import('eslint-plugin-jsonc')),
interopDefault(import('jsonc-eslint-parser')),
] as const);
return [

View File

@@ -1,7 +1,9 @@
import type { Linter } from 'eslint';
export async function node(): Promise<Linter.FlatConfig[]> {
const [pluginNode] = await Promise.all([import('eslint-plugin-n')] as const);
import { interopDefault } from '../util';
export async function node(): Promise<Linter.Config[]> {
const pluginNode = await interopDefault(import('eslint-plugin-n'));
return [
{

View File

@@ -2,7 +2,7 @@ import type { Linter } from 'eslint';
import perfectionistPlugin from 'eslint-plugin-perfectionist';
export async function perfectionist(): Promise<Linter.FlatConfig[]> {
export async function perfectionist(): Promise<Linter.Config[]> {
return [
perfectionistPlugin.configs['recommended-natural'],
{

View File

@@ -1,8 +1,10 @@
import type { Linter } from 'eslint';
export async function prettier(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function prettier(): Promise<Linter.Config[]> {
const [pluginPrettier] = await Promise.all([
import('eslint-plugin-prettier'),
interopDefault(import('eslint-plugin-prettier')),
] as const);
return [
{

View File

@@ -1,8 +1,10 @@
import type { Linter } from 'eslint';
export async function regexp(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function regexp(): Promise<Linter.Config[]> {
const [pluginRegexp] = await Promise.all([
import('eslint-plugin-regexp'),
interopDefault(import('eslint-plugin-regexp')),
] as const);
return [

View File

@@ -1,10 +1,12 @@
import type { Linter } from 'eslint';
export async function test(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function test(): Promise<Linter.Config[]> {
const [pluginTest, pluginNoOnlyTests] = await Promise.all([
import('eslint-plugin-vitest'),
interopDefault(import('eslint-plugin-vitest')),
// @ts-expect-error - no types
import('eslint-plugin-no-only-tests'),
interopDefault(import('eslint-plugin-no-only-tests')),
] as const);
return [

View File

@@ -1,9 +1,11 @@
import type { Linter } from 'eslint';
export async function turbo(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function turbo(): Promise<Linter.Config[]> {
const [pluginTurbo] = await Promise.all([
// @ts-expect-error - no types
import('eslint-config-turbo'),
interopDefault(import('eslint-config-turbo')),
] as const);
return [

View File

@@ -1,10 +1,12 @@
import type { Linter } from 'eslint';
export async function typescript(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function typescript(): Promise<Linter.Config[]> {
const [pluginTs, parserTs] = await Promise.all([
import('@typescript-eslint/eslint-plugin'),
interopDefault(import('@typescript-eslint/eslint-plugin')),
// @ts-expect-error missing types
import('@typescript-eslint/parser'),
interopDefault(import('@typescript-eslint/parser')),
] as const);
return [

View File

@@ -1,9 +1,10 @@
import type { Linter } from 'eslint';
export async function unicorn(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function unicorn(): Promise<Linter.Config[]> {
const [pluginUnicorn] = await Promise.all([
// @ts-expect-error - missing types
import('eslint-plugin-unicorn'),
interopDefault(import('eslint-plugin-unicorn')),
] as const);
return [

View File

@@ -1,12 +1,14 @@
import type { Linter } from 'eslint';
export async function vue(): Promise<Linter.FlatConfig[]> {
import { interopDefault } from '../util';
export async function vue(): Promise<Linter.Config[]> {
const [pluginVue, parserVue, parserTs] = await Promise.all([
// @ts-expect-error missing types
import('eslint-plugin-vue'),
import('vue-eslint-parser'),
interopDefault(import('eslint-plugin-vue')),
interopDefault(import('vue-eslint-parser')),
// @ts-expect-error missing types
import('@typescript-eslint/parser'),
interopDefault(import('@typescript-eslint/parser')),
] as const);
return [

View File

@@ -0,0 +1,8 @@
export type Awaitable<T> = Promise<T> | T;
export async function interopDefault<T>(
m: Awaitable<T>,
): Promise<T extends { default: infer U } ? U : T> {
const resolved = await m;
return (resolved as any).default || resolved;
}

View File

@@ -1,7 +0,0 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
declaration: true,
entries: ['src/index'],
});

View File

@@ -1,33 +0,0 @@
{
"name": "@vben/lint-staged-config",
"version": "5.0.0",
"private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
"type": "git",
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
"directory": "internal/lint-configs/lint-staged-config"
},
"license": "MIT",
"type": "module",
"scripts": {
"stub": "pnpm unbuild --stub"
},
"files": [
"dist"
],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.mjs"
}
},
"dependencies": {
"lint-staged": "^15.2.7"
}
}

View File

@@ -1,20 +0,0 @@
export default {
'*.{js,jsx,ts,tsx}': [
'prettier --cache --ignore-unknown --write',
'eslint --cache --fix',
],
'*.{scss,less,styl,html,vue,css}': [
'prettier --cache --ignore-unknown --write',
'stylelint --fix --allow-empty-input',
],
'*.md': ['prettier --cache --ignore-unknown --write'],
'*.vue': [
'prettier --write',
'eslint --cache --fix',
'stylelint --fix --allow-empty-input',
],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [
'prettier --cache --write--parser json',
],
'package.json': ['prettier --cache --write'],
};

View File

@@ -1,6 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/node.json",
"include": ["src"],
"exclude": ["node_modules"]
}

View File

@@ -1,7 +0,0 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
declaration: true,
entries: ['src/index'],
});

View File

@@ -11,20 +11,14 @@
},
"license": "MIT",
"type": "module",
"scripts": {
"stub": "pnpm unbuild --stub"
},
"files": [
"dist"
],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"main": "./index.mjs",
"module": "./index.mjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.mjs"
"default": "./index.mjs"
}
},
"dependencies": {

View File

@@ -1,6 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/node.json",
"include": ["src"],
"exclude": ["node_modules"]
}

View File

@@ -1,7 +0,0 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
declaration: true,
entries: ['src/index'],
});

View File

@@ -11,20 +11,15 @@
},
"license": "MIT",
"type": "module",
"scripts": {
"stub": "pnpm unbuild --stub"
},
"files": [
"dist"
],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"main": "./index.mjs",
"module": "./index.mjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.mjs"
"import": "./index.mjs",
"default": "./index.mjs"
}
},
"dependencies": {

View File

@@ -1,6 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/node.json",
"include": ["src"],
"exclude": ["node_modules"]
}

View File

@@ -35,7 +35,6 @@
"dayjs": "^1.11.12",
"execa": "^9.3.0",
"find-up": "^7.0.0",
"fs-extra": "^11.2.0",
"nanoid": "^5.0.7",
"ora": "^8.0.1",
"pkg-types": "^1.1.3",
@@ -43,7 +42,6 @@
"rimraf": "^6.0.1"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
"@types/fs-extra": "^11.0.4"
"@types/chalk": "^2.2.0"
}
}

View File

@@ -0,0 +1,39 @@
import { promises as fs } from 'node:fs';
import { dirname } from 'node:path';
export async function outputJSON(
filePath: string,
data: any,
spaces: number = 2,
) {
try {
const dir = dirname(filePath);
await fs.mkdir(dir, { recursive: true });
const jsonData = JSON.stringify(data, null, spaces);
await fs.writeFile(filePath, jsonData, 'utf8');
} catch (error) {
console.error('Error writing JSON file:', error);
throw error;
}
}
export async function ensureFile(filePath: string) {
try {
const dir = dirname(filePath);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(filePath, '', { flag: 'a' });
} catch (error) {
console.error('Error ensuring file:', error);
throw error;
}
}
export async function readJSON(filePath: string) {
try {
const data = await fs.readFile(filePath, 'utf8');
return JSON.parse(data);
} catch (error) {
console.error('Error reading JSON file:', error);
throw error;
}
}

View File

@@ -1,5 +1,6 @@
export * from './constants';
export * from './date';
export * from './fs';
export * from './git';
export { add as gitAdd, getStagedFiles } from './git';
export { generatorContentHash } from './hash';
@@ -11,7 +12,10 @@ export type { Package } from '@manypkg/get-packages';
export { default as colors } from 'chalk';
export { consola } from 'consola';
export * from 'execa';
export { default as fs } from 'fs-extra';
export { nanoid } from 'nanoid';
export { default as fs } from 'node:fs/promises';
export { type PackageJson, readPackageJSON } from 'pkg-types';
export { rimraf } from 'rimraf';

View File

@@ -1,4 +1,5 @@
import fs from 'fs-extra';
import fs from 'node:fs/promises';
import { format, getFileInfo, resolveConfig } from 'prettier';
async function prettierFormat(filepath: string) {
@@ -12,7 +13,7 @@ async function prettierFormat(filepath: string) {
parser: fileInfo.inferredParser as any,
});
if (output !== input) {
fs.writeFileSync(filepath, output, 'utf8');
await fs.writeFile(filepath, output, 'utf8');
}
return output;
}

View File

@@ -1,8 +1,9 @@
import type { Config } from 'tailwindcss';
import fs from 'node:fs';
import path from 'node:path';
import { fs, getPackagesSync } from '@vben/node-utils';
import { getPackagesSync } from '@vben/node-utils';
import { addDynamicIconSelectors } from '@iconify/tailwind';
import typographyPlugin from '@tailwindcss/typography';

View File

@@ -15,8 +15,8 @@ import { getCommonConfig } from './common';
function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) {
return defineConfig(async (config) => {
const { appTitle, base, port, ...envConfig } = await loadAndConvertEnv();
const options = await userConfigPromise?.(config);
const { appTitle, base, port, ...envConfig } = await loadAndConvertEnv();
const { command, mode } = config;
const { application = {}, vite = {} } = options || {};
const root = process.cwd();
@@ -78,16 +78,16 @@ function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) {
port,
warmup: {
// 预热文件
clientFiles: ['./index.html', './src/{views,layouts}/*'],
clientFiles: ['./index.html', './src/{views,layouts,router,store}/*'],
},
},
};
const mergedConfig = mergeConfig(
const mergedCommonConfig = mergeConfig(
await getCommonConfig(),
applicationConfig,
);
return mergeConfig(mergedConfig, vite);
return mergeConfig(mergedCommonConfig, vite);
});
}
@@ -101,7 +101,7 @@ function createCssOptions(injectGlobalScss = true) {
const relativePath = relative(root, filepath);
// apps下的包注入全局样式
if (relativePath.startsWith('apps/')) {
return `@import (reference) "@vben/styles/global";\n${content}`;
return `@import "@vben/styles/global";\n${content}`;
}
return content;
},

View File

@@ -13,8 +13,8 @@ function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) {
return defineConfig(async (config: ConfigEnv) => {
const options = await userConfigPromise?.(config);
const { command, mode } = config;
const root = process.cwd();
const { library = {}, vite = {} } = options || {};
const root = process.cwd();
const isBuild = command === 'build';
const plugins = await loadLibraryPlugins({
@@ -52,8 +52,8 @@ function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) {
plugins,
};
const commonConfig = await getCommonConfig();
const mergedConfig = mergeConfig(commonConfig, packageConfig);
return mergeConfig(mergedConfig, vite);
const mergedConmonConfig = mergeConfig(commonConfig, packageConfig);
return mergeConfig(mergedConmonConfig, vite);
});
}

View File

@@ -28,12 +28,12 @@ const getDefaultPwaOptions = (name: string): Partial<PwaPluginOptions> => ({
const defaultImportmapOptions: ImportmapPluginOptions = {
// 通过 Importmap CDN 方式引入,
// 目前只有esm.sh源兼容性好一点jspm.io对于 esm 入口要求高
defaultProvider: 'jspm.io',
defaultProvider: 'esm.sh',
importmap: [
{ name: 'vue' },
{ name: 'pinia' },
{ name: 'vue-router' },
{ name: 'vue-i18n' },
// { name: 'vue-i18n' },
{ name: 'dayjs' },
{ name: 'vue-demi' },
],

View File

@@ -1,3 +1,3 @@
# inject-app-loading
用于在应用加载时显示加载动画的插件可自行选择加载动画的样式。
用于在应用加载时显示加载动画的插件可自行选择加载动画的样式。

View File

@@ -25,7 +25,7 @@
pointer-events: none;
visibility: hidden;
opacity: 0;
transition: all 0.6s ease-out;
transition: all 1s ease-out;
}
.dark .loading {

View File

@@ -1,7 +1,9 @@
import fs from 'node:fs';
import fsp from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { fs, readPackageJSON } from '@vben/node-utils';
import { readPackageJSON } from '@vben/node-utils';
import { type PluginOption } from 'vite';
@@ -50,19 +52,15 @@ async function viteInjectAppLoadingPlugin(
* 用于获取loading的html模板
*/
async function getLoadingRawByHtmlTemplate(loadingTemplate: string) {
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const defaultLoadingPath = join(__dirname, './default-loading.html');
// 支持在app内自定义loading模板模版参考default-loading.html即可
const appLoadingPath = join(process.cwd(), loadingTemplate);
let loadingPath = defaultLoadingPath;
let appLoadingPath = join(process.cwd(), loadingTemplate);
if (fs.existsSync(appLoadingPath)) {
loadingPath = appLoadingPath;
return;
if (!fs.existsSync(appLoadingPath)) {
const __dirname = fileURLToPath(new URL('.', import.meta.url));
appLoadingPath = join(__dirname, './default-loading.html');
}
const htmlRaw = await fs.readFile(loadingPath, 'utf8');
return htmlRaw;
return await fsp.readFile(appLoadingPath, 'utf8');
}
export { viteInjectAppLoadingPlugin };

View File

@@ -74,13 +74,13 @@ interface CommonPluginOptions {
}
interface ApplicationPluginOptions extends CommonPluginOptions {
/** 开启 gzip 压缩 */
/** 开启 gzip|brotli 压缩 */
compress?: boolean;
/** 压缩类型 */
compressTypes?: ('brotli' | 'gzip')[];
/** 在构建的时候抽离配置文件 */
extraAppConfig?: boolean;
/** html 插件配置 */
/** 是否开启html插件 */
html?: boolean;
/** 是否开启i18n */
i18n?: boolean;
@@ -98,7 +98,7 @@ interface ApplicationPluginOptions extends CommonPluginOptions {
nitroMock?: boolean;
/** nitro mock 插件配置 */
nitroMockOptions?: NitroMockPluginOptions;
/** dev是否开启mock服务 */
/** 开启控制台自定义打印 */
print?: boolean;
/** 打印插件配置 */
printInfoMap?: PrintPluginOptions['infoMap'];

View File

@@ -59,10 +59,9 @@
"@changesets/cli": "^2.27.7",
"@ls-lint/ls-lint": "^2.2.3",
"@types/jsdom": "^21.1.7",
"@types/node": "^22.0.2",
"@types/node": "^22.1.0",
"@vben/commitlint-config": "workspace:*",
"@vben/eslint-config": "workspace:*",
"@vben/lint-staged-config": "workspace:*",
"@vben/prettier-config": "workspace:*",
"@vben/stylelint-config": "workspace:*",
"@vben/tailwind-config": "workspace:*",
@@ -77,6 +76,7 @@
"husky": "^9.1.4",
"is-ci": "^3.0.1",
"jsdom": "^24.1.1",
"lint-staged": "^15.2.7",
"rimraf": "^6.0.1",
"tailwindcss": "^3.4.7",
"turbo": "^2.0.11",

View File

@@ -35,7 +35,7 @@
},
"dependencies": {
"@iconify/vue": "^4.1.2",
"lucide-vue-next": "^0.419.0",
"lucide-vue-next": "^0.424.0",
"vue": "^3.4.35"
}
}

View File

@@ -1,7 +1,8 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { defaultPreferences } from './config';
import { isDarkTheme, PreferenceManager } from './preferences';
import { PreferenceManager } from './preferences';
import { isDarkTheme } from './update-css-variables';
describe('preferences', () => {
let preferenceManager: PreferenceManager;

View File

@@ -19,14 +19,6 @@ const STORAGE_KEY = 'preferences';
const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`;
const STORAGE_KEY_THEME = `${STORAGE_KEY}-theme`;
function isDarkTheme(theme: string) {
let dark = theme === 'dark';
if (theme === 'auto') {
dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
}
return dark;
}
class PreferenceManager {
private cache: null | StorageManager = null;
// private flattenedState: Flatten<Preferences>;
@@ -39,6 +31,7 @@ class PreferenceManager {
constructor() {
this.cache = new StorageManager();
// 避免频繁的操作缓存
this.savePreferences = useDebounceFn(
(preference: Preferences) => this._savePreferences(preference),
150,
@@ -58,7 +51,6 @@ class PreferenceManager {
/**
* 处理更新的键值
* 根据更新的键值执行相应的操作。
*
* @param {DeepPartial<Preferences>} updates - 部分更新的偏好设置
*/
private handleUpdates(updates: DeepPartial<Preferences>) {
@@ -124,7 +116,7 @@ class PreferenceManager {
this.updatePreferences({
theme: { mode: isDark ? 'dark' : 'light' },
});
updateCSSVariables(this.state);
// updateCSSVariables(this.state);
});
}
@@ -232,4 +224,4 @@ class PreferenceManager {
}
const preferencesManager = new PreferenceManager();
export { isDarkTheme, PreferenceManager, preferencesManager };
export { PreferenceManager, preferencesManager };

View File

@@ -115,4 +115,4 @@ function isDarkTheme(theme: string) {
return dark;
}
export { updateCSSVariables };
export { isDarkTheme, updateCSSVariables };

View File

@@ -2,7 +2,8 @@ import { computed } from 'vue';
import { diff } from '@vben-core/shared';
import { isDarkTheme, preferencesManager } from './preferences';
import { preferencesManager } from './preferences';
import { isDarkTheme } from './update-css-variables';
function usePreferences() {
const preferences = preferencesManager.getPreferences();

View File

@@ -445,8 +445,8 @@ $namespace: vben;
--menu-item-color: hsl(var(--foreground) / 80%);
--menu-item-hover-color: hsl(var(--accent-foreground));
--menu-item-hover-background-color: hsl(var(--accent));
--menu-item-active-color: hsl(var(--primary-foreground));
--menu-item-active-background-color: hsl(var(--primary));
--menu-item-active-color: hsl(var(--accent-foreground));
--menu-item-active-background-color: hsl(var(--accent));
--menu-submenu-hover-color: hsl(var(--foreground));
--menu-submenu-hover-background-color: hsl(var(--accent));
--menu-submenu-active-color: hsl(var(--foreground));

View File

@@ -48,7 +48,7 @@
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.11.0",
"class-variance-authority": "^0.7.0",
"lucide-vue-next": "^0.419.0",
"lucide-vue-next": "^0.424.0",
"radix-vue": "^1.9.2",
"vue": "^3.4.35"
}

View File

@@ -209,7 +209,7 @@ export function useElementPlusDesignTokens() {
'--el-text-color-primary': getCssVariableValue('--foreground'),
'--el-text-color-regular': getCssVariableValue('--foreground'),
};
updateCSSVariables(variables, `__vben_ele_styles__`);
updateCSSVariables(variables, `__vben_design_styles__`);
},
{ immediate: true },
);

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { MenuRecordRaw } from '@vben/types';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import {
ArrowDown,
@@ -40,6 +40,7 @@ const props = withDefaults(
const [open, toggleOpen] = useToggle();
const keyword = ref('');
const searchInputRef = ref<HTMLInputElement>();
function handleClose() {
open.value = false;
@@ -54,6 +55,12 @@ whenever(cmd, () => {
}
});
whenever(open, () => {
nextTick(() => {
searchInputRef.value?.focus();
});
});
const preventDefaultBrowserSearchHotKey = (event: KeyboardEvent) => {
if (event.key.toLowerCase() === 'k' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
@@ -115,6 +122,7 @@ onMounted(() => {
>
<Search class="text-muted-foreground size-4" />
<input
ref="searchInputRef"
v-model="keyword"
:placeholder="$t('widgets.search.searchNavigate')"
class="ring-none placeholder:text-muted-foreground w-[80%] rounded-md border border-none bg-transparent p-2 pl-0 text-sm outline-none ring-0 ring-offset-transparent focus-visible:ring-transparent"

View File

@@ -59,10 +59,10 @@ const styleItems = computed((): SelectOption[] => [
<SwitchItem v-model="tabbarShowIcon" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.icon') }}
</SwitchItem>
<SwitchItem v-model="tabbarShowRefresh" :disabled="!tabbarEnable">
<SwitchItem v-model="tabbarShowMore" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.showMore') }}
</SwitchItem>
<SwitchItem v-model="tabbarShowMore" :disabled="!tabbarEnable">
<SwitchItem v-model="tabbarShowRefresh" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.showRefresh') }}
</SwitchItem>
<SwitchItem v-model="tabbarShowMaximize" :disabled="!tabbarEnable">

View File

@@ -206,6 +206,7 @@ if (enableShortcutKey.value) {
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
v-if="preferences.app.enablePreferences"
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleOpenPreference"
>

View File

@@ -3,6 +3,7 @@
* 放在这里是而不是放在 index.html 的app标签内是因为这样比较不会生硬渲染过快可能会有闪烁
* 通过先添加css动画隐藏在动画结束后在移除loading节点来改善体验
* 不好的地方是会增加一些代码量
* 自定义loading可以见https://doc.vben.pro/guide/in-depth/loading.html
*/
export function unmountGlobalLoading() {
// 查找全局 loading 元素

487
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@ export async function run(options: RunOptions) {
// 只显示有对应命令的包
const selectPkgs = packages.filter((pkg) => {
return (pkg?.packageJson as Record<string, any>).scripts?.[command];
return (pkg?.packageJson as Record<string, any>)?.scripts?.[command];
});
const selectPkg = await select<any, string>({

View File

@@ -6,9 +6,9 @@ import {
colors,
consola,
findMonorepoRoot,
fs,
getPackages,
gitAdd,
outputJSON,
prettierFormat,
toPosixPath,
} from '@vben/node-utils';
@@ -38,7 +38,7 @@ async function createCodeWorkspace({
const monorepoRoot = findMonorepoRoot();
const outputPath = join(monorepoRoot, CODE_WORKSPACE_FILE);
await fs.outputJSON(outputPath, { folders }, { encoding: 'utf8', spaces });
await outputJSON(outputPath, { folders }, spaces);
await prettierFormat(outputPath);
if (autoCommit) {

View File

@@ -6,10 +6,12 @@ import { basename, dirname, join } from 'node:path';
import {
colors,
consola,
ensureFile,
findMonorepoRoot,
fs,
generatorContentHash,
getPackages,
outputJSON,
readJSON,
UNICODE,
} from '@vben/node-utils';
@@ -56,8 +58,8 @@ function getCacheFile() {
async function readCache(cacheFile: string) {
try {
await fs.ensureFile(cacheFile);
return await fs.readJSON(cacheFile, { encoding: 'utf8' });
await ensureFile(cacheFile);
return await readJSON(cacheFile);
} catch {
return {};
}
@@ -73,7 +75,7 @@ async function runPublint(files: string[], { check }: PubLintCommandOptions) {
const results = await Promise.all(
lintFiles.map(async (file) => {
try {
const pkgJson = await fs.readJSON(file);
const pkgJson = await readJSON(file);
if (pkgJson.private) {
return null;
@@ -106,7 +108,7 @@ async function runPublint(files: string[], { check }: PubLintCommandOptions) {
}),
);
await fs.outputJSON(cacheFile, cache);
await outputJSON(cacheFile, cache);
printResult(results, check);
}

View File

@@ -37,11 +37,6 @@
"cache": false,
"persistent": true
},
"@vben/backend#dev": {
"outputs": [],
"cache": false,
"persistent": true
},
"typecheck": {
"outputs": []
}

View File

@@ -28,10 +28,6 @@
"name": "@vben/eslint-config",
"path": "internal/lint-configs/eslint-config",
},
{
"name": "@vben/lint-staged-config",
"path": "internal/lint-configs/lint-staged-config",
},
{
"name": "@vben/prettier-config",
"path": "internal/lint-configs/prettier-config",