Skip to content

Commit b97bfc0

Browse files
committed
2 parents e5a1e12 + 343aa7f commit b97bfc0

File tree

6 files changed

+189
-71
lines changed

6 files changed

+189
-71
lines changed

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "generator-bitloops",
3-
"version": "0.3.8",
3+
"version": "0.3.9",
44
"description": "Next.js with TypeScript, Tailwind, Storybook and Cypress generator by Bitloops",
55
"license": "MIT",
66
"author": "Bitloops S.A.",

Diff for: setup/index.js

+132-70
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import { fileURLToPath } from 'url';
88
const __filename = fileURLToPath(import.meta.url);
99
const __dirname = path.dirname(__filename);
1010

11-
1211
function toKebabCase(str) {
13-
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase().replace(/\s+/g, '-');
12+
return str
13+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
14+
.toLowerCase()
15+
.replace(/\s+/g, '-');
1416
}
1517

1618
export default class extends Generator {
@@ -68,7 +70,7 @@ export default class extends Generator {
6870
default: false,
6971
});
7072

71-
this.installNextJS = async function() {
73+
this.installNextJS = async function () {
7274
// Clone Next.js template with Tailwind if specified, using the project name
7375
const createNextAppCommand = ['-y', '[email protected]'];
7476
createNextAppCommand.push(toKebabCase(this.options.project)); // Use the project name for the directory
@@ -80,52 +82,71 @@ export default class extends Generator {
8082
createNextAppCommand.push('@/*');
8183
createNextAppCommand.push('--use-npm');
8284
createNextAppCommand.push('--eslint');
83-
85+
8486
if (this.options.typescript) {
8587
createNextAppCommand.push('--typescript'); // This will avoid the TypeScript prompt
8688
} else {
8789
createNextAppCommand.push('--js');
8890
}
89-
91+
9092
if (this.options.tailwind) {
9193
createNextAppCommand.push('--tailwind');
9294
}
93-
94-
this.log("Installing Next.js...");
95-
const patchPackages = '';//'next@14 react@18 react-dom@18';
95+
96+
this.log('Installing Next.js...');
97+
const patchPackages = ''; //'next@14 react@18 react-dom@18';
9698
const additionalPackages = `react-tooltip ${patchPackages}`;
97-
await new Promise((resolve, error) => {exec(`npx ${createNextAppCommand.join(' ')} && cd ${toKebabCase(this.options.project)} && npm install ${additionalPackages}`).on('exit', (code) => {
98-
this.destinationRoot(this.destinationPath(toKebabCase(this.options.project)));
99-
resolve();
100-
});});
101-
}
99+
await new Promise((resolve, error) => {
100+
exec(
101+
`npx ${createNextAppCommand.join(' ')} && cd ${toKebabCase(
102+
this.options.project
103+
)} && npm install ${additionalPackages}`
104+
).on('exit', (code) => {
105+
this.destinationRoot(
106+
this.destinationPath(toKebabCase(this.options.project))
107+
);
108+
resolve();
109+
});
110+
});
111+
};
102112

103-
this.installStorybook = function() {
113+
this.installStorybook = function () {
104114
// Conditionally initialize Storybook
105115
if (this.options.storybook) {
106116
this.log('Installing Storybook...');
107-
this.spawnCommandSync('npx', ['-y', 'storybook@^8.4', 'init', '--no-dev']);
117+
this.spawnCommandSync('npx', [
118+
'-y',
119+
'storybook@^8.4',
120+
'init',
121+
'--no-dev',
122+
]);
108123
this.log('Storybook installed!');
109124
// if (this.options.tailwind && this.options.storybook) {
110125
// Tailwind CSS specific setup for older versions of Storybook
111126
// this.spawnCommandSync('npx', ['storybook@latest', 'add', '@storybook/addon-styling-webpack']);
112127
// }
113128
}
114-
}
115-
116-
this.installCypress = function() {
129+
};
130+
131+
this.installCypress = function () {
117132
// Conditionally add Cypress
118133
if (this.options.cypress) {
119134
this.log('Installing Cypress...');
120135
this.spawnCommandSync('npm', ['install', '--save-dev', 'cypress']);
121136
this.log('Cypress installed!');
122137
if (this.options.bitloops) {
123-
this.spawnCommandSync('npm', ['install', '--save-dev', 'mochawesome', 'mochawesome-merge', 'mochawesome-report-generator']);
138+
this.spawnCommandSync('npm', [
139+
'install',
140+
'--save-dev',
141+
'mochawesome',
142+
'mochawesome-merge',
143+
'mochawesome-report-generator',
144+
]);
124145
}
125146
}
126-
}
127-
128-
this.patchFiles = async function() {
147+
};
148+
149+
this.patchFiles = async function () {
129150
// Conditionally initialize Storybook
130151
if (this.options.storybook) {
131152
this.log('Making Storybook changes...');
@@ -134,102 +155,134 @@ export default class extends Generator {
134155
this.log('Setting up Tailwind CSS with Storybook...');
135156
this.fs.copyTpl(
136157
this.templatePath('storybook.preview.ts'),
137-
this.destinationPath('.storybook/preview.ts'),
138-
);
158+
this.destinationPath('.storybook/preview.ts')
159+
);
139160
}
140161
this.log('Removing default Storybook stories...');
141162
try {
142-
fs.rmSync(this.destinationPath('src/stories'), { recursive: true, force: true });
163+
fs.rmSync(this.destinationPath('src/stories'), {
164+
recursive: true,
165+
force: true,
166+
});
143167
console.log('Sample stories directory deleted successfully!');
144168
} catch (err) {
145-
console.error('Error deleting sample stories directory:', err);
169+
console.error('Error deleting sample stories directory:', err);
146170
}
147171
fs.unlinkSync(this.destinationPath('tailwind.config.ts'));
148172
this.fs.copyTpl(
149173
this.templatePath('tailwind.config.ts'),
150-
this.destinationPath('tailwind.config.ts'),
174+
this.destinationPath('tailwind.config.ts')
151175
);
152176
}
153-
177+
154178
if (this.options.cypress) {
155179
this.log('Adding Cypress config...');
156180
this.fs.copyTpl(
157181
this.templatePath('cypress.config.ts'),
158-
this.destinationPath('cypress.config.ts'),
159-
);
182+
this.destinationPath('cypress.config.ts')
183+
);
160184
}
161-
185+
162186
fs.unlinkSync(this.destinationPath('src/app/page.tsx'));
163187
this.fs.copyTpl(
164188
this.templatePath('next.app.page.tsx'),
165-
this.destinationPath('src/app/page.tsx'),
166-
);
167-
189+
this.destinationPath('src/app/page.tsx')
190+
);
191+
168192
fs.unlinkSync(this.destinationPath('src/app/layout.tsx'));
169193
this.fs.copyTpl(
170194
this.templatePath('next.app.layout.tsx'),
171195
this.destinationPath('src/app/layout.tsx'),
172-
{ projectName: this.options.project },
196+
{ projectName: this.options.project }
173197
);
174-
198+
175199
this.log('Adding Meyer reset in global.css...');
176200
fs.unlinkSync(this.destinationPath('src/app/globals.css'));
177201
this.fs.copyTpl(
178202
this.templatePath('globals.css'),
179-
this.destinationPath('src/app/globals.css'),
180-
);
203+
this.destinationPath('src/app/globals.css')
204+
);
181205

