Giter Club home page Giter Club logo

lightning-ui's Introduction

Lightning-UI

Lightning-UI provides a set of components that are used very often when you are developing in Lightning, with the following components we hope to help you out with setting up your app a bit faster:

Install

npm i @lightningjs/ui

Contributing

The Lightning-SDK is an open source project. If you want to contribute to it, please consider the following:

  • the main branch is the latest stable release
  • the dev branch is used for upcoming releases
  • all development should be done in dedicated topic branches (from latest dev-branch)
  • please send in your PR against the dev-branch

Before you submit your PR, make sure you install the projects dependencies, as this will activate automatic linting and code formatting in a Git commit hook.

Examples

In the following repository you can find code examples on how to use the components

Ui-component-examples

lightning-ui's People

Contributors

bhargavipalineni79 avatar fernando-j-afonso-alb avatar gopal-moyya avatar jfboeve avatar ricardo-a-alves-alb avatar robbertvancaem avatar sv-th avatar uguraslan avatar wouterlucas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lightning-ui's Issues

Grid index steps diagonally

Steps to reproduce
I've provided an example of what happens in the video below and pushed a separate branch for the code that was used here

Screen.Recording.2022-09-13.at.12.32.18.mov

General description
What seems to happen is that the Grid didn't expect the setIndex method and navigate to be used side-by-side, but always sequentially. When programmatically calling the setIndex method, the this._previous variable wasn't updated, leading to unexpected behaviour.

Proposed solution
I have already created a PR for this: #25
I also added Jest to test this behaviour and updated the documentation for the Grid component a little bit.

Hope it helps :-)

ScrollingLabel's "autoStart" property not working

Hello,

I was trying out the ScrollingLabel as explained in the ScrollingLabel example provided in the documentation here. The documentation explains that we can tell the ScrollingLabel to not start scrolling automatically using the property autoStart. This doesn't actually work.

Steps to reproduce:
Use the example from the documentation and set the autoStart property to false.

Expected Behaviour:
The label should not start scrolling automatically.

Current Behaviour:
The label always starts scrolling automatically, autoStart property is ignored.

I will submit a PR for this.

bug: Grid onIndexChanged is only triggered on main index change

Version 1.3.5

if (previous !== target) {
this.signal('onIndexChanged', obj);
}

When using a Grid component, the above code fails because these values are being replaced:

let { previousIndex: previous, index: target, dataLength: max, mainIndex, previousMainIndex, lines } = obj;
if (!isNaN(previousMainIndex) && !isNaN(mainIndex) && !isNaN(lines)) {
previous = previousMainIndex;
target = mainIndex;
max = lines;
}

However, on the signal it is being sent the original obj variable, containing the correct previousIndex and index.

Will submit a PR to fix this, to use the original obj values instead of the ones that are replaced.

CollectionWrapper: Reload items with onRequestItems

If #47 gets pushed, it would be beneficial to have a method to reload the entire CollectionWrapper so that it triggers the requests from zero.

My use-case would be having an outside filter that when clicked it would need to refresh the CollectionWrapper so that it requests new items with this filter applied.

Right now, the only option is to clear the items from the CollectionWrapper, make the first request and then let CollectionWrapper handle the rest.

Grid - newItem exception when trying to reposition

When trying to reposition the grid from inside a card with this.collectionWrapper.reposition(), a exception is throw saying that newItem was not initialized. It seems to me that this property is missing.
image

ScrollingLabel doesn't work properly when width is a function

Component: ScrollingLabel

To calculate if the current label text is wider than it's wrapper, the component is reading it's width by using this.w. If we set our component's width using a function (w: (w) => w), the property w will always return 0. This is a normal behavior of the LightningJS element. When the width is set through a function, internally it set's it's w property to 0. If we set the w using an int, it works as expected.

Probably it should be using renderWidth instead.

I'll provide a PR to attempt to fix this.

Focus can be lost from carousel after long press left / right

Steps to reproduce:

  1. Run UI components examples app with the latest version of @lightningjs/ui package installed (v1.2.2).
  2. Open "Carousel displayed as Row" page.
  3. Long press left/right for 1 - 2 seconds, then press right/left (the opposite direction) twice. It may be necessary to repeat this several times and alternate between long pressing left & right keys. E.g. long press right, left, left, long press left, right, right...

Result:
Focus is lost. It can be recovered by pressing up/down, but it's no longer possible to control the carousel until the page is refreshed.

