v2.3.1
This commit is contained in:
232
demos/common/Index.css
Normal file
232
demos/common/Index.css
Normal file
@@ -0,0 +1,232 @@
|
||||
.wx-demos.layout {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wx-demos.page-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.wx-demos.page-content-header {
|
||||
height: 70px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
}
|
||||
|
||||
.wx-demos.header-title-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.wx-demos.header-actions-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.wx-demos.layout.active {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.wx-demos.sidebar {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
.wx-demos.sidebar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background-color: #fbfbfb;
|
||||
padding: 19px 16px 19px 18px;
|
||||
}
|
||||
|
||||
.wx-demos.box-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.wx-demos.box-title img:hover,
|
||||
.wx-demos.box-title img:focus {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.wx-demos.box-title img:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.wx-demos.box-title .wx-demos.separator {
|
||||
width: 1px;
|
||||
height: 20px;
|
||||
background: #ebebeb;
|
||||
}
|
||||
|
||||
.wx-demos.sidebar.active {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.wx-demos.sidebar-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 300px;
|
||||
gap: 16px;
|
||||
height: 100%;
|
||||
border-right: 1px solid #ebebeb;
|
||||
overflow-y: auto;
|
||||
font-family: Roboto, Arial, Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
background-color: #fbfbfb;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
}
|
||||
|
||||
.wx-demos.btn-box button.toggle-btn {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
border: 1px solid #ebebeb;
|
||||
color: #42454d;
|
||||
}
|
||||
|
||||
.wx-demos.btn-box button.toggle-btn:hover,
|
||||
.wx-demos.btn-box button.toggle-btn:focus {
|
||||
border: 1px solid #ebebeb;
|
||||
color: #42454d;
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.wx-demos.btn-box button.toggle-btn:active {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
.wx-demos a {
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.wx-demos.wrapper-content {
|
||||
flex: 1;
|
||||
height: calc(100% - 70px);
|
||||
}
|
||||
|
||||
.wx-demos.wrapper-content .wx-demos.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition:
|
||||
transform 0.3s,
|
||||
width 0.3s;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.wx-demos.box-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.wx-demos.hint {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
color: #42454d;
|
||||
}
|
||||
|
||||
.wx-demos.title {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
color: #42454d;
|
||||
}
|
||||
|
||||
.wx-demos.segmented-box div.segmented-themes {
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.wx-demos.segmented-box div.segmented-themes button {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
color: #595b66;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.wx-demos.segmented-box div.segmented-themes button.wx-selected {
|
||||
border-radius: 2px;
|
||||
font-weight: 500;
|
||||
color: #42454d;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 7px 0px rgba(66, 69, 76, 0.07);
|
||||
}
|
||||
|
||||
.wx-demos.content h4 {
|
||||
font-size: 16px;
|
||||
font-weight: 300;
|
||||
margin-bottom: 12px;
|
||||
border-bottom: var(--wx-border);
|
||||
}
|
||||
|
||||
.wx-demos.content h3 {
|
||||
font-size: 18px;
|
||||
margin: 12px 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.wx-demos.content .demo-box {
|
||||
margin: 20px;
|
||||
}
|
||||
.wx-demos.content .demo-box + .demo-box {
|
||||
margin-top: 40px;
|
||||
}
|
||||
.wx-demos.content .demo-code {
|
||||
font-family: monospace;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.wx-demos.content .demo-status {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.wx-demos.content .demo-toolbar {
|
||||
border: 2px solid var(--wx-background-alt);
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.wx-demos.demo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 37px;
|
||||
font-weight: 400;
|
||||
padding-left: 16px;
|
||||
border-left: 4px solid transparent;
|
||||
color: #595b66;
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.wx-demos.demo.active {
|
||||
border-left-color: #087a9f;
|
||||
}
|
||||
|
||||
.wx-demos.demo.active,
|
||||
.wx-demos.demo:hover {
|
||||
font-weight: 500;
|
||||
color: #42454d;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
183
demos/common/Index.jsx
Normal file
183
demos/common/Index.jsx
Normal file
@@ -0,0 +1,183 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { HashRouter, NavLink, useNavigate } from 'react-router-dom';
|
||||
|
||||
import Router from './Router';
|
||||
import { links } from '../routes';
|
||||
import { GitHubLogoIcon, LogoIcon } from '../assets/icons';
|
||||
import './Index.css';
|
||||
|
||||
function DemoExplorerContent({
|
||||
productTag,
|
||||
publicName,
|
||||
skins,
|
||||
Globals,
|
||||
Button,
|
||||
Segmented,
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const [skin, setSkin] = useState(skins[0].id);
|
||||
const [title, setTitle] = useState('');
|
||||
const [githubLink, setGithubLink] = useState('');
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
const baseLink =
|
||||
'https://github.com/svar-widgets/react-' +
|
||||
productTag +
|
||||
'/tree/main/demos/cases/';
|
||||
|
||||
useEffect(() => {
|
||||
document.body.className = `wx-willow-theme`;
|
||||
}, []);
|
||||
|
||||
const handleRouteChange = useCallback(
|
||||
(path) => {
|
||||
const parts = path.split('/');
|
||||
const page = parts[1];
|
||||
const newSkin = parts[2];
|
||||
|
||||
if (newSkin && newSkin !== skin) {
|
||||
setSkin(newSkin);
|
||||
}
|
||||
|
||||
const targetPage = `/${page}/:skin`;
|
||||
const matched = links.find((a) => a[0] === targetPage);
|
||||
if (matched) {
|
||||
setTitle(matched[1]);
|
||||
const name = matched[3] || matched[1];
|
||||
setGithubLink(`${baseLink}${name}.jsx`);
|
||||
}
|
||||
},
|
||||
[skin],
|
||||
);
|
||||
|
||||
const handleSkinChange = ({ value }) => {
|
||||
setSkin(value);
|
||||
const currentPath = window.location.hash.slice(1);
|
||||
const parts = currentPath.split('/');
|
||||
if (parts[1]) {
|
||||
navigate(`/${parts[1]}/${value}`);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleSidebar = () => {
|
||||
setShow(!show);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`wx-demos layout ${show ? 'active' : ''}`}>
|
||||
<div
|
||||
className={`wx-demos sidebar ${show ? 'active' : ''}`}
|
||||
role="tabpanel"
|
||||
>
|
||||
<div className="wx-demos sidebar-content">
|
||||
<div className="wx-demos sidebar-header">
|
||||
<div className="wx-demos box-title">
|
||||
<a
|
||||
href="https://svar.dev/react/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img src={LogoIcon} alt="Logo icon" className="box-title-img" />
|
||||
</a>
|
||||
<div className="wx-demos separator"></div>
|
||||
<a
|
||||
href={`https://svar.dev/react/${productTag}/`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h1 className="wx-demos title">React {publicName}</h1>
|
||||
</a>
|
||||
</div>
|
||||
<div className="wx-demos btn-box">
|
||||
<Button
|
||||
type="secondary"
|
||||
icon="wxi-angle-left"
|
||||
css="toggle-btn"
|
||||
onClick={toggleSidebar}
|
||||
></Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="wx-demos box-links">
|
||||
{links.map((data) => (
|
||||
<NavLink
|
||||
key={data[0]}
|
||||
to={data[0].replace(':skin', skin)}
|
||||
className={({ isActive }) =>
|
||||
`wx-demos demo ${isActive ? 'active' : ''}`
|
||||
}
|
||||
>
|
||||
{data[1]}
|
||||
</NavLink>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="wx-demos page-content">
|
||||
<div className="wx-demos page-content-header">
|
||||
<div className="wx-demos header-title-box">
|
||||
{!show && (
|
||||
<div className="wx-demos btn-box">
|
||||
<Button
|
||||
type="secondary"
|
||||
icon="wxi-angle-right"
|
||||
css="toggle-btn"
|
||||
onClick={toggleSidebar}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="wx-demos hint">{title}</div>
|
||||
</div>
|
||||
<div className="wx-demos header-actions-container">
|
||||
<div className="wx-demos segmented-box">
|
||||
<Segmented
|
||||
value={skin}
|
||||
options={skins}
|
||||
css="segmented-themes"
|
||||
onChange={handleSkinChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="wx-demos btn-box">
|
||||
<a href={githubLink} target="_blank" rel="noopener noreferrer">
|
||||
<Button type="secondary" css="toggle-btn">
|
||||
<img src={GitHubLogoIcon} alt="GitHub icon" />
|
||||
See code on GitHub
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="wx-demos wrapper-content"
|
||||
onClick={() => setShow(false)}
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
className={`wx-demos content wx-${skin}-theme`}
|
||||
role="none"
|
||||
data-wx-portal-root="true"
|
||||
>
|
||||
<Globals>
|
||||
<Router skin={skin} onRouteChange={handleRouteChange} />
|
||||
</Globals>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DemoExplorer(props) {
|
||||
const skins = props.skins;
|
||||
return (
|
||||
<>
|
||||
{skins.map((skin) => (
|
||||
<skin.Component key={skin.id} />
|
||||
))}
|
||||
<HashRouter>
|
||||
<DemoExplorerContent {...props} />
|
||||
</HashRouter>
|
||||
</>
|
||||
);
|
||||
}
|
||||
31
demos/common/Router.jsx
Normal file
31
demos/common/Router.jsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useEffect } from 'react';
|
||||
import {
|
||||
Routes,
|
||||
Route,
|
||||
Navigate,
|
||||
useLocation,
|
||||
useNavigate,
|
||||
} from 'react-router-dom';
|
||||
import { links } from '../routes';
|
||||
|
||||
export default function Router({ onRouteChange }) {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (location.pathname === '/') {
|
||||
navigate('/base/willow', { replace: true });
|
||||
} else {
|
||||
onRouteChange(location.pathname);
|
||||
}
|
||||
}, [location.pathname, onRouteChange, navigate]);
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/" element={<Navigate to="/base/willow" replace />} />
|
||||
{links.map(([path, , Component]) => (
|
||||
<Route key={path} path={path} element={<Component />} />
|
||||
))}
|
||||
</Routes>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user