From bc433b7890548dd7fbf8c2fafc1042f3043ea6bc Mon Sep 17 00:00:00 2001 From: telamonian Date: Thu, 26 Dec 2019 20:14:08 -0500 Subject: [PATCH] refactor of JLIcon.get into JLIcon.getElement and JLIcon.getReact --- packages/ui-components/src/icon/jlicon.tsx | 81 +++++++++++++++++----- 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/packages/ui-components/src/icon/jlicon.tsx b/packages/ui-components/src/icon/jlicon.tsx index 3d8a19ef56c8..5a1aa002ab53 100644 --- a/packages/ui-components/src/icon/jlicon.tsx +++ b/packages/ui-components/src/icon/jlicon.tsx @@ -2,7 +2,6 @@ // Distributed under the terms of the Modified BSD License. import { UUID } from '@lumino/coreutils'; - import React from 'react'; import ReactDOM from 'react-dom'; @@ -28,7 +27,7 @@ export class JLIcon { * * @returns A JLIcon instance */ - static get(name: string, fallback?: JLIcon): JLIcon { + private static _get(name: string, fallback?: JLIcon): JLIcon | undefined { const icon = JLIcon._instances.get(name); if (icon) { @@ -41,10 +40,54 @@ export class JLIcon { } // fail silently - return fallback ?? blankIcon; + return fallback; } } + /** + * Get any existing JLIcon instance by name, construct a DOM element + * from it, then return said element. + * + * @param name - Name of the JLIcon instance to fetch + * + * @param fallback - If left undefined, use automatic fallback to + * icons-as-css-background behavior: elem will be constructed using + * a blank icon with `elem.className = classes(name, props.className)`, + * where elem is the return value. Otherwise, fallback can be used to + * define the default JLIcon instance, returned whenever lookup fails + * + * @param props = passed directly to JLIcon.element + * + * @returns An SVGElement + */ + static getElement({ + name, + fallback, + ...props + }: { name: string; fallback?: JLIcon } & JLIcon.IProps) { + let icon = JLIcon._get(name, fallback); + if (!icon) { + icon = blankIcon; + props.className = classesDedupe(name, props.className); + } + + return icon.element(props); + } + + static getReact({ + name, + fallback, + ...props + }: { name: string; fallback?: JLIcon } & JLIcon.IReactProps) { + let icon = JLIcon._get(name, fallback); + if (!icon) { + icon = blankIcon; + props.className = classesDedupe(name, props.className); + } + + return ; + } + /** * Toggle icon debug from off-to-on, or vice-versa * @@ -56,7 +99,7 @@ export class JLIcon { constructor({ name, svgstr }: JLIcon.IOptions) { this.name = name; - this._className = JLIcon.nameToClassName(name); + this._className = Private.nameToClassName(name); this.svgstr = svgstr; this.react = this._initReact(); @@ -108,13 +151,6 @@ export class JLIcon { return svgElement; } - set svgstr(svgstr: string) { - this._svgstr = svgstr; - - // associate a unique id with this particular svgstr - this._uuid = UUID.uuid4(); - } - render(host: HTMLElement, props: JLIcon.IProps = {}): void { return ReactDOM.render(, host); } @@ -150,10 +186,17 @@ export class JLIcon { } } - string() { + get svgstr() { return this._svgstr; } + set svgstr(svgstr: string) { + this._svgstr = svgstr; + + // associate a unique id with this particular svgstr + this._uuid = UUID.uuid4(); + } + unrender(host: HTMLElement): void { ReactDOM.unmountComponentAtNode(host); } @@ -232,9 +275,7 @@ export class JLIcon { } readonly name: string; - readonly react: React.ForwardRefExoticComponent< - JLIcon.IProps & React.RefAttributes - >; + readonly react: JLIcon.IReact; protected _className: string; protected _svgstr: string; @@ -281,15 +322,19 @@ export namespace JLIcon { title?: string; } - export function nameToClassName(name: string): string { - return 'jp-' + Text.camelCase(name, true) + 'Icon'; - } + export type IReactProps = IProps & React.RefAttributes; + + export type IReact = React.ForwardRefExoticComponent; } export const badIcon = new JLIcon({ name: 'bad', svgstr: badSvg }); export const blankIcon = new JLIcon({ name: 'blank', svgstr: blankSvg }); namespace Private { + export function nameToClassName(name: string): string { + return 'jp-' + Text.camelCase(name, true) + 'Icon'; + } + export function setTitleSvg(svgNode: HTMLElement, title: string): void { // add a title node to the top level svg node let titleNodes = svgNode.getElementsByTagName('title');