mirror of
https://gitea.gofwd.group/dstrawsb/ballistic-builder.git
synced 2025-12-06 02:36:44 -05:00
moved stuff out of app since it is used for routing
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
import { sectionLinks } from "@/app/lib/linkList/sectionLinks";
|
||||
import Link from "next/link";
|
||||
import armoryLinks from "@/app/lib/linkList/sectionLinks";
|
||||
|
||||
let linksArray = [
|
||||
sectionLinks.UPPERS,
|
||||
sectionLinks.LOWERS,
|
||||
sectionLinks.BARRELS,
|
||||
sectionLinks.OPTICS,
|
||||
sectionLinks.ACCESSORIES,
|
||||
];
|
||||
export const Armory = (props) => {
|
||||
return (
|
||||
(<div>
|
||||
{armoryLinks.length}
|
||||
<h4>{props.titleText}</h4>
|
||||
<ul>
|
||||
{linksArray.map((link, index) => (
|
||||
<li key={index}>
|
||||
<Link href={link.URL}>
|
||||
{link.TEXT}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>)
|
||||
);
|
||||
}
|
||||
export default Armory;
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "armory",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import '../../scss/variables.scss';
|
||||
@@ -1,38 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import styles from './style.module.scss'
|
||||
|
||||
const Button = ({
|
||||
children,
|
||||
className,
|
||||
color = 'black',
|
||||
type = 'button',
|
||||
...props
|
||||
}) => (
|
||||
<button
|
||||
className={`${className} Button Button_${color}`}
|
||||
type={type}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
|
||||
const ButtonUnobtrusive = ({
|
||||
children,
|
||||
className,
|
||||
type = 'button',
|
||||
...props
|
||||
}) => (
|
||||
<button
|
||||
className={`${className} Button_unobtrusive`}
|
||||
type={type}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
|
||||
export { ButtonUnobtrusive };
|
||||
|
||||
export default Button;
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "button",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
.Button {
|
||||
padding: 10px;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.25s ease-in-out;
|
||||
transition: background 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
.Button_white {
|
||||
border: 1px solid #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.Button_white:hover {
|
||||
color: #000;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.Button_black {
|
||||
border: 1px solid #000;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.Button_black:hover {
|
||||
color: #fff;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.Button_unobtrusive {
|
||||
padding: 0;
|
||||
color: #000;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
transition: opacity 0.25s ease-in-out;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.Button_unobtrusive:hover {
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.Button_unobtrusive:focus {
|
||||
outline: none;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
const DSTPageHeader = props => {
|
||||
return (
|
||||
<div>{props.title}</div>
|
||||
|
||||
)
|
||||
}
|
||||
export default DSTPageHeader
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "DSTPageHeader",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import styles from './style.module.css';
|
||||
|
||||
const ErrorMessage = ({ error }) => (
|
||||
<div className="ErrorMessage">
|
||||
<small>{error.toString()}</small>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ErrorMessage;
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "error",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
.ErrorMessage {
|
||||
margin: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { ListItemText, Link } from "@mui/material";
|
||||
import styles from './styles.module.css'
|
||||
import { withStyles } from '@mui/material/styles';
|
||||
import styled from '@emotion/styled'
|
||||
import React from "react";
|
||||
|
||||
export default function FooterLink(props) {
|
||||
return (
|
||||
<ListItemText inset >
|
||||
<Link href={props.href}><a className={styles.navLinks}>{props.title}</a></Link>
|
||||
</ListItemText>
|
||||
)
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "footerlink",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
.navLinks:hover {
|
||||
font-weight: bold;
|
||||
text-decoration : none;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { sectionLinks } from "@/app/lib/linkList/sectionLinks";
|
||||
import Link from "next/link";
|
||||
|
||||
let linksArray = [
|
||||
sectionLinks.BLOG,
|
||||
sectionLinks.PRICEDROPS,
|
||||
sectionLinks.BUILDS,
|
||||
sectionLinks.BUILDGUIDES,
|
||||
];
|
||||
|
||||
export const GroundZero = (props) => {
|
||||
return (
|
||||
(<div>
|
||||
<h4>{props.titleText}</h4>
|
||||
<ul>
|
||||
{linksArray.map((link, index) => (
|
||||
<li key={index}>
|
||||
<Link href={link.URL}>
|
||||
{link.TEXT}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>)
|
||||
);
|
||||
}
|
||||
export default GroundZero;
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "groundzero",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import '../../scss/variables.scss';
|
||||
@@ -1,27 +0,0 @@
|
||||
import { infoLinks } from "@/app/lib/linkList/infoLinks";
|
||||
import Link from "next/link";
|
||||
let linksArray = [
|
||||
infoLinks.ABOUT,
|
||||
infoLinks.FAQ,
|
||||
infoLinks.DISCLOSURE,
|
||||
infoLinks.PRIVACYPOLICY,
|
||||
infoLinks.PIP,
|
||||
infoLinks.TOS
|
||||
];
|
||||
export const Information = (props) => {
|
||||
return (
|
||||
(<div>
|
||||
<h4>{props.titleText}</h4>
|
||||
<ul>
|
||||
{linksArray.map((link, index) => (
|
||||
<li key={index}>
|
||||
<Link href={link.URL}>
|
||||
{link.TEXT}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>)
|
||||
);
|
||||
}
|
||||
export default Information;
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "information",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import '../../scss/variables.scss';
|
||||
@@ -1,70 +0,0 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@mui/material/styles';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
import FormHelperText from '@mui/material/FormHelperText';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import Select from '@mui/material/Select';
|
||||
import NativeSelect from '@mui/material/NativeSelect';
|
||||
import { useQuery, gql } from "@apollo/client";
|
||||
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
formControl: {
|
||||
margin: theme.spacing(1),
|
||||
minWidth: 120,
|
||||
},
|
||||
selectEmpty: {
|
||||
marginTop: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
const GET_STATES = gql`
|
||||
{
|
||||
states {
|
||||
abbrev
|
||||
name
|
||||
}
|
||||
}`
|
||||
|
||||
export default function StateNativeSelects() {
|
||||
const classes = useStyles();
|
||||
const [state, setState] = React.useState({
|
||||
abbrev: '',
|
||||
name: '',
|
||||
});
|
||||
|
||||
const handleChange = (event) => {
|
||||
const name = event.target.name;
|
||||
setState({
|
||||
...state,
|
||||
[name]: event.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
const { loading, error, data } = useQuery(GET_STATES);
|
||||
|
||||
if (loading) return <p>Loading...</p>;
|
||||
if (error) return <p>Error :(</p>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel htmlFor="state-native-simple">State</InputLabel>
|
||||
<Select
|
||||
native
|
||||
value={state.abbrev}
|
||||
onChange={handleChange}
|
||||
inputProps={{
|
||||
name: 'abbrev',
|
||||
id: 'abbrev-native-simple',
|
||||
}}
|
||||
>
|
||||
<option aria-label="None" value="" />
|
||||
{data.states.map(({ abbrev, name }) => (
|
||||
<option value={abbrev}>{name}</option>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function About() {
|
||||
|
||||
return (
|
||||
|
||||
(
|
||||
<section id="about" className="bg-gray-200 py-20">
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<h3 className="text-3xl font-bold mb-6">About Us</h3>
|
||||
<p className="text-gray-700">
|
||||
Ballistic Builderis your go-to platform for customizing, building,
|
||||
and exploring firearm parts. Designed for enthusiasts by
|
||||
enthusiasts, we make firearm building easy and accessible.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function BB_Base_Component() {
|
||||
|
||||
return (
|
||||
(
|
||||
<div />
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Contact() {
|
||||
|
||||
return (
|
||||
(
|
||||
<section id="contact" className="py-20">
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<h3 className="text-3xl font-bold mb-6">Contact Us</h3>
|
||||
<p className="text-gray-700 mb-6">
|
||||
Have questions or feedback? We’d love to hear from you!
|
||||
</p>
|
||||
<Link
|
||||
href="mailto:support@firearmbuilder.com"
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
||||
|
||||
Email Us
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function FeaturesSection() {
|
||||
|
||||
return (
|
||||
(
|
||||
<section id="features" className="py-20">
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<h3 className="text-3xl font-bold mb-6">Features</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div className="bg-white shadow-md p-6 rounded">
|
||||
<h4 className="text-xl font-bold mb-2">Extensive Database</h4>
|
||||
<p className="text-gray-600">
|
||||
Access thousands of firearm parts from trusted resellers.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white shadow-md p-6 rounded">
|
||||
<h4 className="text-xl font-bold mb-2">Compatibility Checker</h4>
|
||||
<p className="text-gray-600">
|
||||
Ensure every part works perfectly together.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white shadow-md p-6 rounded">
|
||||
<h4 className="text-xl font-bold mb-2">Save & Share Builds</h4>
|
||||
<p className="text-gray-600">
|
||||
Save your builds or share them with friends.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Footer() {
|
||||
|
||||
return (
|
||||
(
|
||||
<footer className="bg-gray-800 text-white py-4">
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<p>© {new Date().getFullYear()} Firearm Builder. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import styles from './styles.module.css'
|
||||
import List from '@mui/material/List'
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import TypoGraphy from '@mui/material/Typography'
|
||||
import Link from 'next/link'
|
||||
import { makeStyles } from '@mui/material/styles';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
width: '75%',
|
||||
maxWidth: 260,
|
||||
/* backgroundColor: theme.palette.background.paper, */
|
||||
float : 'right',
|
||||
marginRight:'2%',
|
||||
fontSize : '.80em'
|
||||
|
||||
|
||||
},
|
||||
}));
|
||||
|
||||
export default function FooterLinks() {
|
||||
|
||||
const classes = useStyles();
|
||||
return (
|
||||
(<div className={classes.root}>
|
||||
<TypoGraphy variant="subtitle1" color="inherit" >
|
||||
<List component="nav" >
|
||||
|
||||
<ListItemText inset >
|
||||
<TypoGraphy color="inherit" variant="subtitle2">
|
||||
<Link href="/info/faq" className={styles.navLinks}>FAQ</Link>
|
||||
</TypoGraphy>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset >
|
||||
<TypoGraphy color="inherit" variant="subtitle2">
|
||||
<Link href="/info/tos" className={styles.navLinks}>Terms Of Service</Link>
|
||||
</TypoGraphy>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset>
|
||||
<TypoGraphy color="inherit" variant="subtitle2">
|
||||
<Link href="/info/contactus" className={styles.navLinks}>Contact Us</Link>
|
||||
</TypoGraphy>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset>
|
||||
<TypoGraphy color="inherit" variant="subtitle2">
|
||||
<Link href="/info/privacypolicy" className={styles.navLinks}>Privacy Policy</Link>
|
||||
</TypoGraphy>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset>
|
||||
<TypoGraphy color="inherit" variant="subtitle2">
|
||||
<Link href="/info/pip" className={styles.navLinks}>Personal Information Policy</Link>
|
||||
</TypoGraphy>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset>
|
||||
<TypoGraphy color="inherit" variant="subtitle2">
|
||||
<Link href="/info/disclosure" className={styles.navLinks}>Disclosure</Link>
|
||||
</TypoGraphy>
|
||||
</ListItemText>
|
||||
|
||||
|
||||
</List>
|
||||
</TypoGraphy>
|
||||
</div>)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import styles from './styles.module.css'
|
||||
import List from '@mui/material/List'
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import TypoGraphy from '@mui/material/Typography'
|
||||
import Link from 'next/link'
|
||||
import { withStyles } from '@mui/material/styles';
|
||||
import styled from '@emotion/styled'
|
||||
import FooterLink from '@/src/app/Fragments/FooterLink';
|
||||
|
||||
|
||||
class FooterLinks extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<FooterLinksStyled>
|
||||
<div className="footer-links">
|
||||
<List component="nav" >
|
||||
<React.Fragment>
|
||||
<FooterLink href="/info/faq" title="FAQ" />
|
||||
<FooterLink href="/info/tos" title="Terms Of Service" />
|
||||
<FooterLink href="/info/contactus" title="Contact Us" />
|
||||
<FooterLink href="/info/privacypolicy" title="Privacy Policy" />
|
||||
<FooterLink href="/info/pip" title="Personal Information Policy" />
|
||||
<FooterLink href="/info/disclosure" title="Disclosure" />
|
||||
<FooterLink href="/info/about" title="About Us" />
|
||||
</React.Fragment>
|
||||
</List>
|
||||
</div>
|
||||
</FooterLinksStyled>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const FooterLinksStyled = styled.div`
|
||||
.footer-links nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
// export default withStyles(useStyles)(FooterLinks);
|
||||
|
||||
export default FooterLinks;
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "footerlinks",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
.navLinks {
|
||||
color:#000;
|
||||
}
|
||||
.navLinks:hover {
|
||||
font-weight: bold;
|
||||
text-decoration : none;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styles from './styles.module.scss';
|
||||
import Copyright from "@/src/app/components/GB_Info/Copyright";
|
||||
import FooterLinks from "./FooterLinks";
|
||||
import Link from "next/link";
|
||||
import { infoLinks } from "@/src/app/lib/linkList/infoLinks";
|
||||
import { sectionLinks } from "@/src//app/lib/linkList/sectionLinks";
|
||||
import Armory from '@/src/app/Fragments/Armory';
|
||||
import GroundZero from "@/src/app/Fragments/GroundZero";
|
||||
import Information from "@/src/app/Fragments/Information";
|
||||
export const Footer = () => {
|
||||
|
||||
return (
|
||||
// <div className={styles.Footer}>
|
||||
// <FooterLinks></FooterLinks>
|
||||
// <Copyright></Copyright>
|
||||
// </div>
|
||||
(<>
|
||||
<footer className={styles.footer}>
|
||||
<nav className={styles.linksContainer}>
|
||||
<div className={styles.brand}>
|
||||
<div className={styles.logo}>
|
||||
<span>Logo</span>
|
||||
</div>
|
||||
<p>Find Parts.</p>
|
||||
<p>Build Guns.</p>
|
||||
<p>Freedom On.</p>
|
||||
</div>
|
||||
<Armory titleText="Armory"/>
|
||||
<GroundZero titleText="Ground Zero"/>
|
||||
<Information titleText="Information"/>
|
||||
</nav>
|
||||
</footer>
|
||||
<Copyright></Copyright>
|
||||
</>)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Footer.propTypes = {};
|
||||
|
||||
export default Footer;
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "footer",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
@import '../../scss/variables.scss';
|
||||
|
||||
.footer {
|
||||
background: #4c5c3f;
|
||||
min-height: 300px;
|
||||
height: 100%;
|
||||
padding: 1rem 0;
|
||||
border-top: 2px solid #000;
|
||||
|
||||
.brand {
|
||||
font-weight: bolder;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
font-size: 1.25em;
|
||||
color:#FFF;
|
||||
|
||||
.logo span {
|
||||
display: inline-block;
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
background: #FFF;
|
||||
color:#4c5c3f;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.linksContainer {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-start;
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
color:#FFF;
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
transition: all 500ms ease;
|
||||
|
||||
&:hover {
|
||||
color: #ADA17B;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
color: #FFF;
|
||||
border-bottom: 2px solid #fff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types'; //ES6
|
||||
import styles from './styles.module.css';
|
||||
import Link from 'next/link';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material//ListItemText';
|
||||
// import TypoGraphy from '@mui/material/Typography';
|
||||
import Button from '@mui/material//Button';
|
||||
import { infoLinks } from '@/app/lib/linkList/infoLinks';
|
||||
import sectionLinks from '@/app/lib/linkList/sectionLinks';
|
||||
|
||||
export default class Header extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
(<div>
|
||||
<div className="topheader">
|
||||
<Link href="/" legacyBehavior><a className="logo">Gun Builder</a>
|
||||
</Link>
|
||||
</div>
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<List component="nav">
|
||||
<ListItem component="div" className="nav-item">
|
||||
<ListItemText inset>
|
||||
<Link href={sectionLinks.UPPERS.URL} legacyBehavior><a className={styles.navLinks}>{sectionLinks.UPPERS.TEXT}</a></Link>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset>
|
||||
<Link href={sectionLinks.PARTSLIST.URL} legacyBehavior><a className={styles.navLinks}>{sectionLinks.PARTSLIST.TEXT}</a></Link>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset>
|
||||
<Link href={sectionLinks.BUILDS.URL} legacyBehavior><a className={styles.navLinks}>{sectionLinks.BUILDS.TEXT}</a></Link>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemText inset>
|
||||
<Link href={sectionLinks.BLOG.URL} legacyBehavior><a className={styles.navLinks}>{sectionLinks.BLOG.TEXT}</a></Link>
|
||||
</ListItemText>
|
||||
|
||||
{/* <ListItemText inset>
|
||||
<Link href="/admin"><a className={styles.navLinks}>Admin</a></Link>
|
||||
</ListItemText> */}
|
||||
</ListItem>
|
||||
|
||||
</List>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<style jsx>{`
|
||||
header {
|
||||
background:#101010;
|
||||
color:#fff;
|
||||
}
|
||||
.topheader {
|
||||
background:#111;
|
||||
height: 4em;
|
||||
color: #000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.topheader a {
|
||||
color:#fff;
|
||||
padding-left: 15px;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
.nav {
|
||||
display: flex;
|
||||
background: #4c5d34;
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
ul li {
|
||||
margin-right: 10px;
|
||||
padding:1em 1.5em;
|
||||
border-right:2px solid rgba(0,0,0,.3);
|
||||
text-transform: uppercase;
|
||||
font-weight:bold;
|
||||
letter-spacing:2px;
|
||||
}
|
||||
`}</style>
|
||||
</div>)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Header.propTypes = {
|
||||
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "header",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
.navLinks {
|
||||
color:white;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
font-weight: bold;
|
||||
transition: all 500ms ease;
|
||||
}
|
||||
.navLinks:hover {
|
||||
text-decoration : none;
|
||||
}
|
||||
.nav-item:hover {
|
||||
background-color: pink;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import React from 'react';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import MuiLink from '@mui/material/Link';
|
||||
import Button from '@mui/material/Button';
|
||||
|
||||
export default class Hero extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
show: true,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
||||
<div className="hero" styles={{ backgroundImage:`url({${this.props.image}})` }}>
|
||||
<div className="hero-text">
|
||||
<h3>{this.props.heading}</h3>
|
||||
<p>{this.props.subheading}</p>
|
||||
<Button href={this.props.link} variant="contained" color="primary">
|
||||
{this.props.linktext}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
.hero {
|
||||
// background:url('/gb-hero.jpg');
|
||||
background-size:cover;
|
||||
min-height:35vw;
|
||||
color: #fff;
|
||||
display:flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.hero-text {
|
||||
padding: 2em;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "hero",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import styles from './styles.module.css'
|
||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
||||
|
||||
export default function About(props) {
|
||||
|
||||
const GET_SITE_CONTENT = gql`
|
||||
query Get_Site_Content {
|
||||
site_contents(where: {content_id: {_eq: "ABOUTUS"}}, order_by: {content: asc}) {
|
||||
id
|
||||
content_id
|
||||
content
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { loading, error, data } = useQuery(GET_SITE_CONTENT);
|
||||
if (loading) return "Loading ...";
|
||||
if (error) return `Error! ${error.message}`;
|
||||
|
||||
return (
|
||||
<div >
|
||||
<h1>About</h1>
|
||||
{data.site_contents.map((site_content: { content: any; }) => (
|
||||
<span dangerouslySetInnerHTML={{ __html: site_content.content }} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
About.propTypes = {
|
||||
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "about",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import TypoGraphy from '@mui/material/Typography';
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import styles from './styles.module.css';
|
||||
import constants from '@/src/app/lib/constants'
|
||||
|
||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
||||
|
||||
export default function ContactUs(props) {
|
||||
|
||||
const GET_SITE_CONTENT = gql`
|
||||
query Get_Site_Content {
|
||||
site_contents(where: {content_id: {_eq: "CONTACTUS"}}, order_by: {content: asc}) {
|
||||
id
|
||||
content_id
|
||||
content
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { loading, error, data } = useQuery(GET_SITE_CONTENT);
|
||||
if (loading) return "Loading ...";
|
||||
if (error) return `Error! ${error.message}`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TypoGraphy paragraph='true' variant="body" color="inherit" >
|
||||
{data.site_contents.map((site_content: { content: any; }) => (
|
||||
<span dangerouslySetInnerHTML={{ __html: site_content.content }} />
|
||||
))}
|
||||
</TypoGraphy>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
ContactUs.propTypes = {
|
||||
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "contactus",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import { COMPANY_NAME, COMPANY_URL } from '@/src/app/lib/constants';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import MuiLink from '@mui/material/Link';
|
||||
import styles from './styles.module.css'
|
||||
import Link from 'next/link'
|
||||
import styled from '@emotion/styled'
|
||||
|
||||
|
||||
export default class Copyright extends Component {
|
||||
render() {
|
||||
return (
|
||||
(<CopyStyled>
|
||||
<div className="copyright">© {new Date().getFullYear()} {' '}
|
||||
<Link href={COMPANY_URL}>
|
||||
{COMPANY_NAME}
|
||||
</Link>{' '}
|
||||
<span>All Rights Reserved.</span>
|
||||
</div>
|
||||
</CopyStyled>)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const CopyStyled = styled.div`
|
||||
.copyright {
|
||||
background: #4c5c3f;
|
||||
font-size:.80em;
|
||||
text-transform: uppercase;
|
||||
color:#FFF;
|
||||
display: block;
|
||||
width:100%;
|
||||
text-align:center;
|
||||
|
||||
a {
|
||||
color:#FFF;
|
||||
text-decoration:none;
|
||||
}
|
||||
}
|
||||
`
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "copyright",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
.white {
|
||||
color: white;
|
||||
font-size: .5em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
font-family: "hind";
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import TypoGraphy from '@mui/material/Typography';
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import styles from './styles.module.css';
|
||||
import constants from '@/src/app/lib/constants'
|
||||
import {SITE_CONT_TYPE} from '@/src/app/lib/constants'
|
||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
||||
|
||||
export default function Disclosure(props) {
|
||||
|
||||
const GET_SITE_CONTENT = gql`
|
||||
query Get_Site_Content {
|
||||
site_contents(where: {content_id: {_eq: ${SITE_CONT_TYPE.DISCLOSURE}}}, order_by: {content: asc}) {
|
||||
id
|
||||
content_id
|
||||
content
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { loading, error, data } = useQuery(GET_SITE_CONTENT);
|
||||
if (loading) return "Loading ...";
|
||||
if (error) return `Error! ${error.message}`;
|
||||
return (
|
||||
<div>
|
||||
<TypoGraphy paragraph={true} variant="body1" color="inherit" >
|
||||
{constants.SITE_NAME}, owned by {constants.COMPANY_NAME}, receives compensation through affiliate relationships with merchants listed on this site. Please know that this in no way affects reviews, benchmarks, content, or this site's opinions of products, services, manufacturers, partners, or merchants.
|
||||
</TypoGraphy>
|
||||
<TypoGraphy paragraph={true} variant="body1" color="inherit" >
|
||||
The mission of {constants.SITE_NAME} is to provide the best functionality for this site's users, regardless of any potential affiliate commissions.
|
||||
{constants.SITE_NAME} does not accept donations. Instead, income received from affiliate relationships funds site maintenance and feature development. If you desire to donate to PCPartPicker, I kindly ask that you consider donating to a charitable organization instead. I am particularly fond of the NRA, a non-profit organization that provides safety training to gun owners.
|
||||
</TypoGraphy>
|
||||
<div>
|
||||
{data.site_contents.map((site_content: { content: any; }) => (
|
||||
<span dangerouslySetInnerHTML={{ __html: site_content.content }} />
|
||||
))}
|
||||
</div>
|
||||
<TypoGraphy paragraph={true} variant="body1" color="inherit" >
|
||||
Thanks,
|
||||
</TypoGraphy>
|
||||
<TypoGraphy paragraph={true} variant="body1" color="inherit" >
|
||||
{constants.COMPANY_NAME}
|
||||
</TypoGraphy>
|
||||
<TypoGraphy paragraph={true} variant="body1" color="inherit" >
|
||||
{constants.SITE_NAME} is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to amazon.com.
|
||||
</TypoGraphy>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Disclosure.propTypes = {
|
||||
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "disclosure",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import styles from './styles.module.css'
|
||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
||||
|
||||
export default function Faq(props) {
|
||||
|
||||
const GET_SITE_CONTENT_FAQ = gql`
|
||||
query Get_Site_Content_Faq {
|
||||
site_contents(where: {content_id: {_eq: "FAQ"}}, order_by: {content: asc}) {
|
||||
id
|
||||
content_id
|
||||
content
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { loading, error, data } = useQuery(GET_SITE_CONTENT_FAQ);
|
||||
if(loading) return "Loading ...";
|
||||
if(error) return `Error! ${error.message}` ;
|
||||
|
||||
return (
|
||||
|
||||
<div className="faq container">
|
||||
{props.children}
|
||||
<h3>Frequently Asked Questions</h3>
|
||||
<div>
|
||||
{data.site_contents.map((site_content: { content: any; }) => (
|
||||
<span dangerouslySetInnerHTML={{__html: site_content.content}}/>
|
||||
))}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "faq",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import Head from 'next/head';
|
||||
import TypoGraphy from '@mui/material/Typography';
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import styles from './styles.module.css';
|
||||
import constants from '@/src/app/lib/constants'
|
||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
||||
|
||||
export default function PIP(props) {
|
||||
const GET_SITE_CONTENT = gql`
|
||||
query Get_Site_Content {
|
||||
site_contents(where: {content_id: {_eq: "PIP"}}, order_by: {content: asc}) {
|
||||
id
|
||||
content_id
|
||||
content
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { loading, error, data } = useQuery(GET_SITE_CONTENT);
|
||||
if (loading) return "Loading ...";
|
||||
if (error) return `Error! ${error.message}`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Head title="Personal Information" />
|
||||
<TypoGraphy paragraph='true' variant="body" color="inherit" >
|
||||
|
||||
{data.site_contents.map((site_content: { content: any; }) => (
|
||||
<span dangerouslySetInnerHTML={{ __html: site_content.content }} />
|
||||
))}
|
||||
</TypoGraphy>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
PIP.propTypes = {
|
||||
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "pip",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import TypoGraphy from '@mui/material/Typography';
|
||||
import Head from 'next/head';
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import styles from './styles.module.css';
|
||||
import constants from '@/src/app/lib/constants'
|
||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
||||
|
||||
export default function PrivacyPolicy(props) {
|
||||
const GET_SITE_CONTENT = gql`
|
||||
query Get_Site_Content {
|
||||
site_contents(where: {content_id: {_eq: "PP"}}, order_by: {content: asc}) {
|
||||
id
|
||||
content_id
|
||||
content
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { loading, error, data } = useQuery(GET_SITE_CONTENT);
|
||||
if (loading) return "Loading ...";
|
||||
if (error) return `Error! ${error.message}`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Head title="Privacy Policy" />
|
||||
<TypoGraphy paragraph='true' variant="body" color="inherit" >
|
||||
{data.site_contents.map((site_content: { content: any; }) => (
|
||||
<span dangerouslySetInnerHTML={{ __html: site_content.content }} />
|
||||
))}
|
||||
</TypoGraphy>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "privacypolicy",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import Head from 'next/head';
|
||||
import TypoGraphy from '@mui/material/Typography';
|
||||
import PropTypes from 'prop-types' //ES6
|
||||
import constants from '@/src/app/lib/constants'
|
||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
||||
|
||||
export default function TermsOfService(props) {
|
||||
const GET_SITE_CONTENT = gql`
|
||||
query Get_Site_Content {
|
||||
site_contents(where: {content_id: {_eq: "TOS"}}, order_by: {content: asc}) {
|
||||
id
|
||||
content_id
|
||||
content
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { loading, error, data } = useQuery(GET_SITE_CONTENT);
|
||||
if (loading) return "Loading ...";
|
||||
if (error) return `Error! ${error.message}`;
|
||||
return (
|
||||
<div>
|
||||
<Head title="Terms Of Service" />
|
||||
<TypoGraphy paragraph='true' variant="body" color="inherit" >
|
||||
<div>
|
||||
{data.site_contents.map((site_content: { content: any; }) => (
|
||||
<span dangerouslySetInnerHTML={{ __html: site_content.content }} />
|
||||
))}
|
||||
</div>
|
||||
</TypoGraphy>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
TermsOfService.propTypes = {
|
||||
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "termsofservice",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index.tsx",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
import React from 'react';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Button from '@mui/material/Button';
|
||||
import CssBaseline from '@mui/material/CssBaseline';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||
import Checkbox from '@mui/material/Checkbox';
|
||||
import Link from '@mui/material/Link';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import Box from '@mui/material/Box';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { makeStyles } from '@mui/material/styles';
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
function Copyright() {
|
||||
return (
|
||||
<Typography variant="body2" color="textSecondary" align="center">
|
||||
{'Copyright © '}
|
||||
<Link color="inherit" href="https://material-ui.com/">
|
||||
Your Website
|
||||
</Link>{' '}
|
||||
{new Date().getFullYear()}
|
||||
{'.'}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
height: '100vh',
|
||||
},
|
||||
image: {
|
||||
backgroundImage: 'url(https://source.unsplash.com/random)',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundColor:
|
||||
theme.palette.type === 'light' ? theme.palette.grey[50] : theme.palette.grey[900],
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
},
|
||||
paper: {
|
||||
margin: theme.spacing(8, 4),
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
},
|
||||
avatar: {
|
||||
margin: theme.spacing(1),
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
},
|
||||
form: {
|
||||
width: '100%', // Fix IE 11 issue.
|
||||
marginTop: theme.spacing(1),
|
||||
},
|
||||
submit: {
|
||||
margin: theme.spacing(3, 0, 2),
|
||||
},
|
||||
}));
|
||||
|
||||
export default function SignInSide() {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Grid container component="main" className={classes.root}>
|
||||
<CssBaseline />
|
||||
<Grid item xs={false} sm={4} md={7} className={classes.image} />
|
||||
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
|
||||
<div className={classes.paper}>
|
||||
<Avatar className={classes.avatar}>
|
||||
<LockOutlinedIcon />
|
||||
</Avatar>
|
||||
<Typography component="h1" variant="h5">
|
||||
Sign in
|
||||
</Typography>
|
||||
<form className={classes.form} noValidate>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
required
|
||||
fullWidth
|
||||
id="email"
|
||||
label="Email Address"
|
||||
name="email"
|
||||
autoComplete="email"
|
||||
autoFocus
|
||||
/>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
required
|
||||
fullWidth
|
||||
name="password"
|
||||
label="Password"
|
||||
type="password"
|
||||
id="password"
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={<Checkbox value="remember" color="primary" />}
|
||||
label="Remember me"
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.submit}
|
||||
>
|
||||
Sign In
|
||||
</Button>
|
||||
<Grid container>
|
||||
<Grid item xs>
|
||||
<Link href="#" variant="body2">
|
||||
Forgot password?
|
||||
</Link>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Link href="#" variant="body2">
|
||||
{"Don't have an account? Sign Up"}
|
||||
</Link>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Box mt={5}>
|
||||
<Copyright />
|
||||
</Box>
|
||||
</form>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "signin",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./index",
|
||||
"author": {
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Don Strawsburg",
|
||||
"email": "don@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
},
|
||||
{
|
||||
"name": "Sean Strawsburg",
|
||||
"email": "sean@goforward.group",
|
||||
"url": "https://goforward.group/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { Box, Flex, Link, Heading } from "@chakra-ui/react";
|
||||
import NextLink from "next/link";
|
||||
|
||||
const Header: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Box as="header" bg="primary" color="white" px="6" py="4" shadow="md">
|
||||
<Flex justify="space-between" align="center" maxW="5xl" mx="auto">
|
||||
<Heading as="h1" size="lg">
|
||||
<NextLink href="/" passHref>
|
||||
<Link color="white" _hover={{ textDecoration: "none" }}>
|
||||
Ballistic Builder
|
||||
</Link>
|
||||
</NextLink>
|
||||
</Heading>
|
||||
<Flex as="nav" gap="6">
|
||||
<NextLink href="/builder" passHref>
|
||||
<Link color="white" _hover={{ textDecoration: "underline" }}>
|
||||
Builder
|
||||
</Link>
|
||||
</NextLink>
|
||||
<NextLink href="/products" passHref>
|
||||
<Link color="white" _hover={{ textDecoration: "underline" }}>
|
||||
Products
|
||||
</Link>
|
||||
</NextLink>
|
||||
<NextLink href="/auth/signin" passHref>
|
||||
<Link color="white" _hover={{ textDecoration: "underline" }}>
|
||||
Sign In
|
||||
</Link>
|
||||
</NextLink>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@@ -1,23 +0,0 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Header() {
|
||||
{/* Header Section */ }
|
||||
return (
|
||||
(
|
||||
<header className="bg-gray-800 text-white py-4 shadow-md">
|
||||
<div className="container mx-auto px-6 flex justify-between items-center">
|
||||
<h1 className="text-2xl font-bold">Ballistic Builder</h1>
|
||||
<nav>
|
||||
<ul className="flex space-x-4">
|
||||
<li><Link href="#features" className="hover:underline">Features</Link></li>
|
||||
<li><Link href="/builder" className="hover:underline">Builder</Link></li>
|
||||
<li><Link href="/products" className="hover:underline">Products</Link></li>
|
||||
<li><Link href="#contact" className="hover:underline">Contact</Link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
)
|
||||
)}
|
||||
@@ -1,24 +0,0 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Hero() {
|
||||
{/* Hero Section */ }
|
||||
return (
|
||||
|
||||
<section className="bg-gray-700 text-white py-20 text-center">
|
||||
<div className="container mx-auto px-6">
|
||||
<h2 className="text-4xl font-bold mb-4">Build Your Dream Firearm</h2>
|
||||
<p className="text-lg mb-6">
|
||||
Customize every component of your firearm with ease and precision.
|
||||
</p>
|
||||
<Link
|
||||
href="/builder"
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
||||
|
||||
Get Started
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import Link from "next/link";
|
||||
import Header from "../Header";
|
||||
import Hero from "../Hero";
|
||||
import FeaturesSection from "../FeaturesSection";
|
||||
import About from "../About";
|
||||
import Contact from "../Contact";
|
||||
import Footer from "../Footer ";
|
||||
|
||||
export default function HomeContent() {
|
||||
|
||||
return (
|
||||
(
|
||||
<>
|
||||
<Header />
|
||||
<Hero />
|
||||
<FeaturesSection />
|
||||
<About />
|
||||
<Contact />
|
||||
<Footer />
|
||||
</>
|
||||
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { Accordion, HStack } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuChevronDown } from "react-icons/lu"
|
||||
|
||||
interface AccordionItemTriggerProps extends Accordion.ItemTriggerProps {
|
||||
indicatorPlacement?: "start" | "end"
|
||||
}
|
||||
|
||||
export const AccordionItemTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
AccordionItemTriggerProps
|
||||
>(function AccordionItemTrigger(props, ref) {
|
||||
const { children, indicatorPlacement = "end", ...rest } = props
|
||||
return (
|
||||
<Accordion.ItemTrigger {...rest} ref={ref}>
|
||||
{indicatorPlacement === "start" && (
|
||||
<Accordion.ItemIndicator rotate={{ base: "-90deg", _open: "0deg" }}>
|
||||
<LuChevronDown />
|
||||
</Accordion.ItemIndicator>
|
||||
)}
|
||||
<HStack gap="4" flex="1" textAlign="start" width="full">
|
||||
{children}
|
||||
</HStack>
|
||||
{indicatorPlacement === "end" && (
|
||||
<Accordion.ItemIndicator>
|
||||
<LuChevronDown />
|
||||
</Accordion.ItemIndicator>
|
||||
)}
|
||||
</Accordion.ItemTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
interface AccordionItemContentProps extends Accordion.ItemContentProps {}
|
||||
|
||||
export const AccordionItemContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
AccordionItemContentProps
|
||||
>(function AccordionItemContent(props, ref) {
|
||||
return (
|
||||
<Accordion.ItemContent>
|
||||
<Accordion.ItemBody {...props} ref={ref} />
|
||||
</Accordion.ItemContent>
|
||||
)
|
||||
})
|
||||
|
||||
export const AccordionRoot = Accordion.Root
|
||||
export const AccordionItem = Accordion.Item
|
||||
@@ -1,40 +0,0 @@
|
||||
import { ActionBar, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
|
||||
interface ActionBarContentProps extends ActionBar.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
}
|
||||
|
||||
export const ActionBarContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ActionBarContentProps
|
||||
>(function ActionBarContent(props, ref) {
|
||||
const { children, portalled = true, portalRef, ...rest } = props
|
||||
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ActionBar.Positioner>
|
||||
<ActionBar.Content ref={ref} {...rest} asChild={false}>
|
||||
{children}
|
||||
</ActionBar.Content>
|
||||
</ActionBar.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
|
||||
export const ActionBarCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ActionBar.CloseTriggerProps
|
||||
>(function ActionBarCloseTrigger(props, ref) {
|
||||
return (
|
||||
<ActionBar.CloseTrigger {...props} asChild ref={ref}>
|
||||
<CloseButton size="sm" />
|
||||
</ActionBar.CloseTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const ActionBarRoot = ActionBar.Root
|
||||
export const ActionBarSelectionTrigger = ActionBar.SelectionTrigger
|
||||
export const ActionBarSeparator = ActionBar.Separator
|
||||
@@ -1,51 +0,0 @@
|
||||
import { Alert as ChakraAlert } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
|
||||
export interface AlertProps extends Omit<ChakraAlert.RootProps, "title"> {
|
||||
startElement?: React.ReactNode
|
||||
endElement?: React.ReactNode
|
||||
title?: React.ReactNode
|
||||
icon?: React.ReactElement
|
||||
closable?: boolean
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
export const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
||||
function Alert(props, ref) {
|
||||
const {
|
||||
title,
|
||||
children,
|
||||
icon,
|
||||
closable,
|
||||
onClose,
|
||||
startElement,
|
||||
endElement,
|
||||
...rest
|
||||
} = props
|
||||
return (
|
||||
<ChakraAlert.Root ref={ref} {...rest}>
|
||||
{startElement || <ChakraAlert.Indicator>{icon}</ChakraAlert.Indicator>}
|
||||
{children ? (
|
||||
<ChakraAlert.Content>
|
||||
<ChakraAlert.Title>{title}</ChakraAlert.Title>
|
||||
<ChakraAlert.Description>{children}</ChakraAlert.Description>
|
||||
</ChakraAlert.Content>
|
||||
) : (
|
||||
<ChakraAlert.Title flex="1">{title}</ChakraAlert.Title>
|
||||
)}
|
||||
{endElement}
|
||||
{closable && (
|
||||
<CloseButton
|
||||
size="sm"
|
||||
pos="relative"
|
||||
top="-2"
|
||||
insetEnd="-2"
|
||||
alignSelf="flex-start"
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
</ChakraAlert.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,74 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import type { GroupProps, SlotRecipeProps } from "@chakra-ui/react"
|
||||
import { Avatar as ChakraAvatar, Group } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
type ImageProps = React.ImgHTMLAttributes<HTMLImageElement>
|
||||
|
||||
export interface AvatarProps extends ChakraAvatar.RootProps {
|
||||
name?: string
|
||||
src?: string
|
||||
srcSet?: string
|
||||
loading?: ImageProps["loading"]
|
||||
icon?: React.ReactElement
|
||||
fallback?: React.ReactNode
|
||||
}
|
||||
|
||||
export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
|
||||
function Avatar(props, ref) {
|
||||
const { name, src, srcSet, loading, icon, fallback, children, ...rest } =
|
||||
props
|
||||
return (
|
||||
<ChakraAvatar.Root ref={ref} {...rest}>
|
||||
<AvatarFallback name={name} icon={icon}>
|
||||
{fallback}
|
||||
</AvatarFallback>
|
||||
<ChakraAvatar.Image src={src} srcSet={srcSet} loading={loading} />
|
||||
{children}
|
||||
</ChakraAvatar.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
interface AvatarFallbackProps extends ChakraAvatar.FallbackProps {
|
||||
name?: string
|
||||
icon?: React.ReactElement
|
||||
}
|
||||
|
||||
const AvatarFallback = React.forwardRef<HTMLDivElement, AvatarFallbackProps>(
|
||||
function AvatarFallback(props, ref) {
|
||||
const { name, icon, children, ...rest } = props
|
||||
return (
|
||||
<ChakraAvatar.Fallback ref={ref} {...rest}>
|
||||
{children}
|
||||
{name != null && children == null && <>{getInitials(name)}</>}
|
||||
{name == null && children == null && (
|
||||
<ChakraAvatar.Icon asChild={!!icon}>{icon}</ChakraAvatar.Icon>
|
||||
)}
|
||||
</ChakraAvatar.Fallback>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
function getInitials(name: string) {
|
||||
const names = name.trim().split(" ")
|
||||
const firstName = names[0] != null ? names[0] : ""
|
||||
const lastName = names.length > 1 ? names[names.length - 1] : ""
|
||||
return firstName && lastName
|
||||
? `${firstName.charAt(0)}${lastName.charAt(0)}`
|
||||
: firstName.charAt(0)
|
||||
}
|
||||
|
||||
interface AvatarGroupProps extends GroupProps, SlotRecipeProps<"avatar"> {}
|
||||
|
||||
export const AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(
|
||||
function AvatarGroup(props, ref) {
|
||||
const { size, variant, borderless, ...rest } = props
|
||||
return (
|
||||
<ChakraAvatar.PropsProvider value={{ size, variant, borderless }}>
|
||||
<Group gap="0" spaceX="-3" ref={ref} {...rest} />
|
||||
</ChakraAvatar.PropsProvider>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,31 +0,0 @@
|
||||
import { Blockquote as ChakraBlockquote } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface BlockquoteProps extends ChakraBlockquote.RootProps {
|
||||
cite?: React.ReactNode
|
||||
citeUrl?: string
|
||||
icon?: React.ReactNode
|
||||
showDash?: boolean
|
||||
}
|
||||
|
||||
export const Blockquote = React.forwardRef<HTMLDivElement, BlockquoteProps>(
|
||||
function Blockquote(props, ref) {
|
||||
const { children, cite, citeUrl, showDash, icon, ...rest } = props
|
||||
|
||||
return (
|
||||
<ChakraBlockquote.Root ref={ref} {...rest}>
|
||||
{icon}
|
||||
<ChakraBlockquote.Content cite={citeUrl}>
|
||||
{children}
|
||||
</ChakraBlockquote.Content>
|
||||
{cite && (
|
||||
<ChakraBlockquote.Caption>
|
||||
{showDash ? <>—</> : null} <cite>{cite}</cite>
|
||||
</ChakraBlockquote.Caption>
|
||||
)}
|
||||
</ChakraBlockquote.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export const BlockquoteIcon = ChakraBlockquote.Icon
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Breadcrumb, type SystemStyleObject } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface BreadcrumbRootProps extends Breadcrumb.RootProps {
|
||||
separator?: React.ReactNode
|
||||
separatorGap?: SystemStyleObject["gap"]
|
||||
}
|
||||
|
||||
export const BreadcrumbRoot = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
BreadcrumbRootProps
|
||||
>(function BreadcrumbRoot(props, ref) {
|
||||
const { separator, separatorGap, children, ...rest } = props
|
||||
|
||||
const validChildren = React.Children.toArray(children).filter(
|
||||
React.isValidElement,
|
||||
)
|
||||
|
||||
return (
|
||||
<Breadcrumb.Root ref={ref} {...rest}>
|
||||
<Breadcrumb.List gap={separatorGap}>
|
||||
{validChildren.map((child, index) => {
|
||||
const last = index === validChildren.length - 1
|
||||
return (
|
||||
<React.Fragment key={index}>
|
||||
<Breadcrumb.Item>{child}</Breadcrumb.Item>
|
||||
{!last && (
|
||||
<Breadcrumb.Separator>{separator}</Breadcrumb.Separator>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
})}
|
||||
</Breadcrumb.List>
|
||||
</Breadcrumb.Root>
|
||||
)
|
||||
})
|
||||
|
||||
export const BreadcrumbLink = Breadcrumb.Link
|
||||
export const BreadcrumbCurrentLink = Breadcrumb.CurrentLink
|
||||
export const BreadcrumbEllipsis = Breadcrumb.Ellipsis
|
||||
@@ -1,40 +0,0 @@
|
||||
import type { ButtonProps as ChakraButtonProps } from "@chakra-ui/react"
|
||||
import {
|
||||
AbsoluteCenter,
|
||||
Button as ChakraButton,
|
||||
Span,
|
||||
Spinner,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
interface ButtonLoadingProps {
|
||||
loading?: boolean
|
||||
loadingText?: React.ReactNode
|
||||
}
|
||||
|
||||
export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {}
|
||||
|
||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
function Button(props, ref) {
|
||||
const { loading, disabled, loadingText, children, ...rest } = props
|
||||
return (
|
||||
<ChakraButton disabled={loading || disabled} ref={ref} {...rest}>
|
||||
{loading && !loadingText ? (
|
||||
<>
|
||||
<AbsoluteCenter display="inline-flex">
|
||||
<Spinner size="inherit" color="inherit" />
|
||||
</AbsoluteCenter>
|
||||
<Span opacity={0}>{children}</Span>
|
||||
</>
|
||||
) : loading && loadingText ? (
|
||||
<>
|
||||
<Spinner size="inherit" color="inherit" />
|
||||
{loadingText}
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</ChakraButton>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,58 +0,0 @@
|
||||
import { CheckboxCard as ChakraCheckboxCard } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface CheckboxCardProps extends ChakraCheckboxCard.RootProps {
|
||||
icon?: React.ReactElement
|
||||
label?: React.ReactNode
|
||||
description?: React.ReactNode
|
||||
addon?: React.ReactNode
|
||||
indicator?: React.ReactNode | null
|
||||
indicatorPlacement?: "start" | "end" | "inside"
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
}
|
||||
|
||||
export const CheckboxCard = React.forwardRef<
|
||||
HTMLInputElement,
|
||||
CheckboxCardProps
|
||||
>(function CheckboxCard(props, ref) {
|
||||
const {
|
||||
inputProps,
|
||||
label,
|
||||
description,
|
||||
icon,
|
||||
addon,
|
||||
indicator = <ChakraCheckboxCard.Indicator />,
|
||||
indicatorPlacement = "end",
|
||||
...rest
|
||||
} = props
|
||||
|
||||
const hasContent = label || description || icon
|
||||
const ContentWrapper = indicator ? ChakraCheckboxCard.Content : React.Fragment
|
||||
|
||||
return (
|
||||
<ChakraCheckboxCard.Root {...rest}>
|
||||
<ChakraCheckboxCard.HiddenInput ref={ref} {...inputProps} />
|
||||
<ChakraCheckboxCard.Control>
|
||||
{indicatorPlacement === "start" && indicator}
|
||||
{hasContent && (
|
||||
<ContentWrapper>
|
||||
{icon}
|
||||
{label && (
|
||||
<ChakraCheckboxCard.Label>{label}</ChakraCheckboxCard.Label>
|
||||
)}
|
||||
{description && (
|
||||
<ChakraCheckboxCard.Description>
|
||||
{description}
|
||||
</ChakraCheckboxCard.Description>
|
||||
)}
|
||||
{indicatorPlacement === "inside" && indicator}
|
||||
</ContentWrapper>
|
||||
)}
|
||||
{indicatorPlacement === "end" && indicator}
|
||||
</ChakraCheckboxCard.Control>
|
||||
{addon && <ChakraCheckboxCard.Addon>{addon}</ChakraCheckboxCard.Addon>}
|
||||
</ChakraCheckboxCard.Root>
|
||||
)
|
||||
})
|
||||
|
||||
export const CheckboxCardIndicator = ChakraCheckboxCard.Indicator
|
||||
@@ -1,25 +0,0 @@
|
||||
import { Checkbox as ChakraCheckbox } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface CheckboxProps extends ChakraCheckbox.RootProps {
|
||||
icon?: React.ReactNode
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
rootRef?: React.Ref<HTMLLabelElement>
|
||||
}
|
||||
|
||||
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
function Checkbox(props, ref) {
|
||||
const { icon, children, inputProps, rootRef, ...rest } = props
|
||||
return (
|
||||
<ChakraCheckbox.Root ref={rootRef} {...rest}>
|
||||
<ChakraCheckbox.HiddenInput ref={ref} {...inputProps} />
|
||||
<ChakraCheckbox.Control>
|
||||
{icon || <ChakraCheckbox.Indicator />}
|
||||
</ChakraCheckbox.Control>
|
||||
{children != null && (
|
||||
<ChakraCheckbox.Label>{children}</ChakraCheckbox.Label>
|
||||
)}
|
||||
</ChakraCheckbox.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,108 +0,0 @@
|
||||
import type { ButtonProps, InputProps } from "@chakra-ui/react"
|
||||
import {
|
||||
Button,
|
||||
Clipboard as ChakraClipboard,
|
||||
IconButton,
|
||||
Input,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuCheck, LuClipboard, LuLink } from "react-icons/lu"
|
||||
|
||||
const ClipboardIcon = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraClipboard.IndicatorProps
|
||||
>(function ClipboardIcon(props, ref) {
|
||||
return (
|
||||
<ChakraClipboard.Indicator copied={<LuCheck />} {...props} ref={ref}>
|
||||
<LuClipboard />
|
||||
</ChakraClipboard.Indicator>
|
||||
)
|
||||
})
|
||||
|
||||
const ClipboardCopyText = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraClipboard.IndicatorProps
|
||||
>(function ClipboardCopyText(props, ref) {
|
||||
return (
|
||||
<ChakraClipboard.Indicator copied="Copied" {...props} ref={ref}>
|
||||
Copy
|
||||
</ChakraClipboard.Indicator>
|
||||
)
|
||||
})
|
||||
|
||||
export const ClipboardLabel = React.forwardRef<
|
||||
HTMLLabelElement,
|
||||
ChakraClipboard.LabelProps
|
||||
>(function ClipboardLabel(props, ref) {
|
||||
return (
|
||||
<ChakraClipboard.Label
|
||||
textStyle="sm"
|
||||
fontWeight="medium"
|
||||
display="inline-block"
|
||||
mb="1"
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
export const ClipboardButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
function ClipboardButton(props, ref) {
|
||||
return (
|
||||
<ChakraClipboard.Trigger asChild>
|
||||
<Button ref={ref} size="sm" variant="surface" {...props}>
|
||||
<ClipboardIcon />
|
||||
<ClipboardCopyText />
|
||||
</Button>
|
||||
</ChakraClipboard.Trigger>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export const ClipboardLink = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
function ClipboardLink(props, ref) {
|
||||
return (
|
||||
<ChakraClipboard.Trigger asChild>
|
||||
<Button
|
||||
unstyled
|
||||
variant="plain"
|
||||
size="xs"
|
||||
display="inline-flex"
|
||||
alignItems="center"
|
||||
gap="2"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<LuLink />
|
||||
<ClipboardCopyText />
|
||||
</Button>
|
||||
</ChakraClipboard.Trigger>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export const ClipboardIconButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ButtonProps
|
||||
>(function ClipboardIconButton(props, ref) {
|
||||
return (
|
||||
<ChakraClipboard.Trigger asChild>
|
||||
<IconButton ref={ref} size="xs" variant="subtle" {...props}>
|
||||
<ClipboardIcon />
|
||||
<ClipboardCopyText srOnly />
|
||||
</IconButton>
|
||||
</ChakraClipboard.Trigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const ClipboardInput = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
function ClipboardInputElement(props, ref) {
|
||||
return (
|
||||
<ChakraClipboard.Input asChild>
|
||||
<Input ref={ref} {...props} />
|
||||
</ChakraClipboard.Input>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export const ClipboardRoot = ChakraClipboard.Root
|
||||
@@ -1,17 +0,0 @@
|
||||
import type { ButtonProps as ChakraCloseButtonProps } from "@chakra-ui/react"
|
||||
import { IconButton as ChakraIconButton } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuX } from "react-icons/lu"
|
||||
|
||||
export interface CloseButtonProps extends ChakraCloseButtonProps {}
|
||||
|
||||
export const CloseButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
CloseButtonProps
|
||||
>(function CloseButton(props, ref) {
|
||||
return (
|
||||
<ChakraIconButton variant="ghost" aria-label="Close" ref={ref} {...props}>
|
||||
{props.children ?? <LuX />}
|
||||
</ChakraIconButton>
|
||||
)
|
||||
})
|
||||
@@ -1,67 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import type { IconButtonProps } from "@chakra-ui/react"
|
||||
import { ClientOnly, IconButton, Skeleton } from "@chakra-ui/react"
|
||||
import { ThemeProvider, useTheme } from "next-themes"
|
||||
import type { ThemeProviderProps } from "next-themes"
|
||||
import * as React from "react"
|
||||
import { LuMoon, LuSun } from "react-icons/lu"
|
||||
|
||||
export interface ColorModeProviderProps extends ThemeProviderProps {}
|
||||
|
||||
export function ColorModeProvider(props: ColorModeProviderProps) {
|
||||
return (
|
||||
<ThemeProvider attribute="class" disableTransitionOnChange {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
export function useColorMode() {
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
const toggleColorMode = () => {
|
||||
setTheme(resolvedTheme === "light" ? "dark" : "light")
|
||||
}
|
||||
return {
|
||||
colorMode: resolvedTheme,
|
||||
setColorMode: setTheme,
|
||||
toggleColorMode,
|
||||
}
|
||||
}
|
||||
|
||||
export function useColorModeValue<T>(light: T, dark: T) {
|
||||
const { colorMode } = useColorMode()
|
||||
return colorMode === "light" ? light : dark
|
||||
}
|
||||
|
||||
export function ColorModeIcon() {
|
||||
const { colorMode } = useColorMode()
|
||||
return colorMode === "light" ? <LuSun /> : <LuMoon />
|
||||
}
|
||||
|
||||
interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}
|
||||
|
||||
export const ColorModeButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ColorModeButtonProps
|
||||
>(function ColorModeButton(props, ref) {
|
||||
const { toggleColorMode } = useColorMode()
|
||||
return (
|
||||
<ClientOnly fallback={<Skeleton boxSize="8" />}>
|
||||
<IconButton
|
||||
onClick={toggleColorMode}
|
||||
variant="ghost"
|
||||
aria-label="Toggle color mode"
|
||||
size="sm"
|
||||
ref={ref}
|
||||
{...props}
|
||||
css={{
|
||||
_icon: {
|
||||
width: "5",
|
||||
height: "5",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ColorModeIcon />
|
||||
</IconButton>
|
||||
</ClientOnly>
|
||||
)
|
||||
})
|
||||
@@ -1,30 +0,0 @@
|
||||
import { DataList as ChakraDataList } from "@chakra-ui/react"
|
||||
import { InfoTip } from "./toggle-tip"
|
||||
import * as React from "react"
|
||||
|
||||
export const DataListRoot = ChakraDataList.Root
|
||||
|
||||
interface ItemProps extends ChakraDataList.ItemProps {
|
||||
label: React.ReactNode
|
||||
value: React.ReactNode
|
||||
info?: React.ReactNode
|
||||
grow?: boolean
|
||||
}
|
||||
|
||||
export const DataListItem = React.forwardRef<HTMLDivElement, ItemProps>(
|
||||
function DataListItem(props, ref) {
|
||||
const { label, info, value, children, grow, ...rest } = props
|
||||
return (
|
||||
<ChakraDataList.Item ref={ref} {...rest}>
|
||||
<ChakraDataList.ItemLabel flex={grow ? "1" : undefined}>
|
||||
{label}
|
||||
{info && <InfoTip>{info}</InfoTip>}
|
||||
</ChakraDataList.ItemLabel>
|
||||
<ChakraDataList.ItemValue flex={grow ? "1" : undefined}>
|
||||
{value}
|
||||
</ChakraDataList.ItemValue>
|
||||
{children}
|
||||
</ChakraDataList.Item>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,62 +0,0 @@
|
||||
import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
|
||||
interface DialogContentProps extends ChakraDialog.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
backdrop?: boolean
|
||||
}
|
||||
|
||||
export const DialogContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
DialogContentProps
|
||||
>(function DialogContent(props, ref) {
|
||||
const {
|
||||
children,
|
||||
portalled = true,
|
||||
portalRef,
|
||||
backdrop = true,
|
||||
...rest
|
||||
} = props
|
||||
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
{backdrop && <ChakraDialog.Backdrop />}
|
||||
<ChakraDialog.Positioner>
|
||||
<ChakraDialog.Content ref={ref} {...rest} asChild={false}>
|
||||
{children}
|
||||
</ChakraDialog.Content>
|
||||
</ChakraDialog.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
|
||||
export const DialogCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraDialog.CloseTriggerProps
|
||||
>(function DialogCloseTrigger(props, ref) {
|
||||
return (
|
||||
<ChakraDialog.CloseTrigger
|
||||
position="absolute"
|
||||
top="2"
|
||||
insetEnd="2"
|
||||
{...props}
|
||||
asChild
|
||||
>
|
||||
<CloseButton size="sm" ref={ref}>
|
||||
{props.children}
|
||||
</CloseButton>
|
||||
</ChakraDialog.CloseTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const DialogRoot = ChakraDialog.Root
|
||||
export const DialogFooter = ChakraDialog.Footer
|
||||
export const DialogHeader = ChakraDialog.Header
|
||||
export const DialogBody = ChakraDialog.Body
|
||||
export const DialogBackdrop = ChakraDialog.Backdrop
|
||||
export const DialogTitle = ChakraDialog.Title
|
||||
export const DialogDescription = ChakraDialog.Description
|
||||
export const DialogTrigger = ChakraDialog.Trigger
|
||||
export const DialogActionTrigger = ChakraDialog.ActionTrigger
|
||||
@@ -1,52 +0,0 @@
|
||||
import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
|
||||
interface DrawerContentProps extends ChakraDrawer.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
offset?: ChakraDrawer.ContentProps["padding"]
|
||||
}
|
||||
|
||||
export const DrawerContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
DrawerContentProps
|
||||
>(function DrawerContent(props, ref) {
|
||||
const { children, portalled = true, portalRef, offset, ...rest } = props
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraDrawer.Positioner padding={offset}>
|
||||
<ChakraDrawer.Content ref={ref} {...rest} asChild={false}>
|
||||
{children}
|
||||
</ChakraDrawer.Content>
|
||||
</ChakraDrawer.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
|
||||
export const DrawerCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraDrawer.CloseTriggerProps
|
||||
>(function DrawerCloseTrigger(props, ref) {
|
||||
return (
|
||||
<ChakraDrawer.CloseTrigger
|
||||
position="absolute"
|
||||
top="2"
|
||||
insetEnd="2"
|
||||
{...props}
|
||||
asChild
|
||||
>
|
||||
<CloseButton size="sm" ref={ref} />
|
||||
</ChakraDrawer.CloseTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const DrawerTrigger = ChakraDrawer.Trigger
|
||||
export const DrawerRoot = ChakraDrawer.Root
|
||||
export const DrawerFooter = ChakraDrawer.Footer
|
||||
export const DrawerHeader = ChakraDrawer.Header
|
||||
export const DrawerBody = ChakraDrawer.Body
|
||||
export const DrawerBackdrop = ChakraDrawer.Backdrop
|
||||
export const DrawerDescription = ChakraDrawer.Description
|
||||
export const DrawerTitle = ChakraDrawer.Title
|
||||
export const DrawerActionTrigger = ChakraDrawer.ActionTrigger
|
||||
@@ -1,34 +0,0 @@
|
||||
import { EmptyState as ChakraEmptyState, VStack } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface EmptyStateProps extends ChakraEmptyState.RootProps {
|
||||
title: string
|
||||
description?: string
|
||||
icon?: React.ReactNode
|
||||
}
|
||||
|
||||
export const EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(
|
||||
function EmptyState(props, ref) {
|
||||
const { title, description, icon, children, ...rest } = props
|
||||
return (
|
||||
<ChakraEmptyState.Root ref={ref} {...rest}>
|
||||
<ChakraEmptyState.Content>
|
||||
{icon && (
|
||||
<ChakraEmptyState.Indicator>{icon}</ChakraEmptyState.Indicator>
|
||||
)}
|
||||
{description ? (
|
||||
<VStack textAlign="center">
|
||||
<ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
|
||||
<ChakraEmptyState.Description>
|
||||
{description}
|
||||
</ChakraEmptyState.Description>
|
||||
</VStack>
|
||||
) : (
|
||||
<ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
|
||||
)}
|
||||
{children}
|
||||
</ChakraEmptyState.Content>
|
||||
</ChakraEmptyState.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,33 +0,0 @@
|
||||
import { Field as ChakraField } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface FieldProps extends Omit<ChakraField.RootProps, "label"> {
|
||||
label?: React.ReactNode
|
||||
helperText?: React.ReactNode
|
||||
errorText?: React.ReactNode
|
||||
optionalText?: React.ReactNode
|
||||
}
|
||||
|
||||
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
||||
function Field(props, ref) {
|
||||
const { label, children, helperText, errorText, optionalText, ...rest } =
|
||||
props
|
||||
return (
|
||||
<ChakraField.Root ref={ref} {...rest}>
|
||||
{label && (
|
||||
<ChakraField.Label>
|
||||
{label}
|
||||
<ChakraField.RequiredIndicator fallback={optionalText} />
|
||||
</ChakraField.Label>
|
||||
)}
|
||||
{children}
|
||||
{helperText && (
|
||||
<ChakraField.HelperText>{helperText}</ChakraField.HelperText>
|
||||
)}
|
||||
{errorText && (
|
||||
<ChakraField.ErrorText>{errorText}</ChakraField.ErrorText>
|
||||
)}
|
||||
</ChakraField.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,170 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import type { ButtonProps, RecipeProps } from "@chakra-ui/react"
|
||||
import {
|
||||
Button,
|
||||
FileUpload as ChakraFileUpload,
|
||||
Icon,
|
||||
IconButton,
|
||||
Span,
|
||||
Text,
|
||||
useFileUploadContext,
|
||||
useRecipe,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuFile, LuUpload, LuX } from "react-icons/lu"
|
||||
|
||||
export interface FileUploadRootProps extends ChakraFileUpload.RootProps {
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
}
|
||||
|
||||
export const FileUploadRoot = React.forwardRef<
|
||||
HTMLInputElement,
|
||||
FileUploadRootProps
|
||||
>(function FileUploadRoot(props, ref) {
|
||||
const { children, inputProps, ...rest } = props
|
||||
return (
|
||||
<ChakraFileUpload.Root {...rest}>
|
||||
<ChakraFileUpload.HiddenInput ref={ref} {...inputProps} />
|
||||
{children}
|
||||
</ChakraFileUpload.Root>
|
||||
)
|
||||
})
|
||||
|
||||
export interface FileUploadDropzoneProps
|
||||
extends ChakraFileUpload.DropzoneProps {
|
||||
label: React.ReactNode
|
||||
description?: React.ReactNode
|
||||
}
|
||||
|
||||
export const FileUploadDropzone = React.forwardRef<
|
||||
HTMLInputElement,
|
||||
FileUploadDropzoneProps
|
||||
>(function FileUploadDropzone(props, ref) {
|
||||
const { children, label, description, ...rest } = props
|
||||
return (
|
||||
<ChakraFileUpload.Dropzone ref={ref} {...rest}>
|
||||
<Icon fontSize="xl" color="fg.muted">
|
||||
<LuUpload />
|
||||
</Icon>
|
||||
<ChakraFileUpload.DropzoneContent>
|
||||
<div>{label}</div>
|
||||
{description && <Text color="fg.muted">{description}</Text>}
|
||||
</ChakraFileUpload.DropzoneContent>
|
||||
{children}
|
||||
</ChakraFileUpload.Dropzone>
|
||||
)
|
||||
})
|
||||
|
||||
interface VisibilityProps {
|
||||
showSize?: boolean
|
||||
clearable?: boolean
|
||||
}
|
||||
|
||||
interface FileUploadItemProps extends VisibilityProps {
|
||||
file: File
|
||||
}
|
||||
|
||||
const FileUploadItem = React.forwardRef<HTMLLIElement, FileUploadItemProps>(
|
||||
function FileUploadItem(props, ref) {
|
||||
const { file, showSize, clearable } = props
|
||||
return (
|
||||
<ChakraFileUpload.Item file={file} ref={ref}>
|
||||
<ChakraFileUpload.ItemPreview asChild>
|
||||
<Icon fontSize="lg" color="fg.muted">
|
||||
<LuFile />
|
||||
</Icon>
|
||||
</ChakraFileUpload.ItemPreview>
|
||||
|
||||
{showSize ? (
|
||||
<ChakraFileUpload.ItemContent>
|
||||
<ChakraFileUpload.ItemName />
|
||||
<ChakraFileUpload.ItemSizeText />
|
||||
</ChakraFileUpload.ItemContent>
|
||||
) : (
|
||||
<ChakraFileUpload.ItemName flex="1" />
|
||||
)}
|
||||
|
||||
{clearable && (
|
||||
<ChakraFileUpload.ItemDeleteTrigger asChild>
|
||||
<IconButton variant="ghost" color="fg.muted" size="xs">
|
||||
<LuX />
|
||||
</IconButton>
|
||||
</ChakraFileUpload.ItemDeleteTrigger>
|
||||
)}
|
||||
</ChakraFileUpload.Item>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
interface FileUploadListProps
|
||||
extends VisibilityProps,
|
||||
ChakraFileUpload.ItemGroupProps {
|
||||
files?: File[]
|
||||
}
|
||||
|
||||
export const FileUploadList = React.forwardRef<
|
||||
HTMLUListElement,
|
||||
FileUploadListProps
|
||||
>(function FileUploadList(props, ref) {
|
||||
const { showSize, clearable, files, ...rest } = props
|
||||
|
||||
const fileUpload = useFileUploadContext()
|
||||
const acceptedFiles = files ?? fileUpload.acceptedFiles
|
||||
|
||||
if (acceptedFiles.length === 0) return null
|
||||
|
||||
return (
|
||||
<ChakraFileUpload.ItemGroup ref={ref} {...rest}>
|
||||
{acceptedFiles.map((file) => (
|
||||
<FileUploadItem
|
||||
key={file.name}
|
||||
file={file}
|
||||
showSize={showSize}
|
||||
clearable={clearable}
|
||||
/>
|
||||
))}
|
||||
</ChakraFileUpload.ItemGroup>
|
||||
)
|
||||
})
|
||||
|
||||
type Assign<T, U> = Omit<T, keyof U> & U
|
||||
|
||||
interface FileInputProps extends Assign<ButtonProps, RecipeProps<"input">> {
|
||||
placeholder?: React.ReactNode
|
||||
}
|
||||
|
||||
export const FileInput = React.forwardRef<HTMLButtonElement, FileInputProps>(
|
||||
function FileInput(props, ref) {
|
||||
const inputRecipe = useRecipe({ key: "input" })
|
||||
const [recipeProps, restProps] = inputRecipe.splitVariantProps(props)
|
||||
const { placeholder = "Select file(s)", ...rest } = restProps
|
||||
return (
|
||||
<ChakraFileUpload.Trigger asChild>
|
||||
<Button
|
||||
unstyled
|
||||
py="0"
|
||||
ref={ref}
|
||||
{...rest}
|
||||
css={[inputRecipe(recipeProps), props.css]}
|
||||
>
|
||||
<ChakraFileUpload.Context>
|
||||
{({ acceptedFiles }) => {
|
||||
if (acceptedFiles.length === 1) {
|
||||
return <span>{acceptedFiles[0].name}</span>
|
||||
}
|
||||
if (acceptedFiles.length > 1) {
|
||||
return <span>{acceptedFiles.length} files</span>
|
||||
}
|
||||
return <Span color="fg.subtle">{placeholder}</Span>
|
||||
}}
|
||||
</ChakraFileUpload.Context>
|
||||
</Button>
|
||||
</ChakraFileUpload.Trigger>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export const FileUploadLabel = ChakraFileUpload.Label
|
||||
export const FileUploadClearTrigger = ChakraFileUpload.ClearTrigger
|
||||
export const FileUploadTrigger = ChakraFileUpload.Trigger
|
||||
@@ -1,36 +0,0 @@
|
||||
import { HoverCard, Portal } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
interface HoverCardContentProps extends HoverCard.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
}
|
||||
|
||||
export const HoverCardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
HoverCardContentProps
|
||||
>(function HoverCardContent(props, ref) {
|
||||
const { portalled = true, portalRef, ...rest } = props
|
||||
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<HoverCard.Positioner>
|
||||
<HoverCard.Content ref={ref} {...rest} />
|
||||
</HoverCard.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
|
||||
export const HoverCardArrow = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
HoverCard.ArrowProps
|
||||
>(function HoverCardArrow(props, ref) {
|
||||
return (
|
||||
<HoverCard.Arrow ref={ref} {...props}>
|
||||
<HoverCard.ArrowTip />
|
||||
</HoverCard.Arrow>
|
||||
)
|
||||
})
|
||||
|
||||
export const HoverCardRoot = HoverCard.Root
|
||||
export const HoverCardTrigger = HoverCard.Trigger
|
||||
@@ -1,50 +0,0 @@
|
||||
import type { BoxProps, InputElementProps } from "@chakra-ui/react"
|
||||
import { Group, InputElement } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface InputGroupProps extends BoxProps {
|
||||
startElementProps?: InputElementProps
|
||||
endElementProps?: InputElementProps
|
||||
startElement?: React.ReactNode
|
||||
endElement?: React.ReactNode
|
||||
children: React.ReactElement
|
||||
startOffset?: InputElementProps["paddingStart"]
|
||||
endOffset?: InputElementProps["paddingEnd"]
|
||||
}
|
||||
|
||||
export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
||||
function InputGroup(props, ref) {
|
||||
const {
|
||||
startElement,
|
||||
startElementProps,
|
||||
endElement,
|
||||
endElementProps,
|
||||
children,
|
||||
startOffset = "6px",
|
||||
endOffset = "6px",
|
||||
...rest
|
||||
} = props
|
||||
|
||||
return (
|
||||
<Group ref={ref} {...rest}>
|
||||
{startElement && (
|
||||
<InputElement pointerEvents="none" {...startElementProps}>
|
||||
{startElement}
|
||||
</InputElement>
|
||||
)}
|
||||
{React.cloneElement(children, {
|
||||
...(startElement && {
|
||||
ps: `calc(var(--input-height) - ${startOffset})`,
|
||||
}),
|
||||
...(endElement && { pe: `calc(var(--input-height) - ${endOffset})` }),
|
||||
...children.props,
|
||||
})}
|
||||
{endElement && (
|
||||
<InputElement placement="end" {...endElementProps}>
|
||||
{endElement}
|
||||
</InputElement>
|
||||
)}
|
||||
</Group>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,12 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import type { HTMLChakraProps, RecipeProps } from "@chakra-ui/react"
|
||||
import { createRecipeContext } from "@chakra-ui/react"
|
||||
|
||||
export interface LinkButtonProps
|
||||
extends HTMLChakraProps<"a", RecipeProps<"button">> {}
|
||||
|
||||
const { withContext } = createRecipeContext({ key: "button" })
|
||||
|
||||
// Replace "a" with your framework's link component
|
||||
export const LinkButton = withContext<HTMLAnchorElement, LinkButtonProps>("a")
|
||||
@@ -1,110 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { AbsoluteCenter, Menu as ChakraMenu, Portal } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuCheck, LuChevronRight } from "react-icons/lu"
|
||||
|
||||
interface MenuContentProps extends ChakraMenu.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
}
|
||||
|
||||
export const MenuContent = React.forwardRef<HTMLDivElement, MenuContentProps>(
|
||||
function MenuContent(props, ref) {
|
||||
const { portalled = true, portalRef, ...rest } = props
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraMenu.Positioner>
|
||||
<ChakraMenu.Content ref={ref} {...rest} />
|
||||
</ChakraMenu.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export const MenuArrow = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraMenu.ArrowProps
|
||||
>(function MenuArrow(props, ref) {
|
||||
return (
|
||||
<ChakraMenu.Arrow ref={ref} {...props}>
|
||||
<ChakraMenu.ArrowTip />
|
||||
</ChakraMenu.Arrow>
|
||||
)
|
||||
})
|
||||
|
||||
export const MenuCheckboxItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraMenu.CheckboxItemProps
|
||||
>(function MenuCheckboxItem(props, ref) {
|
||||
return (
|
||||
<ChakraMenu.CheckboxItem ref={ref} {...props}>
|
||||
<ChakraMenu.ItemIndicator hidden={false}>
|
||||
<LuCheck />
|
||||
</ChakraMenu.ItemIndicator>
|
||||
{props.children}
|
||||
</ChakraMenu.CheckboxItem>
|
||||
)
|
||||
})
|
||||
|
||||
export const MenuRadioItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraMenu.RadioItemProps
|
||||
>(function MenuRadioItem(props, ref) {
|
||||
const { children, ...rest } = props
|
||||
return (
|
||||
<ChakraMenu.RadioItem ps="8" ref={ref} {...rest}>
|
||||
<AbsoluteCenter axis="horizontal" left="4" asChild>
|
||||
<ChakraMenu.ItemIndicator>
|
||||
<LuCheck />
|
||||
</ChakraMenu.ItemIndicator>
|
||||
</AbsoluteCenter>
|
||||
<ChakraMenu.ItemText>{children}</ChakraMenu.ItemText>
|
||||
</ChakraMenu.RadioItem>
|
||||
)
|
||||
})
|
||||
|
||||
export const MenuItemGroup = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraMenu.ItemGroupProps
|
||||
>(function MenuItemGroup(props, ref) {
|
||||
const { title, children, ...rest } = props
|
||||
return (
|
||||
<ChakraMenu.ItemGroup ref={ref} {...rest}>
|
||||
{title && (
|
||||
<ChakraMenu.ItemGroupLabel userSelect="none">
|
||||
{title}
|
||||
</ChakraMenu.ItemGroupLabel>
|
||||
)}
|
||||
{children}
|
||||
</ChakraMenu.ItemGroup>
|
||||
)
|
||||
})
|
||||
|
||||
export interface MenuTriggerItemProps extends ChakraMenu.ItemProps {
|
||||
startIcon?: React.ReactNode
|
||||
}
|
||||
|
||||
export const MenuTriggerItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuTriggerItemProps
|
||||
>(function MenuTriggerItem(props, ref) {
|
||||
const { startIcon, children, ...rest } = props
|
||||
return (
|
||||
<ChakraMenu.TriggerItem ref={ref} {...rest}>
|
||||
{startIcon}
|
||||
{children}
|
||||
<LuChevronRight />
|
||||
</ChakraMenu.TriggerItem>
|
||||
)
|
||||
})
|
||||
|
||||
export const MenuRadioItemGroup = ChakraMenu.RadioItemGroup
|
||||
export const MenuContextTrigger = ChakraMenu.ContextTrigger
|
||||
export const MenuRoot = ChakraMenu.Root
|
||||
export const MenuSeparator = ChakraMenu.Separator
|
||||
|
||||
export const MenuItem = ChakraMenu.Item
|
||||
export const MenuItemText = ChakraMenu.ItemText
|
||||
export const MenuItemCommand = ChakraMenu.ItemCommand
|
||||
export const MenuTrigger = ChakraMenu.Trigger
|
||||
@@ -1,57 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { NativeSelect as Select } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
interface NativeSelectRootProps extends Select.RootProps {
|
||||
icon?: React.ReactNode
|
||||
}
|
||||
|
||||
export const NativeSelectRoot = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
NativeSelectRootProps
|
||||
>(function NativeSelect(props, ref) {
|
||||
const { icon, children, ...rest } = props
|
||||
return (
|
||||
<Select.Root ref={ref} {...rest}>
|
||||
{children}
|
||||
<Select.Indicator>{icon}</Select.Indicator>
|
||||
</Select.Root>
|
||||
)
|
||||
})
|
||||
|
||||
interface NativeSelectItem {
|
||||
value: string
|
||||
label: string
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
interface NativeSelectField extends Select.FieldProps {
|
||||
items?: Array<string | NativeSelectItem>
|
||||
}
|
||||
|
||||
export const NativeSelectField = React.forwardRef<
|
||||
HTMLSelectElement,
|
||||
NativeSelectField
|
||||
>(function NativeSelectField(props, ref) {
|
||||
const { items: itemsProp, children, ...rest } = props
|
||||
|
||||
const items = React.useMemo(
|
||||
() =>
|
||||
itemsProp?.map((item) =>
|
||||
typeof item === "string" ? { label: item, value: item } : item,
|
||||
),
|
||||
[itemsProp],
|
||||
)
|
||||
|
||||
return (
|
||||
<Select.Field ref={ref} {...rest}>
|
||||
{children}
|
||||
{items?.map((item) => (
|
||||
<option key={item.value} value={item.value} disabled={item.disabled}>
|
||||
{item.label}
|
||||
</option>
|
||||
))}
|
||||
</Select.Field>
|
||||
)
|
||||
})
|
||||
@@ -1,24 +0,0 @@
|
||||
import { NumberInput as ChakraNumberInput } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface NumberInputProps extends ChakraNumberInput.RootProps {}
|
||||
|
||||
export const NumberInputRoot = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
NumberInputProps
|
||||
>(function NumberInput(props, ref) {
|
||||
const { children, ...rest } = props
|
||||
return (
|
||||
<ChakraNumberInput.Root ref={ref} variant="outline" {...rest}>
|
||||
{children}
|
||||
<ChakraNumberInput.Control>
|
||||
<ChakraNumberInput.IncrementTrigger />
|
||||
<ChakraNumberInput.DecrementTrigger />
|
||||
</ChakraNumberInput.Control>
|
||||
</ChakraNumberInput.Root>
|
||||
)
|
||||
})
|
||||
|
||||
export const NumberInputField = ChakraNumberInput.Input
|
||||
export const NumberInputScruber = ChakraNumberInput.Scrubber
|
||||
export const NumberInputLabel = ChakraNumberInput.Label
|
||||
@@ -1,208 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import type { ButtonProps, TextProps } from "@chakra-ui/react"
|
||||
import {
|
||||
Button,
|
||||
Pagination as ChakraPagination,
|
||||
IconButton,
|
||||
Text,
|
||||
createContext,
|
||||
usePaginationContext,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import {
|
||||
HiChevronLeft,
|
||||
HiChevronRight,
|
||||
HiMiniEllipsisHorizontal,
|
||||
} from "react-icons/hi2"
|
||||
import { LinkButton } from "./link-button"
|
||||
|
||||
interface ButtonVariantMap {
|
||||
current: ButtonProps["variant"]
|
||||
default: ButtonProps["variant"]
|
||||
ellipsis: ButtonProps["variant"]
|
||||
}
|
||||
|
||||
type PaginationVariant = "outline" | "solid" | "subtle"
|
||||
|
||||
interface ButtonVariantContext {
|
||||
size: ButtonProps["size"]
|
||||
variantMap: ButtonVariantMap
|
||||
getHref?: (page: number) => string
|
||||
}
|
||||
|
||||
const [RootPropsProvider, useRootProps] = createContext<ButtonVariantContext>({
|
||||
name: "RootPropsProvider",
|
||||
})
|
||||
|
||||
export interface PaginationRootProps
|
||||
extends Omit<ChakraPagination.RootProps, "type"> {
|
||||
size?: ButtonProps["size"]
|
||||
variant?: PaginationVariant
|
||||
getHref?: (page: number) => string
|
||||
}
|
||||
|
||||
const variantMap: Record<PaginationVariant, ButtonVariantMap> = {
|
||||
outline: { default: "ghost", ellipsis: "plain", current: "outline" },
|
||||
solid: { default: "outline", ellipsis: "outline", current: "solid" },
|
||||
subtle: { default: "ghost", ellipsis: "plain", current: "subtle" },
|
||||
}
|
||||
|
||||
export const PaginationRoot = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
PaginationRootProps
|
||||
>(function PaginationRoot(props, ref) {
|
||||
const { size = "sm", variant = "outline", getHref, ...rest } = props
|
||||
return (
|
||||
<RootPropsProvider
|
||||
value={{ size, variantMap: variantMap[variant], getHref }}
|
||||
>
|
||||
<ChakraPagination.Root
|
||||
ref={ref}
|
||||
type={getHref ? "link" : "button"}
|
||||
{...rest}
|
||||
/>
|
||||
</RootPropsProvider>
|
||||
)
|
||||
})
|
||||
|
||||
export const PaginationEllipsis = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraPagination.EllipsisProps
|
||||
>(function PaginationEllipsis(props, ref) {
|
||||
const { size, variantMap } = useRootProps()
|
||||
return (
|
||||
<ChakraPagination.Ellipsis ref={ref} {...props} asChild>
|
||||
<Button as="span" variant={variantMap.ellipsis} size={size}>
|
||||
<HiMiniEllipsisHorizontal />
|
||||
</Button>
|
||||
</ChakraPagination.Ellipsis>
|
||||
)
|
||||
})
|
||||
|
||||
export const PaginationItem = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraPagination.ItemProps
|
||||
>(function PaginationItem(props, ref) {
|
||||
const { page } = usePaginationContext()
|
||||
const { size, variantMap, getHref } = useRootProps()
|
||||
|
||||
const current = page === props.value
|
||||
const variant = current ? variantMap.current : variantMap.default
|
||||
|
||||
if (getHref) {
|
||||
return (
|
||||
<LinkButton href={getHref(props.value)} variant={variant} size={size}>
|
||||
{props.value}
|
||||
</LinkButton>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ChakraPagination.Item ref={ref} {...props} asChild>
|
||||
<Button variant={variant} size={size}>
|
||||
{props.value}
|
||||
</Button>
|
||||
</ChakraPagination.Item>
|
||||
)
|
||||
})
|
||||
|
||||
export const PaginationPrevTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraPagination.PrevTriggerProps
|
||||
>(function PaginationPrevTrigger(props, ref) {
|
||||
const { size, variantMap, getHref } = useRootProps()
|
||||
const { previousPage } = usePaginationContext()
|
||||
|
||||
if (getHref) {
|
||||
return (
|
||||
<LinkButton
|
||||
href={previousPage != null ? getHref(previousPage) : undefined}
|
||||
variant={variantMap.default}
|
||||
size={size}
|
||||
>
|
||||
<HiChevronLeft />
|
||||
</LinkButton>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ChakraPagination.PrevTrigger ref={ref} asChild {...props}>
|
||||
<IconButton variant={variantMap.default} size={size}>
|
||||
<HiChevronLeft />
|
||||
</IconButton>
|
||||
</ChakraPagination.PrevTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const PaginationNextTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraPagination.NextTriggerProps
|
||||
>(function PaginationNextTrigger(props, ref) {
|
||||
const { size, variantMap, getHref } = useRootProps()
|
||||
const { nextPage } = usePaginationContext()
|
||||
|
||||
if (getHref) {
|
||||
return (
|
||||
<LinkButton
|
||||
href={nextPage != null ? getHref(nextPage) : undefined}
|
||||
variant={variantMap.default}
|
||||
size={size}
|
||||
>
|
||||
<HiChevronRight />
|
||||
</LinkButton>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ChakraPagination.NextTrigger ref={ref} asChild {...props}>
|
||||
<IconButton variant={variantMap.default} size={size}>
|
||||
<HiChevronRight />
|
||||
</IconButton>
|
||||
</ChakraPagination.NextTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const PaginationItems = (props: React.HTMLAttributes<HTMLElement>) => {
|
||||
return (
|
||||
<ChakraPagination.Context>
|
||||
{({ pages }) =>
|
||||
pages.map((page, index) => {
|
||||
return page.type === "ellipsis" ? (
|
||||
<PaginationEllipsis key={index} index={index} {...props} />
|
||||
) : (
|
||||
<PaginationItem
|
||||
key={index}
|
||||
type="page"
|
||||
value={page.value}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</ChakraPagination.Context>
|
||||
)
|
||||
}
|
||||
|
||||
interface PageTextProps extends TextProps {
|
||||
format?: "short" | "compact" | "long"
|
||||
}
|
||||
|
||||
export const PaginationPageText = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
PageTextProps
|
||||
>(function PaginationPageText(props, ref) {
|
||||
const { format = "compact", ...rest } = props
|
||||
const { page, totalPages, pageRange, count } = usePaginationContext()
|
||||
const content = React.useMemo(() => {
|
||||
if (format === "short") return `${page} / ${totalPages}`
|
||||
if (format === "compact") return `${page} of ${totalPages}`
|
||||
return `${pageRange.start + 1} - ${pageRange.end} of ${count}`
|
||||
}, [format, page, totalPages, pageRange, count])
|
||||
|
||||
return (
|
||||
<Text fontWeight="medium" ref={ref} {...rest}>
|
||||
{content}
|
||||
</Text>
|
||||
)
|
||||
})
|
||||
@@ -1,148 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import type {
|
||||
ButtonProps,
|
||||
GroupProps,
|
||||
InputProps,
|
||||
StackProps,
|
||||
} from "@chakra-ui/react"
|
||||
import {
|
||||
Box,
|
||||
HStack,
|
||||
IconButton,
|
||||
Input,
|
||||
Stack,
|
||||
mergeRefs,
|
||||
useControllableState,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuEye, LuEyeOff } from "react-icons/lu"
|
||||
import { InputGroup } from "./input-group"
|
||||
|
||||
export interface PasswordVisibilityProps {
|
||||
defaultVisible?: boolean
|
||||
visible?: boolean
|
||||
onVisibleChange?: (visible: boolean) => void
|
||||
visibilityIcon?: { on: React.ReactNode; off: React.ReactNode }
|
||||
}
|
||||
|
||||
export interface PasswordInputProps
|
||||
extends InputProps,
|
||||
PasswordVisibilityProps {
|
||||
rootProps?: GroupProps
|
||||
}
|
||||
|
||||
export const PasswordInput = React.forwardRef<
|
||||
HTMLInputElement,
|
||||
PasswordInputProps
|
||||
>(function PasswordInput(props, ref) {
|
||||
const {
|
||||
rootProps,
|
||||
defaultVisible,
|
||||
visible: visibleProp,
|
||||
onVisibleChange,
|
||||
visibilityIcon = { on: <LuEye />, off: <LuEyeOff /> },
|
||||
...rest
|
||||
} = props
|
||||
|
||||
const [visible, setVisible] = useControllableState({
|
||||
value: visibleProp,
|
||||
defaultValue: defaultVisible || false,
|
||||
onChange: onVisibleChange,
|
||||
})
|
||||
|
||||
const inputRef = React.useRef<HTMLInputElement>(null)
|
||||
|
||||
return (
|
||||
<InputGroup
|
||||
width="full"
|
||||
endElement={
|
||||
<VisibilityTrigger
|
||||
disabled={rest.disabled}
|
||||
onPointerDown={(e) => {
|
||||
if (rest.disabled) return
|
||||
if (e.button !== 0) return
|
||||
e.preventDefault()
|
||||
setVisible(!visible)
|
||||
}}
|
||||
>
|
||||
{visible ? visibilityIcon.off : visibilityIcon.on}
|
||||
</VisibilityTrigger>
|
||||
}
|
||||
{...rootProps}
|
||||
>
|
||||
<Input
|
||||
{...rest}
|
||||
ref={mergeRefs(ref, inputRef)}
|
||||
type={visible ? "text" : "password"}
|
||||
/>
|
||||
</InputGroup>
|
||||
)
|
||||
})
|
||||
|
||||
const VisibilityTrigger = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
function VisibilityTrigger(props, ref) {
|
||||
return (
|
||||
<IconButton
|
||||
tabIndex={-1}
|
||||
ref={ref}
|
||||
me="-2"
|
||||
aspectRatio="square"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
height="calc(100% - {spacing.2})"
|
||||
aria-label="Toggle password visibility"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
interface PasswordStrengthMeterProps extends StackProps {
|
||||
max?: number
|
||||
value: number
|
||||
}
|
||||
|
||||
export const PasswordStrengthMeter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
PasswordStrengthMeterProps
|
||||
>(function PasswordStrengthMeter(props, ref) {
|
||||
const { max = 4, value, ...rest } = props
|
||||
|
||||
const percent = (value / max) * 100
|
||||
const { label, colorPalette } = getColorPalette(percent)
|
||||
|
||||
return (
|
||||
<Stack align="flex-end" gap="1" ref={ref} {...rest}>
|
||||
<HStack width="full" ref={ref} {...rest}>
|
||||
{Array.from({ length: max }).map((_, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
height="1"
|
||||
flex="1"
|
||||
rounded="sm"
|
||||
data-selected={index < value ? "" : undefined}
|
||||
layerStyle="fill.subtle"
|
||||
colorPalette="gray"
|
||||
_selected={{
|
||||
colorPalette,
|
||||
layerStyle: "fill.solid",
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</HStack>
|
||||
{label && <HStack textStyle="xs">{label}</HStack>}
|
||||
</Stack>
|
||||
)
|
||||
})
|
||||
|
||||
function getColorPalette(percent: number) {
|
||||
switch (true) {
|
||||
case percent < 33:
|
||||
return { label: "Low", colorPalette: "red" }
|
||||
case percent < 66:
|
||||
return { label: "Medium", colorPalette: "orange" }
|
||||
default:
|
||||
return { label: "High", colorPalette: "green" }
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { PinInput as ChakraPinInput, Group } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
export interface PinInputProps extends ChakraPinInput.RootProps {
|
||||
rootRef?: React.Ref<HTMLDivElement>
|
||||
count?: number
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
attached?: boolean
|
||||
}
|
||||
|
||||
export const PinInput = React.forwardRef<HTMLInputElement, PinInputProps>(
|
||||
function PinInput(props, ref) {
|
||||
const { count = 4, inputProps, rootRef, attached, ...rest } = props
|
||||
return (
|
||||
<ChakraPinInput.Root ref={rootRef} {...rest}>
|
||||
<ChakraPinInput.HiddenInput ref={ref} {...inputProps} />
|
||||
<ChakraPinInput.Control>
|
||||
<Group attached={attached}>
|
||||
{Array.from({ length: count }).map((_, index) => (
|
||||
<ChakraPinInput.Input key={index} index={index} />
|
||||
))}
|
||||
</Group>
|
||||
</ChakraPinInput.Control>
|
||||
</ChakraPinInput.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -1,59 +0,0 @@
|
||||
import { Popover as ChakraPopover, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
|
||||
interface PopoverContentProps extends ChakraPopover.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
}
|
||||
|
||||
export const PopoverContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
PopoverContentProps
|
||||
>(function PopoverContent(props, ref) {
|
||||
const { portalled = true, portalRef, ...rest } = props
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraPopover.Positioner>
|
||||
<ChakraPopover.Content ref={ref} {...rest} />
|
||||
</ChakraPopover.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
|
||||
export const PopoverArrow = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraPopover.ArrowProps
|
||||
>(function PopoverArrow(props, ref) {
|
||||
return (
|
||||
<ChakraPopover.Arrow {...props} ref={ref}>
|
||||
<ChakraPopover.ArrowTip />
|
||||
</ChakraPopover.Arrow>
|
||||
)
|
||||
})
|
||||
|
||||
export const PopoverCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ChakraPopover.CloseTriggerProps
|
||||
>(function PopoverCloseTrigger(props, ref) {
|
||||
return (
|
||||
<ChakraPopover.CloseTrigger
|
||||
position="absolute"
|
||||
top="1"
|
||||
insetEnd="1"
|
||||
{...props}
|
||||
asChild
|
||||
ref={ref}
|
||||
>
|
||||
<CloseButton size="sm" />
|
||||
</ChakraPopover.CloseTrigger>
|
||||
)
|
||||
})
|
||||
|
||||
export const PopoverTitle = ChakraPopover.Title
|
||||
export const PopoverDescription = ChakraPopover.Description
|
||||
export const PopoverFooter = ChakraPopover.Footer
|
||||
export const PopoverHeader = ChakraPopover.Header
|
||||
export const PopoverRoot = ChakraPopover.Root
|
||||
export const PopoverBody = ChakraPopover.Body
|
||||
export const PopoverTrigger = ChakraPopover.Trigger
|
||||
@@ -1,37 +0,0 @@
|
||||
import type { SystemStyleObject } from "@chakra-ui/react"
|
||||
import {
|
||||
AbsoluteCenter,
|
||||
ProgressCircle as ChakraProgressCircle,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
|
||||
interface ProgressCircleRingProps extends ChakraProgressCircle.CircleProps {
|
||||
trackColor?: SystemStyleObject["stroke"]
|
||||
cap?: SystemStyleObject["strokeLinecap"]
|
||||
}
|
||||
|
||||
export const ProgressCircleRing = React.forwardRef<
|
||||
SVGSVGElement,
|
||||
ProgressCircleRingProps
|
||||
>(function ProgressCircleRing(props, ref) {
|
||||
const { trackColor, cap, color, ...rest } = props
|
||||
return (
|
||||
<ChakraProgressCircle.Circle {...rest} ref={ref}>
|
||||
<ChakraProgressCircle.Track stroke={trackColor} />
|
||||
<ChakraProgressCircle.Range stroke={color} strokeLinecap={cap} />
|
||||
</ChakraProgressCircle.Circle>
|
||||
)
|
||||
})
|
||||
|
||||
export const ProgressCircleValueText = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraProgressCircle.ValueTextProps
|
||||
>(function ProgressCircleValueText(props, ref) {
|
||||
return (
|
||||
<AbsoluteCenter>
|
||||
<ChakraProgressCircle.ValueText {...props} ref={ref} />
|
||||
</AbsoluteCenter>
|
||||
)
|
||||
})
|
||||
|
||||
export const ProgressCircleRoot = ChakraProgressCircle.Root
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user