Giter Club home page Giter Club logo

lit-redux-router's People

Contributors

anoblet avatar bnf avatar dependabot[bot] avatar fernandopasik avatar hutchgrant avatar waxolunist avatar zainafzal08 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

lit-redux-router's Issues

add option to disable / opt-out of Shadow DOM to support global CSS libraries

Feature Request

Problem to solve

As great as Shadow DOM in Web Components is, for projects supporting and / or trying to migrate away from global CSS, they may need to keep global CSS in lieu of encapsulating all styles.

How this relates to this project is that the custom element provided by this library has it enabled, which means for all apps using this library but also trying to use libraries like Bootstrap or Font Awesome (like me ๐Ÿ˜… ), this library will block out all those global styles within the route. (which is the expected behavior, naturally).

(screenshots and more details at the end ๐Ÿ‘‡ )

Possible implementation

Lit provides a way to disable this from the LitElement base class by using createRenderRoot

export class MyComponent extends LitElement {
  ...
  
  createRenderRoot() {
    return this;
  }
}

Thinking of this from a user of this library's perspective, I think it would look something like this

<lit-route
  path="/"
  component="as-route-home"
  shadow="false"
  .resolve="${() => import('/routes/home/home.js')}">
</lit-route>

Not specifically sure how that would be implemented within this project though on the fly though?

export class LitRoute extends LitElement {
  ...

  static get properties() {
    return {
      shadow: {
        type: Boolean
      }
    };
  }

  constructor() {
    super();
    this.shadow = true;
  }

  createRenderRoot() {
    return this.shadow ? this.shadowRoot : this;
  }
}

