@frame-kit/ui-ng 0.2.1 → 0.2.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.
@@ -135,7 +135,7 @@ export class ExampleComponent {}
135
135
  | `underline` | `'none' \| 'hover' \| 'always'` | `'hover'` | Underline behavior |
136
136
  | `target` | `string \| null` | `null` | Target attribute (auto `_blank` for external) |
137
137
  | `rel` | `string \| null` | `null` | Rel attribute (auto `noopener noreferrer` for external) |
138
- | `external` | `boolean` | `false` | Mark as external link (shows icon, sets `target="_blank"`) |
138
+ | `external` | `boolean \| undefined` | `undefined` | Authoritative override for external treatment. `undefined` auto-detects from the href; `true` forces external (icon + `target="_blank"`); `false` forces internal (no icon, same tab) even for an absolute URL |
139
139
  | `disabled` | `boolean` | `false` | Disable the link |
140
140
  | `loading` | `boolean` | `false` | Show loading state |
141
141
  | `download` | `string \| boolean \| null` | `null` | Download attribute (for file downloads) |
@@ -207,14 +207,20 @@ All tokens are defined in `theme/tokens.base.scss`. See `theme/TOKENS.md` for th
207
207
 
208
208
  ### External Links
209
209
 
210
- Always mark external links explicitly or let the component auto-detect:
210
+ `external` is an authoritative override — leave it unset to auto-detect from the
211
+ href, or set it explicitly to force the treatment either way:
211
212
 
212
213
  ```html
213
- <!-- Auto-detection (recommended) -->
214
+ <!-- Auto-detection (recommended): absolute URLs are external -->
214
215
  <fk-link href="https://example.com">External</fk-link>
215
216
 
216
- <!-- Explicit (for internal URLs that should open in new tab) -->
217
+ <!-- Force external for an internal URL (icon + opens in a new tab) -->
217
218
  <fk-link href="/internal" [external]="true">New Tab</fk-link>
219
+
220
+ <!-- Force internal for an absolute URL — no icon, same tab. Use for a
221
+ same-brand sibling app (e.g. a subdomain) that is external by origin but
222
+ should read as internal to the user. -->
223
+ <fk-link href="https://console.example.com" [external]="false">Dashboard</fk-link>
218
224
  ```
219
225
 
220
226
  ### Accessibility