182206
if (this.options.bitloops) {
183207
this.log('Adding Bitloops support components...');
184-
const path = 'src/components/bitloops/Unsupported.tsx';
208+
const unsupportedPath =
209+
'src/components/bitloops/unsupported/Unsupported.tsx';
210+
this.fs.copyTpl(
211+
this.templatePath(unsupportedPath),
212+
this.destinationPath(unsupportedPath)
213+
);
214+
const buttonPath = 'src/components/bitloops/button/Button.tsx';
185215
this.fs.copyTpl(
186-
this.templatePath(path),
187-
this.destinationPath(path),
188-
);
216+
this.templatePath(buttonPath),
217+
this.destinationPath(buttonPath)
218+
);
189219
if (this.options.storybook) {
190-
const path = 'src/components/bitloops/Unsupported.stories.tsx';
220+
const unsupportedPath =
221+
'src/components/bitloops/unsupported/Unsupported.stories.tsx';
191222
this.fs.copyTpl(
192-
this.templatePath(path),
193-
this.destinationPath(path),
194-
);
223+
this.templatePath(unsupportedPath),
224+
this.destinationPath(unsupportedPath)
225+
);
226+
const buttonPath =
227+
'src/components/bitloops/button/Button.stories.tsx';
228+
this.fs.copyTpl(
229+
this.templatePath(buttonPath),
230+
this.destinationPath(buttonPath)
231+
);
195232
}
196233
if (this.options.cypress) {
197234
const path = 'cypress/helpers/index.ts';
198-
this.fs.copyTpl(
199-
this.templatePath(path),
200-
this.destinationPath(path),
201-
);
235+
this.fs.copyTpl(this.templatePath(path), this.destinationPath(path));
202236
}
237+
this.spawnCommandSync('npm', [
238+
'install',
239+
'--save-dev',
240+
'react-aria-components',
241+
]);
203242
}
204-
}
243+
};
205244

