Skip to content

Commit

Permalink
feat: add onSelect, show focus of grid rows (#47)
Browse files Browse the repository at this point in the history
* feat: add onSelect, show focus of grid rows

* feat: add onSelect helper, refactor TS for Row/Column

* fix import paths

* Update packages/solid/components/Column/Grid.types.ts

Co-authored-by: Carolyn Moneymaker <[email protected]>

* fix up onSelect to pass selected in first

* feat: add navigable interfaces

* feat: replace grid interface uses with navigable, add Column and Row Props types which extend Navigable props

* fix: add types path alias to configs

* chore: remove old, unused types file, lint augmentations file

* fix: add types alias to storybook vite config

* remove onSelect for onSelectedChanged

* chore: fix a typo

---------

Co-authored-by: Carolyn Moneymaker <[email protected]>
Co-authored-by: Anthony Gallo <[email protected]>
  • Loading branch information
3 people authored Sep 23, 2024
1 parent ce36faf commit f5651f0
Show file tree
Hide file tree
Showing 23 changed files with 2,421 additions and 5,631 deletions.
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@
"version-publish": "pnpm run lerna:version && pnpm run publish-packages"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
"eslint": "^8.57.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"eslint": "^8.57.1",
"eslint-config-prettier": "8.10.0",
"eslint-plugin-jest": "^28.6.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-solid": "^0.14.1",
"lerna": "^8.1.6",
"eslint-plugin-jest": "^28.8.3",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-solid": "^0.14.3",
"lerna": "^8.1.8",
"prettier": "^3.3.3",
"typescript": "^5.5.3",
"vite": "^5.3.4",
"typescript": "^5.6.2",
"vite": "^5.4.7",
"vite-bundle-visualizer": "^1.2.1",
"vite-plugin-cross-origin-isolation": "^0.1.6",
"vite-plugin-solid": "^2.10.2"
Expand Down
3 changes: 1 addition & 2 deletions packages/shared/types/solid.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

import type { AnimationSettings } from '@lightningtv/core';
export type Color = number | string;
export type AnimationSettings = { duration?: number; delay?: number; timing?: string };
export type TextAlign = 'left' | 'center' | 'right';
export type ContentAlign = 'center' | 'flexStart' | 'flexEnd' | 'spaceBetween' | 'spaceEvenly';
export type States = 'active' | 'focus' | 'disabled';

/**
* allows the property to either be the supplied type,
* or an array containing that type and an animationSettings object
Expand Down
3 changes: 2 additions & 1 deletion packages/solid/.storybook/vite.config.storybook.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ const config = {
resolve: {
alias: {
theme: path.resolve(__dirname, '../../l3-ui-theme-base/theme.js'),
utils: path.resolve(__dirname, '../../shared/utils/index.ts')
utils: path.resolve(__dirname, '../../shared/utils/index.ts'),
types: path.resolve(__dirname, '../types/')
},
dedupe: ['solid-js', '@lightningtv/solid']
},
Expand Down
8 changes: 4 additions & 4 deletions packages/solid/components/Column/Column.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import Column from './Column.jsx';
import type { ColumnProps } from './Column.types.js';
import type { NavigableProps } from 'types/Navigable.types.js';
import Button from '../Button/Button.jsx';
import type { JSX } from 'solid-js/jsx-runtime';
import { View } from '@lightningtv/solid';
Expand Down Expand Up @@ -68,7 +68,7 @@ const createItems = (length: number) => {
const buttons = (num = 7) => createItems(num);

export const AlwaysScroll = {
render: (args: JSX.IntrinsicAttributes & ColumnProps) => {
render: (args: JSX.IntrinsicAttributes & NavigableProps) => {
return (
<View height={720} width={400}>
<Column autofocus {...args} />
Expand All @@ -84,7 +84,7 @@ export const AlwaysScroll = {
};

export const AutoScrollIndex = {
render: (args: JSX.IntrinsicAttributes & ColumnProps) => {
render: (args: JSX.IntrinsicAttributes & NavigableProps) => {
return (
<View height={720} width={400}>
<Column autofocus {...args} />
Expand All @@ -101,7 +101,7 @@ export const AutoScrollIndex = {
};

export const NoneScroll = {
render: (args: JSX.IntrinsicAttributes & ColumnProps) => {
render: (args: JSX.IntrinsicAttributes & NavigableProps) => {
return (
<View height={720} width={400}>
<Column autofocus {...args} />
Expand Down
8 changes: 4 additions & 4 deletions packages/solid/components/Column/Column.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
*/
import theme from 'theme';
import { makeComponentStyles } from '../../utils/index.js';
import type { ColumnStyles, ColumnConfig } from './Column.types.js';
import type { NavigableStyles, NavigableConfig } from 'types/Navigable.types.js';

/* @ts-expect-error next-line themes are supplied by client applications so this setup is necessary */
const { Column: { defaultTone, ...themeStyles } = { themeStyles: {} } } = theme?.componentConfig;

const container: ColumnConfig = {
const container: NavigableConfig = {
themeKeys: {
gap: 'itemSpacing',
scrollIndex: 'scrollIndex',
Expand All @@ -42,9 +42,9 @@ const container: ColumnConfig = {
themeStyles
};

const Container = makeComponentStyles<ColumnStyles['Container']>(container);
const Container = makeComponentStyles<NavigableStyles['Container']>(container);

const styles: ColumnStyles = {
const styles: NavigableStyles = {
tone: defaultTone || 'neutral',
Container
};
Expand Down
22 changes: 11 additions & 11 deletions packages/solid/components/Column/Column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,30 @@
*/

import { type Component } from 'solid-js';
import { View, type KeyHandler } from '@lightningtv/solid';
import { handleNavigation, onGridFocus } from '../../utils/handleNavigation.js';
import { View } from '@lightningtv/solid';
import { handleNavigation, onGridFocus, handleOnSelect } from '../../utils/handleNavigation.js';
import { withScrolling } from '../../utils/withScrolling.js';
import { chainFunctions } from '../../utils/chainFunctions.js';
import styles from './Column.styles.js';
import type { ColumnProps } from './Column.types.js';
import styles from './Column.styles.js';

const Column: Component<ColumnProps> = (props: ColumnProps) => {
const Column: Component<ColumnProps> = props => {
const onUp = handleNavigation('up');
const onDown = handleNavigation('down');
const scroll = withScrolling(false);

return (
<View
{...props}
onUp={chainFunctions<KeyHandler | undefined>(props.onUp, onUp)}
onDown={chainFunctions<KeyHandler | undefined>(props.onDown, onDown)}
onUp={chainFunctions(props.onUp, onUp)}
onDown={chainFunctions(props.onDown, onDown)}
selected={props.selected || 0}
forwardFocus={onGridFocus}
onLayout={
props.selected
? chainFunctions(props.onLayout, scroll)
: props.onLayout
}
onFocus={chainFunctions(
props.onFocus,
props.onSelectedChanged && handleOnSelect(props.onSelectedChanged)
)}
onLayout={props.selected ? chainFunctions(props.onLayout, scroll) : props.onLayout}
onSelectedChanged={chainFunctions(
props.onSelectedChanged,
props.scroll !== 'none' ? scroll : undefined
Expand Down
66 changes: 3 additions & 63 deletions packages/solid/components/Column/Column.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,73 +16,13 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
import type { KeyHandler } from '@lightningtv/core/focusManager';
import type { NavigableProps, NavigableStyleProperties } from 'types/Navigable.types.js';

import type { IntrinsicNodeCommonProps, ElementNode, NodeStyles, KeyHandler } from '@lightningtv/solid';
import type { ComponentStyleConfig, NodeStyleSet, Tone } from 'types/types.js';
import type { UIComponentProps } from 'types/interfaces.js';

export interface ColumnProps extends UIComponentProps, ColumnStyleProperties {
/** function run on component mount */
onCreate?: IntrinsicNodeCommonProps['onCreate'];

export interface ColumnProps extends NavigableProps, NavigableStyleProperties {
/** function to be called on down click */
onDown?: KeyHandler;

/** function to be called on up click */
onUp?: KeyHandler;

/** function to be called when the selected of the component changes */
onSelectedChanged?: (
this: ElementNode,
elm: ElementNode,
active: ElementNode,
selectedIndex: number,
lastSelectedIndex: number
) => void;

/** Determines when to scroll(shift items along the axis):
* auto - scroll items immediately
* edge - scroll items when focus reaches the last item on screen
* always - focus remains at index 0, scroll until the final item is at index 0
* none - disable scrolling behavior, focus shifts as expected
* in both `auto` and `edge` items will only scroll until the last item is on screen */
scroll?: 'always' | 'none' | 'edge' | 'auto';

/** When auto scrolling, item index at which scrolling begins */
scrollIndex?: number;

/** The initial index */
selected?: number;

/**
* Adjust the x position of the row. Initial value is Y
*/
offset?: number;

/**
* Wrap the row so active goes back to the beginning of the row
*/
wrap?: boolean;
}

export interface ColumnStyleProperties {
/**
* the index of which we want scrolling to start
*/
scrollIndex?: number;
/**
* space between each keys
*/
itemSpacing?: NodeStyles['gap'];
/**
* animation transition
*/
itemTransition?: NodeStyles['transition'];
}

export interface ColumnStyles {
tone: Tone;
Container: NodeStyleSet;
}

export type ColumnConfig = ComponentStyleConfig<ColumnStyleProperties>;
1 change: 0 additions & 1 deletion packages/solid/components/Column/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,3 @@

export { default as default } from './Column.jsx';
export { default as columnStyles } from './Column.styles.js';
export type { ColumnProps, ColumnStyles } from './Column.types.js';
8 changes: 4 additions & 4 deletions packages/solid/components/Row/Row.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
*/
import theme from 'theme';
import { makeComponentStyles } from '../../utils/index.js';
import type { RowConfig, RowStyles } from './Row.types.js';
import type { NavigableConfig, NavigableStyles } from 'types/Navigable.types.js';

/* @ts-expect-error next-line themes are supplied by client applications so this setup is necessary */
const { Row: { defaultTone, ...themeStyles } = { themeStyles: {} } } = theme?.componentConfig;

const container: RowConfig = {
const container: NavigableConfig = {
themeKeys: {
gap: 'itemSpacing',
scrollIndex: 'scrollIndex',
Expand All @@ -42,9 +42,9 @@ const container: RowConfig = {
themeStyles
};

const Container = makeComponentStyles<RowStyles['Container']>(container);
const Container = makeComponentStyles<NavigableStyles['Container']>(container);

const styles: RowStyles = {
const styles: NavigableStyles = {
tone: defaultTone,
Container
};
Expand Down
16 changes: 8 additions & 8 deletions packages/solid/components/Row/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
import { type Component } from 'solid-js';
import { View } from '@lightningtv/solid';
import { chainFunctions } from '../../utils/chainFunctions.js';
import { handleNavigation, onGridFocus } from '../../utils/handleNavigation.js';
import { handleNavigation, handleOnSelect, onGridFocus } from '../../utils/handleNavigation.js';
import { withScrolling } from '../../utils/withScrolling.js';
import styles from './Row.styles.js';
import type { RowProps } from './Row.types.js';
import type { NavigableProps } from 'types/Navigable.types.js';

const Row: Component<RowProps> = (props: RowProps) => {
const Row: Component<NavigableProps> = props => {
const onLeft = handleNavigation('left');
const onRight = handleNavigation('right');
const scroll = withScrolling(true);
Expand All @@ -34,12 +34,12 @@ const Row: Component<RowProps> = (props: RowProps) => {
selected={props.selected || 0}
onLeft={chainFunctions(props.onLeft, onLeft)}
onRight={chainFunctions(props.onRight, onRight)}
onFocus={chainFunctions(
props.onFocus,
props.onSelectedChanged && handleOnSelect(props.onSelectedChanged)
)}
forwardFocus={onGridFocus}
onLayout={
props.selected
? chainFunctions(props.onLayout, scroll)
: props.onLayout
}
onLayout={props.selected ? chainFunctions(props.onLayout, scroll) : props.onLayout}
onSelectedChanged={chainFunctions(
props.onSelectedChanged,
props.scroll !== 'none' ? scroll : undefined
Expand Down
76 changes: 10 additions & 66 deletions packages/solid/components/Row/Row.types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
/**
* Copyright 2023 Comcast Cable Communications Management, LLC
* Licensed under the Apache License, Version 2.0 (the "License");
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
Expand All @@ -12,73 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* SPDX-License-Identifier: Apache-2.0
*/
import type { ElementNode, IntrinsicNodeCommonProps, NodeStyles, KeyHandler } from '@lightningtv/solid';
import type { ComponentStyleConfig, NodeStyleSet, Tone } from 'types/types.js';
import type { UIComponentProps } from 'types/interfaces.js';

export interface RowProps extends UIComponentProps, RowStyleProperties {
/** function run on component mount */
onCreate?: IntrinsicNodeCommonProps['onCreate'];
/** When auto scrolling, item index at which scrolling begins */
scrollIndex?: number;

/** Determines when to scroll(shift items along the axis):
* auto - scroll items immediately
* edge - scroll items when focus reaches the last item on screen
* always - focus remains at index 0, scroll until the final item is at index 0
* none - disable scrolling behavior, focus shifts as expected
* in both `auto` and `edge` items will only scroll until the last item is on screen */
scroll?: 'always' | 'none' | 'edge' | 'auto';
import type { KeyHandler } from '@lightningtv/core/focusManager';
import type { NavigableProps, NavigableStyleProperties } from 'types/Navigable.types.js';

/** The initial index */
selected?: number;

/** function to be called on right click */
onRight?: KeyHandler;

/** function to be called on right click */
export interface ColumnProps extends NavigableProps, NavigableStyleProperties {
/** function to be called on down click */
onLeft?: KeyHandler;

/** function to be called when the selected of the component changes */
onSelectedChanged?: (
this: ElementNode,
elm: ElementNode,
active: ElementNode,
selectedIndex: number,
lastSelectedIndex: number
) => void;

/**
* Adjust the x position of the row. Initial value is X
*/
offset?: number;

/**
* Wrap the row so active goes back to the beginning of the row
*/
wrap?: boolean;
}

export interface RowStyleProperties {
/**
* the index of which we want scrolling to start
*/
scrollIndex?: number;
/**
* space between each keys
*/
itemSpacing?: NodeStyles['gap'];
/**
* animation transition
*/
itemTransition?: NodeStyles['transition'];
}

export interface RowStyles {
tone: Tone;
Container: NodeStyleSet;
/** function to be called on up click */
onRight?: KeyHandler;
}

export type RowConfig = ComponentStyleConfig<RowStyleProperties>;
1 change: 0 additions & 1 deletion packages/solid/components/Row/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@
*/
export { default as default } from './Row.jsx';
export { default as rowStyles } from './Row.styles.js';
export type { RowProps, RowStyles } from './Row.types.js';
Loading

0 comments on commit f5651f0

Please sign in to comment.