mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-01-11 22:40:31 +00:00
refactor: use chips instead of multiselect for library filters
This commit is contained in:
parent
1c57dd3a65
commit
1cf2339a35
16 changed files with 321 additions and 69 deletions
129
package-lock.json
generated
129
package-lock.json
generated
|
|
@ -63,6 +63,8 @@
|
|||
"postcss-loader": "6.2.0",
|
||||
"readdirp": "3.6.0",
|
||||
"terser-webpack-plugin": "5.2.4",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.2",
|
||||
"webpack": "5.61.0",
|
||||
"webpack-cli": "4.9.1",
|
||||
"webpack-dev-server": "^4.7.4",
|
||||
|
|
@ -13023,6 +13025,120 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader": {
|
||||
"version": "9.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz",
|
||||
"integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
"enhanced-resolve": "^5.0.0",
|
||||
"micromatch": "^4.0.0",
|
||||
"semver": "^7.3.4",
|
||||
"source-map": "^0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*",
|
||||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/semver": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"license": "0BSD"
|
||||
|
|
@ -13077,6 +13193,19 @@
|
|||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz",
|
||||
"integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.0.1",
|
||||
"dev": true,
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@
|
|||
"postcss-loader": "6.2.0",
|
||||
"readdirp": "3.6.0",
|
||||
"terser-webpack-plugin": "5.2.4",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.2",
|
||||
"webpack": "5.61.0",
|
||||
"webpack-cli": "4.9.1",
|
||||
"webpack-dev-server": "^4.7.4",
|
||||
|
|
|
|||
34
src/common/Chips/Chip/Chip.less
Normal file
34
src/common/Chips/Chip/Chip.less
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (C) 2017-2024 Smart code 203358507
|
||||
|
||||
@height: 2.75rem;
|
||||
|
||||
.chip {
|
||||
flex: none;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: @height;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
color: var(--primary-foreground-color);
|
||||
white-space: nowrap;
|
||||
text-transform: capitalize;
|
||||
padding: 0 1.5rem;
|
||||
border-radius: @height;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: transparent;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--overlay-color);
|
||||
transition: background-color 0.1s ease-out;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: 600;
|
||||
background-color: var(--primary-accent-color);
|
||||
transition: background-color 0.1s ease-in;
|
||||
}
|
||||
}
|
||||
45
src/common/Chips/Chip/Chip.tsx
Normal file
45
src/common/Chips/Chip/Chip.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (C) 2017-2024 Smart code 203358507
|
||||
|
||||
import React, { MouseEvent, memo, useCallback, useEffect, useRef } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Button from 'stremio/common/Button';
|
||||
import styles from './Chip.less';
|
||||
|
||||
type Props = {
|
||||
label: string,
|
||||
value: string,
|
||||
active: boolean,
|
||||
onSelect: (value: string) => void,
|
||||
};
|
||||
|
||||
const Chip = memo(({ label, value, active, onSelect }: Props) => {
|
||||
const ref = useRef<HTMLElement>(null);
|
||||
|
||||
const onClick = useCallback(({ currentTarget }: MouseEvent<HTMLElement>) => {
|
||||
const value = currentTarget.dataset['value'];
|
||||
value && onSelect(value);
|
||||
}, [onselect]);
|
||||
|
||||
useEffect(() => {
|
||||
active && ref.current?.scrollIntoView({
|
||||
block: 'nearest',
|
||||
inline: 'center',
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}, [active]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
key={value}
|
||||
className={classNames(styles['chip'], { [styles['active']]: active })}
|
||||
tabIndex={-1}
|
||||
data-value={value}
|
||||
onClick={onClick}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
);
|
||||
});
|
||||
|
||||
export default Chip;
|
||||
4
src/common/Chips/Chip/index.ts
Normal file
4
src/common/Chips/Chip/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Copyright (C) 2017-2024 Smart code 203358507
|
||||
|
||||
import Chip from './Chip';
|
||||
export default Chip;
|
||||
25
src/common/Chips/Chips.less
Normal file
25
src/common/Chips/Chips.less
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (C) 2017-2024 Smart code 203358507
|
||||
|
||||
@mask-width: 10%;
|
||||
|
||||
.chips {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 1rem;
|
||||
overflow-x: auto;
|
||||
|
||||
&.left {
|
||||
mask-image: linear-gradient(90deg, rgba(0, 0, 0, 1) calc(100% - @mask-width), rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
|
||||
&.right {
|
||||
mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) @mask-width);
|
||||
}
|
||||
|
||||
&.center {
|
||||
mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) @mask-width, rgba(0, 0, 0, 1) calc(100% - @mask-width), rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
}
|
||||
51
src/common/Chips/Chips.tsx
Normal file
51
src/common/Chips/Chips.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (C) 2017-2024 Smart code 203358507
|
||||
|
||||
import React, { memo, useEffect, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Chip from './Chip';
|
||||
import styles from './Chips.less';
|
||||
|
||||
type Option = {
|
||||
label: string,
|
||||
value: string,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
options: Option[],
|
||||
selected: string[],
|
||||
onSelect: (value: string) => {},
|
||||
};
|
||||
|
||||
const Chips = memo(({ options, selected, onSelect }: Props) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [scrollPosition, setScrollPosition] = useState('left');
|
||||
|
||||
useEffect(() => {
|
||||
const onScroll = ({ target }: Event) => {
|
||||
const { scrollLeft, scrollWidth, offsetWidth} = target as HTMLDivElement;
|
||||
const position = scrollLeft === 0 ? 'left' : scrollLeft + offsetWidth >= scrollWidth ? 'right' : 'center';
|
||||
setScrollPosition(position);
|
||||
};
|
||||
|
||||
ref.current?.addEventListener('scroll', onScroll);
|
||||
return () => ref.current?.removeEventListener('scroll', onScroll);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div ref={ref} className={classNames(styles['chips'], [styles[scrollPosition]])}>
|
||||
{
|
||||
options.map(({ label, value }) => (
|
||||
<Chip
|
||||
key={value}
|
||||
label={label}
|
||||
value={value}
|
||||
active={selected.includes(value)}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default Chips;
|
||||
4
src/common/Chips/index.ts
Normal file
4
src/common/Chips/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Copyright (C) 2017-2024 Smart code 203358507
|
||||
|
||||
import Chips from './Chips';
|
||||
export default Chips;
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
const AddonDetailsModal = require('./AddonDetailsModal');
|
||||
const Button = require('./Button');
|
||||
const Checkbox = require('./Checkbox');
|
||||
const { default: Chips } = require('./Chips');
|
||||
const ColorInput = require('./ColorInput');
|
||||
const ContinueWatchingItem = require('./ContinueWatchingItem');
|
||||
const DelayedRenderer = require('./DelayedRenderer');
|
||||
|
|
@ -50,6 +51,7 @@ module.exports = {
|
|||
AddonDetailsModal,
|
||||
Button,
|
||||
Checkbox,
|
||||
Chips,
|
||||
ColorInput,
|
||||
ContinueWatchingItem,
|
||||
DelayedRenderer,
|
||||
|
|
|
|||
5
src/modules.d.ts
vendored
5
src/modules.d.ts
vendored
|
|
@ -1,2 +1,3 @@
|
|||
declare module '*';
|
||||
declare module 'classnames';
|
||||
declare module '*.less';
|
||||
declare module 'stremio/common';
|
||||
declare module 'stremio/common/*';
|
||||
|
|
@ -3,9 +3,8 @@
|
|||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const { default: Icon } = require('@stremio/stremio-icons/react');
|
||||
const NotFound = require('stremio/routes/NotFound');
|
||||
const { Button, DelayedRenderer, Multiselect, MainNavBars, LibItem, Image, ModalDialog, useProfile, useNotifications, routesRegexp, useOnScrollToBottom, useBinaryState, withCoreSuspender } = require('stremio/common');
|
||||
const { Button, Chips, DelayedRenderer, Multiselect, MainNavBars, LibItem, Image, useProfile, useNotifications, routesRegexp, useOnScrollToBottom, withCoreSuspender } = require('stremio/common');
|
||||
const useLibrary = require('./useLibrary');
|
||||
const useSelectableInputs = require('./useSelectableInputs');
|
||||
const styles = require('./styles');
|
||||
|
|
@ -49,8 +48,7 @@ const Library = ({ model, urlParams, queryParams }) => {
|
|||
const profile = useProfile();
|
||||
const notifications = useNotifications();
|
||||
const [library, loadNextPage] = useLibrary(model, urlParams, queryParams);
|
||||
const [typeSelect, sortSelect, hasNextPage] = useSelectableInputs(library);
|
||||
const [inputsModalOpen, openInputsModal, closeInputsModal] = useBinaryState(false);
|
||||
const [typeSelect, sortChips, hasNextPage] = useSelectableInputs(library);
|
||||
const scrollContainerRef = React.useRef(null);
|
||||
const onScrollToBottom = React.useCallback(() => {
|
||||
if (hasNextPage) {
|
||||
|
|
@ -70,11 +68,7 @@ const Library = ({ model, urlParams, queryParams }) => {
|
|||
model === 'continue_watching' || profile.auth !== null ?
|
||||
<div className={styles['selectable-inputs-container']}>
|
||||
<Multiselect {...typeSelect} className={styles['select-input-container']} />
|
||||
<Multiselect {...sortSelect} className={styles['select-input-container']} />
|
||||
<div className={styles['spacing']} />
|
||||
<Button className={styles['filter-container']} title={'All filters'} onClick={openInputsModal}>
|
||||
<Icon className={styles['filter-icon']} name={'filters'} />
|
||||
</Button>
|
||||
<Chips {...sortChips} className={styles['select-input-container']} />
|
||||
</div>
|
||||
:
|
||||
null
|
||||
|
|
@ -122,15 +116,6 @@ const Library = ({ model, urlParams, queryParams }) => {
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
inputsModalOpen ?
|
||||
<ModalDialog title={'Library filters'} className={styles['selectable-inputs-modal']} onCloseRequest={closeInputsModal}>
|
||||
<Multiselect {...typeSelect} className={styles['select-input-container']} />
|
||||
<Multiselect {...sortSelect} className={styles['select-input-container']} />
|
||||
</ModalDialog>
|
||||
:
|
||||
null
|
||||
}
|
||||
</MainNavBars>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,28 +46,6 @@
|
|||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
flex: none;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--overlay-color);
|
||||
|
||||
.filter-icon {
|
||||
flex: none;
|
||||
width: 1.4rem;
|
||||
height: 1.4rem;
|
||||
color: var(--primary-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
.spacing {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.message-container {
|
||||
|
|
@ -241,18 +219,6 @@
|
|||
.library-content {
|
||||
.selectable-inputs-container {
|
||||
justify-content: space-between;
|
||||
|
||||
.select-input-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.spacing {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.meta-items-container {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ const mapSelectableInputs = (library, t) => {
|
|||
window.location = event.value;
|
||||
}
|
||||
};
|
||||
const sortSelect = {
|
||||
title: t.string('SELECT_SORT'),
|
||||
const sortChips = {
|
||||
options: library.selectable.sorts
|
||||
.map(({ sort, deepLinks }) => ({
|
||||
value: deepLinks.library,
|
||||
|
|
@ -28,11 +27,11 @@ const mapSelectableInputs = (library, t) => {
|
|||
selected: library.selectable.sorts
|
||||
.filter(({ selected }) => selected)
|
||||
.map(({ deepLinks }) => deepLinks.library),
|
||||
onSelect: (event) => {
|
||||
window.location = event.value;
|
||||
onSelect: (value) => {
|
||||
window.location = value;
|
||||
}
|
||||
};
|
||||
return [typeSelect, sortSelect, library.selectable.nextPage];
|
||||
return [typeSelect, sortChips, library.selectable.nextPage];
|
||||
};
|
||||
|
||||
const useSelectableInputs = (library) => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
const fs = require('fs');
|
||||
const readdirp = require('readdirp');
|
||||
|
||||
const COPYRIGHT_HEADER = /^\/\/ Copyright \(C\) 2017-2023 Smart code 203358507.*/;
|
||||
const COPYRIGHT_HEADER = /^\/\/ Copyright \(C\) 2017-\d{4} Smart code 203358507.*/;
|
||||
|
||||
describe('copyright', () => {
|
||||
test('js', async () => {
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM", "DOM.Iterable"],
|
||||
"jsx": "preserve",
|
||||
"rootDir": "./src",
|
||||
"jsx": "react",
|
||||
"baseUrl": "src",
|
||||
"moduleResolution": "node",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"stremio/*": ["src/*"],
|
||||
},
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"allowJs": true,
|
||||
"checkJs": false,
|
||||
"noEmit": true,
|
||||
"strict": false
|
||||
"noEmit": false,
|
||||
"strict": true,
|
||||
},
|
||||
"include": [
|
||||
"./src",
|
||||
"src",
|
||||
],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ module.exports = (env, argv) => ({
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(ts|tsx)$/,
|
||||
exclude: /node_modules/,
|
||||
use: 'ts-loader',
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
exclude: /node_modules/,
|
||||
|
|
@ -142,10 +147,10 @@ module.exports = (env, argv) => ({
|
|||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.json', '.less', '.wasm'],
|
||||
extensions: ['.tsx', '.ts', '.js', '.json', '.less', '.wasm'],
|
||||
alias: {
|
||||
'stremio': path.join(__dirname, 'src'),
|
||||
'stremio-router': path.join(__dirname, 'src', 'router')
|
||||
'stremio': path.resolve(__dirname, 'src'),
|
||||
'stremio-router': path.resolve(__dirname, 'src', 'router')
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue