mqtt-control-map/src/components/UiItems/base.js
uwap 856aab41ad Improve the entire icon logic
- Tree Shaking for Icons (Closes #53)
- New API for the config (See 
https://github.com/uwap/mqtt-control-map/wiki/Icons)
- Icons can now be colored everywhere, not just on the map
2020-10-08 08:36:56 +02:00

76 lines
2 KiB
JavaScript

// @flow
import * as React from "react";
import MqttContext from "mqtt/context";
import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction";
import ListItemText from "@material-ui/core/ListItemText";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import throttle from "lodash/throttle";
import type { Icon } from "config/icon";
export type Helpers = {
Icon: (props: { item: { +icon?: Icon }, state: State }) => React.Node,
Label: (props: {}) => React.Node,
Action: (props: {}) => React.Node
};
export type BaseComponent<T> = (
helpers: Helpers,
item: T,
state: State,
nextValue: <T: { +topic: string }> (item: T, next: string) => void
) => React.Node;
export type Component<T> = {
id: string,
name: string,
desc: string,
/*
* TODO: Map<$Keys<T>, string> doesn't really work :(
* See https://github.com/facebook/flow/issues/5276
* If there is progress on the issue try to make it $Exact as well
*/
parameters: Map<$Keys<T>, string>,
baseComponent: BaseComponent<T>
};
type SuperT = $ReadOnly<{ text: string }>;
const IconHelper = ({item, state}: { item: { +icon?: Icon }, state: State }) =>
( <ListItemIcon>
{item.icon == null || item.icon.size(1).render(state)}
</ListItemIcon>
);
const createHelpers = <T: SuperT> (item: T) =>
({
Icon: IconHelper,
Label: () => (
<ListItemText primary={item.text} />
),
Action: (props) => (
<ListItemSecondaryAction {...props} />
)
});
const debouncedChangeState = (chState: (tpc: string, nxt: string) => void) => (
throttle(<T: { +topic: string }> (item: T, next: string) =>
chState(item.topic, next), 50, {
leading: true,
trailing: true
})
);
const createComponent = <T: SuperT> (component: Component<T>) => ({
component: (item: T) => (
<MqttContext.Consumer>
{({state, changeState}) => component.baseComponent(
createHelpers(item), item, state, debouncedChangeState(changeState)
)}
</MqttContext.Consumer>
)
});
export default createComponent;