Skip to content

Commit 6a032e5

Browse files
authored
merge release-7.2.0
Feature 7.2
2 parents 8369c36 + a3902ce commit 6a032e5

File tree

8 files changed

+162
-17
lines changed

8 files changed

+162
-17
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
# [7.2.0](https://github.com/ionic-team/ionicons/compare/v7.1.2...v7.2.0) (2023-10-10)
7+
8+
9+
### Bug Fixes
10+
11+
* **icon:** mapping same icon does not warn ([#1279](https://github.com/ionic-team/ionicons/issues/1279)) ([8297018](https://github.com/ionic-team/ionicons/commit/8297018cb591f5e33a815ceb9e4e765271ecf5ad))
12+
* **icon:** verify the icon loads in the lifecycle ([#1278](https://github.com/ionic-team/ionicons/issues/1278)) ([7f7f346](https://github.com/ionic-team/ionicons/commit/7f7f346af47f45531046e1d2f1a88f53acee77fa))
13+
14+
15+
### Features
16+
17+
* allow passing in only icon SVG data to addIcons ([#1256](https://github.com/ionic-team/ionicons/issues/1256)) ([1e33313](https://github.com/ionic-team/ionicons/commit/1e3331347328c11a8b4c58c9200059bfd76b0e59))
18+
* **icon:** support for dynamic type ([#1246](https://github.com/ionic-team/ionicons/issues/1246)) ([45c04dd](https://github.com/ionic-team/ionicons/commit/45c04dda6c905e535083b171cead374b1c993afa))
19+
20+
21+
22+
23+
624
## [7.1.2](https://github.com/ionic-team/ionicons/compare/v7.1.1...v7.1.2) (2023-05-30)
725

826

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"packages": [
33
"./"
44
],
5-
"version": "7.1.2"
5+
"version": "7.2.0"
66
}

package-lock.json

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ionicons",
3-
"version": "7.1.2",
3+
"version": "7.2.0",
44
"description": "Premium icons for Ionic.",
55
"files": [
66
"components/",
@@ -23,7 +23,7 @@
2323
"test.spec": "stencil test --spec"
2424
},
2525
"dependencies": {
26-
"@stencil/core": "^2.18.0"
26+
"@stencil/core": "^4.0.3"
2727
},
2828
"devDependencies": {
2929
"@playwright/test": "^1.33.0",

src/components/icon/icon.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export class Icon {
1212
private io?: IntersectionObserver;
1313
private iconName: string | null = null;
1414
private inheritedAttributes: { [k: string]: any } = {};
15+
private didLoadIcon = false;
1516

1617
@Element() el!: HTMLElement;
1718

@@ -94,6 +95,18 @@ export class Icon {
9495
});
9596
}
9697

98+
componentDidLoad() {
99+
/**
100+
* Addresses an Angular issue where property values are assigned after the 'connectedCallback' but prior to the registration of watchers.
101+
* This enhancement ensures the loading of an icon when the component has finished rendering and the icon has yet to apply the SVG data.
102+
* This modification pertains to the usage of Angular's binding syntax:
103+
* `<ion-icon [name]="myIconName"></ion-icon>`
104+
*/
105+
if (!this.didLoadIcon) {
106+
this.loadIcon();
107+
}
108+
}
109+
97110
disconnectedCallback() {
98111
if (this.io) {
99112
this.io.disconnect();
@@ -138,6 +151,7 @@ export class Icon {
138151
// async if it hasn't been loaded
139152
getSvgContent(url, this.sanitize).then(() => (this.svgContent = ioniconContent.get(url)));
140153
}
154+
this.didLoadIcon = true;
141155
}
142156
}
143157

src/components/icon/test/utils.spec.ts

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Icon } from '../icon';
2-
import { getName, getSrc, getUrl } from '../utils';
2+
import { addIcons, getIconMap, getName, getSrc, getUrl } from '../utils';
33

44

55
describe('getUrl', () => {
@@ -82,3 +82,82 @@ describe('getName', () => {
8282
});
8383

8484
});
85+
86+
describe('addIcons', () => {
87+
it('should add an svg to the icon cache', () => {
88+
const testData = 'stubbed data';
89+
90+
expect(getIconMap().get('logo-ionic')).toEqual(undefined);
91+
92+
addIcons({ 'logo-ionic': 'stubbed data' });
93+
94+
expect(getIconMap().get('logo-ionic')).toEqual(testData);
95+
});
96+
97+
it('should add kebab and camel case names to the icon cache', () => {
98+
const logoIonitron = 'stubbed data';
99+
100+
expect(getIconMap().get('logo-ionitron')).toEqual(undefined);
101+
expect(getIconMap().get('logoIonitron')).toEqual(undefined);
102+
103+
addIcons({ logoIonitron });
104+
105+
expect(getIconMap().get('logo-ionitron')).toEqual(logoIonitron);
106+
expect(getIconMap().get('logoIonitron')).toEqual(logoIonitron);
107+
});
108+
109+
it('should map to a name that does not match the svg', () => {
110+
const logoIonitron = 'stubbed data';
111+
112+
expect(getIconMap().get('my-fun-icon')).toEqual(undefined);
113+
114+
addIcons({ 'my-fun-icon': logoIonitron });
115+
116+
expect(getIconMap().get('my-fun-icon')).toEqual(logoIonitron);
117+
});
118+
119+
it('should map to an explicit camel case name', () => {
120+
const logoIonitron = 'stubbed data';
121+
122+
expect(getIconMap().get('myCoolIcon')).toEqual(undefined);
123+
124+
addIcons({ 'myCoolIcon': logoIonitron });
125+
126+
expect(getIconMap().get('myCoolIcon')).toEqual(logoIonitron);
127+
});
128+
129+
it('should not warn when mapping the same icon twice', () => {
130+
const spy = jest.spyOn(console, 'warn');
131+
132+
const myIcon = 'my-icon';
133+
134+
expect(spy).not.toHaveBeenCalled();
135+
136+
addIcons({ myIcon });
137+
138+
expect(spy).not.toHaveBeenCalled();
139+
140+
addIcons({ myIcon });
141+
142+
expect(spy).not.toHaveBeenCalled();
143+
});
144+
145+
it('should not overwrite icons', () => {
146+
const spy = jest.spyOn(console, 'warn');
147+
148+
const logoA = 'logo a';
149+
const logoB = 'logo b';
150+
151+
expect(spy).not.toHaveBeenCalled();
152+
153+
expect(getIconMap().get('logo-a')).toEqual(undefined);
154+
155+
addIcons({ 'logo-a': logoB, logoA });
156+
157+
expect(getIconMap().get('logo-a')).toEqual(logoB);
158+
expect(getIconMap().get('logoA')).toEqual(logoA);
159+
160+
expect(spy).toHaveBeenCalled();
161+
});
162+
163+
});

src/components/icon/utils.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,43 @@ export const getIconMap = (): Map<string, string> => {
1818
};
1919

2020
export const addIcons = (icons: { [name: string]: string; }) => {
21-
const map = getIconMap();
22-
Object.keys(icons).forEach(name => map.set(name, icons[name]));
21+
Object.keys(icons).forEach(name => {
22+
addToIconMap(name, icons[name]);
23+
24+
/**
25+
* Developers can also pass in the SVG object directly
26+
* and Ionicons can map the object to a kebab case name.
27+
* Example: addIcons({ addCircleOutline });
28+
* This will create an "addCircleOutline" entry and
29+
* an "add-circle-outline" entry.
30+
* Usage: <ion-icon name="add-circle-outline"></ion-icon>
31+
* Using name="addCircleOutline" is valid too, but the
32+
* kebab case naming is preferred.
33+
*/
34+
const toKebabCase = name.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase();
35+
if (name !== toKebabCase) {
36+
addToIconMap(toKebabCase, icons[name]);
37+
}
38+
});
2339
};
2440

41+
const addToIconMap = (name: string, data: any) => {
42+
const map = getIconMap();
43+
44+
const existingIcon = map.get(name);
45+
46+
if (existingIcon === undefined) {
47+
map.set(name, data);
48+
49+
/**
50+
* Importing and defining the same icon reference
51+
* multiple times should not yield a warning.
52+
*/
53+
} else if (existingIcon !== data) {
54+
console.warn(`[Ionicons Warning]: Multiple icons were mapped to name "${name}". Ensure that multiple icons are not mapped to the same icon name.`)
55+
}
56+
}
57+
2558

2659
export const getUrl = (i: Icon) => {
2760
let url = getSrc(i.src);

stencil.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Config } from '@stencil/core';
33
export const config: Config = {
44
namespace: 'ionicons',
55
buildEs5: 'prod',
6+
sourceMap: false,
67
outputTargets: [
78
{
89
type: 'dist',

0 commit comments

Comments
 (0)