add tailwindcss

This commit is contained in:
xion 2024-10-19 18:25:59 +08:00
parent a7144104e8
commit 9ce91c593c
16 changed files with 989 additions and 33 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules
*storybook.log
*storybook.log
storybook-static

1
.npmrc Normal file
View File

@ -0,0 +1 @@
@kevisual:registry=https://npm.xiongxiao.me

View File

@ -1,21 +1,64 @@
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
const WEBPACK_SERVE = Boolean(process.env.WEBPACK_SERVE);
const mode = WEBPACK_SERVE ? 'development' : 'production';
export const isDev = mode === 'development';
/** @type { import('@storybook/html-webpack5').StorybookConfig } */
const config = {
stories: [
"../stories/**/*.mdx",
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
"../apps/**/*.mdx",
"../apps/**/*.stories.@(js|jsx|mjs|ts|tsx)",
],
stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)', '../apps/**/*.mdx', '../apps/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
"@storybook/addon-webpack5-compiler-swc",
"@storybook/addon-links",
"@storybook/addon-essentials",
"@chromatic-com/storybook",
"@storybook/addon-interactions",
'@storybook/addon-webpack5-compiler-swc',
'@storybook/addon-links',
'@storybook/addon-essentials',
'@chromatic-com/storybook',
'@storybook/addon-interactions',
],
framework: {
name: "@storybook/html-webpack5",
name: '@storybook/html-webpack5',
options: {},
},
webpackFinal: async (config) => {
const newConfig = {
...config,
module: {
...config.module,
rules: [
...config.module.rules.filter((i) => {
if (i.test instanceof RegExp && i.test.test('.css')) {
return false;
}
return true;
}),
{
test: /\.css$/,
use: [
{
loader: !isDev ? MiniCssExtractPlugin.loader : 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: false,
},
},
'postcss-loader',
],
},
],
},
plugins: [
...config.plugins,
// ...(config.plugins ?? [])
// // DocgenPlugin adds to the build time and we don't use storybook's autogenerated docs.
// .filter((plugin) => plugin.constructor.name !== 'DocgenPlugin'),
// ,
new MiniCssExtractPlugin({
filename: '[name].bundle.css',
chunkFilename: '[id].css',
}),
],
};
return newConfig;
},
};
export default config;

View File

@ -0,0 +1,2 @@
<!-- .storybook/preview-head.html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

View File

