ember-inline-svg icon indicating copy to clipboard operation
ember-inline-svg copied to clipboard

Convert to component?

Open NullVoxPopuli opened this issue 6 years ago • 2 comments

I'm also kinda wondering why this is helper?

It'd be great if we could wrap this in something like:

{{#if this.someCondition}}
  <InlineSvg @path={{this.path}} ...attributes />
{{/if}}

there the invocation could then become:

<MyIcon class='blue' />

NullVoxPopuli avatar Oct 23 '19 13:10 NullVoxPopuli

This can be as for Glimmer component, not sure if worth to do with classic component?

Related issue with class attributes #36 .

raido avatar Feb 13 '20 17:02 raido

Context

I wanted to create a component for custom (uploaded) Font Awesome icons so that I can keep the default way of installing FA packages via package manager and using the component provided by FA for all icons and handle only custom icons this way.

Disclaimer

This is a very minimal implementation which I'll further extend so I have one component to render all FA icons from the kit. Please note that all SVGs are manually optimized to the same format FA uses, the regular expressions can easily fail if optimization is not done that way. Also, this is in an addon, hence the addon namespace. (obviously it has the respective app export)

addon/components/icon.ts

import Component from '@glimmer/component';
import { htmlSafe } from '@ember/string';
import { assert } from '@ember/debug';
import { dottify } from 'ember-inline-svg/utils/general';

import type { SafeString } from '@ember/template/-private/handlebars';

const XMLNS_RE = /xmlns="([^"]*)"/;
const VIEWBOX_RE = /viewBox="([^"]*)"/;
const SVG_CONTENT_RE = /^<svg[^>]*>(.*)<\/svg>$/;

function extract(tag: string, attrRe: RegExp): string {
  return (tag.match(attrRe) as RegExpMatchArray)[1];
}

interface Args {
  path: string;
}

export default class IconComponent extends Component<Args> {
  xmlns!: string;
  viewBox!: string;
  svgContent!: SafeString;

  constructor(owner: unknown, args: Args) {
    super(owner, args);

    // @ts-expect-error not bothering to type resolveRegistration
    const svgs = owner.resolveRegistration('svgs:main') || [];
    const svg = svgs[dottify(this.args.path)];

    assert('No SVG found for ' + this.args.path, svg);

    this.xmlns = extract(svg, XMLNS_RE);
    this.viewBox = extract(svg, VIEWBOX_RE);
    this.svgContent = htmlSafe(extract(svg, SVG_CONTENT_RE));
  }
}

addon/components/icon.hbs

<svg xmlns={{this.xmlns}} viewBox={{this.viewBox}} ...attributes>
  {{this.svgContent}}
</svg>

abel-n avatar Dec 02 '21 10:12 abel-n