diff --git a/change/@fluentui-react-file-type-icons-e373acc1-0c3c-491b-baf5-208cf47dfffa.json b/change/@fluentui-react-file-type-icons-e373acc1-0c3c-491b-baf5-208cf47dfffa.json
new file mode 100644
index 00000000000000..ff3bec59b9ab7e
--- /dev/null
+++ b/change/@fluentui-react-file-type-icons-e373acc1-0c3c-491b-baf5-208cf47dfffa.json
@@ -0,0 +1,7 @@
+{
+ "type": "minor",
+ "comment": "Expose getFileTypeIconAsURL helper to get file type icon url instead of HTML element",
+ "packageName": "@fluentui/react-file-type-icons",
+ "email": "tigeroakes@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/react-file-type-icons/src/getFileTypeIconAsHTMLString.ts b/packages/react-file-type-icons/src/getFileTypeIconAsHTMLString.ts
index ce9ddd23ac081c..9d01bb2ded522c 100644
--- a/packages/react-file-type-icons/src/getFileTypeIconAsHTMLString.ts
+++ b/packages/react-file-type-icons/src/getFileTypeIconAsHTMLString.ts
@@ -1,10 +1,7 @@
import { DEFAULT_BASE_URL } from './initializeFileTypeIcons';
-import {
- getFileTypeIconNameFromExtensionOrType,
- getFileTypeIconSuffix,
- DEFAULT_ICON_SIZE,
-} from './getFileTypeIconProps';
+import { getFileTypeIconSuffix, DEFAULT_ICON_SIZE } from './getFileTypeIconProps';
import type { IFileTypeIconOptions } from './getFileTypeIconProps';
+import { getFileTypeIconAsURL } from './getFileTypeIconAsURL';
/**
* Given the `fileTypeIconOptions`, this function returns the DOM element for the `FileTypeIcon`
@@ -17,19 +14,16 @@ export function getFileTypeIconAsHTMLString(
options: IFileTypeIconOptions,
baseUrl: string = DEFAULT_BASE_URL,
): string | undefined {
- const { extension, size = DEFAULT_ICON_SIZE, type, imageFileType } = options;
- const baseIconName = getFileTypeIconNameFromExtensionOrType(extension, type); // eg: docx
+ const { size = DEFAULT_ICON_SIZE, imageFileType } = options;
const baseSuffix = getFileTypeIconSuffix(size, imageFileType); // eg: 96_3x_svg or 96_png
const suffixArray = baseSuffix.split('_'); // eg: ['96', '3x', 'svg']
- let src: string | undefined;
+ const src = getFileTypeIconAsURL(options, baseUrl);
if (suffixArray.length === 3) {
/** suffix is of type 96_3x_svg - it has a pixel ratio > 1*/
- src = `${baseUrl}${size}_${suffixArray[1]}/${baseIconName}.${suffixArray[2]}`;
return `
`;
} else if (suffixArray.length === 2) {
/** suffix is of type 96_svg - it has a pixel ratio of 1*/
- src = `${baseUrl}${size}/${baseIconName}.${suffixArray[1]}`;
return `
`;
}
}
diff --git a/packages/react-file-type-icons/src/getFileTypeIconAsURL.test.ts b/packages/react-file-type-icons/src/getFileTypeIconAsURL.test.ts
new file mode 100644
index 00000000000000..e2e77f8b11a8ed
--- /dev/null
+++ b/packages/react-file-type-icons/src/getFileTypeIconAsURL.test.ts
@@ -0,0 +1,98 @@
+import { ICON_SIZES, DEFAULT_BASE_URL } from './initializeFileTypeIcons';
+import { DEFAULT_ICON_SIZE } from './getFileTypeIconProps';
+import { getFileTypeIconAsURL } from './getFileTypeIconAsURL';
+import type { FileTypeIconSize } from './getFileTypeIconProps';
+
+// Currently this test file only covers the default device pixel ratio, i.e 1
+const getExpectedURL = (iconSize: FileTypeIconSize, suffix: string, expectedExt: string) => {
+ return `${DEFAULT_BASE_URL}${iconSize}/${expectedExt}.${suffix}`;
+};
+
+// Test suite 1
+describe('returns valid URLs', () => {
+ it('returns the correct url for all valid icon sizes with default as svg', () => {
+ ICON_SIZES.forEach((iconSize: number) => {
+ const res = getFileTypeIconAsURL({
+ size: iconSize as FileTypeIconSize,
+ extension: 'doc',
+ });
+ expect(res).toEqual(getExpectedURL(iconSize as FileTypeIconSize, 'svg', 'docx'));
+ });
+
+ ICON_SIZES.forEach((iconSize: number) => {
+ const res = getFileTypeIconAsURL({
+ size: iconSize as FileTypeIconSize,
+ extension: 'accdb',
+ });
+ expect(res).toEqual(getExpectedURL(iconSize as FileTypeIconSize, 'svg', 'accdb'));
+ });
+ });
+
+ it('returns the correct url for all valid icon sizes with type as png', () => {
+ ICON_SIZES.forEach((iconSize: number) => {
+ const res = getFileTypeIconAsURL({
+ size: iconSize as FileTypeIconSize,
+ extension: 'doc',
+ imageFileType: 'png',
+ });
+ expect(res).toEqual(getExpectedURL(iconSize as FileTypeIconSize, 'png', 'docx'));
+ });
+
+ ICON_SIZES.forEach((iconSize: number) => {
+ const res = getFileTypeIconAsURL({
+ size: iconSize as FileTypeIconSize,
+ extension: 'accdb',
+ imageFileType: 'png',
+ });
+ expect(res).toEqual(getExpectedURL(iconSize as FileTypeIconSize, 'png', 'accdb'));
+ });
+ });
+});
+
+// Test suite 2
+describe('Returns genericfile for invalid inputs', () => {
+ it('returns genericfile for invalid extension with default type as svg', () => {
+ ICON_SIZES.forEach((iconSize: number) => {
+ const res = getFileTypeIconAsURL({
+ size: iconSize as FileTypeIconSize,
+ extension: 'blah',
+ });
+ expect(res).toEqual(getExpectedURL(iconSize as FileTypeIconSize, 'svg', 'genericfile'));
+ });
+ });
+
+ it('returns genericfile with type as png', () => {
+ ICON_SIZES.forEach((iconSize: number) => {
+ const res = getFileTypeIconAsURL({
+ size: iconSize as FileTypeIconSize,
+ extension: 'NotAValidExtension',
+ imageFileType: 'png',
+ });
+ expect(res).toEqual(getExpectedURL(iconSize as FileTypeIconSize, 'png', 'genericfile'));
+ });
+ });
+
+ it('returns genericfile with default size for empty size, extension and type', () => {
+ const res = getFileTypeIconAsURL({});
+ expect(res).toEqual(getExpectedURL(DEFAULT_ICON_SIZE, 'svg', 'genericfile'));
+ });
+
+ it('returns genericfile with default size for empty size, extension and type with type as png', () => {
+ const res = getFileTypeIconAsURL({ imageFileType: 'png' });
+ expect(res).toEqual(getExpectedURL(DEFAULT_ICON_SIZE, 'png', 'genericfile'));
+ });
+});
+
+// Test suite 3
+describe('Returns correct element for custom CDN url', () => {
+ it('returns expected url', () => {
+ const elm = getFileTypeIconAsURL(
+ {
+ size: 96,
+ extension: 'docx',
+ },
+ 'https://example-base-url/assets/item-types-fluent/',
+ );
+ expect(elm).toEqual('https://example-base-url/assets/item-types-fluent/96/docx.svg');
+ });
+});
diff --git a/packages/react-file-type-icons/src/getFileTypeIconAsURL.ts b/packages/react-file-type-icons/src/getFileTypeIconAsURL.ts
new file mode 100644
index 00000000000000..2d85de15f6378a
--- /dev/null
+++ b/packages/react-file-type-icons/src/getFileTypeIconAsURL.ts
@@ -0,0 +1,32 @@
+import { DEFAULT_BASE_URL } from './initializeFileTypeIcons';
+import {
+ getFileTypeIconNameFromExtensionOrType,
+ getFileTypeIconSuffix,
+ DEFAULT_ICON_SIZE,
+} from './getFileTypeIconProps';
+import type { IFileTypeIconOptions } from './getFileTypeIconProps';
+
+/**
+ * Given the `fileTypeIconOptions`, this function returns the image for the `FileTypeIcon`
+ * as an URL. Similar to `getFileTypeIconProps`, this also accepts the same type of object
+ * but rather than returning the `iconName`, this returns the entire image URL as a string.
+ * @param options
+ * @param baseUrl - optionally provide a custom CDN base url to fetch icons from
+ */
+export function getFileTypeIconAsURL(
+ options: IFileTypeIconOptions,
+ baseUrl: string = DEFAULT_BASE_URL,
+): string | undefined {
+ const { extension, size = DEFAULT_ICON_SIZE, type, imageFileType } = options;
+ const baseIconName = getFileTypeIconNameFromExtensionOrType(extension, type); // eg: docx
+ const baseSuffix = getFileTypeIconSuffix(size, imageFileType); // eg: 96_3x_svg or 96_png
+ const suffixArray = baseSuffix.split('_'); // eg: ['96', '3x', 'svg']
+
+ if (suffixArray.length === 3) {
+ /** suffix is of type 96_3x_svg - it has a pixel ratio > 1*/
+ return `${baseUrl}${size}_${suffixArray[1]}/${baseIconName}.${suffixArray[2]}`;
+ } else if (suffixArray.length === 2) {
+ /** suffix is of type 96_svg - it has a pixel ratio of 1*/
+ return `${baseUrl}${size}/${baseIconName}.${suffixArray[1]}`;
+ }
+}
diff --git a/packages/react-file-type-icons/src/initializeFileTypeIcons.tsx b/packages/react-file-type-icons/src/initializeFileTypeIcons.tsx
index d13b34e54f9795..8ea0af8aedc1e4 100644
--- a/packages/react-file-type-icons/src/initializeFileTypeIcons.tsx
+++ b/packages/react-file-type-icons/src/initializeFileTypeIcons.tsx
@@ -2,12 +2,13 @@ import * as React from 'react';
import { registerIcons, FLUENT_CDN_BASE_URL } from '@fluentui/style-utilities';
import { FileTypeIconMap } from './FileTypeIconMap';
import type { IIconOptions } from '@fluentui/style-utilities';
+import type { FileTypeIconSize } from './getFileTypeIconProps';
const PNG_SUFFIX = '_png';
const SVG_SUFFIX = '_svg';
export const DEFAULT_BASE_URL = `${FLUENT_CDN_BASE_URL}/assets/item-types/`;
-export const ICON_SIZES: number[] = [16, 20, 24, 32, 40, 48, 64, 96];
+export const ICON_SIZES: FileTypeIconSize[] = [16, 20, 24, 32, 40, 48, 64, 96];
export function initializeFileTypeIcons(baseUrl: string = DEFAULT_BASE_URL, options?: Partial): void {
ICON_SIZES.forEach((size: number) => {