pixi-rainman-game-engine 0.1.20 → 0.1.22

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.
@@ -2,15 +2,17 @@ import i18next from "i18next";
2
2
  import React from "react";
3
3
  import { UI_ITEMS } from "../../utils";
4
4
  import { BetSettings, CloseModalButton, UXSettings } from "../components";
5
+ import { useDeviceOrientations } from "../hooks";
5
6
  export const SystemSettingsComponent = () => {
6
- return (<div className="flex w-full max-w-lg flex-col justify-center gap-2 p-4">
7
+ const deviceOrientation = useDeviceOrientations();
8
+ return (<div className="flex w-full max-w-lg flex-col justify-center gap-2 p-4 sm:max-w-xl">
7
9
  <div className="flex w-full justify-center">
8
10
  <h2 className="text-2xl font-bold uppercase text-primary-500">{i18next.t("systemSettings")}</h2>
9
11
  </div>
10
12
  <CloseModalButton layerId={UI_ITEMS.settings}/>
11
13
  <div className="flex w-full flex-col justify-center">
12
14
  <UXSettings />
13
- <BetSettings className="hidden w-full justify-center sm:flex"/>
15
+ {!deviceOrientation.includes("mobile") ? <BetSettings className="flex w-full justify-center"/> : null}
14
16
  </div>
15
17
  </div>);
16
18
  };
@@ -51,7 +51,7 @@ export const AutoplaySettings = observer(() => {
51
51
  updateLimitsBounds(initialAutoSpinCount);
52
52
  }, []);
53
53
  const { singleWinExceeds, balancedIncreased, balancedDecreased, howManyAutoSpinsLeft, infinitySpinsEnabled, setSingleWinExceeds, setBalancedIncreased, setBalancedDecreased, setAutoSpinsCount, flipInfinitySpinsFlag, resetAutoplaySettings, } = settingStore;
54
- return (<div className="flex w-full max-w-xs flex-col items-center justify-between gap-8 p-4 sm:max-w-md">
54
+ return (<div className="flex w-full max-w-xs flex-col items-center justify-between gap-8 p-4 sm:max-w-xl">
55
55
  <CloseModalButton layerId={UI_ITEMS.autoplay}/>
56
56
  <h2 className="text-center text-3xl font-bold text-primary-500">{i18next.t("autoPlay")}</h2>
57
57
  <div className="flex h-12 w-full flex-wrap items-center justify-center gap-2 sm:max-w-72 sm:flex-nowrap">
@@ -5,7 +5,7 @@ import { useStores } from "../../hooks";
5
5
  import { Button } from "../Button";
6
6
  export const BetControls = observer(() => {
7
7
  const { settingStore } = useStores();
8
- return (<div className="my-7 flex w-full flex-col items-center justify-center gap-2">
8
+ return (<div className="flex w-full flex-col items-center justify-center gap-2 p-4">
9
9
  <h2 className="font-bold uppercase text-primary-500 sm:text-2xl">{i18next.t("totalBet")}</h2>
10
10
  <div className="flex w-full items-center justify-center gap-4">
11
11
  <Button className="flex h-10 w-8 items-center justify-center rounded-lg bg-primary-400 p-4 font-bold text-black shadow-md transition duration-300 hover:bg-primary-300" name="bet-minus">
@@ -22,15 +22,17 @@ export const GameRules = observer(() => {
22
22
  }
23
23
  setPageNumber(pageNumber + incrementor);
24
24
  };
25
- return (<div className="flex h-full max-h-[90vh] w-[90%] flex-col items-center gap-4 p-5">
26
- <h2 className="text-pr text-center text-3xl font-bold text-primary-500">{i18next.t("gameRules")}</h2>
25
+ return (<div className="max-w-5/6 flex h-fit flex-col items-center gap-4 p-5">
26
+ <h2 className="text-center text-3xl font-bold text-primary-500">{i18next.t("gameRules")}</h2>
27
27
  <CloseModalButton layerId={UI_ITEMS.gameRules}/>
28
- <div className="custom-scroll mb-5 h-full min-h-[60vh]">
29
- <CustomScroll className="h-[70%]" allowOuterScroll={true}>
30
- <div className="text-md h-full w-[90%] text-justify">{gameRulesContent.pages[pageNumber]}</div>
28
+ <div className="custom-scroll max-w-5/6 h-full min-h-[60vh]">
29
+ <CustomScroll className="h-full w-full overflow-y-auto portrait:max-h-[60vh]" allowOuterScroll={true}>
30
+ <div className="text-md max-w-5/6 w-full overflow-y-auto landscape:max-h-[50vh]">
31
+ {gameRulesContent.pages[pageNumber]}
32
+ </div>
31
33
  </CustomScroll>
32
34
  </div>
33
- <div className="relative bottom-5 left-5 flex h-[50px] items-center justify-center gap-2">
35
+ <div className="flex h-[50px] items-center justify-center gap-2">
34
36
  <div className="flex h-[24px] w-6 items-center bg-[url('/assets/settings/gameRules/left.png')] bg-contain bg-right bg-no-repeat hover:opacity-50" onClick={() => changePage(-1)}/>
35
37
  <div className="flex h-[24px] w-6 items-center bg-[url('/assets/settings/gameRules/cross.png')] bg-contain bg-no-repeat hover:opacity-50" onClick={() => settingStore.handleModalInvocation?.(UI_ITEMS.gameRules)}/>
36
38
  <div className="flex h-[24px] w-6 items-center bg-[url('/assets/settings/gameRules/right.png')] bg-contain bg-no-repeat hover:opacity-50" onClick={() => changePage(1)}/>
@@ -15,7 +15,7 @@ export const Modal = observer(({ layerId, children, className }) => {
15
15
  <div onClick={() => setOpen(!open)} className="fixed inset-0 bg-zinc-800 bg-opacity-75 transition-opacity"/>
16
16
  <div className="fixed inset-0 z-10 w-screen overflow-y-auto p-6">
17
17
  <div className="flex min-h-full w-full items-center justify-center rounded-lg shadow">
18
- <div ref={ref} className={cn("min-w-3/4 relative flex h-5/6 w-full transform flex-col items-center overflow-hidden rounded-lg bg-zinc-900 p-2 text-left shadow-xl transition-all", className)}>
18
+ <div ref={ref} className={cn("relative flex h-5/6 transform flex-col items-center overflow-hidden rounded-lg bg-zinc-900 p-2 text-left shadow-xl transition-all", className)}>
19
19
  {children}
20
20
  </div>
21
21
  </div>
@@ -15,10 +15,10 @@ export const SpeedSettingsPopup = observer(() => {
15
15
  fast: SPEED_LEVELS.fast,
16
16
  };
17
17
  const { settingStore } = useStores();
18
- return (<div className="flex h-full w-[90%] flex-col items-center justify-between gap-2 p-4">
18
+ return (<div className="flex h-fit w-fit flex-col items-center justify-between gap-2 p-4 portrait:max-w-72">
19
19
  <CloseModalButton layerId={UI_ITEMS.speedSettings}/>
20
20
  <h1 className="mt-3 font-bold uppercase text-white sm:text-xl">{i18next.t("howDoYouWantToPlay")}</h1>
21
- <div className="flex h-fit w-full flex-wrap justify-between gap-2">
21
+ <div className="flex h-fit w-full flex-wrap justify-between gap-2 portrait:items-center portrait:justify-center">
22
22
  {Object.keys(speedLevelMapper).map((speedLevelKey) => (<div id={`${SPEED_PREFIX}${speedLevelKey}`} key={`${SPEED_PREFIX}${speedLevelKey}`} className={cn("flex h-fit w-[145px] items-center justify-center border-2 border-zinc-400 bg-zinc-800 bg-contain bg-no-repeat p-4", speedLevelKey === settingStore.currentSpeed ? "h-fit border-2 border-primary-500" : "")}>
23
23
  <img className="h-12 w-fit" src={`../../../assets/settings/speedPopup/speed-${speedLevelMapper[speedLevelKey]}.png`}/>
24
24
  </div>))}
@@ -26,7 +26,7 @@ export const SymbolMultiplierPopup = observer(() => {
26
26
  left: popupPaytablePosition.x,
27
27
  top: popupPaytablePosition.y,
28
28
  }}>
29
- <div className="flex h-full w-fit flex-col items-center justify-center sm:w-full">
29
+ <div className="flex h-fit w-fit flex-col items-center justify-center sm:w-full">
30
30
  {popupPaytableData.map((popupPaytableRow) => (<div key={popupPaytableRow.prefix} className="flex gap-1 text-xs sm:text-2xl">
31
31
  <div className="text-xs font-bold text-primary-500 sm:text-2xl">
32
32
  {popupPaytableRow.prefix}x
@@ -18,7 +18,7 @@ export const SettingsUI = () => {
18
18
  <Modal layerId={UI_ITEMS.autoplay}>
19
19
  <AutoplaySettings />
20
20
  </Modal>
21
- <Modal layerId={UI_ITEMS.speedSettings} className="absolute left-[25wv] top-[40vh] flex h-fit w-fit items-center justify-center rounded-xl bg-zinc-900 p-4 shadow-primary-500/30 landscape:top-[20vh]">
21
+ <Modal layerId={UI_ITEMS.speedSettings} className="absolute flex h-fit items-center justify-center rounded-xl bg-zinc-900 p-4 shadow-primary-500/30 sm:left-auto sm:top-auto portrait:left-auto portrait:top-auto portrait:items-center">
22
22
  <SpeedSettingsPopup />
23
23
  </Modal>
24
24
  <div id={UI_ITEMS.symbolPayTable}>
@@ -628,10 +628,6 @@ video {
628
628
  bottom: 0.5rem;
629
629
  }
630
630
 
631
- .bottom-5 {
632
- bottom: 1.25rem;
633
- }
634
-
635
631
  .bottom-\[5vh\] {
636
632
  bottom: 5vh;
637
633
  }
@@ -648,10 +644,6 @@ video {
648
644
  left: 1rem;
649
645
  }
650
646
 
651
- .left-5 {
652
- left: 1.25rem;
653
- }
654
-
655
647
  .left-9 {
656
648
  left: 2.25rem;
657
649
  }
@@ -660,10 +652,6 @@ video {
660
652
  left: 1vw;
661
653
  }
662
654
 
663
- .left-\[25wv\] {
664
- left: 25wv;
665
- }
666
-
667
655
  .right-0 {
668
656
  right: 0px;
669
657
  }
@@ -680,23 +668,10 @@ video {
680
668
  top: 0.5rem;
681
669
  }
682
670
 
683
- .top-\[40vh\] {
684
- top: 40vh;
685
- }
686
-
687
671
  .z-10 {
688
672
  z-index: 10;
689
673
  }
690
674
 
691
- .my-7 {
692
- margin-top: 1.75rem;
693
- margin-bottom: 1.75rem;
694
- }
695
-
696
- .mb-5 {
697
- margin-bottom: 1.25rem;
698
- }
699
-
700
675
  .ml-4 {
701
676
  margin-left: 1rem;
702
677
  }
@@ -725,10 +700,6 @@ video {
725
700
  display: table;
726
701
  }
727
702
 
728
- .hidden {
729
- display: none;
730
- }
731
-
732
703
  .h-10 {
733
704
  height: 2.5rem;
734
705
  }
@@ -765,10 +736,6 @@ video {
765
736
  height: 50px;
766
737
  }
767
738
 
768
- .h-\[70\%\] {
769
- height: 70%;
770
- }
771
-
772
739
  .h-\[90\%\] {
773
740
  height: 90%;
774
741
  }
@@ -782,10 +749,6 @@ video {
782
749
  height: 100%;
783
750
  }
784
751
 
785
- .max-h-\[90vh\] {
786
- max-height: 90vh;
787
- }
788
-
789
752
  .min-h-\[60vh\] {
790
753
  min-height: 60vh;
791
754
  }
@@ -1141,10 +1104,6 @@ video {
1141
1104
  text-align: center;
1142
1105
  }
1143
1106
 
1144
- .text-justify {
1145
- text-align: justify;
1146
- }
1147
-
1148
1107
  .text-2xl {
1149
1108
  font-size: 1.5rem;
1150
1109
  line-height: 2rem;
@@ -1557,6 +1516,10 @@ html.is-locked .ios-scroller-animation {
1557
1516
  }
1558
1517
 
1559
1518
  @media (min-width: 640px) {
1519
+ .sm\:left-auto {
1520
+ left: auto;
1521
+ }
1522
+
1560
1523
  .sm\:right-8 {
1561
1524
  right: 2rem;
1562
1525
  }
@@ -1565,6 +1528,10 @@ html.is-locked .ios-scroller-animation {
1565
1528
  top: 1rem;
1566
1529
  }
1567
1530
 
1531
+ .sm\:top-auto {
1532
+ top: auto;
1533
+ }
1534
+
1568
1535
  .sm\:ml-5 {
1569
1536
  margin-left: 1.25rem;
1570
1537
  }
@@ -1573,10 +1540,6 @@ html.is-locked .ios-scroller-animation {
1573
1540
  margin-top: 1.25rem;
1574
1541
  }
1575
1542
 
1576
- .sm\:flex {
1577
- display: flex;
1578
- }
1579
-
1580
1543
  .sm\:w-full {
1581
1544
  width: 100%;
1582
1545
  }
@@ -1585,8 +1548,8 @@ html.is-locked .ios-scroller-animation {
1585
1548
  max-width: 18rem;
1586
1549
  }
1587
1550
 
1588
- .sm\:max-w-md {
1589
- max-width: 28rem;
1551
+ .sm\:max-w-xl {
1552
+ max-width: 36rem;
1590
1553
  }
1591
1554
 
1592
1555
  .sm\:flex-row {
@@ -1617,8 +1580,34 @@ html.is-locked .ios-scroller-animation {
1617
1580
  }
1618
1581
  }
1619
1582
 
1583
+ @media (orientation: portrait) {
1584
+ .portrait\:left-auto {
1585
+ left: auto;
1586
+ }
1587
+
1588
+ .portrait\:top-auto {
1589
+ top: auto;
1590
+ }
1591
+
1592
+ .portrait\:max-h-\[60vh\] {
1593
+ max-height: 60vh;
1594
+ }
1595
+
1596
+ .portrait\:max-w-72 {
1597
+ max-width: 18rem;
1598
+ }
1599
+
1600
+ .portrait\:items-center {
1601
+ align-items: center;
1602
+ }
1603
+
1604
+ .portrait\:justify-center {
1605
+ justify-content: center;
1606
+ }
1607
+ }
1608
+
1620
1609
  @media (orientation: landscape) {
1621
- .landscape\:top-\[20vh\] {
1622
- top: 20vh;
1610
+ .landscape\:max-h-\[50vh\] {
1611
+ max-height: 50vh;
1623
1612
  }
1624
1613
  }
@@ -39,9 +39,6 @@ export class AbstractMainContainer extends Container {
39
39
  }
40
40
  triggerStoreInitState(...containersWithSpines) {
41
41
  RainMan.settingsStore.containersWithSpines.push(...containersWithSpines);
42
- RainMan.settingsStore.containersWithSpines.forEach((spine) => {
43
- spine.setAnimationTimescale(RainMan.settingsStore.batterySaverFlag);
44
- });
45
42
  RainMan.settingsStore.refreshBatterySaver();
46
43
  }
47
44
  get freeSpinPlate() {
@@ -189,7 +186,7 @@ export class AbstractMainContainer extends Container {
189
186
  }
190
187
  createUnderFramePanel() {
191
188
  const underFramePanel = new Graphics();
192
- underFramePanel.beginFill(0x0, 0.5);
189
+ underFramePanel.beginFill(0x0, 0.75);
193
190
  underFramePanel.drawRect(0, 0, 800, 100);
194
191
  return underFramePanel;
195
192
  }
@@ -306,15 +306,15 @@ export class AbstractSymbolsColumn extends Container {
306
306
  this.swapSymbolFace(symbol);
307
307
  }
308
308
  shouldPlaySpecialRollStopSound() {
309
- for (let i = 0; i <= RainMan.config.numberOfColumns; i++) {
310
- const currentColumn = this.columnsContainer.getColumnAtPosition(i);
311
- if (currentColumn !== this)
312
- continue;
313
- return !!currentColumn.symbols
314
- .slice(0, RainMan.config.numberOfRows)
315
- .find((symbol) => symbol.id === this.bonusSymbol);
316
- }
317
- return false;
309
+ return (Array.from({ length: RainMan.config.numberOfColumns }, (_, i) => i)
310
+ .map((i) => {
311
+ const column = this.columnsContainer.getColumnAtPosition(i);
312
+ if (column !== this)
313
+ return null;
314
+ return column.symbols.slice(0, RainMan.config.numberOfRows);
315
+ })
316
+ .flat()
317
+ .filter((symbol) => symbol && symbol.id === this.bonusSymbol).length >= 1);
318
318
  }
319
319
  handleStopping() {
320
320
  if (!this.topMostSymbol || this.phase === Phase.END)
@@ -1,3 +1,4 @@
1
+ import i18next from "i18next";
1
2
  import { Currencies } from "ts-money";
2
3
  import { ApiConfig } from "../application";
3
4
  import { SpinData, } from "../connectivity";
@@ -69,6 +70,7 @@ export class ConnectionWrapper {
69
70
  landscape: true,
70
71
  matched_ratio: "16:9",
71
72
  },
73
+ locale: i18next.language,
72
74
  vendor_id: RainMan.config.gameInitVendorId,
73
75
  }));
74
76
  RainMan.globals.currency = Currencies[this._initData.currency];
@@ -26,6 +26,7 @@ export type InitServerRequest = BaseServerRequest & {
26
26
  landscape: boolean;
27
27
  matched_ratio: string;
28
28
  };
29
+ locale: string;
29
30
  };
30
31
  export type SpinServerRequest = BaseServerRequest & {
31
32
  action: "spin";
@@ -59,6 +59,7 @@ export declare abstract class AbstractController<T> {
59
59
  private setRefreshButtonBasedOnPhase;
60
60
  private setMessageBoxBasedOnPhase;
61
61
  protected getReelIndexesToShowMysteryFx(spinLogic: SpinLogic): number[];
62
+ protected showSuperBonusWin(removeBonusWin: Promise<void>): void;
62
63
  protected handleSpinLogic(): void;
63
64
  protected throttledSpin(): void;
64
65
  private getBoughtNumberOfFreeSpins;
@@ -46,6 +46,7 @@ export class AbstractController {
46
46
  this.uiController = new UiController(this.config);
47
47
  this.componentRegistry = RainMan.componentRegistry;
48
48
  this.setupSpaceOrEnterListener();
49
+ RainMan.settingsStore.showSuperBonusWin = this.showSuperBonusWin.bind(this);
49
50
  }
50
51
  init() {
51
52
  const initData = this.connection.initData();
@@ -259,6 +260,17 @@ export class AbstractController {
259
260
  }
260
261
  return reelsIndexesWithScatter;
261
262
  }
263
+ showSuperBonusWin(removeBonusWin) {
264
+ this.changeGamePhase(gamePhases.BIG_WIN_INVOKED);
265
+ const winAmount = RainMan.settingsStore.cumulativeWinAmount > 0
266
+ ? RainMan.settingsStore.cumulativeWinAmount
267
+ : this.uiController.recentWin;
268
+ this.countWinBigWin(winAmount).then(async () => {
269
+ await removeBonusWin;
270
+ this.changeGamePhase(gamePhases.IDLE);
271
+ });
272
+ RainMan.settingsStore.resetCumulativeWinAmount();
273
+ }
262
274
  handleSpinLogic() {
263
275
  if (this.mainContainer.freeSpinPlate) {
264
276
  if (this.mainContainer.freeSpinPlate.shownAt === null ||
@@ -28,6 +28,7 @@ export declare class SettingsStore {
28
28
  HiResolutionFlag: boolean;
29
29
  batterySaverFlag: boolean;
30
30
  containersWithSpines: (ResumableContainer | SpineWithResumableContainer | SpriteWithResumableContainer)[];
31
+ cumulativeWinAmount: number;
31
32
  progress: number;
32
33
  singleWinExceeds: number;
33
34
  balancedIncreased: number;
@@ -41,6 +42,7 @@ export declare class SettingsStore {
41
42
  popupPaytableRepositionCallback?: () => void;
42
43
  updateVolumeButtonTexture?: () => void;
43
44
  handleModalInvocation?: (layerId: string) => void;
45
+ showSuperBonusWin?: (callback: Promise<void>) => void;
44
46
  private readonly initialAutoplaySettingsState;
45
47
  private modalsAvailable;
46
48
  private paytableMap;
@@ -48,6 +50,8 @@ export declare class SettingsStore {
48
50
  updateBetText(newText: string): void;
49
51
  get indexOfSpeedLevel(): number;
50
52
  get isFreeSpinsPlayEnabled(): boolean;
53
+ addCumulativeWinAmount(amount: number): void;
54
+ resetCumulativeWinAmount(): void;
51
55
  updateBet(newBet: number): void;
52
56
  setBatteryFlag(flag: boolean): void;
53
57
  refreshBatterySaver(): void;
@@ -65,6 +69,7 @@ export declare class SettingsStore {
65
69
  setBalancedDecreased(newValue: number): void;
66
70
  getMinimumPaytableValue(multipliers: RangeQuantityValue[keyof RangeQuantityValue]): number;
67
71
  getMaximumPaytableValue(multipliers: RangeQuantityValue[keyof RangeQuantityValue]): number;
72
+ forceSuperBigWin(removeBonusWin: Promise<void>): void;
68
73
  setDataForSymbolPaytablePopup(symbolId: SymbolId, repositionCallback: () => void): void;
69
74
  resetDataForSymbolPaytablePopup(): void;
70
75
  setUpdateVolumeButtonTexture(fn: () => void): void;
@@ -34,6 +34,7 @@ export class SettingsStore {
34
34
  HiResolutionFlag = getFromLocalStorage(LOCAL_STORAGE.hiResolution, true);
35
35
  batterySaverFlag = getFromLocalStorage(LOCAL_STORAGE.batterySaver, false);
36
36
  containersWithSpines = [];
37
+ cumulativeWinAmount = 0;
37
38
  progress = 0;
38
39
  singleWinExceeds = 0;
39
40
  balancedIncreased = 0;
@@ -47,6 +48,7 @@ export class SettingsStore {
47
48
  popupPaytableRepositionCallback;
48
49
  updateVolumeButtonTexture;
49
50
  handleModalInvocation;
51
+ showSuperBonusWin;
50
52
  initialAutoplaySettingsState = {
51
53
  infinitySpinsEnabled: false,
52
54
  onAnyWin: false,
@@ -105,6 +107,12 @@ export class SettingsStore {
105
107
  get isFreeSpinsPlayEnabled() {
106
108
  return this.howManyFreeSpinsLeft > 0 || this.isLastFreeSpin;
107
109
  }
110
+ addCumulativeWinAmount(amount) {
111
+ this.cumulativeWinAmount = this.cumulativeWinAmount + amount;
112
+ }
113
+ resetCumulativeWinAmount() {
114
+ this.cumulativeWinAmount = 0;
115
+ }
108
116
  updateBet(newBet) {
109
117
  this.bet = newBet;
110
118
  }
@@ -205,6 +213,9 @@ export class SettingsStore {
205
213
  return last(multipliers) || 0;
206
214
  return 0;
207
215
  }
216
+ forceSuperBigWin(removeBonusWin) {
217
+ this.showSuperBonusWin?.(removeBonusWin);
218
+ }
208
219
  setDataForSymbolPaytablePopup(symbolId, repositionCallback) {
209
220
  this.popupPaytableRepositionCallback = repositionCallback;
210
221
  this.popupPaytableRepositionCallback();
@@ -60,11 +60,11 @@ export const waitForAnimationToEnd = async (spine, animationName, loopAnimationN
60
60
  };
61
61
  export const setTimeScale = (spine, flag) => {
62
62
  spine.state.originalTimeScale ||= spine.state.timeScale;
63
- if (flag)
63
+ if (flag) {
64
64
  spine.state.timeScale = spine.state.originalTimeScale;
65
+ }
65
66
  else {
66
67
  spine.state.originalTimeScale = spine.state.timeScale;
67
- spine.state.timeScale = 0;
68
68
  }
69
69
  };
70
70
  export const changeResolution = (high) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixi-rainman-game-engine",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "This repository contains all of the mechanics that used in rainman games.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -9,6 +9,7 @@
9
9
  "copyCss": "yarn build:tailwind && copyfiles -u 1 \"src/**/*.css\" dist/",
10
10
  "build:tailwind": "tailwindcss -i ./src/SettingsUI/index.css -o ./src/SettingsUI/packedStyles.css",
11
11
  "build": "rimraf dist/ && tsc && yarn copyCss",
12
+ "generate:changelog": "yarn changelog generate",
12
13
  "dev:build": "tsc-watch --onSuccess \"yarn copyCss\"",
13
14
  "lint": "eslint src/** --fix",
14
15
  "prepublishOnly": "husky && yarn build",
@@ -56,6 +57,7 @@
56
57
  "eslint-plugin-simple-import-sort": "^12.0.0",
57
58
  "eslint-plugin-sort-class-members": "^1.20.0",
58
59
  "eslint-prettier-config": "^1.0.1",
60
+ "generate-changelog": "^1.8.0",
59
61
  "husky": "^9.0.11",
60
62
  "postcss": "^8.4.38",
61
63
  "prettier": "^3.2.5",