@ -1,3 +1,5 @@
import './tailwind.css';
/** @type { import('@storybook/html').Preview } */
const preview = {
parameters: {

3
.storybook/tailwind.css Normal file
View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -59,7 +59,7 @@ export class MessageContainer {
0 9px 28px 8px rgba(0, 0, 0, 0.05);
justify-content: center;
align-item: center;
animation: message-slide-down 0.5s ease-out forwards; /* 应用动画 */
animation: message-slide-down 0.3s ease-out forwards; /* 应用动画 */
}
/* 添加消失类时 */
.message-wrapper.message-hide {
@ -188,6 +188,7 @@ export class MessageContainer {
}
}
const controller = new MessageContainer();
export const createMessage = (content, opts) => {
let { icon, key, style, className, type } = opts || {};
const div = document.createElement('div');
@ -207,7 +208,6 @@ export const createMessage = (content, opts) => {
i.classList.add('message-icon');
contentDiv.appendChild(i);
}
console.log(content, type, icon, 'content');
if (content instanceof HTMLElement) {
contentDiv.appendChild(content);
} else {
@ -222,13 +222,17 @@ export const createMessage = (content, opts) => {
const methods = ['success', 'info', 'warning', 'error', 'loading'];
export class Message {
static controller = controller;
static open = (message, timeout = 3000, onClose, opts) => {
controller = controller;
constructor() {
this.controller = controller;
}
open = (message, timeout = 3000, onClose, opts) => {
const controller = this.controller;
const div = createMessage(message, opts);
const remove = () => {
div.classList.add('message-hide');
setTimeout(() => {
if (div.isConnected) {
if (div?.isConnected) {
div.remove();
} else {
console.log('not connected');
@ -252,19 +256,21 @@ export class Message {
remove();
};
};
static success = (message, timeout = 3000, onClose) => {
return Message.open(message, timeout, onClose, { type: 'success' });
success = (message, timeout = 1000, onClose) => {
return this.open(message, timeout, onClose, { type: 'success' });
};
static info = (message, timeout = 3000, onClose) => {
return Message.open(message, timeout, onClose, { type: 'info' });
info = (message, timeout = 1500, onClose) => {
return this.open(message, timeout, onClose, { type: 'info' });
};
static warning = (message, timeout = 3000, onClose) => {
return Message.open(message, timeout, onClose, { type: 'warning' });
warning = (message, timeout = 3000, onClose) => {
return this.open(message, timeout, onClose, { type: 'warning' });
};
static error = (message, timeout = 3000, onClose) => {
return Message.open(message, timeout, onClose, { type: 'error' });
error = (message, timeout = 3000, onClose) => {
return this.open(message, timeout, onClose, { type: 'error' });
};
static loading = (message, timeout = 0, onClose) => {
return Message.open(message, timeout, onClose, { type: 'loading' });
loading = (message, timeout = 0, onClose) => {
return this.open(message, timeout, onClose, { type: 'loading' });
};
}
export const message = new Message();

View File

@ -0,0 +1,27 @@
#ui-modal-list {
position: relative;
}
.ui-modal-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 200;
}
.ui-modal-close {
display: none;
}
.ui-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 201;
}
.ui-modal-content {
position: fixed;
z-index: 202;
}

File diff suppressed because one or more lines are too long

7
apps/ui/docs/message.mdx Normal file
View File

@ -0,0 +1,7 @@
# message
类似antd的message但是是直接用 `import` 调用
```js
import { message } from 'https://kevisual.xiongxiao.me/system/ui/message.js'
```

View File

@ -1,11 +1,13 @@
import { Message, createMessage } from '../deploy/message.js';
import { message as Message, createMessage } from '../deploy/message.js';
export default {
title: 'ui/message',
tags: ['autodocs'],
description: 'Message component',
render: ({ label, fn, ...args }) => {
const div = createMessage(label, { type: 'success' });
div.addEventListener('click', () => {
fn('Hello World', 2000);
Message.success('Hello World', 2000);
});
div.style.border = '1px solid #000';
const uiMessage = document.createElement('div');

131
apps/ui/theme/modal.mdx Normal file
View File

@ -0,0 +1,131 @@
import { message } from '../deploy/message.js'
import { DialogModal } from '@kevisual/ui'
import '@kevisual/ui/dist/index.css'
Modal
> 使用原生js实现的弹窗组件
export const ShowModal = () => {
const url = 'https://kevisual.xiongxiao.me/system/theme/index.js'
const onClick = async () => {
console.log('theme', DialogModal)
// console.log('clicked')
// message.info('Hello, this is a message')
const content = document.createElement('div');
content.innerHTML = `
<div class="bg-white p-8 rounded shadow-md w-full max-w-md text-center">
<h2 class="text-2xl font-bold mb-4">Token 无效</h2>
<p class="mb-6">您的登录凭证已失效,请重新登录。</p>
<a href="/user/login" class="inline-block bg-red-500 text-white py-2 px-4 rounded hover:bg-red-600 transition duration-200">确定</a>
</div>
`;
const modal = DialogModal.render(content, {
id: 'redirect-to-login',
contentStyle: {
width: 'unset',
},
dialogTitleStyle: {
display: 'none',
padding: '0',
},
dialogContentStyle: {
padding: '0',
},
mask: true,
open: false,
});
modal.setOpen(true)
}
return <div onClick={onClick}>点击显示弹窗</div>
}
<ShowModal />
使用方法
```js
// import { DialogModal } from 'https://kevisual.xiongxiao.me/system/theme/index.js'
import { DialogModal } from '@kevisual/ui';
import '@kevisual/ui/dist/index.css';
const content = document.createElement('div');
content.innerHTML = `
<div class="bg-white p-8 rounded shadow-md w-full max-w-md text-center">
<h2 class="text-2xl font-bold mb-4">Token 无效</h2>
<p class="mb-6">您的登录凭证已失效,请重新登录。</p>
<a href="/user/login" class="inline-block bg-red-500 text-white py-2 px-4 rounded hover:bg-red-600 transition duration-200">确定</a>
</div>
`;
export const modal = DialogModal.render(content, {
id: 'redirect-to-login',
contentStyle: {
width: 'unset',
},
dialogTitleStyle: {
display: 'none',
padding: '0',
},
dialogContentStyle: {
padding: '0',
},
mask: true,
open: false,
});
```
类型
```typescript
export type ModalOpts<
T = {
[key: string]: any;
},
U = {
[key: string]: any;
},
> = {
root?: HTMLDivElement | string;
id?: string;
mask?: boolean;
maskClassName?: string;
maskStyle?: ElStyle;
maskClose?: boolean;
contentClassName?: string;
contentStyle?: ElStyle;
destroyOnClose?: boolean; // 关闭把Element移动到cacheFragment中
hideOnClose?: boolean; // 关闭后是否销毁设置display:none
open?: boolean;
onClose?: () => void;
defaultStyle?: DefaultStyle<U>;
} & T;
export type DefaultStyle<T> = {
defaultContentStyle?: ObjCss;
defaultMaskStyle?: ObjCss;
} & T;
type DialogModalOpts = {
dialogTitle?: string;
dialogTitleClassName?: string;
dialogTitleStyle?: ElStyle;
dialogTitleEl?: HTMLElement;
dialogTitleCloseIcon?: boolean;
dialogContentClassName?: string;
dialogContentStyle?: ElStyle;
dialogFooterClassName?: string;
dialogFooterStyle?: ElStyle;
} & ModalOpts<KV, DialogDefaultStyle>;
type DialogDefaultStyle = {
defaultDialogTitleStyle?: ObjCss;
defaultDialogContentStyle?: ObjCss;
defaultDialogFooterStyle?: ObjCss;
};
```

View File

@ -1,13 +1,14 @@
{
"name": "system-apps",
"version": "1.0.0",
"version": "0.0.1",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "storybook dev -p 6006",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
"build": "storybook build ",
"deploy": "envision switchOrg docs && envision deploy ./storybook-static -k system-book -v 0.0.5"
},
"keywords": [],
"author": "",
@ -22,6 +23,15 @@
"@storybook/html": "^8.3.6",
"@storybook/html-webpack5": "^8.3.6",
"@storybook/test": "^8.3.6",
"storybook": "^8.3.6"
"autoprefixer": "^10.4.20",
"mini-css-extract-plugin": "^2.9.1",
"postcss": "^8.4.47",
"postcss-loader": "^8.1.1",
"storybook": "^8.3.6",
"tailwindcss": "^3.4.14"
},
"dependencies": {
"@kevisual/ui": "^0.0.2",
"systemjs": "^6.15.1"
}
}

704
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
plugins: [
'tailwindcss',
'autoprefixer',
],
};

10
tailwind.config.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
content: [
'./apps/**/*.{js,mdx,jsx,ts,tsx}',
'./stories/**/*.{js,mdx,jsx,ts,tsx}',
],
theme: {
extend: {},
},
plugins: [],
};