206-
this.commitChanges = async function() {
245+
this.commitChanges = async function () {
207246
this.log('Committing changes to git...');
208-
await new Promise((resolve) => {exec(`cd ${toKebabCase(this.options.project)} && git add . && git commit -m "Initial setup"`).on('exit', (code) => {
209-
if (code !== 0) {
210-
this.log('Error committing changes to git! ', code);
247+
await new Promise((resolve) => {
248+
exec(
249+
`cd ${toKebabCase(
250+
this.options.project
251+
)} && git add . && git commit -m "Initial setup"`
252+
).on('exit', (code) => {
253+
if (code !== 0) {
254+
this.log('Error committing changes to git! ', code);
255+
resolve();
256+
}
257+
this.log('Git changes committed!');
211258
resolve();
212-
}
213-
this.log('Git changes committed!');
214-
resolve();
215-
});});
216-
}
259+
});
260+
});
261+
};
217262
}
218263

219264
initializing() {
220265
// Check if the project name and --nextjs flag are provided
221266
if (!this.options.project) {
222-
this.log("Error: --project option is required to specify the project name.");
267+
this.log(
268+
'Error: --project option is required to specify the project name.'
269+
);
223270
process.exit(1);
224271
}
225272

226273
if (!this.options.nextjs) {
227-
this.log("Error: --nextjs option is currently required to scaffold a project.");
274+
this.log(
275+
'Error: --nextjs option is currently required to scaffold a project.'
276+
);
228277
process.exit(1);
229278
}
230279

231-
this.log(`Initializing project ${toKebabCase(this.options.project)} with the selected options...`);
232-
}
280+
this.log(
281+
`Initializing project ${toKebabCase(
282+
this.options.project
283+
)} with the selected options...`
284+
);
285+
}
233286

234287
async main() {
235288
await this.installNextJS();
@@ -242,12 +295,21 @@ export default class extends Generator {
242295
}
243296

244297
end() {
245-
this.log(`Your Bitloops project '${toKebabCase(this.options.project)}' setup is complete! 🎉🎉🎉`);
298+
this.log(
299+
`Your Bitloops project '${toKebabCase(
300+
this.options.project
301+
)}' setup is complete! 🎉🎉🎉`
302+
);
246303
this.log('');
247304
this.log('Use the following commands to start:');
248-
this.log("- `npm run dev` to start the Next.js app.");
249-
if (this.options.storybook) this.log("- `npm run storybook` to start Storybook.");
250-
if (this.options.cypress) this.log("- `npx cypress open --e2e --browser chrome` to open Cypress.");
251-
if (this.options.cypress) this.log("- `npx cypress run --e2e --browser chrome` to run Cypress on the terminal.");
305+
this.log('- `npm run dev` to start the Next.js app.');
306+
if (this.options.storybook)
307+
this.log('- `npm run storybook` to start Storybook.');
308+
if (this.options.cypress)
309+
this.log('- `npx cypress open --e2e --browser chrome` to open Cypress.');
310+
if (this.options.cypress)
311+
this.log(
312+
'- `npx cypress run --e2e --browser chrome` to run Cypress on the terminal.'
313+
);
252314
}
253-
};
315+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Meta, StoryObj } from '@storybook/react';
2+
import { ButtonElement, ButtonElementProps } from './Button';
3+
4+
const meta: Meta<typeof ButtonElement> = {
5+
title: 'Bitloops/Button',
6+
component: ButtonElement,
7+
parameters: {
8+
layout: 'centered',
9+
},
10+
tags: ['autodocs'],
11+
};
12+
13+
export default meta;
14+
15+
const props: ButtonElementProps = {
16+
disabled: false,
17+
onPress: () => {
18+
console.log('Button pressed');
19+
},
20+
className:
21+
'border-purple-700 bg-purple-700 border opacity-100 w-40 flex-col items-center border-solid',
22+
children: (
23+
<p className='text-white opacity-100 text-lg font-mono'>Hello World!</p>
24+
),
25+
};
26+
27+
type Story = StoryObj<typeof ButtonElement>;
28+
29+
export const Default: Story = {
30+
args: props,
31+
parameters: {
32+
layout: 'fullscreen',
33+
},
34+
};
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Button as AriaButton } from 'react-aria-components';
2+
3+
export type ButtonElementProps = {
4+
name?: string;
5+
disabled?: boolean;
6+
onPress: (e?: unknown) => void;
7+
children?: React.ReactNode;
8+
className?: string;
9+
};
10+
export function ButtonElement(props: ButtonElementProps) {
11+
const { name, disabled, children, className, onPress } = props;
12+
return (
13+
<AriaButton
14+
name={name}
15+
isDisabled={disabled}
16+
onPress={onPress}
17+
className={className}
18+
>
19+
{children}
20+
</AriaButton>
21+
);
22+
}

0 commit comments

Comments
 (0)