The following error is visible in the console:
Carousel.js:133 Uncaught TypeError: Cannot read properties of undefined (reading 'componentIndex') at StateMachineRouter.navigate (Carousel.js:133:58) at StateMachineRouter._attemptNavigation (CollectionWrapper.js:209:25) at StateMachineRouter.left (CollectionWrapper.js:184:21) at StateMachineRouter._handleLeft (CollectionWrapper.js:436:21) at StateMachineRouter.focusBottomUpEvent (lightning.js:13920:55) at StateMachineRouter._receiveKeydown (lightning.js:13943:48) at lightning.js:13736:26 at _keydownListener (lightning.js:11415:17)

This issue has been raised by the Metrological QA team for an app we are developing. It is a medium priority issue and has contributed to a delay in release of our app.

CollectionWrapper: initially not requesting more items to fulfill request threshold

if (previous < target && target + this._requestThreshold >= max) {
this._requestingItems = true;
this.signal('onRequestItems', obj)
.then((response) => {
const type = typeof response;
if (Array.isArray(response) || type === 'object' || type === 'string' || type === 'number') {
this.add(response);
}
if (response === false) {
this.enableRequests = false;
}
this._requestingItems = false;
})
}

Probably the previous < target the condition needs to be dropped, because initially it should be triggering request when there are not enough items to reach the request threshold.

In my use-case, I have a grid that has 6 columns and the requests are made with 10 items, which means that if I do the first request and add the first 10 items, it doesn't trigger more requests until I navigate to the second line of the grid.

This change would also let CollectionWrapper manage the requests exclusively. As of now, we need to add the first items to the CollectionWrapper. If this condition doesn't exist, we only need to provide a onRequestItems callback and CollectionWrapper does all it needs to do.

bug: CollectionWrapper remove method doesn't work

Hello,

We were trying to use the remove() method available on the CollectionWrapper and it doesn't seem to work.

remove(item) {
if(this.hasItems && item.assignedID) {
for(let i = 0; i < this.wrapper.children.length; i++) {
if(this.wrapper.children[i].assignedID === item.assignedID) {
return this.removeAt(i);
}
}
}
else {
throw new Error('remove: item not found');
}
}

From our investigation, the culprit seems to be the that this.wrapper.children doesn't contain the property assignedID.
Using the internal get items() seems to fix the issue, because it returns the component if it is alive.

get items() {
const itemWrappers = this.itemWrappers;
return this._items.map((item, index) => {
if(itemWrappers[index] && itemWrappers[index].component.isAlive) {
return itemWrappers[index].component;
}
return item;
});
}

If replacing the blocks that use this.wrapper.children with this.items seems good to you, I can provide a PR to be merged.

CollectionWrapper: item's marginTop not being applied

Hello,

I was trying to use the marginTop property on an List item and was seen no visual impact. Applying marginBottom would work as expected.

After some debugging and digging, I ended up finding these which I believe are some ancient relics:

const {w, h, margin, marginUp, marginBottom, marginRight, marginLeft} = this;
this.children = [{...component, w, h, margin, marginUp, marginRight, marginLeft, marginBottom}];

mainMarginFrom: directionIsRow ? 'marginLeft' : 'marginUp',

crossMarginFrom: directionIsRow ? 'marginUp' : 'marginLeft',

These should be marginTop I believe, as if I change those to marginTop it starts working as expected. I'll submit a PR and merge it if it is indeed an forgotten ancient relic.

Grid navigation focusing on wrong element

I found an anomalous behaviour with the Grid navigation, where it is incorrectly calculating the wrong element to focus on.
Here is a video of the problem:

GridBug.mp4