(Lit doesn't specify what the default would be, I am assuming it is this.shadowRoot, but i can certainly ask on their issue tracker if it helps)

Alternatives considered

Technically there is one way to work around this, which is to just literally inline / include all that global CSS into the Shadow DOM for each custom element. Unfortunately, this means you'll basically be duplicating all that CSS over and over, which is terrible for bundle size and user experience.

Additional context

You can check out my work in progress in this PR trying to to make all the CSS global, with the following observations:

  • As a test, the header includes an icon from Font Awesome, which displays when the header is NOT in a route, and is not visible when the header IS in a route. Thus <LitRoute> is acting as a Shadow "boundary" preventing FA and Bootstrap from getting through to all the child components.
  • The difference in bundle size when not needing to inline all the duplicate global CSS is pretty significant: going from 1.3 MB to 289 KB!
    Screen Shot 2021-12-24 at 5 41 01 PM

Accessibility

Is your feature request related to a problem? Please describe.
There are several problems associated under the topic of accessibility which would be nice to have addressed

  1. links being able to open new tabs
  2. focus management i.e. page focuses at top of content on route change
  3. keyboard accessibility

Describe the solution you'd like
I suggest an additional component, specifically for router links. That way some of this could be managed easier. As for focus management, maybe when the component renders, the route.ts can automatically force the window to scroll ?

Describe alternatives you've considered
I have considered having new components force the window to the top when first updated. I don't think that's the best idea because you would have to do that for every component on each route. The rest could all be individually addressed in each application but that seems unnecessary if many people will encounter these issues.

Additional context
I was looking at a recent post by the React/Redux developer Dan Abramov in an issue thread about MDN's preference for react instead of web components where he gives good examples, including react reach router, that supports accessibility. I figure, with some effort, some of those features could be implemented in or alongside lit-redux-router as well.

Lazy Loaded components are never rendered

Expected behavior

Lazy loading when using <lit-route .resolve="{() => import('foobar')}" component="โ€ฆ"> renders the given compoent.

Current behavior

Because of a typo in

typeof window.customElements.get(this.component) === 'undefined'
a defined component is always considered unsresolved, which means the lazy component is never being rendered.

Possible solution

Use typeof window.customElements.get(this.component) !== 'undefined' in unsetResolving().

Affected versions

  • v0.15.7 โ€ฆ v0.15.8
  • v0.16.0 โ€ฆ v0.16.1

JS error in Edge v44

Describe the bug
Viewing a page that implements the <lit-route> custom element results in the following javascript error:

0: A custom element with name 'lit-route' has already been defined.

To Reproduce
Steps to reproduce the behavior:

  1. Install pwa-starter-kit (v0.9.0)
  2. Install lit-redux-router (v0.11.5)
  3. Add a <lit-route> tag in the render() method of 'my-app\src\components\my-app.js'
  4. In the console, execute npm run start to serve the demo application
  5. Navigate to localhost:8081 in Microsoft Edge 44.18362.449.0
  6. Hit F12 to bring up the developer console, and see the javascript error.

Expected behavior
<lit-route> should only be registered once, initially, in the CustomElementRegistry.

Screenshots
image

Device (please complete the following information):

  • Type: desktop
  • OS: Microsoft Windows 10 Pro - Version 10.0.18362 Build 18362
  • Browser Microsoft Edge
  • Version 44.18362.449.0

Pass Props to Component

I've gotta say: nice job on lit-redux-router! It was a breeze to set up, and I've been enjoying working with it so far.

Is your feature request related to a problem? Please describe.
As a developer, it would be nice to be able to pass props into the component that's conditionally rendered.

Describe the solution you'd like
Since you're using lit-html's unsafeHtml() function to conditionally render components, it might be easily accomplished by providing an Object-typed property to lit-route that could be called props, or something like that. A consolidation object could be created from using the spread operator (or Object.assign()) with the proposed props object and current params object you're passing to getTemplate(), which already converts that input object's KVPs into a string of element attribute/values. Roughly something like this:

export default (store: Store<State> & LazyStore) => {
  @customElement('lit-route')
  class Route extends connect(store)(LitElement) {
    /* ...other prop declarations here */

    @property({ type: Object })
    private props: Object = {};

    /* ..other method declarations here */

    public render(): TemplateResult {
      if (!this.active) {
        return html``;
      }

      if (this.resolve && this.isResolving) {
        return !this.loading ? html`` : this.getTemplate(this.loading);
      }

      if (!this.component) {
        return html`<slot></slot>`;
      }

      const attrs = [...this.props, ...this.params]; // have params always take merge-precedence
      return this.getTemplate(this.component, attrs);
    }
  }

  RouteClass = Route;
};

Describe alternatives you've considered
I only need this for a layout property that I like passing down the DOM for all of my components. Not sure if that's the best way to handle layouts since media queries are thing, but that's how my team wants to implement responsiveness into our web app (I'd like to get my entire office to switch over from our in-house routing solution to your lit-redux-router package, and my proof-of-concept might actually do it). I find that approach simple too since I can just use attribute selectors for my layout components.

Anyway, being able to inject custom properties would be nice to have because then I can reduce the need for the store for common things like the layout.

EDIT: After looking at my current app demo, it would be helpful to pass other properties down. We need to implement sub-apps where each sub-app uses a reusable app-layout component for the header bar, and the navigation side-bar. Feeding props into my app-layout component instances when their route becomes active would simplify the current way I'm doing this (I made a wrapper component for each sub-app that feeds the data in).

Component reloads on every state change

Current behavior

Everytime something changes in the redux state, the component reloads. I suspect it is because of resolve() being called within stateChanged method.

Expected behavior

If the component is already active, it shouldn't reload again on state change.

Steps to reproduce

  1. Use resolve attribute in lit-route.
  2. Update the state.
  3. Observe that the component reloads despite of being active.

Possible solution

resolve() to be called only when the active property changes for the element.
So, the below could move to updated() - lit-element life-cycle event.

            if (this.active && this.resolve) {
                this.isResolving = true;
                this.resolve()
                    .then(() => {
                    this.isResolving = false;
                })
                    .catch(() => {
                    this.isResolving = false;
                });
            }

route not working.

Describe the bug
I tried to test demo by copy source file in demo to new project but not working on swap a new page function.

To Reproduce
It's show error ('unsafeHTML can only be used in text bindings');

Expected behavior

Screenshots
show normal page

Device (please complete the following information):

  • Type: desktop
  • OS: debien 9
  • Browser : chromium

Screenshot 2020-01-06 07 16 09

Whole element is replaced instead of just the attributes.

The whole lit-route component is replaced everytime only a param is changed.
This should only update the component attribute.
I think the problem is in the way the html is made with the unsafeHTML directive.
Is there a way to optimize this?

getComponentTemplate() {
      const tagName = this.component.replace(/[^A-Za-z-]/, '');
      const attributes = Object
        .keys(this.params)
        .map(param => ` ${param}="${this.params[param]}"`)
        .join('');
      const template = `<${tagName}${attributes}></${tagName}>`;

      return html`${unsafeHTML(template)}`;
    }

Add authentication property

Feature Request

Problem to solve

It would be really good to be able to add an authentication attribute to the lit-route element. I would like some routes to be inaccessible with the correct permissions and it would be easier to manage the authentication process in the router rather than each view.

Possible implementation

Add new property .secure that needs to resolve before the new route is loaded and the previous route is unloaded.

Alternatives considered

The current .resolve property does quite do the job as it still loads the component before waiting for the promise. Fixing it to not show the component until .resolve has returned correctly from the Promise could also solve the issue.

Allow the use of sub-routers

Feature Request

Problem to solve

Allow the use of sub-routers. For big projects having only a single router can end up quite large. Being able to have sub-routers means a project can be more modular as well.

import './views/router';
import './pages/router';

class MyApp extends LitElement {
  render() {
    return html`
      <lit-route><h1>404</h1></lit-route>
      <lit-route path="/" component="home-view"></lit-route>
      <lit-route path="/views" component="views-router"></lit-route>
      <lit-route path="/pages" component="pages-router"></lit-route>
    `;
  }
}
customElements.define('my-app', MyApp);

then an example of ./views/router.js file

[import individual pages here

const tag = 'views-router';
class ViewsRouter extends LitElement {
  createRenderRoot() {
    return this;
  }
  render() {
    return html`
        <lit-route path="/1" component="views-1"></lit-route>
        ...
        <lit-route path="/100" component="views-100"></lit-route>
    `;
  }
}

customElements.define(tag, ViewsRouter);

Possible implementation

In the route.ts file change public firstUpdated(): void {... to

public async firstUpdated(): Promise<void> {
      await this.updateComplete;
      ...

and update the test spec to match with async-await

Alternatives considered

Additional context

There might be further things to change and update. The issues that I've come across with this implementation is:

  • needs to be <lit-route path"..."><sub-router></sub-router></lit-route> instead of using the component property
  • if you define a default route at the top of the sub-router then it gets marked as active as well
  • can't use the shadow dom in the sub-router so need to remember to set the createRenderRoot() { return this; }

how to get query params

Hey,

Is there a way to get the query params using the library?

If not, maybe we could extract it in the navigate method and store it in redux state?

Upgrade to latest version / distribution of `Lit@2`

Problem to solve

lit-html and LitElement have / are getting a new release all under a new top level package namespace called lit.

Although lit is technically still in RC, it would be helpful to ensure that the API of both LitElement and lit-html are indeed backwards compatible, as well as possibly seeding some beta releases for users of this library to help test.

Possible implementation

Per the upgrade docs, lit-redux-router would likely need to do the following:

  1. Update import statements to reference lit instead of lit-element or lit-html
  2. Update package.json to reference a single dependency on the lit package, for both devDependencies and peerDependencies
  3. Any additional steps needed per the guide

Alternatives considered

N / A

Additional context

Happy to help test this out and / or contribute! โœŒ๏ธ

Update

Could you update lit-html, and lit-element? I tried but your tooling wasn't working for me.

handle hash jump

Is it possible to handle a hash link to an id?

e.g. /pageone/section#three

this would ideally scroll down to an element with id="three". i could just split three into another page and load but would like to use the functionality to jump/scroll to an id on some pages.

it looks like the pwa-router helper handles this location logic. so wondering if this is even possible or if you have any recommendations.

Active attribute not updating correctly

When switching between routes, the active attribute doesn't change for the previous route. I have:

<lit-route path="/user" component="user-controller"></lit-route> <lit-route path="/user/:action" component="user-controller"></lit-route>

To control /user and /user/signin respectively. When some navigates to user it redirects using navigate to either user/signin, or user/account. When this happens both lit-routes have the active attribute set. This results in design inconsistencies. Refreshing clears the erroneous active.

Ability to conditionally pre-redirect

Is your feature request related to a problem? Please describe.
In cases where authentication / other setup is required before a route may be fulfilled, there is no way to intercept the navigation event to cancel and redirect.

Describe the solution you'd like
To be able to specify a function on the 's which can either return TRUE meaning continue with the navigation, or FALSE meaning to cancel the request. Additionally, a string may be returned with a redirect URL for a login page etc.

Describe alternatives you've considered
By putting a hook into the components being navigated to, our by hooks on the link items kicking off the navigation, it would be possible to achieve the same thing in a less streamlined way.

Additional context
It may be nice to implement #8 along with this feature to allow any login pages to redirect back to the originally requested URL

Suggestion - enable `scrollDisable` by default

Problem to solve

When paired with other reducers within the same store, lit-route will scroll to the top of the page on every unrelated state-change.

For example, consider this basic implementation....

store.addReducers({
  appState: appStateReducer,
  userState: userStateReducer,
});
connectRouter(store); // adds a `router: routerReducer` to the above store

Whenever appState or userState is updated within the store in any way (say a user.role is updated), lit-route will scroll to the top of the page. Adding a scrollDisable fixes this issue, but I spent an hour trying to figure this out before reading the documentation + code more closely. Unless I am missing something, it is not currently clear that lit-route autoscrolls on every unrelated statechange within a shared store.

Possible implementation

I suggest making scrollDisable the default or explaining this behavior more clearly in the Readme when pairing with other reducers, as it is very useful to have all reducers within the same store for reselect purposes.

Alternatives considered

Simply a suggestion - think this package is great otherwise.

Additional context

Combining reducers into a shared store is more typical than not - simply a suggestion to make it play a bit more nicely with other unrelated reducers by default.

hash on activeroute causes 404 if no querystring present

Describe the bug
A hash in activeroute without a querystring causes 404

To Reproduce
Steps to reproduce the behavior:

  1. yarn start
  2. visit http://127.0.0.1:8000/docs#test

Results in 404

Workaround with any query string

  1. yarn start
  2. visit http://127.0.0.1:8000/docs?query=anything#test

Results in docs component displaying

Expected behavior
I expected the docs component to load regardless of query string present when using a hash. From there we could scroll to the hash within a component.

lit-route lit-plugin typing

I'm trying to render in my lit template but the lit-plugin analyzer is complaining that that tag is not registered .

Unknown tag <lit-route>.
  Check that you've imported the element, and that it's declared on the HTMLElementTagNameMap. If it can't be imported, consider adding it to the 'globalTags' plugin configuration or disabling the 'no-unknown-tag'

Looking at the route.ts file I don't see the component registered into the HTMLElementTagNameMap
Something like the following

declare global {
  interface HTMLElementTagNameMap {
    'lit-route': Route ;
  }
}

Is there something I'm missing to be able to render this element in lit?

Question: Nested routing or subroutes

Hello,

at first, thank you for your good work, It was relatively easy to integrate the lit-redux-router into my project.
I wonder if subrouting is possible with lit-redux-router, like "/route/sub-route/sub-sub-route" where each part will trigger a nested lit-route element? Example:

@customElement('first-view')
export class FirtView extends connect(store)(LitElement) {
  render() {
        return html`
            <lit-route path="/first" component=""></lit-route>
        `;
  }
}

@customElement('second-view')
export class SecondView extends connect(store)(LitElement) {
  render() {
        return html`
            <lit-route path="/second" component=""></lit-route>
        `;
  }
}

@customElement('third-view')
export class ThirdView extends connect(store)(LitElement) {
  render() {
        return html`
            <lit-route path="/third" component="">I am the third view in the row</lit-route>
        `;
  }
}

So in the end, I would want to see I am the third view in the row, when I open the URL /first/second/third.

The only way I see right now is to use variable paths.

Can someone give me a hint on this issue, please?

Thanks,
Stephan

path routing 404 on client side

Describe the bug
I build webapp to serve as a client side via webpack --production.
It's work fine when navigate click on link on a index page.
But when I tried to call in new tab like 'https://__/product/111' it's redirect to 404 not-found page.

Expected behavior
Work on calling from direct path ( /product/111 , /summary )

Device (please complete the following information):

  • Type: desktop
  • OS : Debian 9
  • Browser : Chromium

Usage with redux-toolkit?

Is there a way to make this work with redux-toolkit when using configureStore as the mechanism to create the store?

import {configureStore,} from '@reduxjs/toolkit'
import {lazyReducerEnhancer } from 'pwa-helpers';
import {combineReducers} from 'redux';
import {counterReducer} from './slices/counter';
import { connectRouter } from 'lit-redux-router';

export const store = configureStore({
  reducer: {
    counter: counterReducer
  },
  enhancers: [lazyReducerEnhancer(combineReducers)]
});

connectRouter(store);

Typescript compiler complains about the last line.
It doesn't pick up that store has the function'.addReducer'.

allow path to assume base href

Problem to solve

when html head has a base tag of <base href="/test/">, would love for lit-route to not need that in path, such as <lit-route path="page1"></lit-route> instead of having to declare the base href in the path as currently <lit-route path="/test/page1"></lit-route>

Alternatives considered

currently could be solved through nested routing, but trying to avoid that if possible

Additional context

the component can be imported into different base hrefs, so i'm trying to make it agnostic to work with any base href

Add referral url to the state

Is your feature request related to a problem? Please describe.
A referral URL would be nice in the case that someone needs to sign in before performing an action. After authentication, it would be nice to send them back to that acttion.

Describe the solution you'd like
Before assigning activeRoute assign referralRoute or previousRoute

Describe alternatives you've considered
I really like your simplicity and do not want to invent the same wheel. I will try to provide a pull request.

Additional context
Awesome work!

Imports should specify the file extension

I'm upgrading my project to webpack 5 and I'm seeing the following errors when using the lit-redux-router lib:

[0] ERROR in ./node_modules/project/node_modules/lit-redux-router/lit-redux-router.js 1:0-32
[0] Module not found: Error: Can't resolve './lib/route' in '/node_modules/lit-redux-router'
[0] Did you mean 'route.js'?
[0] BREAKING CHANGE: The request './lib/route' failed to resolve only because it was resolved as fully specified
[0] (probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
[0] The extension in the request is mandatory for it to be fully specified.
[0] Add the extension to the request.
[0] 
[0] ERROR in ./node_modules/project/node_modules/lit-redux-router/lit-redux-router.js 2:0-36
[0] Module not found: Error: Can't resolve './lib/reducer' in node_modules/lit-redux-router'
[0] Did you mean 'reducer.js'?
[0] BREAKING CHANGE: The request './lib/reducer' failed to resolve only because it was resolved as fully specified
[0] (probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
[0] The extension in the request is mandatory for it to be fully specified.
[0] Add the extension to the request.
[0] 
[0] ERROR in ./node_modules/project/node_modules/lit-redux-router/lit-redux-router.js 7:0-41
[0] Module not found: Error: Can't resolve './lib/actions' in '/node_modules/lit-redux-router'
[0] Did you mean 'actions.js'?
[0] BREAKING CHANGE: The request './lib/actions' failed to resolve only because it was resolved as fully specified
[0] (probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
[0] The extension in the request is mandatory for it to be fully specified.
[0] Add the extension to the request.

After googling a bit, I discovered that all imports should specify the extension when the type is set to "module" in the package.json.

When I look at the code, for example the reducer: https://github.com/fernandopasik/lit-redux-router/blob/master/src/lib/reducer.ts

import type { ReadonlyDeep } from 'type-fest';
import type { Actions } from './actions';
import { ActionTypes } from './actions';
import { refreshRoute } from './service';

All the imports are not specifying the extension, which makes my build fail. Is it possible to add the extension, or shall I make a PR which does this?

Can't connect to redux store

Describe the bug
Based on the Lit-Element PWA Starter kit, I tried to connect the lit-redux-router.
But when calling connectRouter(store), I get this error:

TS2345: Argument of type 'Store<{}, Action<any>> & LazyStore & { dispatch: ThunkDispatch<RootState, undefined, RootAction>; }' is not assignable to parameter of type 'Store<State, AnyAction> & LazyStore'.
  Type 'Store<{}, Action<any>> & LazyStore & { dispatch: ThunkDispatch<RootState, undefined, RootAction>; }' is not assignable to type 'Store<State, AnyAction>'.
    Types of property 'getState' are incompatible.
      Type '() => {}' is not assignable to type '() => State'.
        Property 'router' is missing in type '{}' but required in type 'State'.

I create the store like proposed in the starter kit:

// Overall state extends static states and partials lazy states.
export interface RootState {
    app?: AppState;
    counter?: CounterState;
    shop?: ShopState;
}

export type RootAction =
    AppAction
    | CounterAction
    | ShopAction;

// Sets up a Chrome extension for time travel debugging.
// See https://github.com/zalmoxisus/redux-devtools-extension for more information.
const devCompose: <Ext0, Ext1, StateExt0, StateExt1>(
    f1: StoreEnhancer<Ext0, StateExt0>, f2: StoreEnhancer<Ext1, StateExt1>
) => StoreEnhancer<Ext0 & Ext1, StateExt0 & StateExt1> =
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

// Initializes the Redux store with a lazyReducerEnhancer (so that you can
// lazily add reducers after the store has been created) and redux-thunk (so
// that you can dispatch async actions). See the "Redux and state management"
// section of the wiki for more details:
// https://github.com/Polymer/pwa-starter-kit/wiki/4.-Redux-and-state-management
export const store = createStore(
    state => state as Reducer<RootState, RootAction>,
    devCompose(
        lazyReducerEnhancer(combineReducers),
        applyMiddleware(thunk as ThunkMiddleware<RootState, RootAction>)
    )
);

// Initially loaded reducers.
store.addReducers({
    app
});

Expected behavior
No error :)

Device (please complete the following information):
Happens while transpiling under Windows using Webpack 4.30 (ts-loader and babel-loader)

Versions:

  "dependencies": {
    "@polymer/app-layout": "^3.0.2",
    "@polymer/polymer": "^3.2.0",
    "@webcomponents/webcomponentsjs": "^2.2.8",
    "lit-element": "^2.1.0",
    "mapbox-gl": "^0.53.1",
    "pwa-helpers": "^0.9.1",
    "redux": "^4.0.1",
    "redux-thunk": "^2.3.0",
    "reselect": "^4.0.0",
    "lit-redux-router": "^0.8.4"
  },
  "devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@babel/preset-env": "^7.4.3",
    "@types/mapbox-gl": "^0.51.4",
    "autoprefixer": "^9.5.1",
    "babel-loader": "^8.0.5",
    "clean-webpack-plugin": "^2.0.1",
    "copy-webpack-plugin": "^5.0.2",
    "cross-env": "^5.2.0",
    "css-loader": "^2.1.1",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^4.0.0-beta.5",
    "mini-css-extract-plugin": "^0.6.0",
    "node-sass": "^4.11.0",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "ts-loader": "^5.3.3",
    "tslint": "^5.15.0",
    "typescript": "^3.4.3",
    "uglifyjs-webpack-plugin": "^2.1.2",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.3.1",
    "webpack-merge": "^4.2.1",
    "workbox-webpack-plugin": "^4.3.0"
  }

Thanks!

Attribute indicating which route is active

Is your feature request related to a problem? Please describe.
There is no way to style the active lit-route element since there is no attribute indicating which route is active.

Describe the solution you'd like
An attribute automatically populated that indicates the active route.

Should navigate() handle query params?

Is your feature request related to a problem? Please describe.
When using navigate() with a string that includes a query param, the resulting activeRoute contains those query params. For example: navigate("/page?query=value") results in an activeRoute of "/page?query=value".

However, that is not the case if you were to use an anchor element with a query param like <a href="/page?query=value"></a>, or even refresh the page after using navigate() with query params. In both of those cases the resulting activeRoute would just be "/page".

Describe the solution you'd like
It would be nice if navigate() could handle query params and provide a consistent activeRoute value.

Describe alternatives you've considered
It's possible to use window.history.pushState() to accomplish this, but if you need to navigate pages as well (as is my case), you need to use both navigate() (with just the page, no query params) and history.pushState() (with the page and query params), which doesn't necessarily seem ideal.

Support for Dynamic Imports

Is your feature request related to a problem? Please describe.
First, I've been following this project for a few months now and found it to be exactly what I need for my lit-element web component needs. There's one thing I think it's missing, and that's route based lazy loading of components.

Describe the solution you'd like
On route change, it should load an optional developer provided loading component. It should make an asynchronous request for the component associated with the route, then it should replace the loading component with the requested component once the promise is resolved. The additions can be added to the route.ts.

Describe alternatives you've considered
I considered and demonstrated the use of a higher order component to achieve the same result using lit-redux-router. Although, it isn't the cleanest way of doing it. The better way is to modify lit-redux-router. I thought it might be helpful to contribute it to you first. Maybe you have a better idea for how to approach this.

Additional context

An example of what two lazy loaded component routes would look like:

import { html, LitElement } from 'lit-element';
import { connectRouter } from 'lit-redux-router';
import store from './store.js';

import '../pages/home/home.js';
import '../components/Loading';

connectRouter(store);

class AppComponent extends LitElement {

  render() {
    const AboutRoute = {
      load: () => import(/* webpackChunkName: "aboutPage" */ '../pages/home/about'),
      loading: 'eve-loading'
    };
    const DocsRoute = {
      load: () => import(/* webpackChunkName: "docsPage" */ '../pages/home/docs'),
      loading: 'eve-loading'
    };

    return html`
      <div>
        <lit-route path="/" component="home-page"></lit-route>
        <lit-route path="/about" component="about-page" lazy="${true}" .loader="${AboutRoute}"></lit-route>
        <lit-route path="/docs" component="docs-page" lazy="${true}" .loader="${DocsRoute}"></lit-route>
      </div>
    `;
  }

}

customElements.define('eve-app', AppComponent);

Add `module` property in package.json

Is your feature request related to a problem? Please describe.
This package is ES module syntax friendly but doesn't have "module" property in package.json and then tools can detect the package is tree-shackeable

Describe the solution you'd like
I would like package.json include the module property pointing to the ES module entrypoint

Describe alternatives you've considered
N/A

Additional context
N/A

XSS vulnerability when using path params

Bug Report

A path setup like this:

<lit-route path="/agents/:agentIdRoute" component="agent-configuration"></lit-route>

Can, or will cause a XSS vulnerability when the user enters this url:

http://localhost/agents/1"><img%20src%20onerror=alert(%27hi%27)>

That's because unsafeHTML is used over here: https://github.com/fernandopasik/lit-redux-router/blob/main/src/lib/route.ts#L148

Expected behavior

No XSS attack possible

Current behavior

An alert is shown in the browser.

Steps to reproduce

  1. Add a path param to a lit-route
  2. add "><img%20src%20onerror=alert(%27hi%27)> to the url
  3. See the alert

Possible solution

Not sure if we can fully prevent unsafeHTML being used here, so maybe clean all the params?

Component element names cannot include numbers

Describe the bug
Component element names cannot contain numbers in them

To Reproduce
Steps to reproduce the behavior:

  1. Go to ./demo
  2. edit docs.js element to be docs-page2
  3. go to index.html, edit /docs route with component name 'docs-page2'
  4. npm start, go to localhost:8081/docs see nothing there

Expected behavior
I expected to be able to export the component with a number in it

The bug is in route.ts and is simple to fix:

      const tagName = component.replace(/[^A-Za-z-]/, '');

needs to include 0-9 in regex

Ability to change the route with javascript.

I see no way to change the route with javascript.

  1. window.location.href = '/route'; will refresh the page.
  2. window.history.pushState(null, null, '/route'); won't update the view.
  3. And the redux NAVIGATE action isn't publicly available.

How should I do this?

Update Documentation to show store setup

Is your feature request related to a problem? Please describe.
Initially setting up the app caused me to get type errors + crashes because i set up my store without the LazyReducerEnhancer.

Describe the solution you'd like
Just a quick pointer in the documentation about how the redux store that createRouter is expecting should be set up something like

import { createStore, compose, combineReducers } from 'redux';
import { reducer } from './reducer';
import { lazyReducerEnhancer } from 'pwa-helpers';

export const store = createStore(
  reducer,
  compose(lazyReducerEnhancer(combineReducers))
);

for people who are still new to the pwa-helpers magic :)

Describe alternatives you've considered
N/A

Additional context
The library is super cool! Thanks for setting it up and maintaining it :D
Also i would have updated the documentation myself and submitted a PR but wanted to make sure i wasn't missing some context so apologies in advance if this is a straight forward thing!

The demo folder is also published to NPM which causes issues when building

Next to the "lib" folder and the package.json, the demo folder is also part of the release.

This causes my tests to fail:

Error: Cannot find module 'lit-element' from '/Users/user/IdeaProjects/myproject/node_modules/lit-redux-router/lib'

For now I fixed it by installing lit-element as a dev-dep:

npm install --save-dev lit-element

But is it possible to remove the demo folder from the output?

Provide a tail

How would I route to a component and provide a sub-route? In this case :tail

/:controller/:action/:tail
ex: user/posts/read/id

In my scenario I'm routing to a controller action, then want to provide a subroute.

Using subroutes inside of components (with shadowRoot)

This could either be a question or a feature request. Is it possible to make lit-route elements that are nested within components with their own shadowRoot aware of each other?

so instead of:

        <lit-route path="/about">
          <h1>About</h1>
          <a href="/about/me">Me</a>
          <lit-route path="/me">
            <h1>About Me</h1>
          </lit-route>
        </lit-route>

I'd like to do something like:

        <lit-route path="/about" component="about"></lit-route>

With about:

  <h1>About</h1>
  <lit-route path="/me" component="me"></lit-route>

and me:

  <h1>About Me</h1>

I like that the "me" component can be reused at different locations, even in different apps when it's made reusable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.