add tailwindcss
This commit is contained in:
parent
a7144104e8
commit
9ce91c593c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
*storybook.log
|
*storybook.log
|
||||||
|
storybook-static
|
@ -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 } */
|
/** @type { import('@storybook/html-webpack5').StorybookConfig } */
|
||||||
const config = {
|
const config = {
|
||||||
stories: [
|
stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)', '../apps/**/*.mdx', '../apps/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||||
"../stories/**/*.mdx",
|
|
||||||
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
|
|
||||||
"../apps/**/*.mdx",
|
|
||||||
"../apps/**/*.stories.@(js|jsx|mjs|ts|tsx)",
|
|
||||||
],
|
|
||||||
addons: [
|
addons: [
|
||||||
"@storybook/addon-webpack5-compiler-swc",
|
'@storybook/addon-webpack5-compiler-swc',
|
||||||
"@storybook/addon-links",
|
'@storybook/addon-links',
|
||||||
"@storybook/addon-essentials",
|
'@storybook/addon-essentials',
|
||||||
"@chromatic-com/storybook",
|
'@chromatic-com/storybook',
|
||||||
"@storybook/addon-interactions",
|
'@storybook/addon-interactions',
|
||||||
],
|
],
|
||||||
framework: {
|
framework: {
|
||||||
name: "@storybook/html-webpack5",
|
name: '@storybook/html-webpack5',
|
||||||
options: {},
|
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;
|
export default config;
|
||||||
|
2
.storybook/preview-head.html
Normal file
2
.storybook/preview-head.html
Normal 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>
|
@ -1,3 +1,5 @@
|
|||||||
|
import './tailwind.css';
|
||||||
|
|
||||||
/** @type { import('@storybook/html').Preview } */
|
/** @type { import('@storybook/html').Preview } */
|
||||||
const preview = {
|
const preview = {
|
||||||
parameters: {
|
parameters: {
|
||||||
|
3
.storybook/tailwind.css
Normal file
3
.storybook/tailwind.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
@ -59,7 +59,7 @@ export class MessageContainer {
|
|||||||
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-item: 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 {
|
.message-wrapper.message-hide {
|
||||||
@ -188,6 +188,7 @@ export class MessageContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const controller = new MessageContainer();
|
const controller = new MessageContainer();
|
||||||
|
|
||||||
export const createMessage = (content, opts) => {
|
export const createMessage = (content, opts) => {
|
||||||
let { icon, key, style, className, type } = opts || {};
|
let { icon, key, style, className, type } = opts || {};
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
@ -207,7 +208,6 @@ export const createMessage = (content, opts) => {
|
|||||||
i.classList.add('message-icon');
|
i.classList.add('message-icon');
|
||||||
contentDiv.appendChild(i);
|
contentDiv.appendChild(i);
|
||||||
}
|
}
|
||||||
console.log(content, type, icon, 'content');
|
|
||||||
if (content instanceof HTMLElement) {
|
if (content instanceof HTMLElement) {
|
||||||
contentDiv.appendChild(content);
|
contentDiv.appendChild(content);
|
||||||
} else {
|
} else {
|
||||||
@ -222,13 +222,17 @@ export const createMessage = (content, opts) => {
|
|||||||
const methods = ['success', 'info', 'warning', 'error', 'loading'];
|
const methods = ['success', 'info', 'warning', 'error', 'loading'];
|
||||||
|
|
||||||
export class Message {
|
export class Message {
|
||||||
static controller = controller;
|
controller = controller;
|
||||||
static open = (message, timeout = 3000, onClose, opts) => {
|
constructor() {
|
||||||
|
this.controller = controller;
|
||||||
|
}
|
||||||
|
open = (message, timeout = 3000, onClose, opts) => {
|
||||||
|
const controller = this.controller;
|
||||||
const div = createMessage(message, opts);
|
const div = createMessage(message, opts);
|
||||||
const remove = () => {
|
const remove = () => {
|
||||||
div.classList.add('message-hide');
|
div.classList.add('message-hide');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (div.isConnected) {
|
if (div?.isConnected) {
|
||||||
div.remove();
|
div.remove();
|
||||||
} else {
|
} else {
|
||||||
console.log('not connected');
|
console.log('not connected');
|
||||||
@ -252,19 +256,21 @@ export class Message {
|
|||||||
remove();
|
remove();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
static success = (message, timeout = 3000, onClose) => {
|
success = (message, timeout = 1000, onClose) => {
|
||||||
return Message.open(message, timeout, onClose, { type: 'success' });
|
return this.open(message, timeout, onClose, { type: 'success' });
|
||||||
};
|
};
|
||||||
static info = (message, timeout = 3000, onClose) => {
|
info = (message, timeout = 1500, onClose) => {
|
||||||
return Message.open(message, timeout, onClose, { type: 'info' });
|
return this.open(message, timeout, onClose, { type: 'info' });
|
||||||
};
|
};
|
||||||
static warning = (message, timeout = 3000, onClose) => {
|
warning = (message, timeout = 3000, onClose) => {
|
||||||
return Message.open(message, timeout, onClose, { type: 'warning' });
|
return this.open(message, timeout, onClose, { type: 'warning' });
|
||||||
};
|
};
|
||||||
static error = (message, timeout = 3000, onClose) => {
|
error = (message, timeout = 3000, onClose) => {
|
||||||
return Message.open(message, timeout, onClose, { type: 'error' });
|
return this.open(message, timeout, onClose, { type: 'error' });
|
||||||
};
|
};
|
||||||
static loading = (message, timeout = 0, onClose) => {
|
loading = (message, timeout = 0, onClose) => {
|
||||||
return Message.open(message, timeout, onClose, { type: 'loading' });
|
return this.open(message, timeout, onClose, { type: 'loading' });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const message = new Message();
|
||||||
|
27
apps/ui/deploy/theme/index.css
Normal file
27
apps/ui/deploy/theme/index.css
Normal 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;
|
||||||
|
}
|
1
apps/ui/deploy/theme/index.js
Normal file
1
apps/ui/deploy/theme/index.js
Normal file
File diff suppressed because one or more lines are too long
7
apps/ui/docs/message.mdx
Normal file
7
apps/ui/docs/message.mdx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# message
|
||||||
|
|
||||||
|
类似antd的message,但是是直接用 `import` 调用
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { message } from 'https://kevisual.xiongxiao.me/system/ui/message.js'
|
||||||
|
```
|
@ -1,11 +1,13 @@
|
|||||||
import { Message, createMessage } from '../deploy/message.js';
|
import { message as Message, createMessage } from '../deploy/message.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'ui/message',
|
title: 'ui/message',
|
||||||
tags: ['autodocs'],
|
tags: ['autodocs'],
|
||||||
|
description: 'Message component',
|
||||||
render: ({ label, fn, ...args }) => {
|
render: ({ label, fn, ...args }) => {
|
||||||
const div = createMessage(label, { type: 'success' });
|
const div = createMessage(label, { type: 'success' });
|
||||||
div.addEventListener('click', () => {
|
div.addEventListener('click', () => {
|
||||||
fn('Hello World', 2000);
|
Message.success('Hello World', 2000);
|
||||||
});
|
});
|
||||||
div.style.border = '1px solid #000';
|
div.style.border = '1px solid #000';
|
||||||
const uiMessage = document.createElement('div');
|
const uiMessage = document.createElement('div');
|
||||||
|
131
apps/ui/theme/modal.mdx
Normal file
131
apps/ui/theme/modal.mdx
Normal 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
```
|
16
package.json
16
package.json
@ -1,13 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "system-apps",
|
"name": "system-apps",
|
||||||
"version": "1.0.0",
|
"version": "0.0.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "storybook dev -p 6006",
|
"dev": "storybook dev -p 6006",
|
||||||
"storybook": "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": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@ -22,6 +23,15 @@
|
|||||||
"@storybook/html": "^8.3.6",
|
"@storybook/html": "^8.3.6",
|
||||||
"@storybook/html-webpack5": "^8.3.6",
|
"@storybook/html-webpack5": "^8.3.6",
|
||||||
"@storybook/test": "^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
704
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: [
|
||||||
|
'tailwindcss',
|
||||||
|
'autoprefixer',
|
||||||
|
],
|
||||||
|
};
|
10
tailwind.config.js
Normal file
10
tailwind.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
'./apps/**/*.{js,mdx,jsx,ts,tsx}',
|
||||||
|
'./stories/**/*.{js,mdx,jsx,ts,tsx}',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user