mirror of
https://github.com/iconify/iconify.git
synced 2024-11-09 14:50:56 +00:00
Web component: export reusable functions
This commit is contained in:
parent
f4efa1853d
commit
9043ec684f
@ -11,6 +11,7 @@ import type {
|
||||
import { getInline } from './attributes/inline';
|
||||
import { getRenderMode } from './attributes/mode';
|
||||
import type { IconifyIconAttributes } from './attributes/types';
|
||||
import { exportFunctions, IconifyExportedFunctions } from './functions';
|
||||
import { renderIcon } from './render/icon';
|
||||
import { updateStyle } from './render/style';
|
||||
import { IconState, setPendingState } from './state';
|
||||
@ -26,6 +27,8 @@ declare interface PartialIconifyIconHTMLElement extends HTMLElement {
|
||||
// Add dynamically generated getters and setters
|
||||
export declare interface IconifyIconHTMLElement
|
||||
extends PartialIconifyIconHTMLElement,
|
||||
// Functions added dynamically after class creation
|
||||
IconifyExportedFunctions,
|
||||
Required<IconifyIconAttributes> {}
|
||||
|
||||
/**
|
||||
@ -36,7 +39,9 @@ interface PartialIconifyIconHTMLElementClass {
|
||||
prototype: PartialIconifyIconHTMLElement;
|
||||
}
|
||||
|
||||
export interface IconifyIconHTMLElementClass {
|
||||
export interface IconifyIconHTMLElementClass
|
||||
// Functions added dynamically as static methods and methods on instance
|
||||
extends IconifyExportedFunctions {
|
||||
new (): IconifyIconHTMLElement;
|
||||
prototype: IconifyIconHTMLElement;
|
||||
}
|
||||
@ -46,7 +51,7 @@ export interface IconifyIconHTMLElementClass {
|
||||
*/
|
||||
export function defineIconifyIcon(
|
||||
name = 'iconify-icon'
|
||||
): PartialIconifyIconHTMLElementClass | undefined {
|
||||
): IconifyIconHTMLElementClass | undefined {
|
||||
// Check for custom elements registry and HTMLElement
|
||||
let customElements: CustomElementRegistry;
|
||||
let ParentClass: typeof HTMLElement;
|
||||
@ -86,7 +91,7 @@ export function defineIconifyIcon(
|
||||
/**
|
||||
* Component class
|
||||
*/
|
||||
class IconifyIcon extends ParentClass {
|
||||
const IconifyIcon: PartialIconifyIconHTMLElementClass = class extends ParentClass {
|
||||
// Root
|
||||
_shadowRoot: ShadowRoot;
|
||||
|
||||
@ -300,7 +305,7 @@ export function defineIconifyIcon(
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add getters and setters
|
||||
attributes.forEach((attr) => {
|
||||
@ -316,8 +321,19 @@ export function defineIconifyIcon(
|
||||
}
|
||||
});
|
||||
|
||||
// Add exported functions: both as static and instance methods
|
||||
const functions = exportFunctions();
|
||||
for (const key in functions) {
|
||||
IconifyIcon[key] = IconifyIcon.prototype[key] = functions[key];
|
||||
}
|
||||
|
||||
// Define new component
|
||||
customElements.define(name, IconifyIcon);
|
||||
|
||||
return IconifyIcon;
|
||||
return IconifyIcon as IconifyIconHTMLElementClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create exported data: either component instance or functions
|
||||
*/
|
||||
export const IconifyIconComponent = defineIconifyIcon() || exportFunctions();
|
||||
|
168
packages/icon/src/functions.ts
Normal file
168
packages/icon/src/functions.ts
Normal file
@ -0,0 +1,168 @@
|
||||
import type { IconifyJSON } from '@iconify/types';
|
||||
|
||||
// Core
|
||||
import type { IconifyStorageFunctions } from '@iconify/core/lib/storage/functions';
|
||||
import {
|
||||
iconExists,
|
||||
getIcon,
|
||||
addIcon,
|
||||
addCollection,
|
||||
} from '@iconify/core/lib/storage/functions';
|
||||
import { listIcons, shareStorage } from '@iconify/core/lib/storage/storage';
|
||||
import type { IconifyBuilderFunctions } from '@iconify/core/lib/builder/functions';
|
||||
import { buildIcon } from '@iconify/core/lib/builder/functions';
|
||||
import { replaceIDs } from '@iconify/utils/lib/svg/id';
|
||||
import { calculateSize } from '@iconify/utils/lib/svg/size';
|
||||
|
||||
// API
|
||||
import type {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import { setAPIModule } from '@iconify/core/lib/api/modules';
|
||||
import type { PartialIconifyAPIConfig } from '@iconify/core/lib/api/config';
|
||||
import {
|
||||
addAPIProvider,
|
||||
getAPIConfig,
|
||||
listAPIProviders,
|
||||
} from '@iconify/core/lib/api/config';
|
||||
import {
|
||||
fetchAPIModule,
|
||||
setFetch,
|
||||
getFetch,
|
||||
} from '@iconify/core/lib/api/modules/fetch';
|
||||
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
|
||||
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
||||
|
||||
// Cache
|
||||
import { cache } from '@iconify/core/lib/cache';
|
||||
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage';
|
||||
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
|
||||
import type {
|
||||
IconifyBrowserCacheType,
|
||||
IconifyBrowserCacheFunctions,
|
||||
} from '@iconify/core/lib/browser-storage/functions';
|
||||
|
||||
/**
|
||||
* Interface for exported functions
|
||||
*/
|
||||
export interface IconifyExportedFunctions
|
||||
extends IconifyStorageFunctions,
|
||||
IconifyBuilderFunctions,
|
||||
IconifyBrowserCacheFunctions,
|
||||
IconifyAPIFunctions {
|
||||
_api: IconifyAPIInternalFunctions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get functions and initialise stuff
|
||||
*/
|
||||
export function exportFunctions(): IconifyExportedFunctions {
|
||||
/**
|
||||
* Initialise stuff
|
||||
*/
|
||||
// Set API module
|
||||
setAPIModule('', fetchAPIModule);
|
||||
|
||||
/**
|
||||
* Browser stuff
|
||||
*/
|
||||
interface WindowWithIconifyStuff {
|
||||
IconifyPreload?: IconifyJSON[] | IconifyJSON;
|
||||
IconifyProviders?: Record<string, PartialIconifyAPIConfig>;
|
||||
}
|
||||
let _window: WindowWithIconifyStuff;
|
||||
try {
|
||||
_window = window as WindowWithIconifyStuff;
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
if (_window) {
|
||||
// Set cache and load existing cache
|
||||
cache.store = storeCache;
|
||||
loadCache();
|
||||
|
||||
// Load icons from global "IconifyPreload"
|
||||
if (_window.IconifyPreload !== void 0) {
|
||||
const preload = _window.IconifyPreload;
|
||||
const err = 'Invalid IconifyPreload syntax.';
|
||||
if (typeof preload === 'object' && preload !== null) {
|
||||
(preload instanceof Array ? preload : [preload]).forEach(
|
||||
(item) => {
|
||||
try {
|
||||
if (
|
||||
// Check if item is an object and not null/array
|
||||
typeof item !== 'object' ||
|
||||
item === null ||
|
||||
item instanceof Array ||
|
||||
// Check for 'icons' and 'prefix'
|
||||
typeof item.icons !== 'object' ||
|
||||
typeof item.prefix !== 'string' ||
|
||||
// Add icon set
|
||||
!addCollection(item)
|
||||
) {
|
||||
console.error(err);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Set API from global "IconifyProviders"
|
||||
if (_window.IconifyProviders !== void 0) {
|
||||
const providers = _window.IconifyProviders;
|
||||
if (typeof providers === 'object' && providers !== null) {
|
||||
for (const key in providers) {
|
||||
const err = 'IconifyProviders[' + key + '] is invalid.';
|
||||
try {
|
||||
const value = providers[key];
|
||||
if (
|
||||
typeof value !== 'object' ||
|
||||
!value ||
|
||||
value.resources === void 0
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (!addAPIProvider(key, value)) {
|
||||
console.error(err);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const _api: IconifyAPIInternalFunctions = {
|
||||
getAPIConfig,
|
||||
setAPIModule,
|
||||
sendAPIQuery,
|
||||
setFetch,
|
||||
getFetch,
|
||||
listAPIProviders,
|
||||
};
|
||||
|
||||
return {
|
||||
enableCache: (storage: IconifyBrowserCacheType) =>
|
||||
toggleBrowserCache(storage, true),
|
||||
disableCache: (storage: IconifyBrowserCacheType) =>
|
||||
toggleBrowserCache(storage, false),
|
||||
iconExists,
|
||||
getIcon,
|
||||
listIcons,
|
||||
shareStorage,
|
||||
addIcon,
|
||||
addCollection,
|
||||
calculateSize,
|
||||
replaceIDs,
|
||||
buildIcon,
|
||||
loadIcons,
|
||||
loadIcon,
|
||||
addAPIProvider,
|
||||
_api,
|
||||
};
|
||||
}
|
135
packages/icon/src/index.ts
Normal file
135
packages/icon/src/index.ts
Normal file
@ -0,0 +1,135 @@
|
||||
import type { IconifyJSON, IconifyIcon } from '@iconify/types';
|
||||
|
||||
// Core
|
||||
import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
|
||||
import type {
|
||||
IconifyIconSize,
|
||||
IconifyHorizontalIconAlignment,
|
||||
IconifyVerticalIconAlignment,
|
||||
IconifyIconCustomisations,
|
||||
} from '@iconify/utils/lib/customisations';
|
||||
import type { IconifyStorageFunctions } from '@iconify/core/lib/storage/functions';
|
||||
import type { IconifyBuilderFunctions } from '@iconify/core/lib/builder/functions';
|
||||
import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
|
||||
|
||||
// API
|
||||
import type {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import type {
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import type {
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIConfig,
|
||||
GetAPIConfig,
|
||||
} from '@iconify/core/lib/api/config';
|
||||
import type {
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
} from '@iconify/core/lib/api/icons';
|
||||
|
||||
// Cache
|
||||
import type {
|
||||
IconifyBrowserCacheType,
|
||||
IconifyBrowserCacheFunctions,
|
||||
} from '@iconify/core/lib/browser-storage/functions';
|
||||
|
||||
// Component
|
||||
import type { IconifyIconAttributes } from './attributes/types';
|
||||
import { IconifyIconComponent } from './component';
|
||||
|
||||
/**
|
||||
* Export used types
|
||||
*/
|
||||
// Function sets
|
||||
export {
|
||||
IconifyStorageFunctions,
|
||||
IconifyBuilderFunctions,
|
||||
IconifyBrowserCacheFunctions,
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
};
|
||||
|
||||
// JSON stuff
|
||||
export { IconifyIcon, IconifyJSON, IconifyIconName };
|
||||
|
||||
// Customisations
|
||||
export {
|
||||
IconifyIconCustomisations,
|
||||
IconifyIconSize,
|
||||
IconifyHorizontalIconAlignment,
|
||||
IconifyVerticalIconAlignment,
|
||||
};
|
||||
|
||||
// API
|
||||
export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
};
|
||||
|
||||
// Builder functions
|
||||
export { IconifyIconBuildResult };
|
||||
|
||||
// Browser cache
|
||||
export { IconifyBrowserCacheType };
|
||||
|
||||
// Component types
|
||||
export { IconifyIconAttributes };
|
||||
|
||||
/**
|
||||
* Export component
|
||||
*/
|
||||
export { IconifyIconComponent };
|
||||
|
||||
/**
|
||||
* Export functions
|
||||
*/
|
||||
const {
|
||||
enableCache,
|
||||
disableCache,
|
||||
iconExists,
|
||||
getIcon,
|
||||
listIcons,
|
||||
shareStorage,
|
||||
addIcon,
|
||||
addCollection,
|
||||
calculateSize,
|
||||
replaceIDs,
|
||||
buildIcon,
|
||||
loadIcons,
|
||||
loadIcon,
|
||||
addAPIProvider,
|
||||
_api,
|
||||
} = IconifyIconComponent;
|
||||
|
||||
export {
|
||||
enableCache,
|
||||
disableCache,
|
||||
iconExists,
|
||||
getIcon,
|
||||
listIcons,
|
||||
shareStorage,
|
||||
addIcon,
|
||||
addCollection,
|
||||
calculateSize,
|
||||
replaceIDs,
|
||||
buildIcon,
|
||||
loadIcons,
|
||||
loadIcon,
|
||||
addAPIProvider,
|
||||
_api,
|
||||
};
|
@ -26,7 +26,8 @@ describe('Testing icon component', () => {
|
||||
expect(window.customElements.get('iconify-icon')).toBeUndefined();
|
||||
|
||||
// Define component
|
||||
expect(defineIconifyIcon()).toBeDefined();
|
||||
const IconifyIcon = defineIconifyIcon();
|
||||
expect(IconifyIcon).toBeDefined();
|
||||
expect(window.customElements.get('iconify-icon')).toBeDefined();
|
||||
|
||||
// Create element
|
||||
@ -39,6 +40,10 @@ describe('Testing icon component', () => {
|
||||
`<style>${expectedBlock}</style>`
|
||||
);
|
||||
|
||||
// Check for dynamically added methods
|
||||
expect(typeof node.loadIcon).toBe('function');
|
||||
expect(typeof IconifyIcon.loadIcon).toBe('function');
|
||||
|
||||
// Set icon
|
||||
node.icon = {
|
||||
body: '<g />',
|
||||
|
Loading…
Reference in New Issue
Block a user