What you are seeing on the video is the following (these are the steps to reproduce):

  1. Create a Grid with several elements, make sure they have two or more columns
  2. Press the 'Right' button to navigate to the element on the right, and then press back to the 'Left' to navigate back to the initial element.
  3. Now you need to 'clear()' the grid, resize it to a bigger height so that it fits more elements per column, and re-add a bunch of elements (can be different, or not, doesn't matter)
  4. Now when you click 'Left', the navigation is incorrect.

Why is the navigation incorrect?
I debugged this issue, and found the issue to be in the navigate() method of the Grid, somehow related to the this._previous property of the Grid in this condition:

image

What I found strange is that, despite me having called "clear()" on the list and reloaded a bunch of different items in Step 3., the this._previous variable is not properly cleaned up, which is somehow affecting the calculation of the item to navigate to in Step 4.

Expected behaviour:
The navigation should be correct, and I managed to achieve this by overriding the Grid's clear() method like this:
image

ScrollingLabel is broken

Hello,

I was trying out the ScrollingLabel as explained in the ScrollingLabel example provided in the documentation here. In the documentation there are several examples of usage, but none of them work. For example, if I try the first example in the documentation, the app fails to open and I get an error message:

image

Expected Behaviour:
The app should start, and the label should scroll

Current Behaviour:
The app fails to start with a JS error.

I will submit a PR to fix this.

CollectionWrapper - Removing last item while it is focused corrupts current index

While the last item of a CollectionWrapper (e.g. List) is focused/current index, if we remove it via remove() or removeAt() methods, the internal index variable becomes corrupt as it is not updated.

Example

In the example above, if you press Enter it will remove the last item while it is focused and we can see that the previous item is not focused. If you uncomment the line that is commented, it behaves as expected.

CollectionWrapper - Set higher index when enableRequests are on

Hello,

Using a List (that uses CollectionWrapper under-the-hood) that has a lazy-load approach should allow to set a higher index than the current loaded items.

On the following example, there are 50 possible items, however initially it only loads 10 items. However, if we press the Enter key it tries to set the current index to 15. However, since it only has 10 items and on the setIndex method there's a constraint between 0 and current items length, it restricts the index to 10.

Given the lazy-load logic, it should at least attempt to get more items until we reach the requested index.

Playground example and pasting the code here just in case:

import Lightning from '@lightningjs/core';
import { List } from '@lightningjs/ui'

export default class App extends Lightning.Application {
    static _template() {
        return {
            ExampleList: {
                type: List,
                itemType: Item,
                spacing: 16,
                enableRequests: true,
                signals: {
                    onRequestItems: true
                }
            }
        }
    }

    _construct() {
        this._items = [...Array(50)].map((_, idx) => ({ title: idx }))
    }

    _firstActive() {
        this.tag('ExampleList').requestItems()
    }

    _handleEnter() {
        this.tag('ExampleList').setIndex(15)
    }

    onRequestItems({ dataLength, max }) {
        return Promise.resolve(this._items.slice((dataLength || max), (dataLength || max) + 10))
    }

    _getFocused() {
        return this.tag('ExampleList')
    }
}

class Item extends Lightning.Component {
    static _template() {
        return {
            rect: true,
            color: 0xffc0cc0c,
            Label: {
                x: (w) => w / 2,
                y: (h) => h / 2,
                mount: 0.5,
            }
        }
    }

    _focus() {
        this.patch({ color: 0xffff0000 })
    }

    _unfocus() {
        this.patch({ color: 0xffc0cc0c })
    }

    get title() {
        return `${this._title}` || '0'
    }

    set title(value) {
        this._title = value
        this.tag('Label').text = this.title
    }

    static get width() {
        return 70
    }

    static get height() {
        return 50
    }
}

passwordmode + new implementation for show cursor causes a * to always show

Hi,

Thought i would create an issue regarding the comment i left. Easier to keep track this way.
Originally posted by @Sv-Th in #3 (comment)

One issue with the current implementation is that using the space on line 72 of inputfield (link) to have the cursor position correctly would cause the inputfield to always display a * in passwordmode when empty. My fix to this was this commit where the render was done on firstactive.

There could be other ways to solve this, of course.

Anchored carousel destroys items that are still on screen

Steps to produce:

  1. Run the https://github.com/mlapps/ui-component-examples app with @lightningjs/sdk version 4.8.3 and @lightningjs/ui version 1.2.4
  2. Update the ImageCell component's static width to 1465; this ensures that the Carousel displays one entire ImageCell component, with both immediate siblings slightly visible on the sides
  3. Load the Carousel displayed as Row example
  4. Press the left arrow to navigate to the previous item

Expected result: The Carousel slides to the right with the sibling components slightly visible on the sides
Actual result: The Carousel slides to the right, but the left sibling is removed once the transition is complete

I poked around a bit, and it appears that this check (https://github.com/rdkcentral/Lightning-ui/blob/main/src/Carousel.js#L202) is returning true for the left-hand sibling even though it is still on screen. If setting the ImageCell static width to 1464 (1 pixel less than the scenario above) the left sibling remains on screen as expected. See below for the local values depending on the ImageCell width:

ImageCell.width = 1465
boundStart = 1267.2
offset = 1707.5
child[main] = -2975
1707.5 + -2975 < -1267.2 = true (this causes the element to be removed)

ImageCell.width = 1464
boundStart = 1267.2
offset = 1707
child[main] = -2973
1707 + -2973 < -1267.2 = false (this does not mark the element for removal)

Happy to provide any more details and help debug. I have also attached a screen capture of the issue. Thanks!

Screen.Recording.2022-04-22.at.12.48.52.PM.mov

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.