@@ -85,10 +85,19 @@ class LinkComponent {
85
85
  */
86
86
  rel = input(null, ...(ngDevMode ? [{ debugName: "rel" }] : /* istanbul ignore next */ []));
87
87
  /**
88
- * Mark as external link (shows external icon, sets target="_blank")
89
- * @default false
90
- */
91
- external = input(false, ...(ngDevMode ? [{ debugName: "external" }] : /* istanbul ignore next */ []));
88
+ * Authoritative override for whether this is an external link (external icon
89
+ * + `target="_blank"`).
90
+ *
91
+ * - `undefined` (default): auto-detect from the href — absolute `http(s)://`,
92
+ * protocol-relative, `mailto:`, and `tel:` hrefs are treated as external.
93
+ * - `true`: force external (icon + new tab) regardless of the href.
94
+ * - `false`: force internal (no icon, same tab) even for an absolute href —
95
+ * use this for a same-brand sibling app (e.g. a subdomain) that is external
96
+ * by origin but should not read as "leaving the site".
97
+ *
98
+ * @default undefined
99
+ */
100
+ external = input(undefined, ...(ngDevMode ? [{ debugName: "external" }] : /* istanbul ignore next */ []));
92
101
  /**
93
102
  * Disable the link (prevents navigation, changes appearance)
94
103
  * @default false
@@ -158,12 +167,15 @@ class LinkComponent {
158
167
  * Computed: is this an external link?
159
168
  */
160
169
  isExternalLink = computed(() => {
161
- if (this.external())
162
- return true;
170
+ // An explicit `external` value is authoritative — it lets a caller force a
171
+ // same-brand absolute URL to be treated as internal (no icon, same tab).
172
+ const explicit = this.external();
173
+ if (explicit !== undefined)
174
+ return explicit;
163
175
  const href = this.href();
164
176
  if (!href)
165
177
  return false;
166
- // Check if href starts with http://, https://, //, or mailto:, tel:, etc.
178
+ // Auto-detect: href starts with http://, https://, //, or mailto:, tel:, etc.
167
179
  return /^(https?:)?\/\/|^mailto:|^tel:/i.test(href);
168
180
  }, ...(ngDevMode ? [{ debugName: "isExternalLink" }] : /* istanbul ignore next */ []));
169
181
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"frame-kit-ui-ng-core-link.mjs","sources":["../../../../packages/ui-ng/core/link/link.component.ts","../../../../packages/ui-ng/core/link/link.component.html","../../../../packages/ui-ng/core/link/link-icon.directive.ts","../../../../packages/ui-ng/core/link/frame-kit-ui-ng-core-link.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n output,\n} from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\nimport type { LinkSize, LinkUnderline, LinkVariant } from './link.types';\n\n/**\n * Link Component\n *\n * A flexible, accessible link component that supports:\n * - External and internal links\n * - Angular Router integration\n * - Variants, sizes, and underline styles\n * - Analytics tracking via data attributes\n * - Accessibility features (aria-label, keyboard navigation)\n * - Icon support (leading/trailing)\n * - Disabled and loading states\n * - External link indicators\n *\n * @example\n * ```html\n * <!-- Internal router link -->\n * <fk-link routerLink=\"/dashboard\">Dashboard</fk-link>\n *\n * <!-- External link with icon -->\n * <fk-link href=\"https://example.com\" [external]=\"true\">\n * Visit Site\n * </fk-link>\n *\n * <!-- With analytics tracking -->\n * <fk-link\n * href=\"/products\"\n * trackingId=\"nav-products\"\n * trackingCategory=\"navigation\"\n * >\n * Products\n * </fk-link>\n *\n * <!-- Variants -->\n * <fk-link variant=\"primary\" href=\"/signup\">Sign Up</fk-link>\n * <fk-link variant=\"muted\" href=\"/help\">Help</fk-link>\n * <fk-link variant=\"danger\" href=\"/delete\">Delete</fk-link>\n * ```\n */\n@Component({\n selector: 'fk-link',\n standalone: true,\n imports: [RouterLink, NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrl: './link.component.scss',\n templateUrl: './link.component.html',\n})\nexport class LinkComponent {\n // ===== INPUTS =====\n\n /**\n * External href (for standard <a> tags)\n * Use this for external links or when not using Angular Router\n */\n readonly href = input<string | null>(null);\n\n /**\n * Angular Router link (for internal navigation)\n * Use this for internal app navigation\n */\n readonly routerLink = input<string | string[] | null>(null);\n\n /**\n * Query parameters object passed through to the underlying\n * `routerLink` directive. Only meaningful when `routerLink` is set.\n * Equivalent to `<a [routerLink]=\"...\" [queryParams]=\"...\">`.\n */\n readonly queryParams = input<Record<\n string,\n string | number | boolean | null | undefined\n > | null>(null);\n\n /**\n * Link variant (visual style)\n * @default 'default'\n */\n readonly variant = input<LinkVariant>('default');\n\n /**\n * Link size\n * @default 'medium'\n */\n readonly size = input<LinkSize>('medium');\n\n /**\n * Underline behavior\n * @default 'hover'\n */\n readonly underline = input<LinkUnderline>('hover');\n\n /**\n * Target attribute (e.g., '_blank', '_self')\n * Automatically set to '_blank' if external is true\n */\n readonly target = input<string | null>(null);\n\n /**\n * Rel attribute (e.g., 'noopener noreferrer')\n * Automatically set to 'noopener noreferrer' for external links with target=\"_blank\"\n */\n readonly rel = input<string | null>(null);\n\n /**\n * Mark as external link (shows external icon, sets target=\"_blank\")\n * @default false\n */\n readonly external = input<boolean>(false);\n\n /**\n * Disable the link (prevents navigation, changes appearance)\n * @default false\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Loading state (shows loading indicator, prevents navigation)\n * @default false\n */\n readonly loading = input<boolean>(false);\n\n /**\n * Download attribute (for file downloads)\n */\n readonly download = input<string | boolean | null>(null);\n\n /**\n * Additional CSS classes\n */\n readonly className = input<string>('');\n\n /**\n * ID attribute\n */\n readonly id = input<string | null>(null);\n\n /**\n * ARIA label (for accessibility)\n */\n readonly ariaLabel = input<string | null>(null);\n\n /**\n * ARIA described-by (for accessibility)\n */\n readonly ariaDescribedBy = input<string | null>(null);\n\n /**\n * ARIA current (for indicating current page/location)\n */\n readonly ariaCurrent = input<\n 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false' | null\n >(null);\n\n /**\n * Role attribute (usually not needed for <a> tags)\n */\n readonly role = input<string | null>(null);\n\n /**\n * Tab index (for keyboard navigation control)\n */\n readonly tabIndex = input<number | null>(null);\n\n /**\n * Analytics tracking ID\n */\n readonly trackingId = input<string | null>(null);\n\n /**\n * Analytics tracking category\n */\n readonly trackingCategory = input<string | null>(null);\n\n /**\n * Analytics tracking label\n */\n readonly trackingLabel = input<string | null>(null);\n\n /**\n * Custom data attributes (for analytics or other purposes)\n */\n readonly dataAttributes = input<Record<string, string>>({});\n\n // ===== OUTPUTS =====\n\n /**\n * Click event (emitted when link is clicked)\n * Note: Not emitted if disabled or loading\n */\n readonly clicked = output<MouseEvent>();\n\n // ===== COMPUTED PROPERTIES =====\n\n /**\n * Computed: is this an external link?\n */\n readonly isExternalLink = computed(() => {\n if (this.external()) return true;\n\n const href = this.href();\n\n if (!href) return false;\n\n // Check if href starts with http://, https://, //, or mailto:, tel:, etc.\n return /^(https?:)?\\/\\/|^mailto:|^tel:/i.test(href);\n });\n\n /**\n * Computed: effective target attribute\n */\n readonly effectiveTarget = computed(() => {\n if (this.target()) return this.target();\n if (this.isExternalLink()) return '_blank';\n\n return null;\n });\n\n /**\n * Computed: effective rel attribute\n */\n readonly effectiveRel = computed(() => {\n if (this.rel()) return this.rel();\n\n if (this.isExternalLink() && this.effectiveTarget() === '_blank') {\n return 'noopener noreferrer';\n }\n\n return null;\n });\n\n /**\n * Computed: effective download attribute\n */\n readonly effectiveDownload = computed(() => {\n const download = this.download();\n\n if (download === null) return null;\n if (download === true) return '';\n\n return download;\n });\n\n /**\n * Computed: effective tab index\n */\n readonly effectiveTabIndex = computed(() => {\n if (this.tabIndex() !== null) return this.tabIndex();\n if (this.disabled()) return -1;\n\n return null;\n });\n\n /**\n * Host classes — single source of truth\n */\n readonly classes = computed(() => {\n return [\n 'fk-link',\n `fk-link--${this.variant()}`,\n `fk-link--${this.size()}`,\n `fk-link--underline-${this.underline()}`,\n this.disabled() ? 'fk-link--disabled' : '',\n this.loading() ? 'fk-link--loading' : '',\n this.isExternalLink() ? 'fk-link--external' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n /**\n * Computed: data attributes for analytics\n */\n readonly computedDataAttributes = computed(() => {\n const attrs: Record<string, string> = { ...this.dataAttributes() };\n\n const trackingId = this.trackingId();\n\n if (trackingId) {\n attrs['data-tracking-id'] = trackingId;\n }\n\n const trackingCategory = this.trackingCategory();\n\n if (trackingCategory) {\n attrs['data-tracking-category'] = trackingCategory;\n }\n\n const trackingLabel = this.trackingLabel();\n\n if (trackingLabel) {\n attrs['data-tracking-label'] = trackingLabel;\n }\n\n return attrs;\n });\n\n /**\n * Handle click events\n */\n handleClick(event: MouseEvent): void {\n // Prevent navigation if disabled or loading\n if (this.disabled() || this.loading()) {\n event.preventDefault();\n event.stopPropagation();\n\n return;\n }\n\n // Emit click event\n this.clicked.emit(event);\n\n // Track analytics (if tracking service is available)\n this.trackClick();\n }\n\n /**\n * Track click for analytics\n * Override this method or connect to your analytics service\n */\n private trackClick(): void {\n const trackingId = this.trackingId();\n\n if (!trackingId) return;\n\n // Example: integrate with your analytics service\n // this.analytics.track('link_click', {\n // id: trackingId,\n // category: this.trackingCategory(),\n // label: this.trackingLabel(),\n // });\n\n // For now, log to console in dev mode\n if (\n typeof window !== 'undefined' &&\n typeof console !== 'undefined' &&\n console.debug\n ) {\n console.debug('[fk-link] Analytics:', {\n id: trackingId,\n category: this.trackingCategory(),\n label: this.trackingLabel(),\n });\n }\n }\n}\n","<!-- Stable projection point for default content + leading/trailing icons -->\n<ng-template #projected>\n <ng-content select=\"[fkLinkIconStart]\" />\n <span class=\"fk-link__text\">\n <ng-content></ng-content>\n </span>\n <ng-content select=\"[fkLinkIconEnd]\" />\n</ng-template>\n\n<!-- Loading indicator template -->\n<ng-template #loadingIndicator>\n <span class=\"fk-link__loading\" aria-hidden=\"true\">\n <span class=\"fk-link__spinner\"></span>\n </span>\n</ng-template>\n\n<!-- External link icon template -->\n<ng-template #externalIcon>\n <span class=\"fk-link__external-icon\" aria-hidden=\"true\">\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12 8.66667V12.6667C12 13.0203 11.8595 13.3594 11.6095 13.6095C11.3594 13.8595 11.0203 14 10.6667 14H3.33333C2.97971 14 2.64057 13.8595 2.39052 13.6095C2.14048 13.3594 2 13.0203 2 12.6667V5.33333C2 4.97971 2.14048 4.64057 2.39052 4.39052C2.64057 4.14048 2.97971 4 3.33333 4H7.33333M10 2H14M14 2V6M14 2L6.66667 9.33333\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n</ng-template>\n\n<!-- Router Link (Internal Navigation) -->\n@if (routerLink() && !href()) {\n <a\n [routerLink]=\"routerLink()\"\n [queryParams]=\"queryParams()\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-current]=\"ariaCurrent()\"\n [attr.role]=\"role()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.data-tracking-id]=\"\n computedDataAttributes()['data-tracking-id'] || null\n \"\n [attr.data-tracking-category]=\"\n computedDataAttributes()['data-tracking-category'] || null\n \"\n [attr.data-tracking-label]=\"\n computedDataAttributes()['data-tracking-label'] || null\n \"\n (click)=\"handleClick($event)\"\n >\n @if (loading()) {\n <ng-container [ngTemplateOutlet]=\"loadingIndicator\"></ng-container>\n }\n\n <span class=\"fk-link__content\">\n <ng-container [ngTemplateOutlet]=\"projected\"></ng-container>\n </span>\n\n @if (isExternalLink()) {\n <ng-container [ngTemplateOutlet]=\"externalIcon\"></ng-container>\n }\n </a>\n}\n\n<!-- Standard Link (External or href-based) -->\n@if (href() && !routerLink()) {\n <a\n [href]=\"href()\"\n [target]=\"effectiveTarget()\"\n [rel]=\"effectiveRel()\"\n [download]=\"effectiveDownload()\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-current]=\"ariaCurrent()\"\n [attr.role]=\"role()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.data-tracking-id]=\"\n computedDataAttributes()['data-tracking-id'] || null\n \"\n [attr.data-tracking-category]=\"\n computedDataAttributes()['data-tracking-category'] || null\n \"\n [attr.data-tracking-label]=\"\n computedDataAttributes()['data-tracking-label'] || null\n \"\n (click)=\"handleClick($event)\"\n >\n @if (loading()) {\n <ng-container [ngTemplateOutlet]=\"loadingIndicator\"></ng-container>\n }\n\n <span class=\"fk-link__content\">\n <ng-container [ngTemplateOutlet]=\"projected\"></ng-container>\n </span>\n\n @if (isExternalLink()) {\n <ng-container [ngTemplateOutlet]=\"externalIcon\"></ng-container>\n }\n </a>\n}\n\n<!-- Fallback: Button-style link (when no href or routerLink) -->\n@if (!href() && !routerLink()) {\n <button\n type=\"button\"\n [id]=\"id()\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-current]=\"ariaCurrent()\"\n [attr.role]=\"role()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.data-tracking-id]=\"\n computedDataAttributes()['data-tracking-id'] || null\n \"\n [attr.data-tracking-category]=\"\n computedDataAttributes()['data-tracking-category'] || null\n \"\n [attr.data-tracking-label]=\"\n computedDataAttributes()['data-tracking-label'] || null\n \"\n (click)=\"handleClick($event)\"\n >\n @if (loading()) {\n <ng-container [ngTemplateOutlet]=\"loadingIndicator\"></ng-container>\n }\n\n <span class=\"fk-link__content\">\n <ng-container [ngTemplateOutlet]=\"projected\"></ng-container>\n </span>\n </button>\n}\n","import { Directive, InjectionToken } from '@angular/core';\n\nexport const FK_LINK_ICON_START = new InjectionToken<FkLinkIconStartDirective>(\n 'FK_LINK_ICON_START',\n);\n\nexport const FK_LINK_ICON_END = new InjectionToken<FkLinkIconEndDirective>(\n 'FK_LINK_ICON_END',\n);\n\n/**\n * Marker directive for the leading icon slot inside `<fk-link>`.\n * Mirrors the `[fkButtonIconStart]` pattern on `<fk-button>`.\n *\n * Apply to an `<fk-icon>` (or any element) projected as a child:\n *\n * ```html\n * <fk-link variant=\"primary\" (clicked)=\"download()\">\n * <fk-icon name=\"download\" fkLinkIconStart />\n * Download sample CSV\n * </fk-link>\n * ```\n *\n * The directive itself only marks the projection slot and applies\n * `aria-hidden=\"true\"` so screen readers don't announce decorative\n * icons twice.\n */\n@Directive({\n selector: '[fkLinkIconStart]',\n standalone: true,\n providers: [\n { provide: FK_LINK_ICON_START, useExisting: FkLinkIconStartDirective },\n ],\n host: {\n 'aria-hidden': 'true',\n },\n})\nexport class FkLinkIconStartDirective {}\n\n/**\n * Marker directive for the trailing icon slot inside `<fk-link>`.\n * Note: the auto-shown external-link icon (when `href` points\n * off-site) renders separately and is not affected by this slot.\n */\n@Directive({\n selector: '[fkLinkIconEnd]',\n standalone: true,\n providers: [\n { provide: FK_LINK_ICON_END, useExisting: FkLinkIconEndDirective },\n ],\n host: {\n 'aria-hidden': 'true',\n },\n})\nexport class FkLinkIconEndDirective {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frame-kit-ui-ng-core-link.mjs","sources":["../../../../packages/ui-ng/core/link/link.component.ts","../../../../packages/ui-ng/core/link/link.component.html","../../../../packages/ui-ng/core/link/link-icon.directive.ts","../../../../packages/ui-ng/core/link/frame-kit-ui-ng-core-link.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n output,\n} from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\nimport type { LinkSize, LinkUnderline, LinkVariant } from './link.types';\n\n/**\n * Link Component\n *\n * A flexible, accessible link component that supports:\n * - External and internal links\n * - Angular Router integration\n * - Variants, sizes, and underline styles\n * - Analytics tracking via data attributes\n * - Accessibility features (aria-label, keyboard navigation)\n * - Icon support (leading/trailing)\n * - Disabled and loading states\n * - External link indicators\n *\n * @example\n * ```html\n * <!-- Internal router link -->\n * <fk-link routerLink=\"/dashboard\">Dashboard</fk-link>\n *\n * <!-- External link with icon -->\n * <fk-link href=\"https://example.com\" [external]=\"true\">\n * Visit Site\n * </fk-link>\n *\n * <!-- With analytics tracking -->\n * <fk-link\n * href=\"/products\"\n * trackingId=\"nav-products\"\n * trackingCategory=\"navigation\"\n * >\n * Products\n * </fk-link>\n *\n * <!-- Variants -->\n * <fk-link variant=\"primary\" href=\"/signup\">Sign Up</fk-link>\n * <fk-link variant=\"muted\" href=\"/help\">Help</fk-link>\n * <fk-link variant=\"danger\" href=\"/delete\">Delete</fk-link>\n * ```\n */\n@Component({\n selector: 'fk-link',\n standalone: true,\n imports: [RouterLink, NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrl: './link.component.scss',\n templateUrl: './link.component.html',\n})\nexport class LinkComponent {\n // ===== INPUTS =====\n\n /**\n * External href (for standard <a> tags)\n * Use this for external links or when not using Angular Router\n */\n readonly href = input<string | null>(null);\n\n /**\n * Angular Router link (for internal navigation)\n * Use this for internal app navigation\n */\n readonly routerLink = input<string | string[] | null>(null);\n\n /**\n * Query parameters object passed through to the underlying\n * `routerLink` directive. Only meaningful when `routerLink` is set.\n * Equivalent to `<a [routerLink]=\"...\" [queryParams]=\"...\">`.\n */\n readonly queryParams = input<Record<\n string,\n string | number | boolean | null | undefined\n > | null>(null);\n\n /**\n * Link variant (visual style)\n * @default 'default'\n */\n readonly variant = input<LinkVariant>('default');\n\n /**\n * Link size\n * @default 'medium'\n */\n readonly size = input<LinkSize>('medium');\n\n /**\n * Underline behavior\n * @default 'hover'\n */\n readonly underline = input<LinkUnderline>('hover');\n\n /**\n * Target attribute (e.g., '_blank', '_self')\n * Automatically set to '_blank' if external is true\n */\n readonly target = input<string | null>(null);\n\n /**\n * Rel attribute (e.g., 'noopener noreferrer')\n * Automatically set to 'noopener noreferrer' for external links with target=\"_blank\"\n */\n readonly rel = input<string | null>(null);\n\n /**\n * Authoritative override for whether this is an external link (external icon\n * + `target=\"_blank\"`).\n *\n * - `undefined` (default): auto-detect from the href — absolute `http(s)://`,\n * protocol-relative, `mailto:`, and `tel:` hrefs are treated as external.\n * - `true`: force external (icon + new tab) regardless of the href.\n * - `false`: force internal (no icon, same tab) even for an absolute href —\n * use this for a same-brand sibling app (e.g. a subdomain) that is external\n * by origin but should not read as \"leaving the site\".\n *\n * @default undefined\n */\n readonly external = input<boolean | undefined>(undefined);\n\n /**\n * Disable the link (prevents navigation, changes appearance)\n * @default false\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Loading state (shows loading indicator, prevents navigation)\n * @default false\n */\n readonly loading = input<boolean>(false);\n\n /**\n * Download attribute (for file downloads)\n */\n readonly download = input<string | boolean | null>(null);\n\n /**\n * Additional CSS classes\n */\n readonly className = input<string>('');\n\n /**\n * ID attribute\n */\n readonly id = input<string | null>(null);\n\n /**\n * ARIA label (for accessibility)\n */\n readonly ariaLabel = input<string | null>(null);\n\n /**\n * ARIA described-by (for accessibility)\n */\n readonly ariaDescribedBy = input<string | null>(null);\n\n /**\n * ARIA current (for indicating current page/location)\n */\n readonly ariaCurrent = input<\n 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false' | null\n >(null);\n\n /**\n * Role attribute (usually not needed for <a> tags)\n */\n readonly role = input<string | null>(null);\n\n /**\n * Tab index (for keyboard navigation control)\n */\n readonly tabIndex = input<number | null>(null);\n\n /**\n * Analytics tracking ID\n */\n readonly trackingId = input<string | null>(null);\n\n /**\n * Analytics tracking category\n */\n readonly trackingCategory = input<string | null>(null);\n\n /**\n * Analytics tracking label\n */\n readonly trackingLabel = input<string | null>(null);\n\n /**\n * Custom data attributes (for analytics or other purposes)\n */\n readonly dataAttributes = input<Record<string, string>>({});\n\n // ===== OUTPUTS =====\n\n /**\n * Click event (emitted when link is clicked)\n * Note: Not emitted if disabled or loading\n */\n readonly clicked = output<MouseEvent>();\n\n // ===== COMPUTED PROPERTIES =====\n\n /**\n * Computed: is this an external link?\n */\n readonly isExternalLink = computed(() => {\n // An explicit `external` value is authoritative — it lets a caller force a\n // same-brand absolute URL to be treated as internal (no icon, same tab).\n const explicit = this.external();\n\n if (explicit !== undefined) return explicit;\n\n const href = this.href();\n\n if (!href) return false;\n\n // Auto-detect: href starts with http://, https://, //, or mailto:, tel:, etc.\n return /^(https?:)?\\/\\/|^mailto:|^tel:/i.test(href);\n });\n\n /**\n * Computed: effective target attribute\n */\n readonly effectiveTarget = computed(() => {\n if (this.target()) return this.target();\n if (this.isExternalLink()) return '_blank';\n\n return null;\n });\n\n /**\n * Computed: effective rel attribute\n */\n readonly effectiveRel = computed(() => {\n if (this.rel()) return this.rel();\n\n if (this.isExternalLink() && this.effectiveTarget() === '_blank') {\n return 'noopener noreferrer';\n }\n\n return null;\n });\n\n /**\n * Computed: effective download attribute\n */\n readonly effectiveDownload = computed(() => {\n const download = this.download();\n\n if (download === null) return null;\n if (download === true) return '';\n\n return download;\n });\n\n /**\n * Computed: effective tab index\n */\n readonly effectiveTabIndex = computed(() => {\n if (this.tabIndex() !== null) return this.tabIndex();\n if (this.disabled()) return -1;\n\n return null;\n });\n\n /**\n * Host classes — single source of truth\n */\n readonly classes = computed(() => {\n return [\n 'fk-link',\n `fk-link--${this.variant()}`,\n `fk-link--${this.size()}`,\n `fk-link--underline-${this.underline()}`,\n this.disabled() ? 'fk-link--disabled' : '',\n this.loading() ? 'fk-link--loading' : '',\n this.isExternalLink() ? 'fk-link--external' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n /**\n * Computed: data attributes for analytics\n */\n readonly computedDataAttributes = computed(() => {\n const attrs: Record<string, string> = { ...this.dataAttributes() };\n\n const trackingId = this.trackingId();\n\n if (trackingId) {\n attrs['data-tracking-id'] = trackingId;\n }\n\n const trackingCategory = this.trackingCategory();\n\n if (trackingCategory) {\n attrs['data-tracking-category'] = trackingCategory;\n }\n\n const trackingLabel = this.trackingLabel();\n\n if (trackingLabel) {\n attrs['data-tracking-label'] = trackingLabel;\n }\n\n return attrs;\n });\n\n /**\n * Handle click events\n */\n handleClick(event: MouseEvent): void {\n // Prevent navigation if disabled or loading\n if (this.disabled() || this.loading()) {\n event.preventDefault();\n event.stopPropagation();\n\n return;\n }\n\n // Emit click event\n this.clicked.emit(event);\n\n // Track analytics (if tracking service is available)\n this.trackClick();\n }\n\n /**\n * Track click for analytics\n * Override this method or connect to your analytics service\n */\n private trackClick(): void {\n const trackingId = this.trackingId();\n\n if (!trackingId) return;\n\n // Example: integrate with your analytics service\n // this.analytics.track('link_click', {\n // id: trackingId,\n // category: this.trackingCategory(),\n // label: this.trackingLabel(),\n // });\n\n // For now, log to console in dev mode\n if (\n typeof window !== 'undefined' &&\n typeof console !== 'undefined' &&\n console.debug\n ) {\n console.debug('[fk-link] Analytics:', {\n id: trackingId,\n category: this.trackingCategory(),\n label: this.trackingLabel(),\n });\n }\n }\n}\n","<!-- Stable projection point for default content + leading/trailing icons -->\n<ng-template #projected>\n <ng-content select=\"[fkLinkIconStart]\" />\n <span class=\"fk-link__text\">\n <ng-content></ng-content>\n </span>\n <ng-content select=\"[fkLinkIconEnd]\" />\n</ng-template>\n\n<!-- Loading indicator template -->\n<ng-template #loadingIndicator>\n <span class=\"fk-link__loading\" aria-hidden=\"true\">\n <span class=\"fk-link__spinner\"></span>\n </span>\n</ng-template>\n\n<!-- External link icon template -->\n<ng-template #externalIcon>\n <span class=\"fk-link__external-icon\" aria-hidden=\"true\">\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12 8.66667V12.6667C12 13.0203 11.8595 13.3594 11.6095 13.6095C11.3594 13.8595 11.0203 14 10.6667 14H3.33333C2.97971 14 2.64057 13.8595 2.39052 13.6095C2.14048 13.3594 2 13.0203 2 12.6667V5.33333C2 4.97971 2.14048 4.64057 2.39052 4.39052C2.64057 4.14048 2.97971 4 3.33333 4H7.33333M10 2H14M14 2V6M14 2L6.66667 9.33333\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n</ng-template>\n\n<!-- Router Link (Internal Navigation) -->\n@if (routerLink() && !href()) {\n <a\n [routerLink]=\"routerLink()\"\n [queryParams]=\"queryParams()\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-current]=\"ariaCurrent()\"\n [attr.role]=\"role()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.data-tracking-id]=\"\n computedDataAttributes()['data-tracking-id'] || null\n \"\n [attr.data-tracking-category]=\"\n computedDataAttributes()['data-tracking-category'] || null\n \"\n [attr.data-tracking-label]=\"\n computedDataAttributes()['data-tracking-label'] || null\n \"\n (click)=\"handleClick($event)\"\n >\n @if (loading()) {\n <ng-container [ngTemplateOutlet]=\"loadingIndicator\"></ng-container>\n }\n\n <span class=\"fk-link__content\">\n <ng-container [ngTemplateOutlet]=\"projected\"></ng-container>\n </span>\n\n @if (isExternalLink()) {\n <ng-container [ngTemplateOutlet]=\"externalIcon\"></ng-container>\n }\n </a>\n}\n\n<!-- Standard Link (External or href-based) -->\n@if (href() && !routerLink()) {\n <a\n [href]=\"href()\"\n [target]=\"effectiveTarget()\"\n [rel]=\"effectiveRel()\"\n [download]=\"effectiveDownload()\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-current]=\"ariaCurrent()\"\n [attr.role]=\"role()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.data-tracking-id]=\"\n computedDataAttributes()['data-tracking-id'] || null\n \"\n [attr.data-tracking-category]=\"\n computedDataAttributes()['data-tracking-category'] || null\n \"\n [attr.data-tracking-label]=\"\n computedDataAttributes()['data-tracking-label'] || null\n \"\n (click)=\"handleClick($event)\"\n >\n @if (loading()) {\n <ng-container [ngTemplateOutlet]=\"loadingIndicator\"></ng-container>\n }\n\n <span class=\"fk-link__content\">\n <ng-container [ngTemplateOutlet]=\"projected\"></ng-container>\n </span>\n\n @if (isExternalLink()) {\n <ng-container [ngTemplateOutlet]=\"externalIcon\"></ng-container>\n }\n </a>\n}\n\n<!-- Fallback: Button-style link (when no href or routerLink) -->\n@if (!href() && !routerLink()) {\n <button\n type=\"button\"\n [id]=\"id()\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-current]=\"ariaCurrent()\"\n [attr.role]=\"role()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.data-tracking-id]=\"\n computedDataAttributes()['data-tracking-id'] || null\n \"\n [attr.data-tracking-category]=\"\n computedDataAttributes()['data-tracking-category'] || null\n \"\n [attr.data-tracking-label]=\"\n computedDataAttributes()['data-tracking-label'] || null\n \"\n (click)=\"handleClick($event)\"\n >\n @if (loading()) {\n <ng-container [ngTemplateOutlet]=\"loadingIndicator\"></ng-container>\n }\n\n <span class=\"fk-link__content\">\n <ng-container [ngTemplateOutlet]=\"projected\"></ng-container>\n </span>\n </button>\n}\n","import { Directive, InjectionToken } from '@angular/core';\n\nexport const FK_LINK_ICON_START = new InjectionToken<FkLinkIconStartDirective>(\n 'FK_LINK_ICON_START',\n);\n\nexport const FK_LINK_ICON_END = new InjectionToken<FkLinkIconEndDirective>(\n 'FK_LINK_ICON_END',\n);\n\n/**\n * Marker directive for the leading icon slot inside `<fk-link>`.\n * Mirrors the `[fkButtonIconStart]` pattern on `<fk-button>`.\n *\n * Apply to an `<fk-icon>` (or any element) projected as a child:\n *\n * ```html\n * <fk-link variant=\"primary\" (clicked)=\"download()\">\n * <fk-icon name=\"download\" fkLinkIconStart />\n * Download sample CSV\n * </fk-link>\n * ```\n *\n * The directive itself only marks the projection slot and applies\n * `aria-hidden=\"true\"` so screen readers don't announce decorative\n * icons twice.\n */\n@Directive({\n selector: '[fkLinkIconStart]',\n standalone: true,\n providers: [\n { provide: FK_LINK_ICON_START, useExisting: FkLinkIconStartDirective },\n ],\n host: {\n 'aria-hidden': 'true',\n },\n})\nexport class FkLinkIconStartDirective {}\n\n/**\n * Marker directive for the trailing icon slot inside `<fk-link>`.\n * Note: the auto-shown external-link icon (when `href` points\n * off-site) renders separately and is not affected by this slot.\n */\n@Directive({\n selector: '[fkLinkIconEnd]',\n standalone: true,\n providers: [\n { provide: FK_LINK_ICON_END, useExisting: FkLinkIconEndDirective },\n ],\n host: {\n 'aria-hidden': 'true',\n },\n})\nexport class FkLinkIconEndDirective {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frame-kit/ui-ng",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Style-agnostic, token-driven Angular UI component library for FrameKit.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -105,10 +105,19 @@ declare class LinkComponent {
105
105
  */
106
106
  readonly rel: _angular_core.InputSignal<string | null>;
107
107
  /**
108
- * Mark as external link (shows external icon, sets target="_blank")
109
- * @default false
110
- */
111
- readonly external: _angular_core.InputSignal<boolean>;
108
+ * Authoritative override for whether this is an external link (external icon
109
+ * + `target="_blank"`).
110
+ *
111
+ * - `undefined` (default): auto-detect from the href — absolute `http(s)://`,
112
+ * protocol-relative, `mailto:`, and `tel:` hrefs are treated as external.
113
+ * - `true`: force external (icon + new tab) regardless of the href.
114
+ * - `false`: force internal (no icon, same tab) even for an absolute href —
115
+ * use this for a same-brand sibling app (e.g. a subdomain) that is external
116
+ * by origin but should not read as "leaving the site".
117
+ *
118
+ * @default undefined
119
+ */
120
+ readonly external: _angular_core.InputSignal<boolean | undefined>;
112
121
  /**
113
122
  * Disable the link (prevents navigation, changes appearance)
114
123
  * @default false