反射锦标赛
直接执行反应中的单一去除和双去去除括号
探索故事本 ”
查看 Live Demo
• 妇女
报告错误
• 妇女
请求特性
目录
关于项目
我在环球网络上搜索一个很好的组件库, 用于可视化单个消除括号或双消除括号, 但是大多数的这些组件都复杂了数据结构, 或不允许容易的造型, 所以我不得不建造我自己的, 决定与世界分享.
内设
您只需在工程中安装反应即可使用此工程 .
说明: 默认浏览器 ss 使用 小型重置.css 软件包 在故事书演示。 要完全控制匹配组件的外观, 您可以为此构建和提供自己的视图组件
开始
安装
这个项目在公共npm注册,这里是 链接到 npm 页面
npm install @g-loot/react-tournament-brackets
基本用途
图书馆的基本情况
import { SingleEliminationBracket, DoubleEliminationBracket, Match, MATCH_STATES, SVGViewer } from '@g-loot/react-tournament-brackets';
| 构成部分 | 说明 |
|---|---|
| 单一消除 括号 | 显示单一消除括号的组件 |
| 双消除 括号 | 显示双消除括号的组件 |
| 匹配 | 渲染匹配可被覆盖的默认组件 |
| MATCH 统计 | 包含 Match 状态和参与者状态的 enum 常数 |
| SVGviewer 服务器 | 在有平板和缩放功能的固定大小窗口中显示括号的可选组件 |
使用组件
此组件生成您所有括号匹配的 SVG, 您可以使用所提供的可选组件 <SVGViewer /> 就像在下面的例子中将SVG包裹在一个固定大小的窗口中,带有平板和缩放功能,请注意,你也可以自由地提出自己的解决方案,允许用户轻松地浏览巨大的括号.
import { SingleEliminationBracket, DoubleEliminationBracket, Match, SVGViewer } from '@g-loot/react-tournament-brackets';
export const DoubleElimination = () => (
<DoubleEliminationBracket
matches={matches}
matchComponent={Match}
svgWrapper={({ children, ...props }) => (
<SVGViewer width={500} height={500} {...props}>
{children}
</SVGViewer>
)}
/>
);
export const SingleElimination = () => (
<SingleEliminationBracket
matches={matches}
matchComponent={Match}
svgWrapper={({ children, ...props }) => (
<SVGViewer width={500} height={500} {...props}>
{children}
</SVGViewer>
)}
/>
);
- 如果你想要的话
SVGViewer装上容器,你需要某种钩子 才能达到这个目的,比如 使用 WindowSize (), (中文(简体) ), 组合大小 或您的自定义解决方案
import { DoubleEliminationBracket, Match, SVGViewer } from '@g-loot/react-tournament-brackets';
export const DoubleElimination = () => {
const [width, height] = useWindowSize();
const finalWidth = Math.max(width - 50, 500);
const finalHeight = Math.max(height - 100, 500);
return (
<DoubleEliminationBracket
matches={matches}
matchComponent={Match}
svgWrapper={({ children, ...props }) => (
<SVGViewer width={finalWidth} height={finalHeight} {...props}>
{children}
</SVGViewer>
)}
/>
);
};
更多例子请参见 [故事本][demo-url]
数据结构
- 单笔冲销
matches道具结构
[
...,
{
"id": 260005,
"name": "Final - Match",
"nextMatchId": null, // Id for the nextMatch in the bracket, if it's final match it must be null OR undefined
"tournamentRoundText": "4", // Text for Round Header
"startTime": "2021-05-30",
"state": "DONE", // 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY' | 'DONE' | 'SCORE_DONE' Only needed to decide walkovers and if teamNames are TBD (to be decided)
"participants": [
{
"id": "c016cb2a-fdd9-4c40-a81f-0cc6bdf4b9cc", // Unique identifier of any kind
"resultText": "WON", // Any string works
"isWinner": false,
"status": null, // 'PLAYED' | 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY' | null
"name": "giacomo123"
},
{
"id": "9ea9ce1a-4794-4553-856c-9a3620c0531b",
"resultText": null,
"isWinner": true,
"status": null, // 'PLAYED' | 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY'
"name": "Ant"
}
]
}
...
]
- 双冲销
matches道具结构
{
"upper": [
...,
{
"id": 260006, // Unique identifier of any kind
"name": "Semi Final - Match",
"nextMatchId": null, // Id for the next match in upper bracket, if it's final match it must be null OR undefined
"nextLooserMatchId": null, // Id for the next match in lower bracket, if it's final match or a lower bracket match it must be null OR undefined
"startTime": "2021-05-30",
"state": "DONE", // 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY' | 'DONE' | 'SCORE_DONE' Only needed to decide walkovers and if teamNames are TBD (to be decided)
"participants": [
{
"id": "c016cb2a-fdd9-4c40-a81f-0cc6bdf4b9cc", // Unique identifier of any kind
"resultText": "WON", // Any string works
"isWinner": false,
"status": null, // 'PLAYED' | 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY' | null
"name": "giacomo123"
},
{
"id": "9ea9ce1a-4794-4553-856c-9a3620c0531b",
"resultText": "LOST", // Any string works
"isWinner": true,
"status": null, // 'PLAYED' | 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY'
"name": "Ant"
}
]
}
...
],
"lower": [
...,
{
"id": 260005,
"name": "Semi Final - Match",
"nextMatchId": 260006,
"nextLooserMatchId": null,
"tournamentRoundText": "4",
"startTime": "2021-05-30",
"state": "DONE", // 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY' | 'DONE' | 'SCORE_DONE' Only needed to decide walkovers and if teamNames are TBD (to be decided)
"participants": [
{
"id": "c016cb2a-fdd9-4c40-a81f-0cc6bdf4b9cc", // Unique identifier of any kind
"resultText": "WON", // Any string works
"isWinner": false,
"status": null, // 'PLAYED' | 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY' | null
"name": "giacomo123"
},
{
"id": "9ea9ce1a-4794-4553-856c-9a3620c0531b",
"resultText": null,
"isWinner": true,
"status": null, // 'PLAYED' | 'NO_SHOW' | 'WALK_OVER' | 'NO_PARTY'
"name": "Ant"
}
]
}
...
]
}
- 双冲销
matches道具结构 有双打决赛,保持同一种结构,并加入下个MatchId + 下个LooserMatchId,指指同个档次的新相配(决赛可以上下档次) . ưμ㼯A 模拟数据文件夹 具体 数据-倒数倒数 财务报告和审定财务报表 数据-double-last-game-upper-double-playflows.ts 双打 双打 双打 编号
{
[upper|lower]: [
...,
{
"id": "WB R5 M1",
"name": "WB R5 M1",
"nextMatchId": "WB R6 M1",
"nextLooserMatchId": "WB R6 M1",
"startTime": null,
"tournamentRound": "R5",
"state": "SCORE_DONE",
"participants": [
{
"id": "ddfee063-adde-4192-95d2-203eb2ebb8f7",
"resultText": "",
"isWinner": false,
"status": "PLAYED",
"name": "#1"
}
]
},
{
"id": "WB R6 M1",
"name": "WB R6 M1",
"nextMatchId": null,
"nextLooserMatchId": null,
"startTime": null,
"tournamentRound": "R6",
"state": "SCORE_DONE",
"participants": []
}
...,
]
}
- 匹配国/参与国在输出常数中定义
MATCH_STATES
import { MATCH_STATES } from '@g-loot/react-tournament-brackets';
console.log(MATCH_STATES);
// {
// PLAYED: 'PLAYED',
// NO_SHOW: 'NO_SHOW',
// WALK_OVER: 'WALK_OVER',
// NO_PARTY: 'NO_PARTY',
// DONE: 'DONE',
// SCORE_DONE: 'SCORE_DONE',
// };
更多已接受数据的例子,请查看 模拟数据文件夹
赛明和斯提林
此组件的默认主题为截图中的暗主题, 您可以使用此功能 createTheme 从库中导出以创建一个主题,然后传递到该主题上的单括号或双括号 theme 道具
少数说明:
- 一些颜色,如圆头和连接器 还没有绑在主题上,你需要 样式通过
options现在手动的道具,在不远的将来,他们也会被绑在主题上!
完整自定义主题示例 :
import { SingleEliminationBracket, Match, SVGViewer, createTheme } from '@g-loot/react-tournament-brackets';
const WhiteTheme = createTheme({
textColor: { main: '#000000', highlighted: '#07090D', dark: '#3E414D' },
matchBackground: { wonColor: '#daebf9', lostColor: '#96c6da' },
score: {
background: { wonColor: '#87b2c4', lostColor: '#87b2c4' },
text: { highlightedWonColor: '#7BF59D', highlightedLostColor: '#FB7E94' },
},
border: {
color: '#CED1F2',
highlightedColor: '#da96c6',
},
roundHeader: { backgroundColor: '#da96c6', fontColor: '#000' },
connectorColor: '#CED1F2',
connectorColorHighlight: '#da96c6',
svgBackground: '#FAFAFA',
});
export const WhiteThemeBracket = () => {
const [width, height] = useWindowSize();
const finalWidth = Math.max(width - 50, 500);
const finalHeight = Math.max(height - 100, 500);
return (
<SingleEliminationBracket
matches={simpleSmallBracket}
matchComponent={Match}
theme={WhiteTheme}
options={{
style: {
roundHeader: {
backgroundColor: WhiteTheme.roundHeader.backgroundColor,
fontColor: WhiteTheme.roundHeader.fontColor,
},
connectorColor: WhiteTheme.connectorColor,
connectorColorHighlight: WhiteTheme.connectorColorHighlight,
},
}}
svgWrapper={({ children, ...props }) => (
<SvgViewer
background={WhiteTheme.svgBackground}
SVGBackground={WhiteTheme.svgBackground}
width={finalWidth}
height={finalHeight}
{...props}
>
{children}
</SvgViewer>
)}
/>
);
};
如果主题对您还不够, 您总是可以提供您自己的 Match 视图组件, 并使用传递到它的道具来覆盖匹配视图渲染, 您需要再次使用 round 头和连接线来样式 options 道具
自定义匹配组件的基本示例
import { SingleEliminationBracket, SVGViewer } from '@g-loot/react-tournament-brackets';
export const CustomMatchBracket = () => {
const [width, height] = useWindowSize();
const finalWidth = Math.max(width - 50, 500);
const finalHeight = Math.max(height - 100, 500);
return (
<SingleEliminationBracket
matches={simpleSmallBracket}
options={{
style: {
roundHeader: { backgroundColor: '#AAA' },
connectorColor: '#FF8C00',
connectorColorHighlight: '#000',
},
}}
svgWrapper={({ children, ...props }) => (
<SvgViewer
background="#FFF"
SVGBackground="#FFF"
width={finalWidth}
height={finalHeight}
{...props}
>
{children}
</SvgViewer>
)}
matchComponent={({
match,
onMatchClick,
onPartyClick,
onMouseEnter,
onMouseLeave,
topParty,
bottomParty,
topWon,
bottomWon,
topHovered,
bottomHovered,
topText,
bottomText,
connectorColor,
computedStyles,
teamNameFallback,
resultFallback,
}) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-around',
color: '#000',
width: '100%',
height: '100%',
}}
>
<div
onMouseEnter={() => onMouseEnter(topParty.id)}
style={{ display: 'flex' }}
>
<div>{topParty.name || teamNameFallback}</div>
<div>{topParty.resultText ?? resultFallback(topParty)}</div>
</div>
<div
style={{ height: '1px', width: '100%', background: '#FF8C00' }}
/>
<div
onMouseEnter={() => onMouseEnter(bottomParty.id)}
style={{ display: 'flex' }}
>
<div>{bottomParty.name || teamNameFallback}</div>
<div>{bottomParty.resultText ?? resultFallback(topParty)}</div>
</div>
</div>
)}
/>
);
};
更多的例子,请查看[活的故事本][demo-url]
许可证
在GNU LGPL v2.1 许可证下分发. 见 LICENSE 更多信息.
捐款
贡献使得开放源代码社区成为了如此惊人的学习,激励和创造的地方. 你所做的任何贡献 非常感谢。 。 。 .
- 项目叉
- 创建您的特性分支( E)
git checkout -b feature/AmazingFeature(中文(简体) ) - 用于自动反馈, 如果您正在编辑组件或添加新组件运行
npm run dev - 根据 贡献者测试指南
- 提交更改( E)
git commit -m 'Add some AmazingFeature'(中文(简体) ) - 推动到该处
git push origin feature/AmazingFeature(中文(简体) ) - 打开拉请求
贡献者测试指南
单元测试和起伏
- 运行 :
npm run test - 运行 :
npm run lint
检查故事书的作品
- 运行 :
npm run build-storybook检查它是否正确构建了故事本演示网站
检查包在被测试项目消耗时是否有效
- 运行 :
npm run test-lib-build用于测试软件包的构建和包装为 npm 软件包的正确性 - 双方都遵循指南 下一个js 财务报告和审定财务报表 创建- 反应- 应用程序 项目实例
鸣谢
- 启发用户将括号内样式化的组件设置为主题,从而曝光库 重现数据表组件
- 可选组件 SVGViewer 用于缩放和平整括号的库 反应 SVG 泛缩放

