generator-bitloops 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/setup/index.js +132 -70
- package/setup/templates/src/components/bitloops/button/Button.stories.tsx +34 -0
- package/setup/templates/src/components/bitloops/button/Button.tsx +22 -0
- /package/setup/templates/src/components/bitloops/{Unsupported.stories.tsx → unsupported/Unsupported.stories.tsx} +0 -0
- /package/setup/templates/src/components/bitloops/{Unsupported.tsx → unsupported/Unsupported.tsx} +0 -0
package/package.json
CHANGED
package/setup/index.js
CHANGED
|
@@ -8,9 +8,11 @@ import { fileURLToPath } from 'url';
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
function toKebabCase(str) {
|
|
13
|
-
return str
|
|
12
|
+
return str
|
|
13
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/\s+/g, '-');
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export default class extends Generator {
|
|
@@ -68,7 +70,7 @@ export default class extends Generator {
|
|
|
68
70
|
default: false,
|
|
69
71
|
});
|
|
70
72
|
|
|
71
|
-
this.installNextJS = async function() {
|
|
73
|
+
this.installNextJS = async function () {
|
|
72
74
|
// Clone Next.js template with Tailwind if specified, using the project name
|
|
73
75
|
const createNextAppCommand = ['-y', 'create-next-app@14.2.16'];
|
|
74
76
|
createNextAppCommand.push(toKebabCase(this.options.project)); // Use the project name for the directory
|
|
@@ -80,52 +82,71 @@ export default class extends Generator {
|
|
|
80
82
|
createNextAppCommand.push('@/*');
|
|
81
83
|
createNextAppCommand.push('--use-npm');
|
|
82
84
|
createNextAppCommand.push('--eslint');
|
|
83
|
-
|
|
85
|
+
|
|
84
86
|
if (this.options.typescript) {
|
|
85
87
|
createNextAppCommand.push('--typescript'); // This will avoid the TypeScript prompt
|
|
86
88
|
} else {
|
|
87
89
|
createNextAppCommand.push('--js');
|
|
88
90
|
}
|
|
89
|
-
|
|
91
|
+
|
|
90
92
|
if (this.options.tailwind) {
|
|
91
93
|
createNextAppCommand.push('--tailwind');
|
|
92
94
|
}
|
|
93
|
-
|
|
94
|
-
this.log(
|
|
95
|
-
const patchPackages = ''
|
|
95
|
+
|
|
96
|
+
this.log('Installing Next.js...');
|
|
97
|
+
const patchPackages = ''; //'next@14 react@18 react-dom@18';
|
|
96
98
|
const additionalPackages = `react-tooltip ${patchPackages}`;
|
|
97
|
-
await new Promise((resolve, error) => {
|
|
98
|
-
|
|
99
|
-
|
|
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
|
+
};
|
|
102
112
|
|
|
103
|
-
this.installStorybook = function() {
|
|
113
|
+
this.installStorybook = function () {
|
|
104
114
|
// Conditionally initialize Storybook
|
|
105
115
|
if (this.options.storybook) {
|
|
106
116
|
this.log('Installing Storybook...');
|
|
107
|
-
this.spawnCommandSync('npx', [
|
|
117
|
+
this.spawnCommandSync('npx', [
|
|
118
|
+
'-y',
|
|
119
|
+
'storybook@^8.4',
|
|
120
|
+
'init',
|
|
121
|
+
'--no-dev',
|
|
122
|
+
]);
|
|
108
123
|
this.log('Storybook installed!');
|
|
109
124
|
// if (this.options.tailwind && this.options.storybook) {
|
|
110
125
|
// Tailwind CSS specific setup for older versions of Storybook
|
|
111
126
|
// this.spawnCommandSync('npx', ['storybook@latest', 'add', '@storybook/addon-styling-webpack']);
|
|
112
127
|
// }
|
|
113
128
|
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
this.installCypress = function() {
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
this.installCypress = function () {
|
|
117
132
|
// Conditionally add Cypress
|
|
118
133
|
if (this.options.cypress) {
|
|
119
134
|
this.log('Installing Cypress...');
|
|
120
135
|
this.spawnCommandSync('npm', ['install', '--save-dev', 'cypress']);
|
|
121
136
|
this.log('Cypress installed!');
|
|
122
137
|
if (this.options.bitloops) {
|
|
123
|
-
this.spawnCommandSync('npm', [
|
|
138
|
+
this.spawnCommandSync('npm', [
|
|
139
|
+
'install',
|
|
140
|
+
'--save-dev',
|
|
141
|
+
'mochawesome',
|
|
142
|
+
'mochawesome-merge',
|
|
143
|
+
'mochawesome-report-generator',
|
|
144
|
+
]);
|
|
124
145
|
}
|
|
125
146
|
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
this.patchFiles = async function() {
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
this.patchFiles = async function () {
|
|
129
150
|
// Conditionally initialize Storybook
|
|
130
151
|
if (this.options.storybook) {
|
|
131
152
|
this.log('Making Storybook changes...');
|
|
@@ -134,102 +155,134 @@ export default class extends Generator {
|
|
|
134
155
|
this.log('Setting up Tailwind CSS with Storybook...');
|
|
135
156
|
this.fs.copyTpl(
|
|
136
157
|
this.templatePath('storybook.preview.ts'),
|
|
137
|
-
this.destinationPath('.storybook/preview.ts')
|
|
138
|
-
);
|
|
158
|
+
this.destinationPath('.storybook/preview.ts')
|
|
159
|
+
);
|
|
139
160
|
}
|
|
140
161
|
this.log('Removing default Storybook stories...');
|
|
141
162
|
try {
|
|
142
|
-
fs.rmSync(this.destinationPath('src/stories'), {
|
|
163
|
+
fs.rmSync(this.destinationPath('src/stories'), {
|
|
164
|
+
recursive: true,
|
|
165
|
+
force: true,
|
|
166
|
+
});
|
|
143
167
|
console.log('Sample stories directory deleted successfully!');
|
|
144
168
|
} catch (err) {
|
|
145
|
-
|
|
169
|
+
console.error('Error deleting sample stories directory:', err);
|
|
146
170
|
}
|
|
147
171
|
fs.unlinkSync(this.destinationPath('tailwind.config.ts'));
|
|
148
172
|
this.fs.copyTpl(
|
|
149
173
|
this.templatePath('tailwind.config.ts'),
|
|
150
|
-
this.destinationPath('tailwind.config.ts')
|
|
174
|
+
this.destinationPath('tailwind.config.ts')
|
|
151
175
|
);
|
|
152
176
|
}
|
|
153
|
-
|
|
177
|
+
|
|
154
178
|
if (this.options.cypress) {
|
|
155
179
|
this.log('Adding Cypress config...');
|
|
156
180
|
this.fs.copyTpl(
|
|
157
181
|
this.templatePath('cypress.config.ts'),
|
|
158
|
-
this.destinationPath('cypress.config.ts')
|
|
159
|
-
);
|
|
182
|
+
this.destinationPath('cypress.config.ts')
|
|
183
|
+
);
|
|
160
184
|
}
|
|
161
|
-
|
|
185
|
+
|
|
162
186
|
fs.unlinkSync(this.destinationPath('src/app/page.tsx'));
|
|
163
187
|
this.fs.copyTpl(
|
|
164
188
|
this.templatePath('next.app.page.tsx'),
|
|
165
|
-
this.destinationPath('src/app/page.tsx')
|
|
166
|
-
);
|
|
167
|
-
|
|
189
|
+
this.destinationPath('src/app/page.tsx')
|
|
190
|
+
);
|
|
191
|
+
|
|
168
192
|
fs.unlinkSync(this.destinationPath('src/app/layout.tsx'));
|
|
169
193
|
this.fs.copyTpl(
|
|
170
194
|
this.templatePath('next.app.layout.tsx'),
|
|
171
195
|
this.destinationPath('src/app/layout.tsx'),
|
|
172
|
-
{ projectName: this.options.project }
|
|
196
|
+
{ projectName: this.options.project }
|
|
173
197
|
);
|
|
174
|
-
|
|
198
|
+
|
|
175
199
|
this.log('Adding Meyer reset in global.css...');
|
|
176
200
|
fs.unlinkSync(this.destinationPath('src/app/globals.css'));
|
|
177
201
|
this.fs.copyTpl(
|
|
178
202
|
this.templatePath('globals.css'),
|
|
179
|
-
this.destinationPath('src/app/globals.css')
|
|
180
|
-
);
|
|
203
|
+
this.destinationPath('src/app/globals.css')
|
|
204
|
+
);
|
|
181
205
|
|
|
182
206
|
if (this.options.bitloops) {
|
|
183
207
|
this.log('Adding Bitloops support components...');
|
|
184
|
-
const
|
|
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';
|
|
185
215
|
this.fs.copyTpl(
|
|
186
|
-
this.templatePath(
|
|
187
|
-
this.destinationPath(
|
|
188
|
-
);
|
|
216
|
+
this.templatePath(buttonPath),
|
|
217
|
+
this.destinationPath(buttonPath)
|
|
218
|
+
);
|
|
189
219
|
if (this.options.storybook) {
|
|
190
|
-
const
|
|
220
|
+
const unsupportedPath =
|
|
221
|
+
'src/components/bitloops/unsupported/Unsupported.stories.tsx';
|
|
191
222
|
this.fs.copyTpl(
|
|
192
|
-
this.templatePath(
|
|
193
|
-
this.destinationPath(
|
|
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
|
+
);
|
|
195
232
|
}
|
|
196
233
|
if (this.options.cypress) {
|
|
197
234
|
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));
|
|
202
236
|
}
|
|
237
|
+
this.spawnCommandSync('npm', [
|
|
238
|
+
'install',
|
|
239
|
+
'--save-dev',
|
|
240
|
+
'react-aria-components',
|
|
241
|
+
]);
|
|
203
242
|
}
|
|
204
|
-
}
|
|
243
|
+
};
|
|
205
244
|
|
|
206
|
-
this.commitChanges = async function() {
|
|
245
|
+
this.commitChanges = async function () {
|
|
207
246
|
this.log('Committing changes to git...');
|
|
208
|
-
await new Promise((resolve) => {
|
|
209
|
-
|
|
210
|
-
|
|
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!');
|
|
211
258
|
resolve();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
});});
|
|
216
|
-
}
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
};
|
|
217
262
|
}
|
|
218
263
|
|
|
219
264
|
initializing() {
|
|
220
265
|
// Check if the project name and --nextjs flag are provided
|
|
221
266
|
if (!this.options.project) {
|
|
222
|
-
this.log(
|
|
267
|
+
this.log(
|
|
268
|
+
'Error: --project option is required to specify the project name.'
|
|
269
|
+
);
|
|
223
270
|
process.exit(1);
|
|
224
271
|
}
|
|
225
272
|
|
|
226
273
|
if (!this.options.nextjs) {
|
|
227
|
-
this.log(
|
|
274
|
+
this.log(
|
|
275
|
+
'Error: --nextjs option is currently required to scaffold a project.'
|
|
276
|
+
);
|
|
228
277
|
process.exit(1);
|
|
229
278
|
}
|
|
230
279
|
|
|
231
|
-
this.log(
|
|
232
|
-
|
|
280
|
+
this.log(
|
|
281
|
+
`Initializing project ${toKebabCase(
|
|
282
|
+
this.options.project
|
|
283
|
+
)} with the selected options...`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
233
286
|
|
|
234
287
|
async main() {
|
|
235
288
|
await this.installNextJS();
|
|
@@ -242,12 +295,21 @@ export default class extends Generator {
|
|
|
242
295
|
}
|
|
243
296
|
|
|
244
297
|
end() {
|
|
245
|
-
this.log(
|
|
298
|
+
this.log(
|
|
299
|
+
`Your Bitloops project '${toKebabCase(
|
|
300
|
+
this.options.project
|
|
301
|
+
)}' setup is complete! 🎉🎉🎉`
|
|
302
|
+
);
|
|
246
303
|
this.log('');
|
|
247
304
|
this.log('Use the following commands to start:');
|
|
248
|
-
this.log(
|
|
249
|
-
if (this.options.storybook)
|
|
250
|
-
|
|
251
|
-
if (this.options.cypress)
|
|
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
|
+
);
|
|
252
314
|
}
|
|
253
|
-
}
|
|
315
|
+
}
|
|
@@ -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
|
+
};
|
|
@@ -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
|
+
}
|
|
File without changes
|
/package/setup/templates/src/components/bitloops/{Unsupported.tsx → unsupported/Unsupported.tsx}
RENAMED
|
File without changes
|