Browse Source

simplified createIcon function by refactoring it into JLIcon class

individual icons are now instances of JLIcon class
telamonian 5 years ago
parent
commit
268905dc27

+ 3 - 3
buildutils/src/ensure-package.ts

@@ -21,7 +21,7 @@ const HEADER_TEMPLATE = `
 `;
 
 const ICON_IMPORTS_TEMPLATE = `
-import { createIcon } from './jlicon';
+import { JLIcon } from './jlicon';
 import { Icon } from './interfaces';
 
 // icon svg import statements
@@ -389,12 +389,12 @@ export async function ensureUiComponents(
     } else {
       // load the icon svg using `import`
       const svgname = utils.camelCase(name) + 'Svg';
-      const iconname = utils.camelCase(name, true) + 'Icon';
+      const iconname = utils.camelCase(name) + 'Icon';
 
       _iconImportStatements.push(`import ${svgname} from '${svgpath}';`);
       _iconModelDeclarations.push(`{ name: '${name}', svg: ${svgname} }`);
       _wrappedIconDefs.push(
-        `export const ${iconname} = createIcon('${name}', ${svgname});`
+        `export const ${iconname} = new JLIcon('${iconname}', ${svgname});`
       );
     }
   });

+ 3 - 3
packages/notebook/src/truststatus.tsx

@@ -6,7 +6,7 @@ import { INotebookModel, Notebook } from '.';
 
 import { Cell } from '@jupyterlab/cells';
 
-import { NotTrustedIcon, TrustedIcon } from '@jupyterlab/ui-components';
+import { notTrustedIcon, trustedIcon } from '@jupyterlab/ui-components';
 
 import { toArray } from '@lumino/algorithm';
 
@@ -45,9 +45,9 @@ function NotebookTrustComponent(
   props: NotebookTrustComponent.IProps
 ): React.ReactElement<NotebookTrustComponent.IProps> {
   if (props.allCellsTrusted) {
-    return <TrustedIcon top={'2px'} kind={'statusBar'} />;
+    return <trustedIcon.react top={'2px'} kind={'statusBar'} />;
   } else {
-    return <NotTrustedIcon top={'2px'} kind={'statusBar'} />;
+    return <notTrustedIcon.react top={'2px'} kind={'statusBar'} />;
   }
 }
 

+ 33 - 33
packages/ui-components/src/icon/iconimports.ts

@@ -5,7 +5,7 @@
 
 /* This file was auto-generated by ensureUiComponents() in @jupyterlab/buildutils */
 
-import { createIcon } from './jlicon';
+import { JLIcon } from './jlicon';
 import { Icon } from './interfaces';
 
 // icon svg import statements
@@ -83,37 +83,37 @@ export namespace IconImports {
 }
 
 // wrapped icon definitions
-export const FileIcon = createIcon('file', fileSvg);
-export const FolderIcon = createIcon('folder', folderSvg);
-export const Html5Icon = createIcon('html5', html5Svg);
-export const ImageIcon = createIcon('image', imageSvg);
-export const JsonIcon = createIcon('json', jsonSvg);
-export const MarkdownIcon = createIcon('markdown', markdownSvg);
-export const NotebookIcon = createIcon('notebook', notebookSvg);
-export const PythonIcon = createIcon('python', pythonSvg);
-export const RKernelIcon = createIcon('r-kernel', rKernelSvg);
-export const ReactIcon = createIcon('react', reactSvg);
-export const SpreadsheetIcon = createIcon('spreadsheet', spreadsheetSvg);
-export const YamlIcon = createIcon('yaml', yamlSvg);
-export const BuildIcon = createIcon('build', buildSvg);
-export const ExtensionIcon = createIcon('extension', extensionSvg);
-export const PaletteIcon = createIcon('palette', paletteSvg);
-export const RunningIcon = createIcon('running', runningSvg);
-export const TabIcon = createIcon('tab', tabSvg);
-export const JupyterFaviconIcon = createIcon(
-  'jupyter-favicon',
+export const fileIcon = new JLIcon('fileIcon', fileSvg);
+export const folderIcon = new JLIcon('folderIcon', folderSvg);
+export const html5Icon = new JLIcon('html5Icon', html5Svg);
+export const imageIcon = new JLIcon('imageIcon', imageSvg);
+export const jsonIcon = new JLIcon('jsonIcon', jsonSvg);
+export const markdownIcon = new JLIcon('markdownIcon', markdownSvg);
+export const notebookIcon = new JLIcon('notebookIcon', notebookSvg);
+export const pythonIcon = new JLIcon('pythonIcon', pythonSvg);
+export const rKernelIcon = new JLIcon('rKernelIcon', rKernelSvg);
+export const reactIcon = new JLIcon('reactIcon', reactSvg);
+export const spreadsheetIcon = new JLIcon('spreadsheetIcon', spreadsheetSvg);
+export const yamlIcon = new JLIcon('yamlIcon', yamlSvg);
+export const buildIcon = new JLIcon('buildIcon', buildSvg);
+export const extensionIcon = new JLIcon('extensionIcon', extensionSvg);
+export const paletteIcon = new JLIcon('paletteIcon', paletteSvg);
+export const runningIcon = new JLIcon('runningIcon', runningSvg);
+export const tabIcon = new JLIcon('tabIcon', tabSvg);
+export const jupyterFaviconIcon = new JLIcon(
+  'jupyterFaviconIcon',
   jupyterFaviconSvg
 );
-export const KernelIcon = createIcon('kernel', kernelSvg);
-export const LineFormIcon = createIcon('line-form', lineFormSvg);
-export const NotTrustedIcon = createIcon('not-trusted', notTrustedSvg);
-export const TerminalIcon = createIcon('terminal', terminalSvg);
-export const TrustedIcon = createIcon('trusted', trustedSvg);
-export const AddIcon = createIcon('add', addSvg);
-export const CopyIcon = createIcon('copy', copySvg);
-export const CutIcon = createIcon('cut', cutSvg);
-export const PasteIcon = createIcon('paste', pasteSvg);
-export const RefreshIcon = createIcon('refresh', refreshSvg);
-export const RunIcon = createIcon('run', runSvg);
-export const SaveIcon = createIcon('save', saveSvg);
-export const StopIcon = createIcon('stop', stopSvg);
+export const kernelIcon = new JLIcon('kernelIcon', kernelSvg);
+export const lineFormIcon = new JLIcon('lineFormIcon', lineFormSvg);
+export const notTrustedIcon = new JLIcon('notTrustedIcon', notTrustedSvg);
+export const terminalIcon = new JLIcon('terminalIcon', terminalSvg);
+export const trustedIcon = new JLIcon('trustedIcon', trustedSvg);
+export const addIcon = new JLIcon('addIcon', addSvg);
+export const copyIcon = new JLIcon('copyIcon', copySvg);
+export const cutIcon = new JLIcon('cutIcon', cutSvg);
+export const pasteIcon = new JLIcon('pasteIcon', pasteSvg);
+export const refreshIcon = new JLIcon('refreshIcon', refreshSvg);
+export const runIcon = new JLIcon('runIcon', runSvg);
+export const saveIcon = new JLIcon('saveIcon', saveSvg);
+export const stopIcon = new JLIcon('stopIcon', stopSvg);

+ 49 - 58
packages/ui-components/src/icon/jlicon.tsx

@@ -1,25 +1,24 @@
-import React, {
-  ForwardRefExoticComponent,
-  PropsWithoutRef,
-  RefAttributes,
-  RefObject
-} from 'react';
+import React, { RefObject } from 'react';
 import { classes } from 'typestyle';
 import { iconStyle, IIconStyle } from '../style/icon';
 
-export function createIcon(
-  svgname: string,
-  svgstr: string,
-  debug: boolean = false
-): JLIcon.IComponent {
-  function resolveSvg(svgstr: string, title?: string): HTMLElement | null {
-    const svgElement = new DOMParser().parseFromString(svgstr, 'image/svg+xml')
-      .documentElement;
+export class JLIcon {
+  constructor(
+    readonly name: string,
+    readonly svgstr: string,
+    protected _debug: boolean = false
+  ) {}
+
+  resolveSvg(title?: string): HTMLElement | null {
+    const svgElement = new DOMParser().parseFromString(
+      this.svgstr,
+      'image/svg+xml'
+    ).documentElement;
 
     if (svgElement.getElementsByTagName('parsererror').length > 0) {
       const errmsg = `SVG HTML was malformed for icon name: ${name}`;
       // parse failed, svgElement will be an error box
-      if (debug) {
+      if (this._debug) {
         // fail noisily, render the error box
         console.error(errmsg);
         return svgElement;
@@ -38,48 +37,19 @@ export function createIcon(
     }
   }
 
-  const JLIcon: JLIcon.IComponent = React.forwardRef<
-    HTMLDivElement,
-    JLIcon.IProps
-  >(
-    (props: JLIcon.IProps, ref: RefObject<HTMLDivElement>): JSX.Element => {
-      const { className, title, tag = 'div', ...propsStyle } = props;
-      const Tag = tag;
-      const classNames = classes(
-        className,
-        propsStyle ? iconStyle(propsStyle) : ''
-      );
-
-      // ensure that svg html is valid
-      const svgElement = resolveSvg(svgstr, title);
-      if (!svgElement) {
-        // bail if failing silently
-        return <></>;
-      }
-
-      return (
-        <Tag
-          className={classNames}
-          dangerouslySetInnerHTML={{ __html: svgElement.outerHTML }}
-          ref={ref}
-        />
-      );
-    }
-  );
-
-  JLIcon.element = ({
+  element({
     className,
     title,
     tag = 'div',
     ...propsStyle
-  }: JLIcon.IProps): HTMLElement | null => {
+  }: JLIcon.IProps): HTMLElement | null {
     const classNames = classes(
       className,
       propsStyle ? iconStyle(propsStyle) : ''
     );
 
     // ensure that svg html is valid
-    const svgElement = resolveSvg(svgstr, title);
+    const svgElement = this.resolveSvg(title);
     if (!svgElement) {
       // bail if failing silently
       return null;
@@ -89,12 +59,40 @@ export function createIcon(
     container.appendChild(svgElement);
     container.className = classNames;
     return container;
-  };
+  }
 
-  // set display name of JLIcon for debugging
-  JLIcon.displayName = `JLIcon_${svgname}`;
+  get react() {
+    const component = React.forwardRef(
+      (
+        { className, title, tag = 'div', ...propsStyle }: JLIcon.IProps,
+        ref: RefObject<HTMLDivElement>
+      ) => {
+        const Tag = tag;
+        const classNames = classes(
+          className,
+          propsStyle ? iconStyle(propsStyle) : ''
+        );
+
+        // ensure that svg html is valid
+        const svgElement = this.resolveSvg(title);
+        if (!svgElement) {
+          // bail if failing silently
+          return <></>;
+        }
+
+        return (
+          <Tag
+            className={classNames}
+            dangerouslySetInnerHTML={{ __html: svgElement.outerHTML }}
+            ref={ref}
+          />
+        );
+      }
+    );
 
-  return JLIcon;
+    component.displayName = `JLIcon_${this.name}`;
+    return component;
+  }
 }
 
 /**
@@ -117,13 +115,6 @@ export namespace JLIcon {
      */
     title?: string;
   }
-
-  export interface IComponent
-    extends ForwardRefExoticComponent<
-      PropsWithoutRef<IProps> & RefAttributes<HTMLDivElement>
-    > {
-    element?: (props: IProps) => HTMLElement;
-  }
 }
 
 namespace Private {