Skip to content

Commit 5eb78b8

Browse files
authored
Merge pull request #4 from brionmario/main
chore: move configurations to a `meetup.config`
2 parents 5002c98 + 99e6feb commit 5eb78b8

23 files changed

+338
-263
lines changed

.eslintrc.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* MIT License
33
*
4-
* Copyright (c) 2024, Brion Mario
4+
* Copyright (c) 2024, JavaScript Colombo
55
*
66
* Permission is hereby granted, free of charge, to any person obtaining a copy
77
* of this software and associated documentation files (the "Software"), to deal
@@ -22,11 +22,45 @@
2222
* SOFTWARE.
2323
*/
2424

25+
const LICENSE_HEADER_DEFAULT_PATTERN = [
26+
'*',
27+
' * MIT License',
28+
' *',
29+
{
30+
pattern: ' Copyright \\(c\\) \\d{4}, JavaScript Colombo',
31+
template: ` * Copyright (c) ${new Date().getFullYear()}, JavaScript Colombo`,
32+
},
33+
' *',
34+
' * Permission is hereby granted, free of charge, to any person obtaining a copy',
35+
' * of this software and associated documentation files (the "Software"), to deal',
36+
' * in the Software without restriction, including without limitation the rights',
37+
' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell',
38+
' * copies of the Software, and to permit persons to whom the Software is',
39+
' * furnished to do so, subject to the following conditions:',
40+
' *',
41+
' * The above copyright notice and this permission notice shall be included in all',
42+
' * copies or substantial portions of the Software.',
43+
' *',
44+
' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR',
45+
' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,',
46+
' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE',
47+
' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER',
48+
' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,',
49+
' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE',
50+
' * SOFTWARE.',
51+
' ',
52+
];
53+
2554
module.exports = {
2655
env: {
2756
es6: true,
2857
node: true,
2958
},
3059
extends: ['turbo', 'plugin:@brionmario/internal', 'plugin:@brionmario/prettier'],
3160
plugins: ['@brionmario'],
61+
rules: {
62+
// Enforce JavaScript Colombo's license header.
63+
// https://github.com/Stuk/eslint-plugin-header
64+
'header/header': ['warn', 'block', LICENSE_HEADER_DEFAULT_PATTERN, 2],
65+
},
3266
};

.husky/commit-msg

Lines changed: 0 additions & 1 deletion
This file was deleted.

.husky/pre-commit

Whitespace-only changes.

.husky/prepare-commit-msg

Lines changed: 0 additions & 4 deletions
This file was deleted.

apps/www/.eslintrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ module.exports = {
3535
'plugin:@brionmario/prettier',
3636
'plugin:@brionmario/next',
3737
'plugin:react/jsx-runtime',
38+
'../../.eslintrc.js'
3839
],
3940
parserOptions: {
4041
project: [path.resolve(__dirname, 'tsconfig.json')],

apps/www/app/layout.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
import type {Metadata} from 'next';
2626
import {ReactElement} from 'react';
2727
import ThemeProvider from '@/components/ThemeProvider';
28-
import './globals.scss';
29-
import './custom.scss';
3028
import {inter, spaceGrotesk} from './fonts';
29+
import useMeetupConfig from '@/hooks/useMeetupConfig';
30+
import './custom.scss';
31+
import './globals.scss';
3132

3233
export const metadata: Metadata = {
3334
title: 'JavaScript Colombo',
@@ -39,14 +40,23 @@ const RootLayout = ({
3940
children,
4041
}: Readonly<{
4142
children: React.ReactNode;
42-
}>): ReactElement => (
43-
<html lang="en">
44-
<body className={`${spaceGrotesk.className} ${inter.className}`}>
45-
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
46-
{children}
47-
</ThemeProvider>
48-
</body>
49-
</html>
50-
);
43+
}>): ReactElement => {
44+
const {config} = useMeetupConfig();
45+
46+
return (
47+
<html lang="en">
48+
<body className={`${spaceGrotesk.className} ${inter.className}`}>
49+
<ThemeProvider
50+
attribute="class"
51+
defaultTheme={config.theme.defaultTheme}
52+
enableSystem
53+
disableTransitionOnChange
54+
>
55+
{children}
56+
</ThemeProvider>
57+
</body>
58+
</html>
59+
);
60+
};
5161

5262
export default RootLayout;

