@involvex/youtube-music-cli 0.0.28 → 0.0.30
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/CHANGELOG.md +8 -0
- package/dist/source/components/common/ShortcutsBar.js +4 -3
- package/dist/source/components/layouts/MainLayout.js +3 -1
- package/dist/source/components/layouts/MiniPlayerLayout.js +2 -1
- package/dist/source/components/layouts/SearchLayout.js +2 -1
- package/dist/source/components/player/NowPlaying.js +2 -1
- package/dist/source/components/player/PlayerControls.js +2 -1
- package/dist/source/utils/icons.d.ts +19 -0
- package/dist/source/utils/icons.js +26 -0
- package/dist/youtube-music-cli.exe +0 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## [0.0.30](https://github.com/involvex/youtube-music-cli/compare/v0.0.29...v0.0.30) (2026-02-22)
|
|
2
|
+
|
|
3
|
+
## [0.0.29](https://github.com/involvex/youtube-music-cli/compare/v0.0.28...v0.0.29) (2026-02-22)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- prevent import navigation when in settings view ([d805b5a](https://github.com/involvex/youtube-music-cli/commit/d805b5a182a2241ab5494565dcf6645da82da954))
|
|
8
|
+
|
|
1
9
|
## [0.0.28](https://github.com/involvex/youtube-music-cli/compare/v0.0.27...v0.0.28) (2026-02-22)
|
|
2
10
|
|
|
3
11
|
### Bug Fixes
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// Shortcuts bar component
|
|
3
3
|
import { Box, Text } from 'ink';
|
|
4
4
|
import { usePlayer } from "../../hooks/usePlayer.js";
|
|
5
5
|
import { useTheme } from "../../hooks/useTheme.js";
|
|
6
6
|
import { useKeyBinding } from "../../hooks/useKeyboard.js";
|
|
7
7
|
import { KEYBINDINGS } from "../../utils/constants.js";
|
|
8
|
+
import { ICONS } from "../../utils/icons.js";
|
|
8
9
|
export default function ShortcutsBar() {
|
|
9
10
|
const { theme } = useTheme();
|
|
10
11
|
const { state: playerState, pause, resume, next, previous, volumeUp, volumeDown, volumeFineUp, volumeFineDown, toggleShuffle, toggleRepeat, } = usePlayer();
|
|
@@ -27,7 +28,7 @@ export default function ShortcutsBar() {
|
|
|
27
28
|
useKeyBinding(KEYBINDINGS.SHUFFLE, toggleShuffle);
|
|
28
29
|
useKeyBinding(KEYBINDINGS.REPEAT, toggleRepeat);
|
|
29
30
|
// Note: SETTINGS keybinding handled by MainLayout to avoid double-dispatch
|
|
30
|
-
return (_jsxs(Box, { borderStyle: "single", borderColor: theme.colors.dim, paddingX: 1, justifyContent: "space-between", children: [_jsxs(Text, { color: theme.colors.dim, children: [
|
|
31
|
+
return (_jsxs(Box, { borderStyle: "single", borderColor: theme.colors.dim, paddingX: 1, justifyContent: "space-between", children: [_jsxs(Text, { color: theme.colors.dim, children: [_jsxs(Text, { color: theme.colors.text, children: [ICONS.PLAY_PAUSE_ON, "/", ICONS.PAUSE, " [Space]"] }), ' ', "| ", _jsxs(Text, { color: theme.colors.text, children: [ICONS.PREV, " [B/\u2190]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.NEXT, " [N/\u2192]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.SHUFFLE, " [Shift+S]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.REPEAT_ALL, " [R]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.PLAYLIST, " [Shift+P]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.DOWNLOAD, " [Shift+D]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.SEARCH, " [/]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.HELP, " [?]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.BG_PLAY, " [Shift+Q]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.RESUME, " [Shift+R]"] }), " |", ' ', _jsxs(Text, { color: theme.colors.text, children: [ICONS.QUIT, " [Q]"] })] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: playerState.shuffle ? theme.colors.primary : theme.colors.dim, children: ICONS.SHUFFLE }), ' ', _jsx(Text, { color: playerState.repeat === 'off'
|
|
31
32
|
? theme.colors.dim
|
|
32
|
-
: theme.colors.secondary, children: playerState.repeat === 'one' ?
|
|
33
|
+
: theme.colors.secondary, children: playerState.repeat === 'one' ? ICONS.REPEAT_ONE : ICONS.REPEAT_ALL }), ' ', _jsxs(Text, { color: theme.colors.dim, children: [ICONS.VOLUME, " [=/-]"] }), ' ', _jsxs(Text, { color: theme.colors.primary, children: [playerState.volume, "%"] })] })] }));
|
|
33
34
|
}
|
|
@@ -80,7 +80,9 @@ function MainLayout() {
|
|
|
80
80
|
}, [dispatch, navState.currentView]);
|
|
81
81
|
const goToImport = useCallback(() => {
|
|
82
82
|
// Don't navigate to import if we're in plugins view (i key is used for plugin install there)
|
|
83
|
-
if (
|
|
83
|
+
// Don't navigate to import if we're in settings view (user navigates settings items with Enter)
|
|
84
|
+
if (navState.currentView !== VIEW.PLUGINS &&
|
|
85
|
+
navState.currentView !== VIEW.SETTINGS) {
|
|
84
86
|
dispatch({ category: 'NAVIGATE', view: VIEW.IMPORT });
|
|
85
87
|
}
|
|
86
88
|
}, [dispatch, navState.currentView]);
|
|
@@ -4,6 +4,7 @@ import { Box, Text } from 'ink';
|
|
|
4
4
|
import { usePlayer } from "../../hooks/usePlayer.js";
|
|
5
5
|
import { useTheme } from "../../hooks/useTheme.js";
|
|
6
6
|
import { formatTime } from "../../utils/format.js";
|
|
7
|
+
import { ICONS } from "../../utils/icons.js";
|
|
7
8
|
export default function MiniPlayerLayout() {
|
|
8
9
|
const { theme } = useTheme();
|
|
9
10
|
const { state } = usePlayer();
|
|
@@ -12,7 +13,7 @@ export default function MiniPlayerLayout() {
|
|
|
12
13
|
const title = track?.title ?? 'No track playing';
|
|
13
14
|
const progress = formatTime(state.progress);
|
|
14
15
|
const duration = formatTime(state.duration);
|
|
15
|
-
const playIcon = state.isPlaying ?
|
|
16
|
+
const playIcon = state.isPlaying ? ICONS.PLAY : ICONS.PAUSE;
|
|
16
17
|
const vol = `${state.volume}%`;
|
|
17
18
|
const speed = (state.speed ?? 1.0) !== 1.0 ? ` ${(state.speed ?? 1.0).toFixed(2)}x` : '';
|
|
18
19
|
return (_jsxs(Box, { flexDirection: "row", paddingX: 1, gap: 1, children: [_jsx(Text, { color: state.isPlaying ? theme.colors.success : theme.colors.dim, children: playIcon }), _jsx(Text, { bold: true, color: theme.colors.primary, children: title }), _jsx(Text, { color: theme.colors.dim, children: "\u2014" }), _jsx(Text, { color: theme.colors.secondary, children: artist }), _jsx(Text, { color: theme.colors.dim, children: "|" }), _jsxs(Text, { color: theme.colors.text, children: [progress, "/", duration] }), _jsx(Text, { color: theme.colors.dim, children: "|" }), _jsxs(Text, { color: theme.colors.text, children: ["vol:", vol] }), speed && _jsx(Text, { color: theme.colors.accent, children: speed }), state.isLoading && _jsx(Text, { color: theme.colors.accent, children: "Loading..." })] }));
|
|
@@ -11,6 +11,7 @@ import { useKeyBinding } from "../../hooks/useKeyboard.js";
|
|
|
11
11
|
import { KEYBINDINGS, VIEW } from "../../utils/constants.js";
|
|
12
12
|
import { Box, Text } from 'ink';
|
|
13
13
|
import { usePlayer } from "../../hooks/usePlayer.js";
|
|
14
|
+
import { ICONS } from "../../utils/icons.js";
|
|
14
15
|
function SearchLayout() {
|
|
15
16
|
const { theme } = useTheme();
|
|
16
17
|
const { state: navState, dispatch } = useNavigation();
|
|
@@ -118,7 +119,7 @@ function SearchLayout() {
|
|
|
118
119
|
lastAutoSearchedQueryRef.current = null;
|
|
119
120
|
};
|
|
120
121
|
}, [dispatch]);
|
|
121
|
-
return (_jsxs(Box, { flexDirection: "column", children: [playerState.currentTrack && (_jsxs(Box, { children: [_jsx(Text, { color: theme.colors.dim, children: playerState.isPlaying ?
|
|
122
|
+
return (_jsxs(Box, { flexDirection: "column", children: [playerState.currentTrack && (_jsxs(Box, { children: [_jsx(Text, { color: theme.colors.dim, children: playerState.isPlaying ? `${ICONS.PLAY} ` : `${ICONS.PAUSE} ` }), _jsx(Text, { color: theme.colors.primary, bold: true, children: playerState.currentTrack.title }), playerState.currentTrack.artists &&
|
|
122
123
|
playerState.currentTrack.artists.length > 0 && (_jsxs(Text, { color: theme.colors.secondary, children: [' • ', playerState.currentTrack.artists.map(a => a.name).join(', ')] }))] })), _jsxs(Text, { color: theme.colors.dim, children: ["Limit: ", navState.searchLimit, " (Use [ or ] to adjust)"] }), _jsx(SearchBar, { isActive: isTyping && !isSearching, onInput: input => {
|
|
123
124
|
void performSearch(input);
|
|
124
125
|
} }), (isLoading || isSearching) && (_jsx(Text, { color: theme.colors.accent, children: "Searching..." })), error && _jsx(Text, { color: theme.colors.error, children: error }), !isLoading && navState.hasSearched && (_jsx(SearchResults, { results: results, selectedIndex: navState.selectedResult, isActive: !isTyping, onMixCreated: handleMixCreated, onDownloadStatus: handleDownloadStatus })), !isLoading && navState.hasSearched && results.length === 0 && !error && (_jsx(Text, { color: theme.colors.dim, children: "No results found" })), actionMessage && (_jsx(Text, { color: theme.colors.accent, children: actionMessage })), _jsx(Text, { color: theme.colors.dim, children: isTyping
|
|
@@ -7,6 +7,7 @@ import { formatTime } from "../../utils/format.js";
|
|
|
7
7
|
import { useTerminalSize } from "../../hooks/useTerminalSize.js";
|
|
8
8
|
import { getSleepTimerService } from "../../services/sleep-timer/sleep-timer.service.js";
|
|
9
9
|
import { useState, useEffect } from 'react';
|
|
10
|
+
import { ICONS } from "../../utils/icons.js";
|
|
10
11
|
export default function NowPlaying() {
|
|
11
12
|
const { theme } = useTheme();
|
|
12
13
|
const { state: playerState } = usePlayer();
|
|
@@ -40,5 +41,5 @@ export default function NowPlaying() {
|
|
|
40
41
|
const percentage = duration > 0 ? Math.min(100, Math.floor((progress / duration) * 100)) : 0;
|
|
41
42
|
const barWidth = Math.max(10, columns - 8);
|
|
42
43
|
const filledWidth = duration > 0 ? Math.floor((progress / duration) * barWidth) : 0;
|
|
43
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.colors.primary, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: theme.colors.primary, children: track.title }), _jsx(Text, { color: theme.colors.dim, children: " \u2022 " }), _jsx(Text, { color: theme.colors.secondary, children: artists })] }), track.album && _jsx(Text, { color: theme.colors.dim, children: track.album.name }), _jsxs(Box, { children: [_jsx(Text, { color: theme.colors.primary, children: '█'.repeat(Math.min(filledWidth, barWidth)) }), _jsx(Text, { color: theme.colors.dim, children: '░'.repeat(Math.max(0, barWidth - filledWidth)) })] }), _jsxs(Box, { children: [_jsx(Text, { color: theme.colors.text, children: formatTime(progress) }), _jsxs(Text, { color: theme.colors.dim, children: [" / ", formatTime(duration), " "] }), _jsxs(Text, { color: theme.colors.dim, children: ["[", percentage, "%]"] }), playerState.isLoading && (_jsx(Text, { color: theme.colors.accent, children: " Loading..." })), !playerState.isPlaying && progress > 0 && (
|
|
44
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.colors.primary, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: theme.colors.primary, children: track.title }), _jsx(Text, { color: theme.colors.dim, children: " \u2022 " }), _jsx(Text, { color: theme.colors.secondary, children: artists })] }), track.album && _jsx(Text, { color: theme.colors.dim, children: track.album.name }), _jsxs(Box, { children: [_jsx(Text, { color: theme.colors.primary, children: '█'.repeat(Math.min(filledWidth, barWidth)) }), _jsx(Text, { color: theme.colors.dim, children: '░'.repeat(Math.max(0, barWidth - filledWidth)) })] }), _jsxs(Box, { children: [_jsx(Text, { color: theme.colors.text, children: formatTime(progress) }), _jsxs(Text, { color: theme.colors.dim, children: [" / ", formatTime(duration), " "] }), _jsxs(Text, { color: theme.colors.dim, children: ["[", percentage, "%]"] }), playerState.isLoading && (_jsx(Text, { color: theme.colors.accent, children: " Loading..." })), !playerState.isPlaying && progress > 0 && (_jsxs(Text, { color: theme.colors.dim, children: [" ", ICONS.PAUSE] })), playerState.shuffle && (_jsxs(Text, { color: theme.colors.primary, children: [" ", ICONS.SHUFFLE] })), sleepRemaining !== null && (_jsxs(Text, { color: theme.colors.warning, children: [' ', "\u23FE ", formatTime(sleepRemaining)] }))] }), playerState.error && (_jsx(Text, { color: theme.colors.error, children: playerState.error }))] }));
|
|
44
45
|
}
|
|
@@ -7,6 +7,7 @@ import { useTheme } from "../../hooks/useTheme.js";
|
|
|
7
7
|
import { Box, Text } from 'ink';
|
|
8
8
|
import { useEffect } from 'react';
|
|
9
9
|
import { logger } from "../../services/logger/logger.service.js";
|
|
10
|
+
import { ICONS } from "../../utils/icons.js";
|
|
10
11
|
let mountCount = 0;
|
|
11
12
|
export default function PlayerControls() {
|
|
12
13
|
const instanceId = ++mountCount;
|
|
@@ -40,5 +41,5 @@ export default function PlayerControls() {
|
|
|
40
41
|
useKeyBinding(KEYBINDINGS.SPEED_UP, speedUp);
|
|
41
42
|
useKeyBinding(KEYBINDINGS.SPEED_DOWN, speedDown);
|
|
42
43
|
useKeyBinding(KEYBINDINGS.SHUFFLE, toggleShuffle);
|
|
43
|
-
return (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", paddingX: 2, borderStyle: "classic", borderColor: theme.colors.dim, children: [_jsxs(Text, { color: theme.colors.text, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "\u2190 / b" }), "] Prev"] }), _jsx(Text, { color: theme.colors.primary, children: playerState.isPlaying ? (_jsxs(Text, { children: ["[", _jsx(Text, { color: theme.colors.dim, children: "Space" }), "] Pause"] })) : (_jsxs(Text, { children: ["[", _jsx(Text, { color: theme.colors.dim, children: "Space" }), "] Play"] })) }), _jsxs(Text, { color: theme.colors.text, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "\u2192 / n" }), "] Next"] }), _jsxs(Text, { color: theme.colors.text, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "+/-" }), "] Vol: ", playerState.volume, "%"] }), _jsxs(Text, { color: playerState.shuffle ? theme.colors.primary : theme.colors.dim, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "Shift+S" }), "]", ' ', playerState.shuffle ?
|
|
44
|
+
return (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", paddingX: 2, borderStyle: "classic", borderColor: theme.colors.dim, children: [_jsxs(Text, { color: theme.colors.text, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "\u2190 / b" }), "] Prev"] }), _jsx(Text, { color: theme.colors.primary, children: playerState.isPlaying ? (_jsxs(Text, { children: ["[", _jsx(Text, { color: theme.colors.dim, children: "Space" }), "] Pause"] })) : (_jsxs(Text, { children: ["[", _jsx(Text, { color: theme.colors.dim, children: "Space" }), "] Play"] })) }), _jsxs(Text, { color: theme.colors.text, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "\u2192 / n" }), "] Next"] }), _jsxs(Text, { color: theme.colors.text, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "+/-" }), "] Vol: ", playerState.volume, "%"] }), _jsxs(Text, { color: playerState.shuffle ? theme.colors.primary : theme.colors.dim, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "Shift+S" }), "]", ' ', playerState.shuffle ? `${ICONS.SHUFFLE} ON` : `${ICONS.SHUFFLE} OFF`] }), (playerState.speed ?? 1.0) !== 1.0 && (_jsxs(Text, { color: theme.colors.accent, children: ["[", _jsx(Text, { color: theme.colors.dim, children: "<>" }), "]", ' ', (playerState.speed ?? 1.0).toFixed(2), "x"] }))] }));
|
|
44
45
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const ICONS: {
|
|
2
|
+
readonly PLAY: "▶";
|
|
3
|
+
readonly PAUSE: "‖";
|
|
4
|
+
readonly PLAY_PAUSE_ON: "▶";
|
|
5
|
+
readonly PLAY_PAUSE_OFF: "‖";
|
|
6
|
+
readonly NEXT: "▶|";
|
|
7
|
+
readonly PREV: "|◀";
|
|
8
|
+
readonly SHUFFLE: "⇄";
|
|
9
|
+
readonly REPEAT_ALL: "↻";
|
|
10
|
+
readonly REPEAT_ONE: "↺";
|
|
11
|
+
readonly PLAYLIST: "☰";
|
|
12
|
+
readonly SEARCH: "/";
|
|
13
|
+
readonly HELP: "?";
|
|
14
|
+
readonly DOWNLOAD: "↓";
|
|
15
|
+
readonly QUIT: "×";
|
|
16
|
+
readonly RESUME: "⟳";
|
|
17
|
+
readonly BG_PLAY: "○";
|
|
18
|
+
readonly VOLUME: "♪";
|
|
19
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Universal icon constants using widely-supported Unicode BMP characters.
|
|
2
|
+
// No emoji, no Nerd Font codepoints — renders correctly on any terminal font.
|
|
3
|
+
export const ICONS = {
|
|
4
|
+
// Playback controls
|
|
5
|
+
PLAY: '▶', // U+25B6
|
|
6
|
+
PAUSE: '‖', // U+2016
|
|
7
|
+
PLAY_PAUSE_ON: '▶', // when playing
|
|
8
|
+
PLAY_PAUSE_OFF: '‖', // when paused
|
|
9
|
+
NEXT: '▶|', // next track
|
|
10
|
+
PREV: '|◀', // previous track
|
|
11
|
+
// Playback modes
|
|
12
|
+
SHUFFLE: '⇄', // U+21C4
|
|
13
|
+
REPEAT_ALL: '↻', // U+21BB
|
|
14
|
+
REPEAT_ONE: '↺', // U+21BA
|
|
15
|
+
// Navigation / views
|
|
16
|
+
PLAYLIST: '☰', // U+2630
|
|
17
|
+
SEARCH: '/', // ASCII
|
|
18
|
+
HELP: '?', // ASCII
|
|
19
|
+
// Actions
|
|
20
|
+
DOWNLOAD: '↓', // U+2193
|
|
21
|
+
QUIT: '×', // U+00D7
|
|
22
|
+
RESUME: '⟳', // U+27F3
|
|
23
|
+
BG_PLAY: '○', // U+25CB
|
|
24
|
+
// Status
|
|
25
|
+
VOLUME: '♪', // U+266A
|
|
26
|
+
};
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@involvex/youtube-music-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"description": "- A Commandline music player for youtube-music",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -65,11 +65,11 @@
|
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"@distube/ytdl-core": "^4.16.12",
|
|
67
67
|
"ansi-escapes": "^7.3.0",
|
|
68
|
-
"ink": "^6.
|
|
68
|
+
"ink": "^6.8.0",
|
|
69
69
|
"ink-table": "^3.1.0",
|
|
70
70
|
"ink-text-input": "^6.0.0",
|
|
71
71
|
"jiti": "^2.6.1",
|
|
72
|
-
"meow": "^14.
|
|
72
|
+
"meow": "^14.1.0",
|
|
73
73
|
"node-notifier": "^10.0.1",
|
|
74
74
|
"discord-rpc": "^4.0.1",
|
|
75
75
|
"node-youtube-music": "^0.10.3",
|
|
@@ -77,20 +77,20 @@
|
|
|
77
77
|
"react": "^19.2.4",
|
|
78
78
|
"youtube-ext": "^1.1.25",
|
|
79
79
|
"youtubei.js": "^16.0.1",
|
|
80
|
-
"ws": "^8.
|
|
80
|
+
"ws": "^8.19.0"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@eslint/js": "^10.0.1",
|
|
84
84
|
"@sindresorhus/tsconfig": "^8.1.0",
|
|
85
|
-
"@types/node": "^25.
|
|
85
|
+
"@types/node": "^25.3.0",
|
|
86
86
|
"@types/node-notifier": "^8.0.5",
|
|
87
87
|
"@types/react": "^19.2.14",
|
|
88
|
-
"@types/ws": "^8.
|
|
88
|
+
"@types/ws": "^8.18.1",
|
|
89
89
|
"@vdemedes/prettier-config": "^2.0.1",
|
|
90
90
|
"ava": "^6.4.1",
|
|
91
91
|
"chalk": "^5.6.2",
|
|
92
92
|
"conventional-changelog-cli": "^5.0.0",
|
|
93
|
-
"eslint": "^10.0.
|
|
93
|
+
"eslint": "^10.0.1",
|
|
94
94
|
"eslint-plugin-react": "^7.37.5",
|
|
95
95
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
96
96
|
"globals": "^17.3.0",
|