/ src / components / SFSymbol.svelte
SFSymbol.svelte
 1  <!--
 2  @component
 3  Renders a supported "SF Symbol" from the icons available in `~/sf-symbols`
 4  -->
 5  <script lang="ts" context="module">
 6      import type { ComponentType } from 'svelte';
 7  
 8      const iconComponents = import.meta.glob('~/sf-symbols/*.svg', {
 9          eager: true,
10          import: 'default',
11      });
12  
13      const iconNameToComponent: Record<string, ComponentType | undefined> =
14          Object.fromEntries(
15              Object.entries(iconComponents).map(
16                  ([fullPathToIcon, iconComponent]) => {
17                      const iconName = fullPathToIcon
18                          .replace('/src/sf-symbols/', '')
19                          .replace('.svg', '');
20  
21                      return [iconName, iconComponent as ComponentType];
22                  },
23              ),
24          );
25  
26      /**
27       * The list of all supported icons
28       *
29       * This is exposed only for testing/Storybook purposes
30       */
31      export const __iconNames = Object.keys(iconNameToComponent);
32  
33      export function getIconComponentByName(iconName: string) {
34          return iconNameToComponent[iconName];
35      }
36  </script>
37  
38  <script lang="ts">
39      /**
40       * The name of the SF Symbol to render
41       *
42       * Must match the name of an `.svg` file in `~/sf-symbols`. If a file with a matching
43       * name does not exist, nothing will be rendered
44       */
45      export let name: string;
46      export let ariaHidden: boolean = false;
47  
48      $: icon = getIconComponentByName(name);
49  </script>
50  
51  <svelte:component this={icon} aria-hidden={ariaHidden ? 'true' : 'false'} />