@pine-ds/icons 9.6.0 → 9.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/pds-icon.js +151 -18
- package/components/pds-icon.js.map +1 -1
- package/dist/cheatsheet.html +3 -3
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/pds-icon.cjs.entry.js +148 -15
- package/dist/cjs/pds-icon.cjs.entry.js.map +1 -1
- package/dist/cjs/pds-icon.entry.cjs.js.map +1 -1
- package/dist/cjs/pds-icons.cjs.js +1 -1
- package/dist/collection/components/pds-icon/pds-icon.js +122 -10
- package/dist/collection/components/pds-icon/pds-icon.js.map +1 -1
- package/dist/collection/components/pds-icon/request.js +26 -5
- package/dist/collection/components/pds-icon/request.js.map +1 -1
- package/dist/docs.json +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pds-icon.entry.js +148 -15
- package/dist/esm/pds-icon.entry.js.map +1 -1
- package/dist/esm/pds-icons.js +1 -1
- package/dist/pds-icons/p-5ea9f963.entry.js +2 -0
- package/dist/pds-icons/p-5ea9f963.entry.js.map +1 -0
- package/dist/pds-icons/pds-icon.entry.esm.js.map +1 -1
- package/dist/pds-icons/pds-icons.esm.js +1 -1
- package/dist/pds-icons.json +1 -1
- package/dist/pds-icons.symbols.svg +1 -1
- package/dist/types/components/pds-icon/pds-icon.d.ts +8 -0
- package/icons/index.d.ts +1 -1
- package/icons/index.js +1 -1
- package/icons/index.mjs +1 -1
- package/icons/package.json +1 -1
- package/package.json +1 -1
- package/dist/pds-icons/p-5a3a5e3c.entry.js +0 -2
- package/dist/pds-icons/p-5a3a5e3c.entry.js.map +0 -1
|
@@ -39,10 +39,26 @@ export class PdsIcon {
|
|
|
39
39
|
if (!this.didLoadIcon) {
|
|
40
40
|
this.loadIcon();
|
|
41
41
|
}
|
|
42
|
+
// Fallback: Ensure icon loads even if IntersectionObserver doesn't fire
|
|
43
|
+
setTimeout(() => {
|
|
44
|
+
if (!this.svgContent && !this.isVisible) {
|
|
45
|
+
this.isVisible = true;
|
|
46
|
+
this.loadIcon();
|
|
47
|
+
}
|
|
48
|
+
}, 100);
|
|
49
|
+
// Additional fallback for client-side navigation (React Router, etc.)
|
|
50
|
+
// React's useLayoutEffect and rendering cycles can delay visibility detection
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
if (!this.svgContent && !this.isVisible) {
|
|
53
|
+
this.isVisible = true;
|
|
54
|
+
this.loadIcon();
|
|
55
|
+
}
|
|
56
|
+
}, 500);
|
|
42
57
|
}
|
|
43
58
|
componentWillLoad() {
|
|
44
59
|
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
|
45
60
|
this.setCSSVariables();
|
|
61
|
+
this.setupInitialAriaLabel();
|
|
46
62
|
}
|
|
47
63
|
setCSSVariables() {
|
|
48
64
|
this.el.style.setProperty(`--dimension-icon-height`, this.iconSize());
|
|
@@ -50,10 +66,18 @@ export class PdsIcon {
|
|
|
50
66
|
this.el.style.setProperty(`--color-icon-fill`, typeof this.color !== 'undefined' ? this.color : 'currentColor');
|
|
51
67
|
}
|
|
52
68
|
connectedCallback() {
|
|
53
|
-
|
|
69
|
+
// Handle re-connection during client-side navigation
|
|
70
|
+
if (!this.isVisible && !this.svgContent) {
|
|
71
|
+
this.waitUntilVisible(this.el, '50px', () => {
|
|
72
|
+
this.isVisible = true;
|
|
73
|
+
this.loadIcon();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Immediate load attempt if already visible (e.g., during React navigation)
|
|
77
|
+
if (this.isElementInViewport(this.el)) {
|
|
54
78
|
this.isVisible = true;
|
|
55
79
|
this.loadIcon();
|
|
56
|
-
}
|
|
80
|
+
}
|
|
57
81
|
}
|
|
58
82
|
disconnectedCallback() {
|
|
59
83
|
if (this.io) {
|
|
@@ -64,7 +88,16 @@ export class PdsIcon {
|
|
|
64
88
|
updateStyles() {
|
|
65
89
|
this.setCSSVariables();
|
|
66
90
|
}
|
|
91
|
+
onIconPropertyChange() {
|
|
92
|
+
this.loadIcon();
|
|
93
|
+
// Update aria-label when icon properties change
|
|
94
|
+
this.setupInitialAriaLabel();
|
|
95
|
+
}
|
|
67
96
|
loadIcon() {
|
|
97
|
+
// Reset load state when URL changes
|
|
98
|
+
this.didLoadIcon = false;
|
|
99
|
+
// Clear existing content to prevent stale content when switching icons
|
|
100
|
+
this.svgContent = undefined;
|
|
68
101
|
if (Build.isBrowser && this.isVisible) {
|
|
69
102
|
const url = getUrl(this);
|
|
70
103
|
if (url) {
|
|
@@ -72,15 +105,23 @@ export class PdsIcon {
|
|
|
72
105
|
this.svgContent = pdsIconContent.get(url);
|
|
73
106
|
}
|
|
74
107
|
else {
|
|
75
|
-
|
|
108
|
+
// Fix: Ensure promise callback triggers re-render and handle errors
|
|
109
|
+
getSvgContent(url)
|
|
110
|
+
.then(() => {
|
|
111
|
+
// Force re-render by setting state in next tick
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
this.svgContent = pdsIconContent.get(url);
|
|
114
|
+
}, 0);
|
|
115
|
+
})
|
|
116
|
+
.catch(() => {
|
|
117
|
+
// Handle fetch errors gracefully
|
|
118
|
+
this.svgContent = '';
|
|
119
|
+
});
|
|
76
120
|
}
|
|
77
121
|
this.didLoadIcon = true;
|
|
78
122
|
}
|
|
79
123
|
}
|
|
80
124
|
this.iconName = getName(this.name, this.icon);
|
|
81
|
-
if (this.iconName) {
|
|
82
|
-
this.ariaLabel = this.iconName.replace(/\-/g, ' ');
|
|
83
|
-
}
|
|
84
125
|
}
|
|
85
126
|
render() {
|
|
86
127
|
const { ariaLabel, flipRtl, iconName, inheritedAttributes } = this;
|
|
@@ -88,11 +129,22 @@ export class PdsIcon {
|
|
|
88
129
|
? shouldRtlFlipIcon(iconName, this.el) && flipRtl !== false
|
|
89
130
|
: false;
|
|
90
131
|
const shouldFlip = flipRtl || shouldIconAutoFlip;
|
|
91
|
-
|
|
132
|
+
// Use inherited aria-label if provided, otherwise fall back to auto-generated one
|
|
133
|
+
const finalAriaLabel = inheritedAttributes['aria-label'] || ariaLabel;
|
|
134
|
+
return (h(Host, Object.assign({ key: '43aa73531314e6529a887468e69362430d006229', "aria-label": finalAriaLabel !== undefined && !this.hasAriaHidden() ? finalAriaLabel : null, alt: "", role: "img", class: Object.assign(Object.assign({}, createColorClasses(this.color)), { 'flip-rtl': shouldFlip, 'icon-rtl': shouldFlip && isRTL(this.el) }) }, inheritedAttributes), Build.isBrowser && this.svgContent ? (h("div", { class: "icon-inner", innerHTML: this.svgContent })) : (h("div", { class: "icon-inner" }))));
|
|
92
135
|
}
|
|
93
136
|
/*****
|
|
94
137
|
* Private Methods
|
|
95
138
|
****/
|
|
139
|
+
setupInitialAriaLabel() {
|
|
140
|
+
// Only set aria-label during initial load if one isn't already provided
|
|
141
|
+
if (!this.inheritedAttributes['aria-label']) {
|
|
142
|
+
const iconName = getName(this.name, this.icon);
|
|
143
|
+
if (iconName) {
|
|
144
|
+
this.ariaLabel = iconName.replace(/\-/g, ' ');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
96
148
|
waitUntilVisible(el, rootMargin, cb) {
|
|
97
149
|
if (Build.isBrowser && typeof window !== 'undefined' && (window).IntersectionObserver) {
|
|
98
150
|
const io = (this.io = new (window).IntersectionObserver((data) => {
|
|
@@ -103,6 +155,18 @@ export class PdsIcon {
|
|
|
103
155
|
}
|
|
104
156
|
}, { rootMargin }));
|
|
105
157
|
io.observe(el);
|
|
158
|
+
// Safety timeout for client-side navigation scenarios
|
|
159
|
+
// Sometimes IntersectionObserver doesn't fire during React navigation
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
if (this.io && !this.isVisible) {
|
|
162
|
+
// Check if element is actually visible in viewport
|
|
163
|
+
if (this.isElementInViewport(el)) {
|
|
164
|
+
this.io.disconnect();
|
|
165
|
+
this.io = undefined;
|
|
166
|
+
cb();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}, 1000);
|
|
106
170
|
}
|
|
107
171
|
else {
|
|
108
172
|
// browser doesn't support IntersectionObserver
|
|
@@ -110,6 +174,54 @@ export class PdsIcon {
|
|
|
110
174
|
cb();
|
|
111
175
|
}
|
|
112
176
|
}
|
|
177
|
+
isElementInViewport(el) {
|
|
178
|
+
if (!el || !el.isConnected)
|
|
179
|
+
return false;
|
|
180
|
+
const rect = el.getBoundingClientRect();
|
|
181
|
+
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
182
|
+
const windowWidth = window.innerWidth || document.documentElement.clientWidth;
|
|
183
|
+
return (rect.top >= 0 &&
|
|
184
|
+
rect.left >= 0 &&
|
|
185
|
+
rect.bottom <= windowHeight &&
|
|
186
|
+
rect.right <= windowWidth) || (
|
|
187
|
+
// Also consider partially visible elements
|
|
188
|
+
rect.top < windowHeight &&
|
|
189
|
+
rect.bottom > 0 &&
|
|
190
|
+
rect.left < windowWidth &&
|
|
191
|
+
rect.right > 0);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Debug method to help diagnose loading issues
|
|
195
|
+
* Call from browser console: document.querySelector('pds-icon').debugIconState()
|
|
196
|
+
*/
|
|
197
|
+
debugIconState() {
|
|
198
|
+
var _a;
|
|
199
|
+
const url = getUrl(this);
|
|
200
|
+
const rect = this.el.getBoundingClientRect();
|
|
201
|
+
console.log('PdsIcon Debug State:', {
|
|
202
|
+
name: this.name,
|
|
203
|
+
src: this.src,
|
|
204
|
+
icon: this.icon,
|
|
205
|
+
iconName: this.iconName,
|
|
206
|
+
url,
|
|
207
|
+
isVisible: this.isVisible,
|
|
208
|
+
didLoadIcon: this.didLoadIcon,
|
|
209
|
+
hasSvgContent: !!this.svgContent,
|
|
210
|
+
svgContentLength: ((_a = this.svgContent) === null || _a === void 0 ? void 0 : _a.length) || 0,
|
|
211
|
+
isInCache: url ? pdsIconContent.has(url) : false,
|
|
212
|
+
cachedContent: url ? pdsIconContent.get(url) : null,
|
|
213
|
+
element: this.el,
|
|
214
|
+
// Client-side navigation specific debug info
|
|
215
|
+
isConnected: this.el.isConnected,
|
|
216
|
+
isInViewport: this.isElementInViewport(this.el),
|
|
217
|
+
hasIntersectionObserver: !!this.io,
|
|
218
|
+
boundingClientRect: rect,
|
|
219
|
+
windowDimensions: {
|
|
220
|
+
width: window.innerWidth || document.documentElement.clientWidth,
|
|
221
|
+
height: window.innerHeight || document.documentElement.clientHeight
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
113
225
|
static get is() { return "pds-icon"; }
|
|
114
226
|
static get encapsulation() { return "shadow"; }
|
|
115
227
|
static get originalStyleUrls() {
|
|
@@ -259,13 +371,13 @@ export class PdsIcon {
|
|
|
259
371
|
"methodName": "updateStyles"
|
|
260
372
|
}, {
|
|
261
373
|
"propName": "name",
|
|
262
|
-
"methodName": "
|
|
374
|
+
"methodName": "onIconPropertyChange"
|
|
263
375
|
}, {
|
|
264
376
|
"propName": "src",
|
|
265
|
-
"methodName": "
|
|
377
|
+
"methodName": "onIconPropertyChange"
|
|
266
378
|
}, {
|
|
267
379
|
"propName": "icon",
|
|
268
|
-
"methodName": "
|
|
380
|
+
"methodName": "onIconPropertyChange"
|
|
269
381
|
}];
|
|
270
382
|
}
|
|
271
383
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pds-icon.js","sourceRoot":"","sources":["../../../../src/components/pds-icon/pds-icon.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Build, Component, Element, Host, Prop, State, Watch, h } from '@stencil/core';\nimport { getSvgContent, pdsIconContent } from './request';\nimport { getName, getUrl, inheritAttributes, isRTL, shouldRtlFlipIcon } from './utils';\n\n@Component({\n tag: 'pds-icon',\n assetsDirs: ['svg'],\n styleUrl: 'pds-icon.scss',\n shadow: true,\n})\nexport class PdsIcon {\n private didLoadIcon = false;\n private iconName: string | null = null;\n private io?: IntersectionObserver;\n private inheritedAttributes: { [k: string]: any } = {}; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n @Element() el!: HTMLPdsIconElement;\n\n @State() private ariaLabel?: string;\n @State() private isVisible = false;\n @State() private svgContent?: string;\n\n /**\n *\n * The color of the icon\n *\n */\n @Prop() color?: string;\n\n /**\n * Determines if the icon should be flipped when the `dir` is right-to-left (`\"rtl\"`).\n * This is automatically enabled for icons that are in the `ICONS_TO_FLIP` list and\n * when the `dir` is `\"rtl\"`. If `flipRtl` is set to `false`, the icon will not be flipped\n * even if the `dir` is `\"rtl\"`.\n */\n @Prop() flipRtl?: boolean;\n\n /**\n * This is a combination of both `name` and `src`. If a `src` URL is detected,\n * it will set the `src` property. Otherwise it assumes it's a built-in named\n * SVG and sets the `name` property.\n */\n @Prop() icon?: any;\n\n /**\n * The name of the icon to use from\n * the built-in set.\n */\n @Prop({ reflect: true }) name?: string;\n\n /**\n * The size of the icon. This can be\n * 'small', 'regular', 'medium', 'large', or a\n * custom value (40px, 1rem, etc)\n *\n */\n @Prop({ reflect: true }) size?:\n | 'small' // 12px\n | 'regular' // 16px\n | 'medium' // 20px\n | 'large' // 24px\n | 'auto'\n | string = 'regular'\n\n /**\n *\n * Specifies the exact `src` of an SVG file to use.\n */\n @Prop() src?: string;\n\n private iconSize() {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sizes: { [key: string]: any } = {\n small: '12px',\n regular: '16px',\n medium: '20px',\n large: '24px',\n }\n\n if (sizes[this.size]) {\n return sizes[this.size];\n } else {\n return this.size;\n }\n }\n\n componentDidLoad() {\n this.setCSSVariables();\n\n if (!this.didLoadIcon) {\n this.loadIcon();\n }\n }\n\n componentWillLoad() {\n this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);\n this.setCSSVariables();\n }\n\n setCSSVariables() {\n this.el.style.setProperty(`--dimension-icon-height`, this.iconSize());\n this.el.style.setProperty(`--dimension-icon-width`, this.iconSize());\n this.el.style.setProperty(`--color-icon-fill`, typeof this.color !== 'undefined' ? this.color : 'currentColor');\n }\n\n connectedCallback() {\n this.waitUntilVisible(this.el, '50px', () => {\n this.isVisible = true;\n this.loadIcon();\n })\n }\n\n disconnectedCallback() {\n if (this.io) {\n this.io.disconnect();\n this.io = undefined;\n }\n }\n\n @Watch('size')\n @Watch('color')\n updateStyles() {\n this.setCSSVariables();\n }\n\n @Watch('name')\n @Watch('src')\n @Watch('icon')\n loadIcon() {\n if (Build.isBrowser && this.isVisible) {\n const url = getUrl(this);\n if (url) {\n if (pdsIconContent.has(url)) {\n this.svgContent = pdsIconContent.get(url);\n } else {\n getSvgContent(url).then(() => (this.svgContent = pdsIconContent.get(url)));\n }\n this.didLoadIcon = true;\n }\n }\n\n this.iconName = getName(this.name, this.icon);\n\n if (this.iconName) {\n this.ariaLabel = this.iconName.replace(/\\-/g, ' ');\n }\n }\n\n render() {\n const { ariaLabel, flipRtl, iconName,inheritedAttributes } = this;\n const shouldIconAutoFlip = iconName\n ? shouldRtlFlipIcon(iconName, this.el) && flipRtl !== false\n : false;\n const shouldFlip = flipRtl || shouldIconAutoFlip;\n\n return (\n\n <Host\n aria-label={ariaLabel !== undefined && !this.hasAriaHidden() ? ariaLabel : null }\n alt=\"\"\n role=\"img\"\n class={{\n ...createColorClasses(this.color),\n 'flip-rtl': shouldFlip,\n 'icon-rtl': shouldFlip && isRTL(this.el)\n }}\n {...inheritedAttributes}\n >\n {Build.isBrowser && this.svgContent ? (\n <div class=\"icon-inner\" innerHTML={this.svgContent}></div>\n ) : (\n <div class=\"icon-inner\"></div>\n )}\n </Host>\n )\n }\n\n /*****\n * Private Methods\n ****/\n\n private waitUntilVisible(el: HTMLElement, rootMargin: string, cb: () => void) {\n if (Build.isBrowser && typeof window !== 'undefined' && (window).IntersectionObserver) {\n const io = (this.io = new (window).IntersectionObserver(\n (data: IntersectionObserverEntry[]) => {\n if (data[0].isIntersecting) {\n io.disconnect();\n this.io = undefined;\n cb();\n }\n },\n { rootMargin },\n ));\n\n io.observe(el);\n } else {\n // browser doesn't support IntersectionObserver\n // so just fallback to always show it\n cb();\n }\n }\n\n private hasAriaHidden = () => {\n const { el } = this;\n\n return el.hasAttribute('aria-hidden') && el.getAttribute('aria-hidden') === 'true';\n }\n}\n\nconst createColorClasses = (color: string | undefined) => {\n return color\n ? {\n 'pds-color': true,\n [`pds-color-${color}`]: true,\n }\n : null;\n };\n"]}
|
|
1
|
+
{"version":3,"file":"pds-icon.js","sourceRoot":"","sources":["../../../../src/components/pds-icon/pds-icon.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Build, Component, Element, Host, Prop, State, Watch, h } from '@stencil/core';\nimport { getSvgContent, pdsIconContent } from './request';\nimport { getName, getUrl, inheritAttributes, isRTL, shouldRtlFlipIcon } from './utils';\n\n@Component({\n tag: 'pds-icon',\n assetsDirs: ['svg'],\n styleUrl: 'pds-icon.scss',\n shadow: true,\n})\nexport class PdsIcon {\n private didLoadIcon = false;\n private iconName: string | null = null;\n private io?: IntersectionObserver;\n private inheritedAttributes: { [k: string]: any } = {}; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n @Element() el!: HTMLPdsIconElement;\n\n @State() private ariaLabel?: string;\n @State() private isVisible = false;\n @State() private svgContent?: string;\n\n /**\n *\n * The color of the icon\n *\n */\n @Prop() color?: string;\n\n /**\n * Determines if the icon should be flipped when the `dir` is right-to-left (`\"rtl\"`).\n * This is automatically enabled for icons that are in the `ICONS_TO_FLIP` list and\n * when the `dir` is `\"rtl\"`. If `flipRtl` is set to `false`, the icon will not be flipped\n * even if the `dir` is `\"rtl\"`.\n */\n @Prop() flipRtl?: boolean;\n\n /**\n * This is a combination of both `name` and `src`. If a `src` URL is detected,\n * it will set the `src` property. Otherwise it assumes it's a built-in named\n * SVG and sets the `name` property.\n */\n @Prop() icon?: any;\n\n /**\n * The name of the icon to use from\n * the built-in set.\n */\n @Prop({ reflect: true }) name?: string;\n\n /**\n * The size of the icon. This can be\n * 'small', 'regular', 'medium', 'large', or a\n * custom value (40px, 1rem, etc)\n *\n */\n @Prop({ reflect: true }) size?:\n | 'small' // 12px\n | 'regular' // 16px\n | 'medium' // 20px\n | 'large' // 24px\n | 'auto'\n | string = 'regular'\n\n /**\n *\n * Specifies the exact `src` of an SVG file to use.\n */\n @Prop() src?: string;\n\n private iconSize() {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sizes: { [key: string]: any } = {\n small: '12px',\n regular: '16px',\n medium: '20px',\n large: '24px',\n }\n\n if (sizes[this.size]) {\n return sizes[this.size];\n } else {\n return this.size;\n }\n }\n\n componentDidLoad() {\n this.setCSSVariables();\n\n if (!this.didLoadIcon) {\n this.loadIcon();\n }\n\n // Fallback: Ensure icon loads even if IntersectionObserver doesn't fire\n setTimeout(() => {\n if (!this.svgContent && !this.isVisible) {\n this.isVisible = true;\n this.loadIcon();\n }\n }, 100);\n\n // Additional fallback for client-side navigation (React Router, etc.)\n // React's useLayoutEffect and rendering cycles can delay visibility detection\n setTimeout(() => {\n if (!this.svgContent && !this.isVisible) {\n this.isVisible = true;\n this.loadIcon();\n }\n }, 500);\n }\n\n componentWillLoad() {\n this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);\n this.setCSSVariables();\n this.setupInitialAriaLabel();\n }\n\n setCSSVariables() {\n this.el.style.setProperty(`--dimension-icon-height`, this.iconSize());\n this.el.style.setProperty(`--dimension-icon-width`, this.iconSize());\n this.el.style.setProperty(`--color-icon-fill`, typeof this.color !== 'undefined' ? this.color : 'currentColor');\n }\n\n connectedCallback() {\n // Handle re-connection during client-side navigation\n if (!this.isVisible && !this.svgContent) {\n this.waitUntilVisible(this.el, '50px', () => {\n this.isVisible = true;\n this.loadIcon();\n });\n }\n\n // Immediate load attempt if already visible (e.g., during React navigation)\n if (this.isElementInViewport(this.el)) {\n this.isVisible = true;\n this.loadIcon();\n }\n }\n\n disconnectedCallback() {\n if (this.io) {\n this.io.disconnect();\n this.io = undefined;\n }\n }\n\n @Watch('size')\n @Watch('color')\n updateStyles() {\n this.setCSSVariables();\n }\n\n @Watch('name')\n @Watch('src')\n @Watch('icon')\n onIconPropertyChange() {\n this.loadIcon();\n // Update aria-label when icon properties change\n this.setupInitialAriaLabel();\n }\n\n loadIcon() {\n // Reset load state when URL changes\n this.didLoadIcon = false;\n\n // Clear existing content to prevent stale content when switching icons\n this.svgContent = undefined;\n\n if (Build.isBrowser && this.isVisible) {\n const url = getUrl(this);\n if (url) {\n if (pdsIconContent.has(url)) {\n this.svgContent = pdsIconContent.get(url);\n } else {\n // Fix: Ensure promise callback triggers re-render and handle errors\n getSvgContent(url)\n .then(() => {\n // Force re-render by setting state in next tick\n setTimeout(() => {\n this.svgContent = pdsIconContent.get(url);\n }, 0);\n })\n .catch(() => {\n // Handle fetch errors gracefully\n this.svgContent = '';\n });\n }\n this.didLoadIcon = true;\n }\n }\n\n this.iconName = getName(this.name, this.icon);\n }\n\n render() {\n const { ariaLabel, flipRtl, iconName,inheritedAttributes } = this;\n const shouldIconAutoFlip = iconName\n ? shouldRtlFlipIcon(iconName, this.el) && flipRtl !== false\n : false;\n const shouldFlip = flipRtl || shouldIconAutoFlip;\n\n // Use inherited aria-label if provided, otherwise fall back to auto-generated one\n const finalAriaLabel = inheritedAttributes['aria-label'] || ariaLabel;\n\n return (\n\n <Host\n aria-label={finalAriaLabel !== undefined && !this.hasAriaHidden() ? finalAriaLabel : null }\n alt=\"\"\n role=\"img\"\n class={{\n ...createColorClasses(this.color),\n 'flip-rtl': shouldFlip,\n 'icon-rtl': shouldFlip && isRTL(this.el)\n }}\n {...inheritedAttributes}\n >\n {Build.isBrowser && this.svgContent ? (\n <div class=\"icon-inner\" innerHTML={this.svgContent}></div>\n ) : (\n <div class=\"icon-inner\"></div>\n )}\n </Host>\n )\n }\n\n /*****\n * Private Methods\n ****/\n\n private setupInitialAriaLabel() {\n // Only set aria-label during initial load if one isn't already provided\n if (!this.inheritedAttributes['aria-label']) {\n const iconName = getName(this.name, this.icon);\n if (iconName) {\n this.ariaLabel = iconName.replace(/\\-/g, ' ');\n }\n }\n }\n\n private waitUntilVisible(el: HTMLElement, rootMargin: string, cb: () => void) {\n if (Build.isBrowser && typeof window !== 'undefined' && (window).IntersectionObserver) {\n const io = (this.io = new (window).IntersectionObserver(\n (data: IntersectionObserverEntry[]) => {\n if (data[0].isIntersecting) {\n io.disconnect();\n this.io = undefined;\n cb();\n }\n },\n { rootMargin },\n ));\n\n io.observe(el);\n\n // Safety timeout for client-side navigation scenarios\n // Sometimes IntersectionObserver doesn't fire during React navigation\n setTimeout(() => {\n if (this.io && !this.isVisible) {\n // Check if element is actually visible in viewport\n if (this.isElementInViewport(el)) {\n this.io.disconnect();\n this.io = undefined;\n cb();\n }\n }\n }, 1000);\n } else {\n // browser doesn't support IntersectionObserver\n // so just fallback to always show it\n cb();\n }\n }\n\n private isElementInViewport(el: HTMLElement): boolean {\n if (!el || !el.isConnected) return false;\n\n const rect = el.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n\n return (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= windowHeight &&\n rect.right <= windowWidth\n ) || (\n // Also consider partially visible elements\n rect.top < windowHeight &&\n rect.bottom > 0 &&\n rect.left < windowWidth &&\n rect.right > 0\n );\n }\n\n private hasAriaHidden = () => {\n const { el } = this;\n\n return el.hasAttribute('aria-hidden') && el.getAttribute('aria-hidden') === 'true';\n }\n\n /**\n * Debug method to help diagnose loading issues\n * Call from browser console: document.querySelector('pds-icon').debugIconState()\n */\n debugIconState() {\n const url = getUrl(this);\n const rect = this.el.getBoundingClientRect();\n\n console.log('PdsIcon Debug State:', {\n name: this.name,\n src: this.src,\n icon: this.icon,\n iconName: this.iconName,\n url,\n isVisible: this.isVisible,\n didLoadIcon: this.didLoadIcon,\n hasSvgContent: !!this.svgContent,\n svgContentLength: this.svgContent?.length || 0,\n isInCache: url ? pdsIconContent.has(url) : false,\n cachedContent: url ? pdsIconContent.get(url) : null,\n element: this.el,\n // Client-side navigation specific debug info\n isConnected: this.el.isConnected,\n isInViewport: this.isElementInViewport(this.el),\n hasIntersectionObserver: !!this.io,\n boundingClientRect: rect,\n windowDimensions: {\n width: window.innerWidth || document.documentElement.clientWidth,\n height: window.innerHeight || document.documentElement.clientHeight\n }\n });\n }\n}\n\nconst createColorClasses = (color: string | undefined) => {\n return color\n ? {\n 'pds-color': true,\n [`pds-color-${color}`]: true,\n }\n : null;\n };\n"]}
|
|
@@ -10,10 +10,18 @@ export const getSvgContent = (url, sanitize = false) => {
|
|
|
10
10
|
if (!parser) {
|
|
11
11
|
parser = new DOMParser();
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
try {
|
|
14
|
+
const doc = parser.parseFromString(url, 'text/html');
|
|
15
|
+
const svg = doc.querySelector('svg');
|
|
16
|
+
if (svg) {
|
|
17
|
+
pdsIconContent.set(url, svg.outerHTML);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
pdsIconContent.set(url, '');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
pdsIconContent.set(url, '');
|
|
17
25
|
}
|
|
18
26
|
return Promise.resolve();
|
|
19
27
|
}
|
|
@@ -23,12 +31,25 @@ export const getSvgContent = (url, sanitize = false) => {
|
|
|
23
31
|
if (rsp.ok) {
|
|
24
32
|
return rsp.text().then((svgContent) => {
|
|
25
33
|
if (svgContent && sanitize !== false) {
|
|
26
|
-
|
|
34
|
+
try {
|
|
35
|
+
svgContent = validateContent(svgContent);
|
|
36
|
+
}
|
|
37
|
+
catch (validationError) {
|
|
38
|
+
svgContent = '';
|
|
39
|
+
}
|
|
27
40
|
}
|
|
28
41
|
pdsIconContent.set(url, svgContent || '');
|
|
29
42
|
});
|
|
30
43
|
}
|
|
44
|
+
else {
|
|
45
|
+
// Handle HTTP errors
|
|
46
|
+
throw new Error(`Failed to load SVG: ${rsp.status} ${rsp.statusText}`);
|
|
47
|
+
}
|
|
48
|
+
}).catch((error) => {
|
|
49
|
+
// Handle all fetch errors gracefully
|
|
50
|
+
console.warn('Failed to load SVG:', url, error);
|
|
31
51
|
pdsIconContent.set(url, '');
|
|
52
|
+
// Don't re-throw to prevent unhandled promise rejections
|
|
32
53
|
});
|
|
33
54
|
requests.set(url, req);
|
|
34
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../../../src/components/pds-icon/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7E,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;AACxD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC,CAAC,yDAAyD;AAE3G,IAAI,MAAiB,CAAC;AAEtB,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,QAAQ,GAAG,KAAK,EAAE,EAAE;IAC7D,IAAI,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE5B,IAAG,CAAC,GAAG,EAAE,CAAC;QACR,IAAI,OAAO,KAAK,IAAI,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YACnE,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;gBAC3B,CAAC;gBAED,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../../../src/components/pds-icon/request.ts"],"names":[],"mappings":"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","sourcesContent":["import { isEncodedDataUrl, isSvgDataUrl, validateContent } from './validate';\n\nexport const pdsIconContent = new Map<string, string>();\nconst requests = new Map<string, Promise<any>>(); // eslint-disable-line @typescript-eslint/no-explicit-any\n\nlet parser: DOMParser;\n\nexport const getSvgContent = (url: string, sanitize = false) => {\n let req = requests.get(url);\n\n if(!req) {\n if (typeof fetch != 'undefined' && typeof document !== 'undefined') {\n if (isSvgDataUrl(url) && isEncodedDataUrl(url)) {\n if (!parser) {\n parser = new DOMParser();\n }\n\n try {\n const doc = parser.parseFromString(url, 'text/html');\n const svg = doc.querySelector('svg');\n\n if (svg) {\n pdsIconContent.set(url, svg.outerHTML);\n } else {\n pdsIconContent.set(url, '');\n }\n } catch (error) {\n pdsIconContent.set(url, '');\n }\n\n return Promise.resolve();\n } else {\n // we don't have a request\n req = fetch(url).then((rsp) => {\n if (rsp.ok) {\n return rsp.text().then((svgContent) => {\n if (svgContent && sanitize !== false) {\n try {\n svgContent = validateContent(svgContent);\n } catch (validationError) {\n svgContent = '';\n }\n }\n pdsIconContent.set(url, svgContent || '');\n });\n } else {\n // Handle HTTP errors\n throw new Error(`Failed to load SVG: ${rsp.status} ${rsp.statusText}`);\n }\n }).catch((error) => {\n // Handle all fetch errors gracefully\n console.warn('Failed to load SVG:', url, error);\n pdsIconContent.set(url, '');\n // Don't re-throw to prevent unhandled promise rejections\n });\n\n requests.set(url, req);\n }\n } else {\n pdsIconContent.set(url, '');\n return Promise.resolve();\n }\n }\n\n return req;\n}\n"]}
|
package/dist/docs.json
CHANGED
package/dist/esm/loader.js
CHANGED
|
@@ -5,7 +5,7 @@ import { g as globalScripts } from './app-globals-DQuL1Twl.js';
|
|
|
5
5
|
const defineCustomElements = async (win, options) => {
|
|
6
6
|
if (typeof window === 'undefined') return undefined;
|
|
7
7
|
await globalScripts();
|
|
8
|
-
return bootstrapLazy([["pds-icon",[[1,"pds-icon",{"color":[1],"flipRtl":[4,"flip-rtl"],"icon":[8],"name":[513],"size":[513],"src":[1],"ariaLabel":[32],"isVisible":[32],"svgContent":[32]},null,{"size":["updateStyles"],"color":["updateStyles"],"name":["
|
|
8
|
+
return bootstrapLazy([["pds-icon",[[1,"pds-icon",{"color":[1],"flipRtl":[4,"flip-rtl"],"icon":[8],"name":[513],"size":[513],"src":[1],"ariaLabel":[32],"isVisible":[32],"svgContent":[32]},null,{"size":["updateStyles"],"color":["updateStyles"],"name":["onIconPropertyChange"],"src":["onIconPropertyChange"],"icon":["onIconPropertyChange"]}]]]], options);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export { defineCustomElements };
|
|
@@ -57,10 +57,18 @@ const getSvgContent = (url, sanitize = false) => {
|
|
|
57
57
|
if (!parser) {
|
|
58
58
|
parser = new DOMParser();
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
try {
|
|
61
|
+
const doc = parser.parseFromString(url, 'text/html');
|
|
62
|
+
const svg = doc.querySelector('svg');
|
|
63
|
+
if (svg) {
|
|
64
|
+
pdsIconContent.set(url, svg.outerHTML);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
pdsIconContent.set(url, '');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
pdsIconContent.set(url, '');
|
|
64
72
|
}
|
|
65
73
|
return Promise.resolve();
|
|
66
74
|
}
|
|
@@ -70,12 +78,25 @@ const getSvgContent = (url, sanitize = false) => {
|
|
|
70
78
|
if (rsp.ok) {
|
|
71
79
|
return rsp.text().then((svgContent) => {
|
|
72
80
|
if (svgContent && sanitize !== false) {
|
|
73
|
-
|
|
81
|
+
try {
|
|
82
|
+
svgContent = validateContent(svgContent);
|
|
83
|
+
}
|
|
84
|
+
catch (validationError) {
|
|
85
|
+
svgContent = '';
|
|
86
|
+
}
|
|
74
87
|
}
|
|
75
88
|
pdsIconContent.set(url, svgContent || '');
|
|
76
89
|
});
|
|
77
90
|
}
|
|
91
|
+
else {
|
|
92
|
+
// Handle HTTP errors
|
|
93
|
+
throw new Error(`Failed to load SVG: ${rsp.status} ${rsp.statusText}`);
|
|
94
|
+
}
|
|
95
|
+
}).catch((error) => {
|
|
96
|
+
// Handle all fetch errors gracefully
|
|
97
|
+
console.warn('Failed to load SVG:', url, error);
|
|
78
98
|
pdsIconContent.set(url, '');
|
|
99
|
+
// Don't re-throw to prevent unhandled promise rejections
|
|
79
100
|
});
|
|
80
101
|
requests.set(url, req);
|
|
81
102
|
}
|
|
@@ -129,10 +150,26 @@ const PdsIcon = class {
|
|
|
129
150
|
if (!this.didLoadIcon) {
|
|
130
151
|
this.loadIcon();
|
|
131
152
|
}
|
|
153
|
+
// Fallback: Ensure icon loads even if IntersectionObserver doesn't fire
|
|
154
|
+
setTimeout(() => {
|
|
155
|
+
if (!this.svgContent && !this.isVisible) {
|
|
156
|
+
this.isVisible = true;
|
|
157
|
+
this.loadIcon();
|
|
158
|
+
}
|
|
159
|
+
}, 100);
|
|
160
|
+
// Additional fallback for client-side navigation (React Router, etc.)
|
|
161
|
+
// React's useLayoutEffect and rendering cycles can delay visibility detection
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
if (!this.svgContent && !this.isVisible) {
|
|
164
|
+
this.isVisible = true;
|
|
165
|
+
this.loadIcon();
|
|
166
|
+
}
|
|
167
|
+
}, 500);
|
|
132
168
|
}
|
|
133
169
|
componentWillLoad() {
|
|
134
170
|
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
|
135
171
|
this.setCSSVariables();
|
|
172
|
+
this.setupInitialAriaLabel();
|
|
136
173
|
}
|
|
137
174
|
setCSSVariables() {
|
|
138
175
|
this.el.style.setProperty(`--dimension-icon-height`, this.iconSize());
|
|
@@ -140,10 +177,18 @@ const PdsIcon = class {
|
|
|
140
177
|
this.el.style.setProperty(`--color-icon-fill`, typeof this.color !== 'undefined' ? this.color : 'currentColor');
|
|
141
178
|
}
|
|
142
179
|
connectedCallback() {
|
|
143
|
-
|
|
180
|
+
// Handle re-connection during client-side navigation
|
|
181
|
+
if (!this.isVisible && !this.svgContent) {
|
|
182
|
+
this.waitUntilVisible(this.el, '50px', () => {
|
|
183
|
+
this.isVisible = true;
|
|
184
|
+
this.loadIcon();
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
// Immediate load attempt if already visible (e.g., during React navigation)
|
|
188
|
+
if (this.isElementInViewport(this.el)) {
|
|
144
189
|
this.isVisible = true;
|
|
145
190
|
this.loadIcon();
|
|
146
|
-
}
|
|
191
|
+
}
|
|
147
192
|
}
|
|
148
193
|
disconnectedCallback() {
|
|
149
194
|
if (this.io) {
|
|
@@ -154,7 +199,16 @@ const PdsIcon = class {
|
|
|
154
199
|
updateStyles() {
|
|
155
200
|
this.setCSSVariables();
|
|
156
201
|
}
|
|
202
|
+
onIconPropertyChange() {
|
|
203
|
+
this.loadIcon();
|
|
204
|
+
// Update aria-label when icon properties change
|
|
205
|
+
this.setupInitialAriaLabel();
|
|
206
|
+
}
|
|
157
207
|
loadIcon() {
|
|
208
|
+
// Reset load state when URL changes
|
|
209
|
+
this.didLoadIcon = false;
|
|
210
|
+
// Clear existing content to prevent stale content when switching icons
|
|
211
|
+
this.svgContent = undefined;
|
|
158
212
|
if (this.isVisible) {
|
|
159
213
|
const url = getUrl(this);
|
|
160
214
|
if (url) {
|
|
@@ -162,15 +216,23 @@ const PdsIcon = class {
|
|
|
162
216
|
this.svgContent = pdsIconContent.get(url);
|
|
163
217
|
}
|
|
164
218
|
else {
|
|
165
|
-
|
|
219
|
+
// Fix: Ensure promise callback triggers re-render and handle errors
|
|
220
|
+
getSvgContent(url)
|
|
221
|
+
.then(() => {
|
|
222
|
+
// Force re-render by setting state in next tick
|
|
223
|
+
setTimeout(() => {
|
|
224
|
+
this.svgContent = pdsIconContent.get(url);
|
|
225
|
+
}, 0);
|
|
226
|
+
})
|
|
227
|
+
.catch(() => {
|
|
228
|
+
// Handle fetch errors gracefully
|
|
229
|
+
this.svgContent = '';
|
|
230
|
+
});
|
|
166
231
|
}
|
|
167
232
|
this.didLoadIcon = true;
|
|
168
233
|
}
|
|
169
234
|
}
|
|
170
235
|
this.iconName = getName(this.name, this.icon);
|
|
171
|
-
if (this.iconName) {
|
|
172
|
-
this.ariaLabel = this.iconName.replace(/\-/g, ' ');
|
|
173
|
-
}
|
|
174
236
|
}
|
|
175
237
|
render() {
|
|
176
238
|
const { ariaLabel, flipRtl, iconName, inheritedAttributes } = this;
|
|
@@ -178,11 +240,22 @@ const PdsIcon = class {
|
|
|
178
240
|
? shouldRtlFlipIcon(iconName, this.el) && flipRtl !== false
|
|
179
241
|
: false;
|
|
180
242
|
const shouldFlip = flipRtl || shouldIconAutoFlip;
|
|
181
|
-
|
|
243
|
+
// Use inherited aria-label if provided, otherwise fall back to auto-generated one
|
|
244
|
+
const finalAriaLabel = inheritedAttributes['aria-label'] || ariaLabel;
|
|
245
|
+
return (h(Host, Object.assign({ key: '43aa73531314e6529a887468e69362430d006229', "aria-label": finalAriaLabel !== undefined && !this.hasAriaHidden() ? finalAriaLabel : null, alt: "", role: "img", class: Object.assign(Object.assign({}, createColorClasses(this.color)), { 'flip-rtl': shouldFlip, 'icon-rtl': shouldFlip && isRTL(this.el) }) }, inheritedAttributes), this.svgContent ? (h("div", { class: "icon-inner", innerHTML: this.svgContent })) : (h("div", { class: "icon-inner" }))));
|
|
182
246
|
}
|
|
183
247
|
/*****
|
|
184
248
|
* Private Methods
|
|
185
249
|
****/
|
|
250
|
+
setupInitialAriaLabel() {
|
|
251
|
+
// Only set aria-label during initial load if one isn't already provided
|
|
252
|
+
if (!this.inheritedAttributes['aria-label']) {
|
|
253
|
+
const iconName = getName(this.name, this.icon);
|
|
254
|
+
if (iconName) {
|
|
255
|
+
this.ariaLabel = iconName.replace(/\-/g, ' ');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
186
259
|
waitUntilVisible(el, rootMargin, cb) {
|
|
187
260
|
if (typeof window !== 'undefined' && (window).IntersectionObserver) {
|
|
188
261
|
const io = (this.io = new (window).IntersectionObserver((data) => {
|
|
@@ -193,6 +266,18 @@ const PdsIcon = class {
|
|
|
193
266
|
}
|
|
194
267
|
}, { rootMargin }));
|
|
195
268
|
io.observe(el);
|
|
269
|
+
// Safety timeout for client-side navigation scenarios
|
|
270
|
+
// Sometimes IntersectionObserver doesn't fire during React navigation
|
|
271
|
+
setTimeout(() => {
|
|
272
|
+
if (this.io && !this.isVisible) {
|
|
273
|
+
// Check if element is actually visible in viewport
|
|
274
|
+
if (this.isElementInViewport(el)) {
|
|
275
|
+
this.io.disconnect();
|
|
276
|
+
this.io = undefined;
|
|
277
|
+
cb();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}, 1000);
|
|
196
281
|
}
|
|
197
282
|
else {
|
|
198
283
|
// browser doesn't support IntersectionObserver
|
|
@@ -200,14 +285,62 @@ const PdsIcon = class {
|
|
|
200
285
|
cb();
|
|
201
286
|
}
|
|
202
287
|
}
|
|
288
|
+
isElementInViewport(el) {
|
|
289
|
+
if (!el || !el.isConnected)
|
|
290
|
+
return false;
|
|
291
|
+
const rect = el.getBoundingClientRect();
|
|
292
|
+
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
293
|
+
const windowWidth = window.innerWidth || document.documentElement.clientWidth;
|
|
294
|
+
return (rect.top >= 0 &&
|
|
295
|
+
rect.left >= 0 &&
|
|
296
|
+
rect.bottom <= windowHeight &&
|
|
297
|
+
rect.right <= windowWidth) || (
|
|
298
|
+
// Also consider partially visible elements
|
|
299
|
+
rect.top < windowHeight &&
|
|
300
|
+
rect.bottom > 0 &&
|
|
301
|
+
rect.left < windowWidth &&
|
|
302
|
+
rect.right > 0);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Debug method to help diagnose loading issues
|
|
306
|
+
* Call from browser console: document.querySelector('pds-icon').debugIconState()
|
|
307
|
+
*/
|
|
308
|
+
debugIconState() {
|
|
309
|
+
var _a;
|
|
310
|
+
const url = getUrl(this);
|
|
311
|
+
const rect = this.el.getBoundingClientRect();
|
|
312
|
+
console.log('PdsIcon Debug State:', {
|
|
313
|
+
name: this.name,
|
|
314
|
+
src: this.src,
|
|
315
|
+
icon: this.icon,
|
|
316
|
+
iconName: this.iconName,
|
|
317
|
+
url,
|
|
318
|
+
isVisible: this.isVisible,
|
|
319
|
+
didLoadIcon: this.didLoadIcon,
|
|
320
|
+
hasSvgContent: !!this.svgContent,
|
|
321
|
+
svgContentLength: ((_a = this.svgContent) === null || _a === void 0 ? void 0 : _a.length) || 0,
|
|
322
|
+
isInCache: url ? pdsIconContent.has(url) : false,
|
|
323
|
+
cachedContent: url ? pdsIconContent.get(url) : null,
|
|
324
|
+
element: this.el,
|
|
325
|
+
// Client-side navigation specific debug info
|
|
326
|
+
isConnected: this.el.isConnected,
|
|
327
|
+
isInViewport: this.isElementInViewport(this.el),
|
|
328
|
+
hasIntersectionObserver: !!this.io,
|
|
329
|
+
boundingClientRect: rect,
|
|
330
|
+
windowDimensions: {
|
|
331
|
+
width: window.innerWidth || document.documentElement.clientWidth,
|
|
332
|
+
height: window.innerHeight || document.documentElement.clientHeight
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
203
336
|
static get assetsDirs() { return ["svg"]; }
|
|
204
337
|
get el() { return getElement(this); }
|
|
205
338
|
static get watchers() { return {
|
|
206
339
|
"size": ["updateStyles"],
|
|
207
340
|
"color": ["updateStyles"],
|
|
208
|
-
"name": ["
|
|
209
|
-
"src": ["
|
|
210
|
-
"icon": ["
|
|
341
|
+
"name": ["onIconPropertyChange"],
|
|
342
|
+
"src": ["onIconPropertyChange"],
|
|
343
|
+
"icon": ["onIconPropertyChange"]
|
|
211
344
|
}; }
|
|
212
345
|
};
|
|
213
346
|
const createColorClasses = (color) => {
|