@life-cockpit/angular-ui-kit 2.13.0 → 2.13.1
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.
|
@@ -533,6 +533,27 @@ const ICON_FALLBACK_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
|
533
533
|
'<rect x="3.5" y="3.5" width="17" height="17" rx="3" stroke-dasharray="2.5 2.5" />' +
|
|
534
534
|
'<text x="12" y="16.5" text-anchor="middle" font-size="12" font-weight="700" font-family="system-ui, -apple-system, sans-serif" fill="currentColor" stroke="none">?</text>' +
|
|
535
535
|
'</svg>';
|
|
536
|
+
/**
|
|
537
|
+
* Icon names already reported to the console. A page with dozens of instances
|
|
538
|
+
* of the same typo must produce exactly one warning, not one per instance —
|
|
539
|
+
* and the warning fires in production too (unlike the old dev-only warning,
|
|
540
|
+
* which left prod incidents invisible in the console).
|
|
541
|
+
*/
|
|
542
|
+
const warnedIconNames = new Set();
|
|
543
|
+
function warnOnce(name, message) {
|
|
544
|
+
if (warnedIconNames.has(name))
|
|
545
|
+
return;
|
|
546
|
+
warnedIconNames.add(name);
|
|
547
|
+
console.warn(message);
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Clears the warn-once-per-name registry. Only needed by unit tests that
|
|
551
|
+
* assert on console warnings across multiple cases.
|
|
552
|
+
* @internal
|
|
553
|
+
*/
|
|
554
|
+
function resetIconWarnings() {
|
|
555
|
+
warnedIconNames.clear();
|
|
556
|
+
}
|
|
536
557
|
/**
|
|
537
558
|
* Icon component - Tabler Icons wrapper for displaying SVG icons
|
|
538
559
|
*
|
|
@@ -543,10 +564,15 @@ const ICON_FALLBACK_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
|
543
564
|
* - Custom color support (CSS colors, variables)
|
|
544
565
|
* - Accessibility attributes (ARIA labels, decorative icons)
|
|
545
566
|
* - Dynamic SVG loading from Tabler Icons
|
|
546
|
-
* - Fail-loud on unknown names: a
|
|
547
|
-
* (never a silent empty space)
|
|
548
|
-
*
|
|
549
|
-
*
|
|
567
|
+
* - Fail-loud on unknown names: a console warning (once per name, in dev AND
|
|
568
|
+
* prod) + a visible placeholder (never a silent empty space) — and **no
|
|
569
|
+
* network request**, because in SPA deployments the server answers missing
|
|
570
|
+
* asset paths with the index.html fallback. See {@link ICON_NAMES} /
|
|
571
|
+
* {@link isValidIconName} for the canonical set of valid names, and
|
|
572
|
+
* {@link ICON_ALIASES} for the supported Heroicon/Material aliases.
|
|
573
|
+
* - Fetched responses are validated (content-type + parsed `<svg>` root)
|
|
574
|
+
* before anything is trusted — a non-SVG response (e.g. the SPA index.html
|
|
575
|
+
* fallback) is dropped and replaced by the placeholder.
|
|
550
576
|
*
|
|
551
577
|
* @example
|
|
552
578
|
* ```html
|
|
@@ -679,14 +705,18 @@ class IconComponent {
|
|
|
679
705
|
return;
|
|
680
706
|
}
|
|
681
707
|
// Fail loud on names outside the canonical set (typos, un-aliased
|
|
682
|
-
// Heroicon names, …)
|
|
683
|
-
//
|
|
684
|
-
//
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
708
|
+
// Heroicon names, …) — in dev AND prod, once per name. Crucially, an
|
|
709
|
+
// unknown name is never fetched: in SPA deployments the server answers
|
|
710
|
+
// missing asset paths with the index.html fallback (status 200), so a
|
|
711
|
+
// fetch for a typo'd name would come back as a full HTML document. The
|
|
712
|
+
// placeholder is rendered instead.
|
|
713
|
+
if (!isValidIconName(rawName)) {
|
|
714
|
+
warnOnce(rawName, `[lc-icon] Unknown icon "${rawName}". Use a Tabler name or a documented alias (see ICON_NAMES / ICON_ALIASES). Rendering a placeholder instead.`);
|
|
715
|
+
if (isDevMode() && this.strict()) {
|
|
688
716
|
throw new Error(`[lc-icon] Unknown icon "${rawName}" (strict mode). Use a Tabler name or a documented alias.`);
|
|
689
717
|
}
|
|
718
|
+
this.renderFallback();
|
|
719
|
+
return;
|
|
690
720
|
}
|
|
691
721
|
// Resolve aliases (Heroicon/Material -> Tabler)
|
|
692
722
|
const iconName = ICON_ALIASES[rawName] ?? rawName;
|
|
@@ -694,7 +724,12 @@ class IconComponent {
|
|
|
694
724
|
const inlineSvg = INLINE_ICON_SVGS[iconName]?.[iconVariant];
|
|
695
725
|
if (inlineSvg) {
|
|
696
726
|
const processed = this.processSvgString(inlineSvg);
|
|
697
|
-
|
|
727
|
+
if (processed !== null) {
|
|
728
|
+
this.setTrustedSvg(processed);
|
|
729
|
+
}
|
|
730
|
+
else {
|
|
731
|
+
this.renderFallback();
|
|
732
|
+
}
|
|
698
733
|
return;
|
|
699
734
|
}
|
|
700
735
|
// Fallback to HTTP loading (may not work in all environments)
|
|
@@ -709,7 +744,7 @@ class IconComponent {
|
|
|
709
744
|
// otherwise-valid icon stuck on the placeholder. A genuine 404 (missing
|
|
710
745
|
// asset) is not retried.
|
|
711
746
|
this.http
|
|
712
|
-
.get(path, { responseType: 'text' })
|
|
747
|
+
.get(path, { observe: 'response', responseType: 'text' })
|
|
713
748
|
.pipe(retry({
|
|
714
749
|
count: 2,
|
|
715
750
|
delay: (error, retryCount) => error instanceof HttpErrorResponse && error.status === 404
|
|
@@ -717,10 +752,24 @@ class IconComponent {
|
|
|
717
752
|
: timer(200 * retryCount),
|
|
718
753
|
}))
|
|
719
754
|
.subscribe({
|
|
720
|
-
next: (
|
|
721
|
-
//
|
|
722
|
-
|
|
723
|
-
|
|
755
|
+
next: (response) => {
|
|
756
|
+
// Validate before anything touches the DOM: SPA deployments answer
|
|
757
|
+
// missing asset paths with `index.html` and status 200 — that
|
|
758
|
+
// document must be dropped, never injected. A text/html content-type
|
|
759
|
+
// is rejected outright; everything else must parse as a standalone
|
|
760
|
+
// <svg> document (see processSvgString).
|
|
761
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
762
|
+
const processed = contentType.includes('text/html')
|
|
763
|
+
? null
|
|
764
|
+
: this.processSvgString(response.body ?? '');
|
|
765
|
+
if (processed === null) {
|
|
766
|
+
warnOnce(rawName, `[lc-icon] "${rawName}": ${path} returned non-SVG content` +
|
|
767
|
+
(contentType ? ` (${contentType})` : '') +
|
|
768
|
+
' — dropped. In SPA deployments this is typically the index.html fallback for a missing asset.');
|
|
769
|
+
this.renderFallback();
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
this.setTrustedSvg(processed);
|
|
724
773
|
},
|
|
725
774
|
error: () => {
|
|
726
775
|
// Asset missing or unreachable: render a visible placeholder so the
|
|
@@ -728,23 +777,53 @@ class IconComponent {
|
|
|
728
777
|
// already reported above; a known-but-unloadable name (e.g. offline,
|
|
729
778
|
// SSR, or unit tests where assets are not served) stays quiet here to
|
|
730
779
|
// avoid console noise.
|
|
731
|
-
|
|
732
|
-
this.svgContent.set(this.sanitizer.bypassSecurityTrustHtml(processed));
|
|
780
|
+
this.renderFallback();
|
|
733
781
|
},
|
|
734
782
|
});
|
|
735
783
|
});
|
|
736
784
|
}
|
|
737
785
|
/**
|
|
738
|
-
*
|
|
786
|
+
* The single funnel to `bypassSecurityTrustHtml`. The bypass is only safe
|
|
787
|
+
* because every caller passes the output of {@link processSvgString}, which
|
|
788
|
+
* guarantees the markup is a parsed and re-serialized standalone `<svg>`
|
|
789
|
+
* document — never raw fetched text. Do NOT add callers that skip that
|
|
790
|
+
* validation, and do NOT "simplify" the gates away: without them, a SPA
|
|
791
|
+
* server's index.html fallback (status 200, text/html) gets injected into
|
|
792
|
+
* the page once per icon instance.
|
|
793
|
+
* @private
|
|
794
|
+
*/
|
|
795
|
+
setTrustedSvg(processedSvg) {
|
|
796
|
+
this.svgContent.set(this.sanitizer.bypassSecurityTrustHtml(processedSvg));
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Renders the visible "?" placeholder for anything that cannot be resolved
|
|
800
|
+
* to a real icon (unknown name, failed load, non-SVG response).
|
|
801
|
+
* @private
|
|
802
|
+
*/
|
|
803
|
+
renderFallback() {
|
|
804
|
+
this.setTrustedSvg(this.processSvgString(ICON_FALLBACK_SVG) ?? ICON_FALLBACK_SVG);
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Parse an SVG string and add size, color, and accessibility attributes.
|
|
808
|
+
*
|
|
809
|
+
* Returns `null` when the input is not a standalone SVG document — a parse
|
|
810
|
+
* error, or a non-`<svg>` root such as an HTML page. Callers must treat
|
|
811
|
+
* `null` as "do not render"; the raw input is never passed through.
|
|
739
812
|
* @private
|
|
740
813
|
*/
|
|
741
814
|
processSvgString(svgText) {
|
|
742
815
|
// Parse as DOM to manipulate
|
|
743
816
|
const parser = new DOMParser();
|
|
744
817
|
const doc = parser.parseFromString(svgText, 'image/svg+xml');
|
|
745
|
-
const svg = doc.
|
|
746
|
-
|
|
747
|
-
|
|
818
|
+
const svg = doc.documentElement;
|
|
819
|
+
// Reject anything that is not a clean, standalone <svg> document. On
|
|
820
|
+
// parse errors DOMParser yields a <parsererror> root (Firefox) or embeds
|
|
821
|
+
// a <parsererror> element in partially-parsed output (Chromium) — both
|
|
822
|
+
// must never reach the DOM.
|
|
823
|
+
if (svg.nodeName.toLowerCase() !== 'svg' ||
|
|
824
|
+
doc.getElementsByTagName('parsererror').length > 0) {
|
|
825
|
+
return null;
|
|
826
|
+
}
|
|
748
827
|
// Set size
|
|
749
828
|
const size = this.sizeInPixels();
|
|
750
829
|
svg.setAttribute('width', size);
|
|
@@ -16730,5 +16809,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
|
|
|
16730
16809
|
* Generated bundle index. Do not edit.
|
|
16731
16810
|
*/
|
|
16732
16811
|
|
|
16733
|
-
export { AccordionComponent, AccordionContentDirective, AccordionGroupComponent, AccordionHeaderDirective, AlertComponent, AnimationDurationFast, AnimationEasingEaseIn, AnimationEasingEaseInOut, AnimationEasingEaseOut, AreaChartComponent, AvatarComponent, AvatarGroupComponent, BadgeComponent, BarChartComponent, BorderRadius2xl, BorderRadiusFull, BorderRadiusLg, BorderRadiusMd, BorderRadiusNone, BorderRadiusSm, BorderRadiusXl, BreadcrumbsComponent, ButtonComponent, CalendarComponent, CalloutComponent, CardComponent, ChatComponent, CheckboxComponent, ChipComponent, CodeBlockComponent, ColorAccentOrange, ColorAccentPurple, ColorAccentRed, ColorAccentRust, ColorAccentViolet, ColorBackgroundDark, ColorErrorDark, ColorErrorDefault, ColorErrorLight, ColorInfoDark, ColorInfoDefault, ColorInfoLight, ColorNeutral100, ColorNeutral200, ColorNeutral300, ColorNeutral400, ColorNeutral50, ColorNeutral500, ColorNeutral600, ColorNeutral700, ColorNeutral800, ColorNeutral900, ColorPickerComponent, ColorPrimary100, ColorPrimary200, ColorPrimary300, ColorPrimary400, ColorPrimary50, ColorPrimary500, ColorPrimary600, ColorPrimary700, ColorPrimary800, ColorPrimary900, ColorSecondary100, ColorSecondary200, ColorSecondary300, ColorSecondary400, ColorSecondary50, ColorSecondary500, ColorSecondary600, ColorSecondary700, ColorSecondary800, ColorSecondary900, ColorSidebarDark, ColorSuccessDark, ColorSuccessDefault, ColorSuccessLight, ColorSurfaceDarkBase, ColorSurfaceDarkRaised, ColorSurfaceDarkSunken, ColorTextDarkPrimary, ColorTextDarkSecondary, ColorTextDarkTertiary, ColorWarningDark, ColorWarningDefault, ColorWarningLight, ComboboxComponent, ConfirmDialogComponent, ConfirmService, ContainerComponent, DateRangePickerComponent, DatepickerComponent, DependencyViewerComponent, DescriptionListComponent, DiffViewerComponent, DividerComponent, DocumentViewerComponent, DonutChartComponent, DrawerComponent, Elevation1, Elevation2, Elevation3, Elevation4, EmailInputComponent, EmptyStateComponent, ErrorDisplayComponent, FILE_FALLBACK_ICON, FOLDER_ICON, FOLDER_OPEN_ICON, FieldGroupComponent, FileUploadComponent, FilterBarComponent, FooterComponent, FunnelChartComponent, GalleryComponent, GanttChartComponent, GaugeComponent, HeaderComponent, HeatmapComponent, HeroComponent, ICON_ALIASES, ICON_NAMES, IconComponent, InputComponent, KanbanBoardComponent, LC_LOGO_BASE_PATH, LineChartComponent, ListComponent, ListItemTemplateDirective, LogViewerComponent, LogoComponent, MarkdownComponent, MenuComponent, ModalComponent, NotificationCenterComponent, NumberInputComponent, PageHeaderComponent, PageLayoutComponent, PaginationComponent, PasswordInputComponent, PieChartComponent, PipelineComponent, PopoverComponent, ProgressBarComponent, ProgressRingComponent, RadarChartComponent, RadioComponent, RatingComponent, RichTextEditorComponent, ScatterPlotComponent, SearchInputComponent, SectionComponent, SelectComponent, SidenavComponent, SizeContentMaxWidth, SizeInteractiveLgFontSize, SizeInteractiveLgHeight, SizeInteractiveLgPadding, SizeInteractiveMdFontSize, SizeInteractiveMdHeight, SizeInteractiveMdPadding, SizeInteractiveSmFontSize, SizeInteractiveSmHeight, SizeInteractiveSmPadding, SizeInteractiveXsFontSize, SizeInteractiveXsHeight, SizeInteractiveXsPadding, SizeMinTouchHeight, SizeMinTouchWidth, SkeletonComponent, SliderComponent, SpacerComponent, Spacing0, Spacing05, Spacing1, Spacing10, Spacing11, Spacing12, Spacing14, Spacing15, Spacing16, Spacing2, Spacing25, Spacing3, Spacing35, Spacing4, Spacing5, Spacing6, Spacing7, Spacing8, Spacing9, SparklineComponent, SpinnerComponent, SplitPaneComponent, StackComponent, StackedBarChartComponent, StageListComponent, StatTrendComponent, StepperComponent, SwitchComponent, TabComponent, TableCellDirective, TableComponent, TabsComponent, TagInputComponent, TextareaComponent, ThemeService, TimelineComponent, ToastComponent, ToastService, ToggleGroupComponent, ToolbarComponent, TooltipContentComponent, TooltipDirective, TreeViewComponent, TypographyComponent, TypographyFontFamilyBase, TypographyFontFamilyMono, TypographyFontSize2xl, TypographyFontSize3xl, TypographyFontSize4xl, TypographyFontSize5xl, TypographyFontSize6xl, TypographyFontSizeBase, TypographyFontSizeLg, TypographyFontSizeSm, TypographyFontSizeXl, TypographyFontSizeXs, TypographyFontWeightBold, TypographyFontWeightMedium, TypographyFontWeightNormal, TypographyFontWeightSemibold, TypographyLineHeightNormal, TypographyLineHeightRelaxed, TypographyLineHeightTight, VerificationCodeInputComponent, WaterfallChartComponent, isValidIconName, resolveFileIcon };
|
|
16812
|
+
export { AccordionComponent, AccordionContentDirective, AccordionGroupComponent, AccordionHeaderDirective, AlertComponent, AnimationDurationFast, AnimationEasingEaseIn, AnimationEasingEaseInOut, AnimationEasingEaseOut, AreaChartComponent, AvatarComponent, AvatarGroupComponent, BadgeComponent, BarChartComponent, BorderRadius2xl, BorderRadiusFull, BorderRadiusLg, BorderRadiusMd, BorderRadiusNone, BorderRadiusSm, BorderRadiusXl, BreadcrumbsComponent, ButtonComponent, CalendarComponent, CalloutComponent, CardComponent, ChatComponent, CheckboxComponent, ChipComponent, CodeBlockComponent, ColorAccentOrange, ColorAccentPurple, ColorAccentRed, ColorAccentRust, ColorAccentViolet, ColorBackgroundDark, ColorErrorDark, ColorErrorDefault, ColorErrorLight, ColorInfoDark, ColorInfoDefault, ColorInfoLight, ColorNeutral100, ColorNeutral200, ColorNeutral300, ColorNeutral400, ColorNeutral50, ColorNeutral500, ColorNeutral600, ColorNeutral700, ColorNeutral800, ColorNeutral900, ColorPickerComponent, ColorPrimary100, ColorPrimary200, ColorPrimary300, ColorPrimary400, ColorPrimary50, ColorPrimary500, ColorPrimary600, ColorPrimary700, ColorPrimary800, ColorPrimary900, ColorSecondary100, ColorSecondary200, ColorSecondary300, ColorSecondary400, ColorSecondary50, ColorSecondary500, ColorSecondary600, ColorSecondary700, ColorSecondary800, ColorSecondary900, ColorSidebarDark, ColorSuccessDark, ColorSuccessDefault, ColorSuccessLight, ColorSurfaceDarkBase, ColorSurfaceDarkRaised, ColorSurfaceDarkSunken, ColorTextDarkPrimary, ColorTextDarkSecondary, ColorTextDarkTertiary, ColorWarningDark, ColorWarningDefault, ColorWarningLight, ComboboxComponent, ConfirmDialogComponent, ConfirmService, ContainerComponent, DateRangePickerComponent, DatepickerComponent, DependencyViewerComponent, DescriptionListComponent, DiffViewerComponent, DividerComponent, DocumentViewerComponent, DonutChartComponent, DrawerComponent, Elevation1, Elevation2, Elevation3, Elevation4, EmailInputComponent, EmptyStateComponent, ErrorDisplayComponent, FILE_FALLBACK_ICON, FOLDER_ICON, FOLDER_OPEN_ICON, FieldGroupComponent, FileUploadComponent, FilterBarComponent, FooterComponent, FunnelChartComponent, GalleryComponent, GanttChartComponent, GaugeComponent, HeaderComponent, HeatmapComponent, HeroComponent, ICON_ALIASES, ICON_NAMES, IconComponent, InputComponent, KanbanBoardComponent, LC_LOGO_BASE_PATH, LineChartComponent, ListComponent, ListItemTemplateDirective, LogViewerComponent, LogoComponent, MarkdownComponent, MenuComponent, ModalComponent, NotificationCenterComponent, NumberInputComponent, PageHeaderComponent, PageLayoutComponent, PaginationComponent, PasswordInputComponent, PieChartComponent, PipelineComponent, PopoverComponent, ProgressBarComponent, ProgressRingComponent, RadarChartComponent, RadioComponent, RatingComponent, RichTextEditorComponent, ScatterPlotComponent, SearchInputComponent, SectionComponent, SelectComponent, SidenavComponent, SizeContentMaxWidth, SizeInteractiveLgFontSize, SizeInteractiveLgHeight, SizeInteractiveLgPadding, SizeInteractiveMdFontSize, SizeInteractiveMdHeight, SizeInteractiveMdPadding, SizeInteractiveSmFontSize, SizeInteractiveSmHeight, SizeInteractiveSmPadding, SizeInteractiveXsFontSize, SizeInteractiveXsHeight, SizeInteractiveXsPadding, SizeMinTouchHeight, SizeMinTouchWidth, SkeletonComponent, SliderComponent, SpacerComponent, Spacing0, Spacing05, Spacing1, Spacing10, Spacing11, Spacing12, Spacing14, Spacing15, Spacing16, Spacing2, Spacing25, Spacing3, Spacing35, Spacing4, Spacing5, Spacing6, Spacing7, Spacing8, Spacing9, SparklineComponent, SpinnerComponent, SplitPaneComponent, StackComponent, StackedBarChartComponent, StageListComponent, StatTrendComponent, StepperComponent, SwitchComponent, TabComponent, TableCellDirective, TableComponent, TabsComponent, TagInputComponent, TextareaComponent, ThemeService, TimelineComponent, ToastComponent, ToastService, ToggleGroupComponent, ToolbarComponent, TooltipContentComponent, TooltipDirective, TreeViewComponent, TypographyComponent, TypographyFontFamilyBase, TypographyFontFamilyMono, TypographyFontSize2xl, TypographyFontSize3xl, TypographyFontSize4xl, TypographyFontSize5xl, TypographyFontSize6xl, TypographyFontSizeBase, TypographyFontSizeLg, TypographyFontSizeSm, TypographyFontSizeXl, TypographyFontSizeXs, TypographyFontWeightBold, TypographyFontWeightMedium, TypographyFontWeightNormal, TypographyFontWeightSemibold, TypographyLineHeightNormal, TypographyLineHeightRelaxed, TypographyLineHeightTight, VerificationCodeInputComponent, WaterfallChartComponent, isValidIconName, resetIconWarnings, resolveFileIcon };
|
|
16734
16813
|
//# sourceMappingURL=life-cockpit-angular-ui-kit.mjs.map
|