apps/www/app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ export default function Home(): ReactElement {
5050
<div dir="ltr">
5151
<NavBar items={[]} />
5252
<div className="mx-auto flex">
53-
<div className="overflow-x-hidden w-full">
53+
<div className="overflow-x-hidden w-full" style={{height: 'calc(100vh - 89px)'}}>
5454
<main className="relative">
5555
<Hero />
56+
<Footer />
5657
</main>
5758
</div>
5859
</div>
59-
<Footer />
6060
</div>
6161
);
6262
}

apps/www/components/FlipWords.tsx

Lines changed: 69 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@
2424

2525
'use client';
2626

27-
import React, {useCallback, useEffect, useRef, useState} from 'react';
27+
import React, {PropsWithChildren, useCallback, useEffect, useRef, useState} from 'react';
2828
import {AnimatePresence, motion, LayoutGroup} from 'framer-motion';
2929
import {cn} from '@/lib/utils';
3030

31-
const FlipWords = ({words, duration = 3000, className}: {className?: string; duration?: number; words: string[]}) => {
31+
export interface FlipWordsProps {
32+
className?: string;
33+
duration?: number;
34+
words: string[];
35+
}
36+
37+
const FlipWords = ({words, duration = 3000, className, children}: PropsWithChildren<FlipWordsProps>) => {
3238
const [currentWord, setCurrentWord] = useState(words[0]);
3339
const [isAnimating, setIsAnimating] = useState<boolean>(false);
3440

35-
// thanks for the fix Julian - https://github.com/Julian-AT
3641
const startAnimation = useCallback(() => {
3742
const word = words[words.indexOf(currentWord) + 1] || words[0];
3843
setCurrentWord(word);
@@ -47,67 +52,69 @@ const FlipWords = ({words, duration = 3000, className}: {className?: string; dur
4752
}, [isAnimating, duration, startAnimation]);
4853

4954
return (
50-
<AnimatePresence
51-
onExitComplete={() => {
52-
setIsAnimating(false);
53-
}}
54-
>
55-
<motion.div
56-
initial={{
57-
opacity: 0,
58-
y: 10,
59-
}}
60-
animate={{
61-
opacity: 1,
62-
y: 0,
63-
}}
64-
transition={{
65-
type: 'spring',
66-
stiffness: 100,
67-
damping: 10,
68-
}}
69-
exit={{
70-
opacity: 0,
71-
y: -40,
72-
x: 40,
73-
filter: 'blur(8px)',
74-
scale: 2,
75-
position: 'absolute',
55+
<>
56+
<AnimatePresence
57+
onExitComplete={() => {
58+
setIsAnimating(false);
7659
}}
77-
className={cn('z-10 inline-block relative text-left px-2', className)}
78-
key={currentWord}
7960
>
80-
{/* edit suggested by Sajal: https://x.com/DewanganSajal */}
81-
{currentWord.split(' ').map((word, wordIndex) => (
82-
<motion.span
83-
key={word + wordIndex}
84-
initial={{opacity: 0, y: 10, filter: 'blur(8px)'}}
85-
animate={{opacity: 1, y: 0, filter: 'blur(0px)'}}
86-
transition={{
87-
delay: wordIndex * 0.3,
88-
duration: 0.3,
89-
}}
90-
className="inline-block whitespace-nowrap"
91-
>
92-
{word.split('').map((letter, letterIndex) => (
93-
<motion.span
94-
key={word + letterIndex}
95-
initial={{opacity: 0, y: 10, filter: 'blur(8px)'}}
96-
animate={{opacity: 1, y: 0, filter: 'blur(0px)'}}
97-
transition={{
98-
delay: wordIndex * 0.3 + letterIndex * 0.05,
99-
duration: 0.2,
100-
}}
101-
className="inline-block"
102-
>
103-
{letter}
104-
</motion.span>
105-
))}
106-
<span className="inline-block">&nbsp;</span>
107-
</motion.span>
108-
))}
109-
</motion.div>
110-
</AnimatePresence>
61+
<motion.div
62+
initial={{
63+
opacity: 0,
64+
y: 10,
65+
}}
66+
animate={{
67+
opacity: 1,
68+
y: 0,
69+
}}
70+
transition={{
71+
type: 'spring',
72+
stiffness: 100,
73+
damping: 10,
74+
}}
75+
exit={{
76+
opacity: 0,
77+
y: -40,
78+
x: 40,
79+
filter: 'blur(8px)',
80+
scale: 2,
81+
position: 'absolute',
82+
}}
83+
className={cn('z-10 inline-block relative text-left px-2', className)}
84+
key={currentWord}
85+
>
86+
{currentWord.split(' ').map((word, wordIndex) => (
87+
<motion.span
88+
key={word + wordIndex}
89+
initial={{opacity: 0, y: 10, filter: 'blur(8px)'}}
90+
animate={{opacity: 1, y: 0, filter: 'blur(0px)'}}
91+
transition={{
92+
delay: wordIndex * 0.3,
93+
duration: 0.3,
94+
}}
95+
className="inline-block whitespace-nowrap"
96+
>
97+
{word.split('').map((letter, letterIndex) => (
98+
<motion.span
99+
key={word + letterIndex}
100+
initial={{opacity: 0, y: 10, filter: 'blur(8px)'}}
101+
animate={{opacity: 1, y: 0, filter: 'blur(0px)'}}
102+
transition={{
103+
delay: wordIndex * 0.3 + letterIndex * 0.05,
104+
duration: 0.2,
105+
}}
106+
className="inline-block"
107+
>
108+
{letter}
109+
</motion.span>
110+
))}
111+
<span className="inline-block">&nbsp;</span>
112+
</motion.span>
113+
))}
114+
</motion.div>
115+
{children}
116+
</AnimatePresence>
117+
</>
111118
);
112119
};
113120

apps/www/components/Footer.tsx

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,39 +27,45 @@ import {cn} from '@/lib/utils';
2727
import {TestableComponent} from '@/types/dom';
2828
import {ExternalLink, GithubIcon, Heart} from 'lucide-react';
2929
import WSO2 from '@/icons/WSO2';
30+
import useMeetupConfig from '@/hooks/useMeetupConfig';
3031

3132
export type FooterProps = HTMLAttributes<HTMLDivElement> & TestableComponent;
3233

3334
const Footer: ForwardRefExoticComponent<FooterProps & RefAttributes<HTMLDivElement>> = forwardRef<
3435
HTMLDivElement,
3536
FooterProps
36-
>(({className, ...rest}: FooterProps, ref: ForwardedRef<HTMLDivElement>) => (
37-
<footer className={cn('footer', className)} ref={ref} {...rest}>
38-
<div className="container mx-auto py-4">
39-
<p className="text-center text-sm text-gray-600 dark:text-gray-400">
40-
&copy; {new Date().getFullYear()} JavaScript Colombo. All rights reserved.
41-
</p>
42-
<div className="mt-4 text-center">
43-
<p className="text-sm text-gray-600 dark:text-gray-400 flex items-center justify-center gap-1">
44-
<Heart width={16} height={16} stroke="#c96198" />
45-
<span>Sponsored by</span>
46-
<a href="https://wso2.com" className="text-blue-500 hover:underline">
47-
<WSO2 height={20} width={40} />
48-
</a>
37+
>(({className, ...rest}: FooterProps, ref: ForwardedRef<HTMLDivElement>) => {
38+
const {config} = useMeetupConfig();
39+
40+
return (
41+
<footer className={cn('footer', className)} ref={ref} {...rest}>
42+
<div className="container mx-auto py-4">
43+
<p className="text-center text-sm text-gray-600 dark:text-gray-400">
44+
&copy; {new Date().getFullYear()} JavaScript Colombo. All rights reserved.
4945
</p>
46+
<div className="mt-4 text-center">
47+
<p className="text-sm text-gray-600 dark:text-gray-400 flex items-center justify-center gap-1">
48+
<Heart width={16} height={16} stroke="#c96198" />
49+
<span>Sponsored by</span>
50+
<a href={config.sponsor.mainSponsor.website} className="text-blue-500 hover:underline" target="_blank">
51+
{config.sponsor.mainSponsor.name}
52+
</a>
53+
</p>
54+
</div>
55+
<div className="mt-4 text-center">
56+
<a
57+
href={config.links.source.github.url}
58+
target={config.links.source.github.target}
59+
className="text-sm text-gray-600 dark:text-gray-400 flex items-center justify-center gap-1 hover:underline"
60+
>
61+
<GithubIcon width={16} height={16} />
62+
<span>Source Code</span>
63+
<ExternalLink width={16} height={16} />
64+
</a>
65+
</div>
5066
</div>
51-
<div className="mt-4 text-center">
52-
<a
53-
href="https://github.com/javascript-colombo/javascriptcolombo.com"
54-
className="text-sm text-gray-600 dark:text-gray-400 flex items-center justify-center gap-1 hover:underline"
55-
>
56-
<GithubIcon width={16} height={16} />
57-
<span>Source Code</span>
58-
<ExternalLink width={16} height={16} />
59-
</a>
60-
</div>
61-
</div>
62-
</footer>
63-
));
67+
</footer>
68+
);
69+
});
6470

6571
export default Footer;

0 commit comments

Comments
 (0)