generator-bitloops 0.3.32 → 0.3.34

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-bitloops",
3
- "version": "0.3.32",
3
+ "version": "0.3.34",
4
4
  "description": "Next.js with TypeScript, Tailwind, Storybook and Cypress generator by Bitloops",
5
5
  "license": "MIT",
6
6
  "author": "Bitloops S.A.",
package/setup/index.js CHANGED
@@ -17,6 +17,8 @@ const PLATFORM_NEXT_FOLDER = 'platform-next';
17
17
  const PLATFORM_NEXT_SRC_FOLDER = `${PLATFORM_NEXT_FOLDER}/src`;
18
18
  const PLATFORM_VITE_FOLDER = 'platform-vite';
19
19
  const PLATFORM_VITE_SRC_FOLDER = `${PLATFORM_VITE_FOLDER}/src`;
20
+ const LIB_TYPES_FOLDER = 'src/lib/types';
21
+ const LIB_ROUTER_FOLDER = 'src/lib/router';
20
22
 
21
23
  function isKebabCase(str) {
22
24
  // Check if the string is empty
@@ -289,17 +291,21 @@ export default class extends Generator {
289
291
 
290
292
  this.log(`Latest stable 10.x version: ${latest10}`);
291
293
  // Initializing storybook with nextjs+vite
292
- runSync('npx', [
293
- '-y',
294
- `storybook@${latest10}`,
295
- 'init',
296
- '--no-dev',
297
- '--yes',
298
- '--type',
299
- 'nextjs',
300
- '--builder',
301
- 'vite',
302
- ], { cwd: this.destinationRoot() });
294
+ runSync(
295
+ 'npx',
296
+ [
297
+ '-y',
298
+ `storybook@${latest10}`,
299
+ 'init',
300
+ '--no-dev',
301
+ '--yes',
302
+ '--type',
303
+ 'nextjs',
304
+ '--builder',
305
+ 'vite',
306
+ ],
307
+ { cwd: this.destinationRoot() },
308
+ );
303
309
  this.log('Storybook installed!');
304
310
  // Verifies the correct nextjs-vite framework is used
305
311
  runSync('pnpm', ['add', '-D', '@storybook/nextjs-vite@^10'], {
@@ -318,13 +324,17 @@ export default class extends Generator {
318
324
  });
319
325
  this.log('Cypress installed!');
320
326
  if (this.options.bitloops) {
321
- runSync('pnpm', [
322
- 'add',
323
- '-D',
324
- 'mochawesome',
325
- 'mochawesome-merge',
326
- 'mochawesome-report-generator',
327
- ], { cwd: this.destinationRoot() });
327
+ runSync(
328
+ 'pnpm',
329
+ [
330
+ 'add',
331
+ '-D',
332
+ 'mochawesome',
333
+ 'mochawesome-merge',
334
+ 'mochawesome-report-generator',
335
+ ],
336
+ { cwd: this.destinationRoot() },
337
+ );
328
338
  }
329
339
  }
330
340
  };
@@ -366,21 +376,25 @@ export default class extends Generator {
366
376
  // Conditionally add Vitest and related testing packages
367
377
  if (this.options.vitest) {
368
378
  this.log('Installing Vitest and testing packages...');
369
- runSync('pnpm', [
370
- 'add',
371
- '-D',
372
- 'vitest',
373
- '@vitest/ui',
374
- '@vitest/coverage-v8',
375
- '@vitest/browser-playwright',
376
- '@testing-library/react',
377
- '@testing-library/jest-dom',
378
- '@testing-library/user-event',
379
- '@vitejs/plugin-react',
380
- 'vite',
381
- 'jsdom',
382
- 'playwright',
383
- ], { cwd: this.destinationRoot() });
379
+ runSync(
380
+ 'pnpm',
381
+ [
382
+ 'add',
383
+ '-D',
384
+ 'vitest',
385
+ '@vitest/ui',
386
+ '@vitest/coverage-v8',
387
+ '@vitest/browser-playwright',
388
+ '@testing-library/react',
389
+ '@testing-library/jest-dom',
390
+ '@testing-library/user-event',
391
+ '@vitejs/plugin-react',
392
+ 'vite',
393
+ 'jsdom',
394
+ 'playwright',
395
+ ],
396
+ { cwd: this.destinationRoot() },
397
+ );
384
398
  this.log('Vitest and testing packages installed!');
385
399
  }
386
400
  };
@@ -507,6 +521,36 @@ export default class extends Generator {
507
521
  );
508
522
  });
509
523
 
524
+ // Lib types files
525
+ const libTypesFiles = [
526
+ `${LIB_TYPES_FOLDER}/primitives.types.ts`,
527
+ `${LIB_TYPES_FOLDER}/image.types.ts`,
528
+ `${LIB_TYPES_FOLDER}/types.d.ts`,
529
+ ];
530
+
531
+ libTypesFiles.forEach((filePath) => {
532
+ deleteFileIfExists(this.destinationPath(filePath));
533
+ this.fs.copyTpl(
534
+ this.templatePath(filePath),
535
+ this.destinationPath(filePath),
536
+ );
537
+ });
538
+
539
+ // Lib router files
540
+ const libRouterFiles = [
541
+ `${LIB_ROUTER_FOLDER}/index.ts`,
542
+ `${LIB_ROUTER_FOLDER}/types.ts`,
543
+ `${LIB_ROUTER_FOLDER}/useRouter.ts`,
544
+ ];
545
+
546
+ libRouterFiles.forEach((filePath) => {
547
+ deleteFileIfExists(this.destinationPath(filePath));
548
+ this.fs.copyTpl(
549
+ this.templatePath(filePath),
550
+ this.destinationPath(filePath),
551
+ );
552
+ });
553
+
510
554
  this.log('Primitives installed!');
511
555
  }
512
556
  };
@@ -517,10 +561,7 @@ export default class extends Generator {
517
561
  this.log('Making Storybook changes...');
518
562
 
519
563
  // Copy .storybook template files
520
- const storybookFiles = [
521
- `${STORYBOOK_FOLDER}/main.ts`,
522
- `${STORYBOOK_FOLDER}/vitest.setup.ts`,
523
- ];
564
+ const storybookFiles = [`${STORYBOOK_FOLDER}/main.ts`];
524
565
 
525
566
  // Delete .storybook/preview.ts if it exists (generated by storybook init)
526
567
  deleteFileIfExists(
@@ -724,7 +765,10 @@ export default class extends Generator {
724
765
  await this.withRetry(() => this.installNextJS(), 'Next.js install');
725
766
  await this.withRetry(() => this.installCypress(), 'Cypress');
726
767
  await this.withRetry(() => this.installI18n(), 'i18n');
727
- await this.withRetry(() => this.installIntlMessageFormat(), 'intl-messageformat');
768
+ await this.withRetry(
769
+ () => this.installIntlMessageFormat(),
770
+ 'intl-messageformat',
771
+ );
728
772
  await this.withRetry(() => this.installBaseUi(), 'Base UI');
729
773
  await this.withRetry(() => this.installRedux(), 'Redux');
730
774
  await this.withRetry(() => this.installVitest(), 'Vitest');
@@ -737,7 +781,10 @@ export default class extends Generator {
737
781
  await this.withRetry(() => this.installPrimitives(), 'Primitives');
738
782
  await this.withRetry(() => this.installStorybook(), 'Storybook');
739
783
  await this.withRetry(() => this.patchFiles(), 'Patch files');
740
- await this.withRetry(() => this.patchPackageJsonScripts(), 'Patch package.json');
784
+ await this.withRetry(
785
+ () => this.patchPackageJsonScripts(),
786
+ 'Patch package.json',
787
+ );
741
788
  if (this.options.git) {
742
789
  await this.withRetry(() => this.commitChanges(), 'Git commit');
743
790
  }
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ export { useRouter } from "./useRouter";
@@ -0,0 +1,5 @@
1
+ export interface Router {
2
+ push: (url: string) => void;
3
+ replace: (url: string) => void;
4
+ back: () => void;
5
+ }
@@ -0,0 +1,18 @@
1
+ import type { Router } from './types';
2
+
3
+ // This will be implemented by platform-specific code
4
+ // The implementation will be injected at build time
5
+ let routerImplementation: (() => Router) | null = null;
6
+
7
+ export function setRouterImplementation(implementation: () => Router) {
8
+ routerImplementation = implementation;
9
+ }
10
+
11
+ export function useRouter(): Router {
12
+ if (!routerImplementation) {
13
+ throw new Error(
14
+ 'Router implementation not set. Make sure to call setRouterImplementation in your platform setup.'
15
+ );
16
+ }
17
+ return routerImplementation();
18
+ }
@@ -0,0 +1,5 @@
1
+ export interface ImageProperties {
2
+ src: string;
3
+ width: number;
4
+ height: number;
5
+ }
@@ -0,0 +1,64 @@
1
+ // shared types (export them from both adapters)
2
+ export type ImgProps = {
3
+ src: string;
4
+ alt: string;
5
+ width?: number;
6
+ height?: number;
7
+ fill?: boolean;
8
+ sizes?: string;
9
+ priority?: boolean;
10
+ quality?: number;
11
+ className?: string;
12
+ style?: React.CSSProperties;
13
+ loading?: "eager" | "lazy";
14
+ decoding?: "auto" | "sync" | "async";
15
+ responsive?: { sources: Array<{ media: string; srcSet: string }> }; // optional <picture>
16
+ };
17
+
18
+ export type LinkProps = {
19
+ href: string;
20
+ children: React.ReactNode;
21
+ prefetch?: boolean;
22
+ replace?: boolean;
23
+ scroll?: boolean;
24
+ target?: React.HTMLAttributeAnchorTarget;
25
+ rel?: string;
26
+ className?: string;
27
+ style?: React.CSSProperties;
28
+ onClick?: React.MouseEventHandler<HTMLAnchorElement>;
29
+ "aria-label"?: string;
30
+ };
31
+
32
+ export type ButtonProps = {
33
+ children: React.ReactNode;
34
+ onClick?: () => void;
35
+ type?: "button" | "submit" | "reset";
36
+ disabled?: boolean;
37
+ className?: string;
38
+ style?: React.CSSProperties;
39
+ "aria-label"?: string;
40
+ };
41
+
42
+ export type MetaProps = {
43
+ title?: string;
44
+ description?: string;
45
+ lang?: string;
46
+ openGraph?: {
47
+ title?: string;
48
+ description?: string;
49
+ image?: string;
50
+ url?: string;
51
+ type?: string;
52
+ };
53
+ twitter?: {
54
+ card?: string;
55
+ title?: string;
56
+ description?: string;
57
+ image?: string;
58
+ };
59
+ icons?: { icon?: string; apple?: string };
60
+ };
61
+
62
+ export type FontSpec =
63
+ | { kind: "next"; fonts: Array<{ variable: string; loader: () => unknown }> } // Next native loaders
64
+ | { kind: "css"; hrefs: string[]; className?: string };
@@ -0,0 +1,4 @@
1
+ declare module "*.svg" {
2
+ const content: string;
3
+ export default content;
4
+ }
@@ -1,7 +0,0 @@
1
- import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
2
- import { setProjectAnnotations } from '@storybook/nextjs-vite';
3
- import * as projectAnnotations from './preview';
4
-
5
- // This is an important step to apply the right configuration when testing your stories.
6
- // More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
7
- setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);