@eduboxpro/studio 0.1.1 → 0.1.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.
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, signal, effect, Injectable, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, input, computed, ChangeDetectionStrategy, Component, output } from '@angular/core';
3
3
  import { DOCUMENT } from '@angular/common';
4
4
  import * as i1 from 'lucide-angular';
5
- import { icons, LucideAngularModule, LucideIconProvider, LUCIDE_ICONS, Loader2, Loader, RotateCw, RefreshCw, Printer, Save, Image, Folder, FileText, File, HelpCircle, XCircle, CheckCircle, Info, AlertTriangle, AlertCircle, LogOut, LogIn, Unlock, Lock, EyeOff, Eye, Clock, Calendar, Bell, MoreHorizontal, MoreVertical, Menu, Home, Share2, Copy, Link, ExternalLink, Filter, Search, X, Check, Minus, Plus, Edit, Trash2, User, Settings, Star, Heart, Phone, Mail, Upload, Download, ChevronRight, ChevronLeft, ChevronUp, ChevronDown, ArrowLeft, ArrowRight } from 'lucide-angular';
5
+ import { icons, LucideAngularModule, LucideIconProvider, LUCIDE_ICONS, ShoppingCart, Loader2, Loader, RotateCw, RefreshCw, Printer, Save, Image, Folder, FileText, File, HelpCircle, XCircle, CheckCircle, Info, AlertTriangle, AlertCircle, LogOut, LogIn, Unlock, Lock, EyeOff, Eye, Clock, Calendar, Bell, MoreHorizontal, MoreVertical, Menu, Home, Share2, Copy, Link, ExternalLink, Filter, Search, X, Check, Minus, Plus, Edit, Trash2, User, Settings, Star, Heart, Phone, Mail, Upload, Download, ChevronRight, ChevronLeft, ChevronUp, ChevronDown, ArrowLeft, ArrowRight } from 'lucide-angular';
6
6
 
7
7
  /**
8
8
  * Injection token for Studio configuration
@@ -362,48 +362,378 @@ function provideStudioIcons() {
362
362
  RefreshCw,
363
363
  RotateCw,
364
364
  Loader,
365
- Loader2
365
+ Loader2,
366
+ ShoppingCart
366
367
  })
367
368
  }
368
369
  ]);
369
370
  }
370
371
 
372
+ /**
373
+ * Проверяет безопасность URL для навигации
374
+ *
375
+ * @param url - URL для проверки
376
+ * @returns true если URL безопасен (http/https или относительный)
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * isSafeUrl('https://example.com') // true
381
+ * isSafeUrl('javascript:alert(1)') // false
382
+ * isSafeUrl('/relative/path') // true
383
+ * ```
384
+ */
385
+ function isSafeUrl(url) {
386
+ if (!url || typeof url !== 'string') {
387
+ return false;
388
+ }
389
+ try {
390
+ const parsed = new URL(url, window.location.origin);
391
+ // Разрешаем только http(s) и относительные URL (пустой protocol)
392
+ return ['http:', 'https:', ''].includes(parsed.protocol);
393
+ }
394
+ catch {
395
+ // Невалидный URL
396
+ return false;
397
+ }
398
+ }
399
+ /**
400
+ * Sanitize URL перед использованием в навигации
401
+ *
402
+ * @param url - URL для sanitization
403
+ * @returns Безопасный URL или '#' если URL небезопасен
404
+ *
405
+ * @example
406
+ * ```typescript
407
+ * sanitizeUrl('https://example.com') // 'https://example.com'
408
+ * sanitizeUrl('javascript:alert(1)') // '#' (с предупреждением в консоли)
409
+ * ```
410
+ */
411
+ function sanitizeUrl(url) {
412
+ if (!isSafeUrl(url)) {
413
+ console.warn(`[Studio] Unsafe URL blocked: ${url}`);
414
+ return '#';
415
+ }
416
+ return url;
417
+ }
418
+
419
+ /**
420
+ * Объединяет CSS классы, игнорируя falsy значения
421
+ *
422
+ * @param classes - Массив классов (строки, undefined, null, false)
423
+ * @returns Строка с объединенными классами
424
+ *
425
+ * @example
426
+ * ```typescript
427
+ * classNames('btn', 'btn-primary') // 'btn btn-primary'
428
+ * classNames('btn', isActive && 'active') // 'btn active' если isActive=true, иначе 'btn'
429
+ * classNames('btn', undefined, null, false, 'large') // 'btn large'
430
+ * ```
431
+ */
432
+ function classNames(...classes) {
433
+ return classes.filter(Boolean).join(' ');
434
+ }
435
+
436
+ /**
437
+ * Создает computed signal с fallback chain: input → config → default
438
+ *
439
+ * Упрощает паттерн configurable inputs, убирая boilerplate код.
440
+ *
441
+ * @param inputSignal - Input signal от пользователя
442
+ * @param configSignal - Config значение (может быть undefined)
443
+ * @param defaultValue - Fallback значение
444
+ * @returns Computed signal с resolved значением
445
+ *
446
+ * @example
447
+ * ```typescript
448
+ * export class ButtonComponent {
449
+ * private defaults = computed(() => this.configService.config().components?.button);
450
+ *
451
+ * // Input
452
+ * variantInput = input<Variant | undefined>(undefined, { alias: 'variant' });
453
+ *
454
+ * // Resolved value с config fallback
455
+ * variant = withConfigDefault(
456
+ * this.variantInput,
457
+ * computed(() => this.defaults()?.variant),
458
+ * 'solid'
459
+ * );
460
+ * }
461
+ * ```
462
+ */
463
+ function withConfigDefault(inputSignal, configSignal, defaultValue) {
464
+ return computed(() => {
465
+ const inputValue = inputSignal();
466
+ if (inputValue !== undefined)
467
+ return inputValue;
468
+ const configValue = configSignal();
469
+ if (configValue !== undefined)
470
+ return configValue;
471
+ return defaultValue;
472
+ });
473
+ }
474
+
475
+ /**
476
+ * @eduboxpro/studio - Utilities
477
+ *
478
+ * Helper functions and utilities for the Studio library
479
+ */
480
+
481
+ class BadgeComponent {
482
+ configService = inject(StudioConfigService);
483
+ badgeDefaults = computed(() => this.configService.config().components?.badge, ...(ngDevMode ? [{ debugName: "badgeDefaults" }] : []));
484
+ // Appearance - inputs
485
+ variantInput = input(undefined, ...(ngDevMode ? [{ debugName: "variantInput", alias: 'variant' }] : [{ alias: 'variant' }]));
486
+ sizeInput = input(undefined, ...(ngDevMode ? [{ debugName: "sizeInput", alias: 'size' }] : [{ alias: 'size' }]));
487
+ colorInput = input(undefined, ...(ngDevMode ? [{ debugName: "colorInput", alias: 'color' }] : [{ alias: 'color' }]));
488
+ radiusInput = input(undefined, ...(ngDevMode ? [{ debugName: "radiusInput", alias: 'radius' }] : [{ alias: 'radius' }]));
489
+ // Values with config defaults
490
+ variant = withConfigDefault(this.variantInput, computed(() => this.badgeDefaults()?.variant), 'solid');
491
+ size = withConfigDefault(this.sizeInput, computed(() => this.badgeDefaults()?.size), 'md');
492
+ color = withConfigDefault(this.colorInput, computed(() => this.badgeDefaults()?.color), 'primary');
493
+ radius = withConfigDefault(this.radiusInput, computed(() => this.badgeDefaults()?.radius), 'full');
494
+ // Icon
495
+ icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : []));
496
+ iconPosition = input('left', ...(ngDevMode ? [{ debugName: "iconPosition" }] : []));
497
+ // Dot indicator
498
+ dot = input(false, ...(ngDevMode ? [{ debugName: "dot" }] : []));
499
+ dotColor = input(...(ngDevMode ? [undefined, { debugName: "dotColor" }] : []));
500
+ // Removable
501
+ removable = input(false, ...(ngDevMode ? [{ debugName: "removable" }] : []));
502
+ removed = output();
503
+ // Clickable & Navigation
504
+ href = input(...(ngDevMode ? [undefined, { debugName: "href" }] : []));
505
+ target = input('_self', ...(ngDevMode ? [{ debugName: "target" }] : []));
506
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
507
+ clicked = output();
508
+ // Number badge
509
+ value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
510
+ max = input(...(ngDevMode ? [undefined, { debugName: "max" }] : []));
511
+ showZero = input(true, ...(ngDevMode ? [{ debugName: "showZero" }] : []));
512
+ // Typography
513
+ uppercase = input(false, ...(ngDevMode ? [{ debugName: "uppercase" }] : []));
514
+ bold = input(false, ...(ngDevMode ? [{ debugName: "bold" }] : []));
515
+ // Animation
516
+ pulse = input(false, ...(ngDevMode ? [{ debugName: "pulse" }] : []));
517
+ // Auto color (будет реализовано позже если нужно)
518
+ autoColor = input(false, ...(ngDevMode ? [{ debugName: "autoColor" }] : []));
519
+ iconSize = computed(() => {
520
+ const sizeMap = { sm: 12, md: 14, lg: 16 };
521
+ return sizeMap[this.size()];
522
+ }, ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
523
+ displayValue = computed(() => {
524
+ const val = this.value();
525
+ if (val === undefined || val === null)
526
+ return '';
527
+ const numVal = typeof val === 'number' ? val : parseInt(val, 10);
528
+ // Если это число
529
+ if (!isNaN(numVal)) {
530
+ // Не показывать 0 если showZero = false
531
+ if (numVal === 0 && !this.showZero())
532
+ return '';
533
+ // Показать max+ если превышает максимум
534
+ const maxVal = this.max();
535
+ if (maxVal !== undefined && numVal > maxVal) {
536
+ return `${maxVal}+`;
537
+ }
538
+ return numVal.toString();
539
+ }
540
+ return val.toString();
541
+ }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
542
+ isVisible = computed(() => {
543
+ // Скрыть если значение 0 и showZero = false
544
+ const val = this.value();
545
+ if (val !== undefined && val !== null) {
546
+ const numVal = typeof val === 'number' ? val : parseInt(val, 10);
547
+ if (!isNaN(numVal) && numVal === 0 && !this.showZero()) {
548
+ return false;
549
+ }
550
+ }
551
+ return true;
552
+ }, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
553
+ hostClasses = computed(() => classNames('studio-badge', `studio-badge--${this.variant()}`, `studio-badge--${this.size()}`, `studio-badge--${this.color()}`, `studio-badge--radius-${this.radius()}`, this.disabled() && 'studio-badge--disabled', this.uppercase() && 'studio-badge--uppercase', this.bold() && 'studio-badge--bold', this.pulse() && 'studio-badge--pulse', this.href() && 'studio-badge--clickable'), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
554
+ handleClick(event) {
555
+ if (this.disabled()) {
556
+ event.preventDefault();
557
+ event.stopPropagation();
558
+ return;
559
+ }
560
+ // Handle link navigation
561
+ const url = this.href();
562
+ if (url) {
563
+ const safeUrl = sanitizeUrl(url);
564
+ if (safeUrl === '#') {
565
+ // URL was blocked - don't navigate
566
+ return;
567
+ }
568
+ const target = this.target();
569
+ if (target === '_blank') {
570
+ window.open(safeUrl, '_blank', 'noopener,noreferrer');
571
+ }
572
+ else {
573
+ window.location.href = safeUrl;
574
+ }
575
+ }
576
+ this.clicked.emit(event);
577
+ }
578
+ handleRemove(event) {
579
+ event.preventDefault();
580
+ event.stopPropagation();
581
+ if (this.disabled())
582
+ return;
583
+ this.removed.emit();
584
+ }
585
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: BadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
586
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: BadgeComponent, isStandalone: true, selector: "studio-badge", inputs: { variantInput: { classPropertyName: "variantInput", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, sizeInput: { classPropertyName: "sizeInput", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, colorInput: { classPropertyName: "colorInput", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, radiusInput: { classPropertyName: "radiusInput", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null }, dot: { classPropertyName: "dot", publicName: "dot", isSignal: true, isRequired: false, transformFunction: null }, dotColor: { classPropertyName: "dotColor", publicName: "dotColor", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, showZero: { classPropertyName: "showZero", publicName: "showZero", isSignal: true, isRequired: false, transformFunction: null }, uppercase: { classPropertyName: "uppercase", publicName: "uppercase", isSignal: true, isRequired: false, transformFunction: null }, bold: { classPropertyName: "bold", publicName: "bold", isSignal: true, isRequired: false, transformFunction: null }, pulse: { classPropertyName: "pulse", publicName: "pulse", isSignal: true, isRequired: false, transformFunction: null }, autoColor: { classPropertyName: "autoColor", publicName: "autoColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed", clicked: "clicked" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null", "attr.href": "href()", "attr.target": "href() ? target() : null", "attr.rel": "href() && target() === \"_blank\" ? \"noopener noreferrer\" : null", "style.display": "isVisible() ? null : \"none\"" } }, ngImport: i0, template: `
587
+ <span class="studio-badge__content">
588
+ @if (dot()) {
589
+ <span
590
+ class="studio-badge__dot"
591
+ [class]="'studio-badge__dot--' + (dotColor() || color())"
592
+ ></span>
593
+ }
594
+ @if (icon() && iconPosition() === 'left') {
595
+ <studio-icon [name]="icon()!" [size]="iconSize()" />
596
+ }
597
+ <span class="studio-badge__text">
598
+ @if (displayValue()) {
599
+ {{ displayValue() }}
600
+ } @else {
601
+ <ng-content />
602
+ }
603
+ </span>
604
+ @if (icon() && iconPosition() === 'right') {
605
+ <studio-icon [name]="icon()!" [size]="iconSize()" />
606
+ }
607
+ @if (removable()) {
608
+ <button
609
+ type="button"
610
+ class="studio-badge__remove"
611
+ (click)="handleRemove($event)"
612
+ aria-label="Remove"
613
+ >
614
+ <studio-icon name="x" [size]="iconSize()" />
615
+ </button>
616
+ }
617
+ </span>
618
+ `, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;font-family:var(--studio-font-family);font-weight:var(--studio-badge-font-weight, 500);line-height:1;white-space:nowrap;transition:all .2s ease;cursor:default;-webkit-user-select:none;user-select:none}.studio-badge__content{display:inline-flex;align-items:center;gap:var(--studio-badge-gap);padding:var(--studio-badge-padding-y) var(--studio-badge-padding-x);border-radius:var(--studio-badge-radius);background:var(--studio-badge-bg);color:var(--studio-badge-color);border:var(--studio-badge-border-width, 1px) solid var(--studio-badge-border-color, transparent);font-size:var(--studio-badge-font-size)}.studio-badge__text{display:inline-block}.studio-badge__dot{width:var(--studio-badge-dot-size, 6px);height:var(--studio-badge-dot-size, 6px);border-radius:50%;background:var(--studio-badge-dot-bg);flex-shrink:0}.studio-badge__remove{all:unset;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;opacity:.7;transition:opacity .2s ease}.studio-badge__remove:hover{opacity:1}.studio-badge__remove:focus-visible{outline:2px solid currentColor;outline-offset:2px;border-radius:2px}:host(.studio-badge--solid){--studio-badge-bg: var(--studio-primary);--studio-badge-color: white}:host(.studio-badge--solid).studio-badge--primary{--studio-badge-bg: var(--studio-primary)}:host(.studio-badge--solid).studio-badge--secondary{--studio-badge-bg: var(--studio-secondary)}:host(.studio-badge--solid).studio-badge--success{--studio-badge-bg: var(--studio-success)}:host(.studio-badge--solid).studio-badge--error{--studio-badge-bg: var(--studio-error)}:host(.studio-badge--solid).studio-badge--warning{--studio-badge-bg: var(--studio-warning)}:host(.studio-badge--solid).studio-badge--info{--studio-badge-bg: var(--studio-info)}:host(.studio-badge--solid).studio-badge--neutral{--studio-badge-bg: var(--studio-border-secondary);--studio-badge-color: var(--studio-text-primary)}:host(.studio-badge--outline){--studio-badge-bg: transparent;--studio-badge-color: var(--studio-primary);--studio-badge-border-color: var(--studio-primary)}:host(.studio-badge--outline).studio-badge--primary{--studio-badge-color: var(--studio-primary);--studio-badge-border-color: var(--studio-primary)}:host(.studio-badge--outline).studio-badge--secondary{--studio-badge-color: var(--studio-secondary);--studio-badge-border-color: var(--studio-secondary)}:host(.studio-badge--outline).studio-badge--success{--studio-badge-color: var(--studio-success);--studio-badge-border-color: var(--studio-success)}:host(.studio-badge--outline).studio-badge--error{--studio-badge-color: var(--studio-error);--studio-badge-border-color: var(--studio-error)}:host(.studio-badge--outline).studio-badge--warning{--studio-badge-color: var(--studio-warning);--studio-badge-border-color: var(--studio-warning)}:host(.studio-badge--outline).studio-badge--info{--studio-badge-color: var(--studio-info);--studio-badge-border-color: var(--studio-info)}:host(.studio-badge--outline).studio-badge--neutral{--studio-badge-color: var(--studio-text-secondary);--studio-badge-border-color: var(--studio-border-secondary)}:host(.studio-badge--soft){--studio-badge-bg: rgba(124, 58, 237, .1);--studio-badge-color: var(--studio-primary)}:host(.studio-badge--soft).studio-badge--primary{--studio-badge-bg: rgba(124, 58, 237, .1);--studio-badge-color: var(--studio-primary)}:host(.studio-badge--soft).studio-badge--secondary{--studio-badge-bg: rgba(99, 102, 241, .1);--studio-badge-color: var(--studio-secondary)}:host(.studio-badge--soft).studio-badge--success{--studio-badge-bg: var(--studio-success-bg);--studio-badge-color: var(--studio-success)}:host(.studio-badge--soft).studio-badge--error{--studio-badge-bg: var(--studio-error-bg);--studio-badge-color: var(--studio-error)}:host(.studio-badge--soft).studio-badge--warning{--studio-badge-bg: var(--studio-warning-bg);--studio-badge-color: var(--studio-warning)}:host(.studio-badge--soft).studio-badge--info{--studio-badge-bg: var(--studio-info-bg);--studio-badge-color: var(--studio-info)}:host(.studio-badge--soft).studio-badge--neutral{--studio-badge-bg: var(--studio-bg-secondary);--studio-badge-color: var(--studio-text-secondary)}:host(.studio-badge--dot){--studio-badge-bg: transparent;--studio-badge-color: var(--studio-text-primary);--studio-badge-border-width: 0}:host(.studio-badge--sm){--studio-badge-padding-y: .125rem;--studio-badge-padding-x: .5rem;--studio-badge-font-size: .6875rem;--studio-badge-gap: .25rem}:host(.studio-badge--md){--studio-badge-padding-y: .25rem;--studio-badge-padding-x: .625rem;--studio-badge-font-size: .75rem;--studio-badge-gap: .375rem}:host(.studio-badge--lg){--studio-badge-padding-y: .375rem;--studio-badge-padding-x: .75rem;--studio-badge-font-size: .875rem;--studio-badge-gap: .5rem}:host(.studio-badge--radius-sm){--studio-badge-radius: 2px}:host(.studio-badge--radius-md){--studio-badge-radius: 4px}:host(.studio-badge--radius-lg){--studio-badge-radius: 8px}:host(.studio-badge--radius-full){--studio-badge-radius: 9999px}.studio-badge__dot--primary{--studio-badge-dot-bg: var(--studio-primary)}.studio-badge__dot--secondary{--studio-badge-dot-bg: var(--studio-secondary)}.studio-badge__dot--success{--studio-badge-dot-bg: var(--studio-success)}.studio-badge__dot--error{--studio-badge-dot-bg: var(--studio-error)}.studio-badge__dot--warning{--studio-badge-dot-bg: var(--studio-warning)}.studio-badge__dot--info{--studio-badge-dot-bg: var(--studio-info)}.studio-badge__dot--neutral{--studio-badge-dot-bg: var(--studio-text-secondary)}:host(.studio-badge--clickable){cursor:pointer}:host(.studio-badge--clickable):hover{opacity:.9;transform:translateY(-1px)}:host(.studio-badge--clickable):active{transform:translateY(0)}:host(.studio-badge--disabled){opacity:.5;cursor:not-allowed;pointer-events:none}:host(.studio-badge--uppercase){text-transform:uppercase;letter-spacing:.5px}:host(.studio-badge--bold){--studio-badge-font-weight: 600}@keyframes badge-pulse{0%,to{opacity:1}50%{opacity:.5}}:host(.studio-badge--pulse) .studio-badge__dot{animation:badge-pulse 2s cubic-bezier(.4,0,.6,1) infinite}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "studio-icon", inputs: ["name", "size", "color", "strokeWidth", "absoluteStrokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
619
+ }
620
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: BadgeComponent, decorators: [{
621
+ type: Component,
622
+ args: [{ selector: 'studio-badge', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
623
+ '[class]': 'hostClasses()',
624
+ '[attr.disabled]': 'disabled() ? "" : null',
625
+ '[attr.href]': 'href()',
626
+ '[attr.target]': 'href() ? target() : null',
627
+ '[attr.rel]': 'href() && target() === "_blank" ? "noopener noreferrer" : null',
628
+ '[style.display]': 'isVisible() ? null : "none"',
629
+ '(click)': 'handleClick($event)'
630
+ }, template: `
631
+ <span class="studio-badge__content">
632
+ @if (dot()) {
633
+ <span
634
+ class="studio-badge__dot"
635
+ [class]="'studio-badge__dot--' + (dotColor() || color())"
636
+ ></span>
637
+ }
638
+ @if (icon() && iconPosition() === 'left') {
639
+ <studio-icon [name]="icon()!" [size]="iconSize()" />
640
+ }
641
+ <span class="studio-badge__text">
642
+ @if (displayValue()) {
643
+ {{ displayValue() }}
644
+ } @else {
645
+ <ng-content />
646
+ }
647
+ </span>
648
+ @if (icon() && iconPosition() === 'right') {
649
+ <studio-icon [name]="icon()!" [size]="iconSize()" />
650
+ }
651
+ @if (removable()) {
652
+ <button
653
+ type="button"
654
+ class="studio-badge__remove"
655
+ (click)="handleRemove($event)"
656
+ aria-label="Remove"
657
+ >
658
+ <studio-icon name="x" [size]="iconSize()" />
659
+ </button>
660
+ }
661
+ </span>
662
+ `, styles: [":host{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;font-family:var(--studio-font-family);font-weight:var(--studio-badge-font-weight, 500);line-height:1;white-space:nowrap;transition:all .2s ease;cursor:default;-webkit-user-select:none;user-select:none}.studio-badge__content{display:inline-flex;align-items:center;gap:var(--studio-badge-gap);padding:var(--studio-badge-padding-y) var(--studio-badge-padding-x);border-radius:var(--studio-badge-radius);background:var(--studio-badge-bg);color:var(--studio-badge-color);border:var(--studio-badge-border-width, 1px) solid var(--studio-badge-border-color, transparent);font-size:var(--studio-badge-font-size)}.studio-badge__text{display:inline-block}.studio-badge__dot{width:var(--studio-badge-dot-size, 6px);height:var(--studio-badge-dot-size, 6px);border-radius:50%;background:var(--studio-badge-dot-bg);flex-shrink:0}.studio-badge__remove{all:unset;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;opacity:.7;transition:opacity .2s ease}.studio-badge__remove:hover{opacity:1}.studio-badge__remove:focus-visible{outline:2px solid currentColor;outline-offset:2px;border-radius:2px}:host(.studio-badge--solid){--studio-badge-bg: var(--studio-primary);--studio-badge-color: white}:host(.studio-badge--solid).studio-badge--primary{--studio-badge-bg: var(--studio-primary)}:host(.studio-badge--solid).studio-badge--secondary{--studio-badge-bg: var(--studio-secondary)}:host(.studio-badge--solid).studio-badge--success{--studio-badge-bg: var(--studio-success)}:host(.studio-badge--solid).studio-badge--error{--studio-badge-bg: var(--studio-error)}:host(.studio-badge--solid).studio-badge--warning{--studio-badge-bg: var(--studio-warning)}:host(.studio-badge--solid).studio-badge--info{--studio-badge-bg: var(--studio-info)}:host(.studio-badge--solid).studio-badge--neutral{--studio-badge-bg: var(--studio-border-secondary);--studio-badge-color: var(--studio-text-primary)}:host(.studio-badge--outline){--studio-badge-bg: transparent;--studio-badge-color: var(--studio-primary);--studio-badge-border-color: var(--studio-primary)}:host(.studio-badge--outline).studio-badge--primary{--studio-badge-color: var(--studio-primary);--studio-badge-border-color: var(--studio-primary)}:host(.studio-badge--outline).studio-badge--secondary{--studio-badge-color: var(--studio-secondary);--studio-badge-border-color: var(--studio-secondary)}:host(.studio-badge--outline).studio-badge--success{--studio-badge-color: var(--studio-success);--studio-badge-border-color: var(--studio-success)}:host(.studio-badge--outline).studio-badge--error{--studio-badge-color: var(--studio-error);--studio-badge-border-color: var(--studio-error)}:host(.studio-badge--outline).studio-badge--warning{--studio-badge-color: var(--studio-warning);--studio-badge-border-color: var(--studio-warning)}:host(.studio-badge--outline).studio-badge--info{--studio-badge-color: var(--studio-info);--studio-badge-border-color: var(--studio-info)}:host(.studio-badge--outline).studio-badge--neutral{--studio-badge-color: var(--studio-text-secondary);--studio-badge-border-color: var(--studio-border-secondary)}:host(.studio-badge--soft){--studio-badge-bg: rgba(124, 58, 237, .1);--studio-badge-color: var(--studio-primary)}:host(.studio-badge--soft).studio-badge--primary{--studio-badge-bg: rgba(124, 58, 237, .1);--studio-badge-color: var(--studio-primary)}:host(.studio-badge--soft).studio-badge--secondary{--studio-badge-bg: rgba(99, 102, 241, .1);--studio-badge-color: var(--studio-secondary)}:host(.studio-badge--soft).studio-badge--success{--studio-badge-bg: var(--studio-success-bg);--studio-badge-color: var(--studio-success)}:host(.studio-badge--soft).studio-badge--error{--studio-badge-bg: var(--studio-error-bg);--studio-badge-color: var(--studio-error)}:host(.studio-badge--soft).studio-badge--warning{--studio-badge-bg: var(--studio-warning-bg);--studio-badge-color: var(--studio-warning)}:host(.studio-badge--soft).studio-badge--info{--studio-badge-bg: var(--studio-info-bg);--studio-badge-color: var(--studio-info)}:host(.studio-badge--soft).studio-badge--neutral{--studio-badge-bg: var(--studio-bg-secondary);--studio-badge-color: var(--studio-text-secondary)}:host(.studio-badge--dot){--studio-badge-bg: transparent;--studio-badge-color: var(--studio-text-primary);--studio-badge-border-width: 0}:host(.studio-badge--sm){--studio-badge-padding-y: .125rem;--studio-badge-padding-x: .5rem;--studio-badge-font-size: .6875rem;--studio-badge-gap: .25rem}:host(.studio-badge--md){--studio-badge-padding-y: .25rem;--studio-badge-padding-x: .625rem;--studio-badge-font-size: .75rem;--studio-badge-gap: .375rem}:host(.studio-badge--lg){--studio-badge-padding-y: .375rem;--studio-badge-padding-x: .75rem;--studio-badge-font-size: .875rem;--studio-badge-gap: .5rem}:host(.studio-badge--radius-sm){--studio-badge-radius: 2px}:host(.studio-badge--radius-md){--studio-badge-radius: 4px}:host(.studio-badge--radius-lg){--studio-badge-radius: 8px}:host(.studio-badge--radius-full){--studio-badge-radius: 9999px}.studio-badge__dot--primary{--studio-badge-dot-bg: var(--studio-primary)}.studio-badge__dot--secondary{--studio-badge-dot-bg: var(--studio-secondary)}.studio-badge__dot--success{--studio-badge-dot-bg: var(--studio-success)}.studio-badge__dot--error{--studio-badge-dot-bg: var(--studio-error)}.studio-badge__dot--warning{--studio-badge-dot-bg: var(--studio-warning)}.studio-badge__dot--info{--studio-badge-dot-bg: var(--studio-info)}.studio-badge__dot--neutral{--studio-badge-dot-bg: var(--studio-text-secondary)}:host(.studio-badge--clickable){cursor:pointer}:host(.studio-badge--clickable):hover{opacity:.9;transform:translateY(-1px)}:host(.studio-badge--clickable):active{transform:translateY(0)}:host(.studio-badge--disabled){opacity:.5;cursor:not-allowed;pointer-events:none}:host(.studio-badge--uppercase){text-transform:uppercase;letter-spacing:.5px}:host(.studio-badge--bold){--studio-badge-font-weight: 600}@keyframes badge-pulse{0%,to{opacity:1}50%{opacity:.5}}:host(.studio-badge--pulse) .studio-badge__dot{animation:badge-pulse 2s cubic-bezier(.4,0,.6,1) infinite}\n"] }]
663
+ }], propDecorators: { variantInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], sizeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], colorInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], radiusInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], dot: [{ type: i0.Input, args: [{ isSignal: true, alias: "dot", required: false }] }], dotColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "dotColor", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], showZero: [{ type: i0.Input, args: [{ isSignal: true, alias: "showZero", required: false }] }], uppercase: [{ type: i0.Input, args: [{ isSignal: true, alias: "uppercase", required: false }] }], bold: [{ type: i0.Input, args: [{ isSignal: true, alias: "bold", required: false }] }], pulse: [{ type: i0.Input, args: [{ isSignal: true, alias: "pulse", required: false }] }], autoColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoColor", required: false }] }] } });
664
+
665
+ /**
666
+ * Badge component
667
+ */
668
+
371
669
  class ButtonComponent {
372
- variant = input('solid', ...(ngDevMode ? [{ debugName: "variant" }] : []));
373
- size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
374
- color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : []));
670
+ configService = inject(StudioConfigService);
671
+ buttonDefaults = computed(() => this.configService.config().components?.button, ...(ngDevMode ? [{ debugName: "buttonDefaults" }] : []));
672
+ // Appearance - inputs
673
+ variantInput = input(undefined, ...(ngDevMode ? [{ debugName: "variantInput", alias: 'variant' }] : [{ alias: 'variant' }]));
674
+ sizeInput = input(undefined, ...(ngDevMode ? [{ debugName: "sizeInput", alias: 'size' }] : [{ alias: 'size' }]));
675
+ colorInput = input(undefined, ...(ngDevMode ? [{ debugName: "colorInput", alias: 'color' }] : [{ alias: 'color' }]));
676
+ radiusInput = input(undefined, ...(ngDevMode ? [{ debugName: "radiusInput", alias: 'radius' }] : [{ alias: 'radius' }]));
677
+ shadowInput = input(undefined, ...(ngDevMode ? [{ debugName: "shadowInput", alias: 'shadow' }] : [{ alias: 'shadow' }]));
678
+ compactInput = input(undefined, ...(ngDevMode ? [{ debugName: "compactInput", alias: 'compact' }] : [{ alias: 'compact' }]));
679
+ // Values with config defaults
680
+ variant = withConfigDefault(this.variantInput, computed(() => this.buttonDefaults()?.variant), 'solid');
681
+ size = withConfigDefault(this.sizeInput, computed(() => this.buttonDefaults()?.size), 'md');
682
+ color = withConfigDefault(this.colorInput, computed(() => this.buttonDefaults()?.color), 'primary');
683
+ radius = withConfigDefault(this.radiusInput, computed(() => this.buttonDefaults()?.radius), 'sm');
684
+ shadow = withConfigDefault(this.shadowInput, computed(() => this.buttonDefaults()?.shadow), 'none');
685
+ compact = withConfigDefault(this.compactInput, computed(() => this.buttonDefaults()?.compact), false);
686
+ // State
375
687
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
376
- fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : []));
377
688
  loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
689
+ loadingText = input('Loading...', ...(ngDevMode ? [{ debugName: "loadingText" }] : []));
690
+ // Layout
691
+ fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : []));
692
+ // Button props
378
693
  type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : []));
694
+ // Icon
379
695
  icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : []));
380
696
  iconPosition = input('left', ...(ngDevMode ? [{ debugName: "iconPosition" }] : []));
697
+ // Link mode
698
+ href = input(...(ngDevMode ? [undefined, { debugName: "href" }] : []));
699
+ target = input('_self', ...(ngDevMode ? [{ debugName: "target" }] : []));
700
+ // Badge
701
+ badge = input(...(ngDevMode ? [undefined, { debugName: "badge" }] : []));
702
+ badgeColor = input('error', ...(ngDevMode ? [{ debugName: "badgeColor" }] : []));
703
+ // Accessibility
704
+ ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : []));
381
705
  clicked = output();
382
706
  iconSize = computed(() => {
383
707
  const sizeMap = { sm: 16, md: 18, lg: 20 };
384
708
  return sizeMap[this.size()];
385
709
  }, ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
386
- hostClasses = computed(() => {
387
- return [
388
- 'studio-button',
389
- `studio-button--${this.variant()}`,
390
- `studio-button--${this.size()}`,
391
- `studio-button--${this.color()}`,
392
- this.fullWidth() ? 'studio-button--full' : '',
393
- this.loading() ? 'studio-button--loading' : '',
394
- this.iconPosition() === 'only' ? 'studio-button--icon-only' : ''
395
- ].filter(Boolean).join(' ');
396
- }, ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
710
+ hostClasses = computed(() => classNames('studio-button', `studio-button--${this.variant()}`, `studio-button--${this.size()}`, `studio-button--${this.color()}`, `studio-button--radius-${this.radius()}`, `studio-button--shadow-${this.shadow()}`, this.compact() && 'studio-button--compact', this.fullWidth() && 'studio-button--full', this.loading() && 'studio-button--loading', this.iconPosition() === 'only' && 'studio-button--icon-only'), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
397
711
  handleClick(event) {
398
712
  if (this.disabled() || this.loading()) {
399
713
  event.preventDefault();
400
714
  event.stopPropagation();
401
715
  return;
402
716
  }
717
+ // Handle link navigation
718
+ const url = this.href();
719
+ if (url) {
720
+ const safeUrl = sanitizeUrl(url);
721
+ if (safeUrl === '#') {
722
+ // URL was blocked - don't navigate
723
+ return;
724
+ }
725
+ const target = this.target();
726
+ if (target === '_blank') {
727
+ window.open(safeUrl, '_blank', 'noopener,noreferrer');
728
+ }
729
+ else {
730
+ window.location.href = safeUrl;
731
+ }
732
+ }
403
733
  this.clicked.emit(event);
404
734
  }
405
735
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
406
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: ButtonComponent, isStandalone: true, selector: "studio-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() || loading() ? \"\" : null", "attr.type": "type()" } }, ngImport: i0, template: `
736
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: ButtonComponent, isStandalone: true, selector: "studio-button", inputs: { variantInput: { classPropertyName: "variantInput", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, sizeInput: { classPropertyName: "sizeInput", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, colorInput: { classPropertyName: "colorInput", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, radiusInput: { classPropertyName: "radiusInput", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, shadowInput: { classPropertyName: "shadowInput", publicName: "shadow", isSignal: true, isRequired: false, transformFunction: null }, compactInput: { classPropertyName: "compactInput", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, badgeColor: { classPropertyName: "badgeColor", publicName: "badgeColor", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() || loading() ? \"\" : null", "attr.type": "href() ? null : type()", "attr.href": "href()", "attr.target": "href() ? target() : null", "attr.rel": "href() && target() === \"_blank\" ? \"noopener noreferrer\" : null", "attr.aria-label": "ariaLabel()" } }, ngImport: i0, template: `
407
737
  <span class="studio-button__content">
408
738
  @if (loading()) {
409
739
  <studio-icon
@@ -427,17 +757,26 @@ class ButtonComponent {
427
757
  @if (loading() && iconPosition() === 'only') {
428
758
  <!-- Empty, spinner already shown -->
429
759
  } @else if (loading()) {
430
- <span>Loading...</span>
760
+ <span>{{ loadingText() }}</span>
761
+ }
762
+ @if (badge() !== undefined && badge() !== null && badge() !== '') {
763
+ <span class="studio-button__badge studio-button__badge--{{ badgeColor() }}">
764
+ {{ badge() }}
765
+ </span>
431
766
  }
432
767
  </span>
433
- `, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--studio-spacing-sm);font-family:var(--studio-font-family);font-weight:var(--studio-font-weight-medium);border:none;cursor:pointer;-webkit-user-select:none;user-select:none;position:relative;white-space:nowrap;vertical-align:middle;border-radius:var(--studio-radius-md);transition:background-color var(--studio-transition-fast),color var(--studio-transition-fast),border-color var(--studio-transition-fast),box-shadow var(--studio-transition-fast),transform var(--studio-transition-fast)}:host:focus-visible{outline:2px solid var(--studio-primary);outline-offset:2px}:host(.studio-button--sm){padding:var(--studio-spacing-xs) var(--studio-spacing-sm);font-size:var(--studio-font-size-sm);height:2rem;min-width:2rem}:host(.studio-button--md){padding:var(--studio-spacing-sm) var(--studio-spacing-md);font-size:var(--studio-font-size-base);height:2.5rem;min-width:2.5rem}:host(.studio-button--lg){padding:var(--studio-spacing-md) var(--studio-spacing-lg);font-size:var(--studio-font-size-lg);height:3rem;min-width:3rem}:host(.studio-button--solid.studio-button--primary){background:var(--studio-primary);color:#fff}:host(.studio-button--solid.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary-hover)}:host(.studio-button--outline.studio-button--primary){background:transparent;border:1px solid var(--studio-primary);color:var(--studio-primary)}:host(.studio-button--outline.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary);color:#fff}:host(.studio-button--ghost.studio-button--primary){background:transparent;color:var(--studio-primary)}:host(.studio-button--ghost.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:#3b82f61a}:host(.studio-button--solid.studio-button--secondary){background:var(--studio-secondary);color:#fff}:host(.studio-button--solid.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary-hover)}:host(.studio-button--outline.studio-button--secondary){background:transparent;border:1px solid var(--studio-secondary);color:var(--studio-secondary)}:host(.studio-button--outline.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary);color:#fff}:host(.studio-button--ghost.studio-button--secondary){background:transparent;color:var(--studio-secondary)}:host(.studio-button--ghost.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:#8b5cf61a}:host(.studio-button--solid.studio-button--success){background:var(--studio-success);color:#fff}:host(.studio-button--solid.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-hover)}:host(.studio-button--outline.studio-button--success){background:transparent;border:1px solid var(--studio-success);color:var(--studio-success)}:host(.studio-button--outline.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success);color:#fff}:host(.studio-button--ghost.studio-button--success){background:transparent;color:var(--studio-success)}:host(.studio-button--ghost.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-bg)}:host(.studio-button--solid.studio-button--error){background:var(--studio-error);color:#fff}:host(.studio-button--solid.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-hover)}:host(.studio-button--outline.studio-button--error){background:transparent;border:1px solid var(--studio-error);color:var(--studio-error)}:host(.studio-button--outline.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error);color:#fff}:host(.studio-button--ghost.studio-button--error){background:transparent;color:var(--studio-error)}:host(.studio-button--ghost.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-bg)}:host(.studio-button--solid.studio-button--warning){background:var(--studio-warning);color:#fff}:host(.studio-button--solid.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-hover)}:host(.studio-button--outline.studio-button--warning){background:transparent;border:1px solid var(--studio-warning);color:var(--studio-warning)}:host(.studio-button--outline.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning);color:#fff}:host(.studio-button--ghost.studio-button--warning){background:transparent;color:var(--studio-warning)}:host(.studio-button--ghost.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-bg)}:host(.studio-button--full){width:100%}:host(.studio-button--icon-only){padding:0;aspect-ratio:1}:host(.studio-button--icon-only.studio-button--sm){width:2rem;padding:0}:host(.studio-button--icon-only.studio-button--md){width:2.5rem;padding:0}:host(.studio-button--icon-only.studio-button--lg){width:3rem;padding:0}:host(.studio-button--loading){cursor:wait;pointer-events:none}:host([disabled]){opacity:.6;cursor:not-allowed!important;background:var(--studio-bg-secondary)!important;color:var(--studio-text-tertiary)!important;border-color:var(--studio-border-primary)!important}:host([disabled]:hover){transform:none!important;background:var(--studio-bg-secondary)!important}:host(:active:not([disabled]):not(.studio-button--loading)){transform:scale(.98)}.studio-button__content{display:inline-flex;align-items:center;gap:var(--studio-spacing-sm)}.studio-button__spinner{animation:studio-spin 1s linear infinite}@keyframes studio-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "studio-icon", inputs: ["name", "size", "color", "strokeWidth", "absoluteStrokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
768
+ `, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--studio-spacing-sm);font-family:var(--studio-font-family);font-weight:var(--studio-font-weight-medium);border:none;cursor:pointer;-webkit-user-select:none;user-select:none;position:relative;white-space:nowrap;vertical-align:middle;transition:background-color var(--studio-transition-fast),color var(--studio-transition-fast),border-color var(--studio-transition-fast),box-shadow var(--studio-transition-fast),transform var(--studio-transition-fast)}:host:focus-visible{outline:2px solid var(--studio-primary);outline-offset:2px}:host(.studio-button--sm){padding:var(--studio-spacing-xs) var(--studio-spacing-sm);font-size:var(--studio-font-size-sm);height:2rem;min-width:2rem}:host(.studio-button--md){padding:var(--studio-spacing-sm) var(--studio-spacing-md);font-size:var(--studio-font-size-base);height:2.5rem;min-width:2.5rem}:host(.studio-button--lg){padding:var(--studio-spacing-md) var(--studio-spacing-lg);font-size:var(--studio-font-size-lg);height:3rem;min-width:3rem}:host(.studio-button--radius-none){border-radius:var(--studio-radius-none)}:host(.studio-button--radius-sm){border-radius:var(--studio-radius-sm)}:host(.studio-button--radius-md){border-radius:var(--studio-radius-md)}:host(.studio-button--radius-lg){border-radius:var(--studio-radius-lg)}:host(.studio-button--radius-xl){border-radius:var(--studio-radius-xl)}:host(.studio-button--radius-full){border-radius:var(--studio-radius-full)}:host(.studio-button--shadow-none){box-shadow:none}:host(.studio-button--shadow-sm){box-shadow:var(--studio-shadow-sm)}:host(.studio-button--shadow-md){box-shadow:var(--studio-shadow-md)}:host(.studio-button--shadow-lg){box-shadow:var(--studio-shadow-lg)}:host(.studio-button--compact.studio-button--sm){padding:var(--studio-spacing-xs) var(--studio-spacing-sm);height:1.75rem;min-width:1.75rem;font-size:.813rem}:host(.studio-button--compact.studio-button--md){padding:var(--studio-spacing-sm) var(--studio-spacing-md);height:2rem;min-width:2rem;font-size:.875rem}:host(.studio-button--compact.studio-button--lg){padding:var(--studio-spacing-sm) var(--studio-spacing-lg);height:2.5rem;min-width:2.5rem;font-size:1rem}:host(.studio-button--solid.studio-button--primary){background:var(--studio-primary);color:#fff}:host(.studio-button--solid.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary-hover)}:host(.studio-button--outline.studio-button--primary){background:transparent;border:1px solid var(--studio-primary);color:var(--studio-primary)}:host(.studio-button--outline.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary);color:#fff}:host(.studio-button--ghost.studio-button--primary){background:transparent;color:var(--studio-primary)}:host(.studio-button--ghost.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:#3b82f61a}:host(.studio-button--solid.studio-button--secondary){background:var(--studio-secondary);color:#fff}:host(.studio-button--solid.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary-hover)}:host(.studio-button--outline.studio-button--secondary){background:transparent;border:1px solid var(--studio-secondary);color:var(--studio-secondary)}:host(.studio-button--outline.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary);color:#fff}:host(.studio-button--ghost.studio-button--secondary){background:transparent;color:var(--studio-secondary)}:host(.studio-button--ghost.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:#8b5cf61a}:host(.studio-button--solid.studio-button--success){background:var(--studio-success);color:#fff}:host(.studio-button--solid.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-hover)}:host(.studio-button--outline.studio-button--success){background:transparent;border:1px solid var(--studio-success);color:var(--studio-success)}:host(.studio-button--outline.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success);color:#fff}:host(.studio-button--ghost.studio-button--success){background:transparent;color:var(--studio-success)}:host(.studio-button--ghost.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-bg)}:host(.studio-button--solid.studio-button--error){background:var(--studio-error);color:#fff}:host(.studio-button--solid.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-hover)}:host(.studio-button--outline.studio-button--error){background:transparent;border:1px solid var(--studio-error);color:var(--studio-error)}:host(.studio-button--outline.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error);color:#fff}:host(.studio-button--ghost.studio-button--error){background:transparent;color:var(--studio-error)}:host(.studio-button--ghost.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-bg)}:host(.studio-button--solid.studio-button--warning){background:var(--studio-warning);color:#fff}:host(.studio-button--solid.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-hover)}:host(.studio-button--outline.studio-button--warning){background:transparent;border:1px solid var(--studio-warning);color:var(--studio-warning)}:host(.studio-button--outline.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning);color:#fff}:host(.studio-button--ghost.studio-button--warning){background:transparent;color:var(--studio-warning)}:host(.studio-button--ghost.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-bg)}:host(.studio-button--full){width:100%}:host(.studio-button--icon-only){padding:0;aspect-ratio:1}:host(.studio-button--icon-only.studio-button--sm){width:2rem;padding:0}:host(.studio-button--icon-only.studio-button--md){width:2.5rem;padding:0}:host(.studio-button--icon-only.studio-button--lg){width:3rem;padding:0}:host(.studio-button--loading){cursor:wait;pointer-events:none}:host([disabled]){opacity:.6;cursor:not-allowed!important;background:var(--studio-bg-secondary)!important;color:var(--studio-text-tertiary)!important;border-color:var(--studio-border-primary)!important}:host([disabled]:hover){transform:none!important;background:var(--studio-bg-secondary)!important}:host(:active:not([disabled]):not(.studio-button--loading)){transform:scale(.98)}.studio-button__content{display:inline-flex;align-items:center;gap:var(--studio-spacing-sm)}.studio-button__spinner{animation:studio-spin 1s linear infinite}@keyframes studio-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.studio-button__badge{position:absolute;top:-.375rem;right:-.375rem;display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .25rem;font-size:.625rem;font-weight:var(--studio-font-weight-semibold);line-height:1;color:#fff;border-radius:var(--studio-radius-full);box-shadow:0 0 0 2px var(--studio-bg-primary)}.studio-button__badge--primary{background:var(--studio-primary)}.studio-button__badge--error{background:var(--studio-error)}.studio-button__badge--warning{background:var(--studio-warning)}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "studio-icon", inputs: ["name", "size", "color", "strokeWidth", "absoluteStrokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
434
769
  }
435
770
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonComponent, decorators: [{
436
771
  type: Component,
437
772
  args: [{ selector: 'studio-button', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
438
773
  '[class]': 'hostClasses()',
439
774
  '[attr.disabled]': 'disabled() || loading() ? "" : null',
440
- '[attr.type]': 'type()',
775
+ '[attr.type]': 'href() ? null : type()',
776
+ '[attr.href]': 'href()',
777
+ '[attr.target]': 'href() ? target() : null',
778
+ '[attr.rel]': 'href() && target() === "_blank" ? "noopener noreferrer" : null',
779
+ '[attr.aria-label]': 'ariaLabel()',
441
780
  '(click)': 'handleClick($event)'
442
781
  }, template: `
443
782
  <span class="studio-button__content">
@@ -463,11 +802,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
463
802
  @if (loading() && iconPosition() === 'only') {
464
803
  <!-- Empty, spinner already shown -->
465
804
  } @else if (loading()) {
466
- <span>Loading...</span>
805
+ <span>{{ loadingText() }}</span>
806
+ }
807
+ @if (badge() !== undefined && badge() !== null && badge() !== '') {
808
+ <span class="studio-button__badge studio-button__badge--{{ badgeColor() }}">
809
+ {{ badge() }}
810
+ </span>
467
811
  }
468
812
  </span>
469
- `, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--studio-spacing-sm);font-family:var(--studio-font-family);font-weight:var(--studio-font-weight-medium);border:none;cursor:pointer;-webkit-user-select:none;user-select:none;position:relative;white-space:nowrap;vertical-align:middle;border-radius:var(--studio-radius-md);transition:background-color var(--studio-transition-fast),color var(--studio-transition-fast),border-color var(--studio-transition-fast),box-shadow var(--studio-transition-fast),transform var(--studio-transition-fast)}:host:focus-visible{outline:2px solid var(--studio-primary);outline-offset:2px}:host(.studio-button--sm){padding:var(--studio-spacing-xs) var(--studio-spacing-sm);font-size:var(--studio-font-size-sm);height:2rem;min-width:2rem}:host(.studio-button--md){padding:var(--studio-spacing-sm) var(--studio-spacing-md);font-size:var(--studio-font-size-base);height:2.5rem;min-width:2.5rem}:host(.studio-button--lg){padding:var(--studio-spacing-md) var(--studio-spacing-lg);font-size:var(--studio-font-size-lg);height:3rem;min-width:3rem}:host(.studio-button--solid.studio-button--primary){background:var(--studio-primary);color:#fff}:host(.studio-button--solid.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary-hover)}:host(.studio-button--outline.studio-button--primary){background:transparent;border:1px solid var(--studio-primary);color:var(--studio-primary)}:host(.studio-button--outline.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary);color:#fff}:host(.studio-button--ghost.studio-button--primary){background:transparent;color:var(--studio-primary)}:host(.studio-button--ghost.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:#3b82f61a}:host(.studio-button--solid.studio-button--secondary){background:var(--studio-secondary);color:#fff}:host(.studio-button--solid.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary-hover)}:host(.studio-button--outline.studio-button--secondary){background:transparent;border:1px solid var(--studio-secondary);color:var(--studio-secondary)}:host(.studio-button--outline.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary);color:#fff}:host(.studio-button--ghost.studio-button--secondary){background:transparent;color:var(--studio-secondary)}:host(.studio-button--ghost.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:#8b5cf61a}:host(.studio-button--solid.studio-button--success){background:var(--studio-success);color:#fff}:host(.studio-button--solid.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-hover)}:host(.studio-button--outline.studio-button--success){background:transparent;border:1px solid var(--studio-success);color:var(--studio-success)}:host(.studio-button--outline.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success);color:#fff}:host(.studio-button--ghost.studio-button--success){background:transparent;color:var(--studio-success)}:host(.studio-button--ghost.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-bg)}:host(.studio-button--solid.studio-button--error){background:var(--studio-error);color:#fff}:host(.studio-button--solid.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-hover)}:host(.studio-button--outline.studio-button--error){background:transparent;border:1px solid var(--studio-error);color:var(--studio-error)}:host(.studio-button--outline.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error);color:#fff}:host(.studio-button--ghost.studio-button--error){background:transparent;color:var(--studio-error)}:host(.studio-button--ghost.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-bg)}:host(.studio-button--solid.studio-button--warning){background:var(--studio-warning);color:#fff}:host(.studio-button--solid.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-hover)}:host(.studio-button--outline.studio-button--warning){background:transparent;border:1px solid var(--studio-warning);color:var(--studio-warning)}:host(.studio-button--outline.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning);color:#fff}:host(.studio-button--ghost.studio-button--warning){background:transparent;color:var(--studio-warning)}:host(.studio-button--ghost.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-bg)}:host(.studio-button--full){width:100%}:host(.studio-button--icon-only){padding:0;aspect-ratio:1}:host(.studio-button--icon-only.studio-button--sm){width:2rem;padding:0}:host(.studio-button--icon-only.studio-button--md){width:2.5rem;padding:0}:host(.studio-button--icon-only.studio-button--lg){width:3rem;padding:0}:host(.studio-button--loading){cursor:wait;pointer-events:none}:host([disabled]){opacity:.6;cursor:not-allowed!important;background:var(--studio-bg-secondary)!important;color:var(--studio-text-tertiary)!important;border-color:var(--studio-border-primary)!important}:host([disabled]:hover){transform:none!important;background:var(--studio-bg-secondary)!important}:host(:active:not([disabled]):not(.studio-button--loading)){transform:scale(.98)}.studio-button__content{display:inline-flex;align-items:center;gap:var(--studio-spacing-sm)}.studio-button__spinner{animation:studio-spin 1s linear infinite}@keyframes studio-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
470
- }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
813
+ `, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--studio-spacing-sm);font-family:var(--studio-font-family);font-weight:var(--studio-font-weight-medium);border:none;cursor:pointer;-webkit-user-select:none;user-select:none;position:relative;white-space:nowrap;vertical-align:middle;transition:background-color var(--studio-transition-fast),color var(--studio-transition-fast),border-color var(--studio-transition-fast),box-shadow var(--studio-transition-fast),transform var(--studio-transition-fast)}:host:focus-visible{outline:2px solid var(--studio-primary);outline-offset:2px}:host(.studio-button--sm){padding:var(--studio-spacing-xs) var(--studio-spacing-sm);font-size:var(--studio-font-size-sm);height:2rem;min-width:2rem}:host(.studio-button--md){padding:var(--studio-spacing-sm) var(--studio-spacing-md);font-size:var(--studio-font-size-base);height:2.5rem;min-width:2.5rem}:host(.studio-button--lg){padding:var(--studio-spacing-md) var(--studio-spacing-lg);font-size:var(--studio-font-size-lg);height:3rem;min-width:3rem}:host(.studio-button--radius-none){border-radius:var(--studio-radius-none)}:host(.studio-button--radius-sm){border-radius:var(--studio-radius-sm)}:host(.studio-button--radius-md){border-radius:var(--studio-radius-md)}:host(.studio-button--radius-lg){border-radius:var(--studio-radius-lg)}:host(.studio-button--radius-xl){border-radius:var(--studio-radius-xl)}:host(.studio-button--radius-full){border-radius:var(--studio-radius-full)}:host(.studio-button--shadow-none){box-shadow:none}:host(.studio-button--shadow-sm){box-shadow:var(--studio-shadow-sm)}:host(.studio-button--shadow-md){box-shadow:var(--studio-shadow-md)}:host(.studio-button--shadow-lg){box-shadow:var(--studio-shadow-lg)}:host(.studio-button--compact.studio-button--sm){padding:var(--studio-spacing-xs) var(--studio-spacing-sm);height:1.75rem;min-width:1.75rem;font-size:.813rem}:host(.studio-button--compact.studio-button--md){padding:var(--studio-spacing-sm) var(--studio-spacing-md);height:2rem;min-width:2rem;font-size:.875rem}:host(.studio-button--compact.studio-button--lg){padding:var(--studio-spacing-sm) var(--studio-spacing-lg);height:2.5rem;min-width:2.5rem;font-size:1rem}:host(.studio-button--solid.studio-button--primary){background:var(--studio-primary);color:#fff}:host(.studio-button--solid.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary-hover)}:host(.studio-button--outline.studio-button--primary){background:transparent;border:1px solid var(--studio-primary);color:var(--studio-primary)}:host(.studio-button--outline.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-primary);color:#fff}:host(.studio-button--ghost.studio-button--primary){background:transparent;color:var(--studio-primary)}:host(.studio-button--ghost.studio-button--primary:hover:not(:disabled):not(.studio-button--loading)){background:#3b82f61a}:host(.studio-button--solid.studio-button--secondary){background:var(--studio-secondary);color:#fff}:host(.studio-button--solid.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary-hover)}:host(.studio-button--outline.studio-button--secondary){background:transparent;border:1px solid var(--studio-secondary);color:var(--studio-secondary)}:host(.studio-button--outline.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-secondary);color:#fff}:host(.studio-button--ghost.studio-button--secondary){background:transparent;color:var(--studio-secondary)}:host(.studio-button--ghost.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading)){background:#8b5cf61a}:host(.studio-button--solid.studio-button--success){background:var(--studio-success);color:#fff}:host(.studio-button--solid.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-hover)}:host(.studio-button--outline.studio-button--success){background:transparent;border:1px solid var(--studio-success);color:var(--studio-success)}:host(.studio-button--outline.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success);color:#fff}:host(.studio-button--ghost.studio-button--success){background:transparent;color:var(--studio-success)}:host(.studio-button--ghost.studio-button--success:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-success-bg)}:host(.studio-button--solid.studio-button--error){background:var(--studio-error);color:#fff}:host(.studio-button--solid.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-hover)}:host(.studio-button--outline.studio-button--error){background:transparent;border:1px solid var(--studio-error);color:var(--studio-error)}:host(.studio-button--outline.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error);color:#fff}:host(.studio-button--ghost.studio-button--error){background:transparent;color:var(--studio-error)}:host(.studio-button--ghost.studio-button--error:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-error-bg)}:host(.studio-button--solid.studio-button--warning){background:var(--studio-warning);color:#fff}:host(.studio-button--solid.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-hover)}:host(.studio-button--outline.studio-button--warning){background:transparent;border:1px solid var(--studio-warning);color:var(--studio-warning)}:host(.studio-button--outline.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning);color:#fff}:host(.studio-button--ghost.studio-button--warning){background:transparent;color:var(--studio-warning)}:host(.studio-button--ghost.studio-button--warning:hover:not(:disabled):not(.studio-button--loading)){background:var(--studio-warning-bg)}:host(.studio-button--full){width:100%}:host(.studio-button--icon-only){padding:0;aspect-ratio:1}:host(.studio-button--icon-only.studio-button--sm){width:2rem;padding:0}:host(.studio-button--icon-only.studio-button--md){width:2.5rem;padding:0}:host(.studio-button--icon-only.studio-button--lg){width:3rem;padding:0}:host(.studio-button--loading){cursor:wait;pointer-events:none}:host([disabled]){opacity:.6;cursor:not-allowed!important;background:var(--studio-bg-secondary)!important;color:var(--studio-text-tertiary)!important;border-color:var(--studio-border-primary)!important}:host([disabled]:hover){transform:none!important;background:var(--studio-bg-secondary)!important}:host(:active:not([disabled]):not(.studio-button--loading)){transform:scale(.98)}.studio-button__content{display:inline-flex;align-items:center;gap:var(--studio-spacing-sm)}.studio-button__spinner{animation:studio-spin 1s linear infinite}@keyframes studio-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.studio-button__badge{position:absolute;top:-.375rem;right:-.375rem;display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .25rem;font-size:.625rem;font-weight:var(--studio-font-weight-semibold);line-height:1;color:#fff;border-radius:var(--studio-radius-full);box-shadow:0 0 0 2px var(--studio-bg-primary)}.studio-button__badge--primary{background:var(--studio-primary)}.studio-button__badge--error{background:var(--studio-error)}.studio-button__badge--warning{background:var(--studio-warning)}\n"] }]
814
+ }], propDecorators: { variantInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], sizeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], colorInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], radiusInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], shadowInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "shadow", required: false }] }], compactInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], badgeColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeColor", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
471
815
 
472
816
  /**
473
817
  * Button component
@@ -488,11 +832,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
488
832
  * Domain-specific components for educational platforms
489
833
  */
490
834
 
491
- /**
492
- * Utilities
493
- * Helper functions, directives, pipes
494
- */
495
-
496
835
  /**
497
836
  * Public API Surface of @eduboxpro/studio
498
837
  */
@@ -504,5 +843,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
504
843
  * Generated bundle index. Do not edit.
505
844
  */
506
845
 
507
- export { ButtonComponent, IconComponent, STUDIO_CONFIG, StudioConfigService, provideStudioConfig, provideStudioIcons };
846
+ export { BadgeComponent, ButtonComponent, IconComponent, STUDIO_CONFIG, StudioConfigService, classNames, isSafeUrl, provideStudioConfig, provideStudioIcons, sanitizeUrl, withConfigDefault };
508
847
  //# sourceMappingURL=eduboxpro-studio.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"eduboxpro-studio.mjs","sources":["../../../projects/studio/src/lib/config/studio.config.ts","../../../projects/studio/src/lib/config/studio.service.ts","../../../projects/studio/src/lib/config/provide-studio.ts","../../../projects/studio/src/lib/config/index.ts","../../../projects/studio/src/lib/primitives/icon/icon.component.ts","../../../projects/studio/src/lib/primitives/icon/icon.provider.ts","../../../projects/studio/src/lib/primitives/button/button.component.ts","../../../projects/studio/src/lib/primitives/button/index.ts","../../../projects/studio/src/lib/primitives/index.ts","../../../projects/studio/src/lib/composites/index.ts","../../../projects/studio/src/lib/education/index.ts","../../../projects/studio/src/lib/utils/index.ts","../../../projects/studio/src/public-api.ts","../../../projects/studio/src/eduboxpro-studio.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * Theme mode: light or dark\n */\nexport type ThemeMode = 'light' | 'dark';\n\n/**\n * Color configuration with hover and active states\n */\nexport interface ColorConfig {\n base?: string;\n hover?: string;\n active?: string;\n bg?: string;\n}\n\n/**\n * Theme configuration interface\n */\nexport interface StudioThemeConfig {\n /**\n * Theme mode (default: 'light')\n */\n mode?: ThemeMode;\n\n /**\n * Color tokens override with hover/active states\n */\n colors?: {\n primary?: ColorConfig | string;\n secondary?: ColorConfig | string;\n success?: ColorConfig | string;\n error?: ColorConfig | string;\n warning?: ColorConfig | string;\n info?: ColorConfig | string;\n bg?: {\n primary?: string;\n secondary?: string;\n tertiary?: string;\n };\n text?: {\n primary?: string;\n secondary?: string;\n tertiary?: string;\n inverse?: string;\n };\n border?: {\n primary?: string;\n secondary?: string;\n };\n };\n\n /**\n * Typography tokens override\n */\n typography?: {\n fontFamily?: string;\n fontMono?: string;\n fontSize?: {\n xs?: string;\n sm?: string;\n base?: string;\n lg?: string;\n xl?: string;\n '2xl'?: string;\n };\n fontWeight?: {\n normal?: number;\n medium?: number;\n semibold?: number;\n bold?: number;\n };\n lineHeight?: {\n tight?: number;\n normal?: number;\n relaxed?: number;\n };\n };\n\n /**\n * Spacing tokens override\n */\n spacing?: {\n xs?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n '2xl'?: string;\n };\n\n /**\n * Border radius tokens override\n */\n borderRadius?: {\n none?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n full?: string;\n };\n\n /**\n * Shadow tokens override\n */\n shadows?: {\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n };\n\n /**\n * Transition tokens override\n */\n transitions?: {\n fast?: string;\n base?: string;\n slow?: string;\n };\n\n /**\n * Z-index tokens override\n */\n zIndex?: {\n dropdown?: number;\n sticky?: number;\n fixed?: number;\n modalBackdrop?: number;\n modal?: number;\n popover?: number;\n tooltip?: number;\n };\n}\n\n/**\n * Main Studio configuration interface\n */\nexport interface StudioConfig {\n /**\n * Theme configuration\n */\n theme?: StudioThemeConfig;\n}\n\n/**\n * Injection token for Studio configuration\n */\nexport const STUDIO_CONFIG = new InjectionToken<StudioConfig>('STUDIO_CONFIG', {\n providedIn: 'root',\n factory: () => ({})\n});\n","import { Injectable, inject, signal, effect } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\nimport { StudioConfig, StudioThemeConfig, ThemeMode, ColorConfig } from './studio.config';\n\n@Injectable({ providedIn: 'root' })\nexport class StudioConfigService {\n private readonly document = inject(DOCUMENT);\n\n readonly config = signal<StudioConfig>({});\n readonly themeMode = signal<ThemeMode>('light');\n\n constructor() {\n effect(() => {\n this.applyTheme(this.config().theme);\n }, { allowSignalWrites: false });\n }\n\n configure(config: StudioConfig): void {\n this.config.set(config);\n if (config.theme?.mode) {\n this.setThemeMode(config.theme.mode);\n }\n }\n\n setThemeMode(mode: ThemeMode): void {\n this.themeMode.set(mode);\n this.document.documentElement.setAttribute('data-theme', mode);\n }\n\n toggleTheme(): void {\n const newMode = this.themeMode() === 'light' ? 'dark' : 'light';\n this.setThemeMode(newMode);\n }\n\n async loadFromBackend(organizationSlug: string): Promise<void> {\n try {\n const response = await fetch(`/api/organizations/${organizationSlug}/design-config`);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const config = await response.json();\n this.configure(config);\n } catch (error) {\n console.error('[Studio] Failed to load config from backend:', error);\n throw error;\n }\n }\n\n private applyTheme(theme?: StudioThemeConfig): void {\n if (!theme) return;\n\n const root = this.document.documentElement;\n\n // Apply colors\n if (theme.colors) {\n this.applyColorTokens(root, theme.colors);\n }\n\n // Apply typography\n if (theme.typography) {\n if (theme.typography.fontFamily) {\n root.style.setProperty('--studio-font-family', theme.typography.fontFamily);\n }\n if (theme.typography.fontMono) {\n root.style.setProperty('--studio-font-mono', theme.typography.fontMono);\n }\n if (theme.typography.fontSize) {\n this.applyTokens(root, 'studio-font-size', theme.typography.fontSize);\n }\n if (theme.typography.fontWeight) {\n this.applyTokens(root, 'studio-font-weight', theme.typography.fontWeight);\n }\n if (theme.typography.lineHeight) {\n this.applyTokens(root, 'studio-line-height', theme.typography.lineHeight);\n }\n }\n\n // Apply spacing\n if (theme.spacing) {\n this.applyTokens(root, 'studio-spacing', theme.spacing);\n }\n\n // Apply border radius\n if (theme.borderRadius) {\n this.applyTokens(root, 'studio-radius', theme.borderRadius);\n }\n\n // Apply shadows\n if (theme.shadows) {\n this.applyTokens(root, 'studio-shadow', theme.shadows);\n }\n\n // Apply transitions\n if (theme.transitions) {\n this.applyTokens(root, 'studio-transition', theme.transitions);\n }\n\n // Apply z-index\n if (theme.zIndex) {\n this.applyZIndexTokens(root, theme.zIndex);\n }\n }\n\n private applyColorTokens(\n root: HTMLElement,\n colors: NonNullable<StudioThemeConfig['colors']>\n ): void {\n // Brand colors with hover/active states\n const brandColors = ['primary', 'secondary', 'success', 'error', 'warning', 'info'] as const;\n\n brandColors.forEach(colorName => {\n const colorValue = colors[colorName];\n if (!colorValue) return;\n\n if (typeof colorValue === 'string') {\n root.style.setProperty(`--studio-${colorName}`, colorValue);\n } else {\n const config = colorValue as ColorConfig;\n if (config.base) {\n root.style.setProperty(`--studio-${colorName}`, config.base);\n }\n if (config.hover) {\n root.style.setProperty(`--studio-${colorName}-hover`, config.hover);\n }\n if (config.active) {\n root.style.setProperty(`--studio-${colorName}-active`, config.active);\n }\n if (config.bg) {\n root.style.setProperty(`--studio-${colorName}-bg`, config.bg);\n }\n }\n });\n\n // Background colors\n if (colors.bg) {\n this.applyTokens(root, 'studio-bg', colors.bg);\n }\n\n // Text colors\n if (colors.text) {\n this.applyTokens(root, 'studio-text', colors.text);\n }\n\n // Border colors\n if (colors.border) {\n this.applyTokens(root, 'studio-border', colors.border);\n }\n }\n\n private applyZIndexTokens(\n root: HTMLElement,\n zIndex: NonNullable<StudioThemeConfig['zIndex']>\n ): void {\n const zIndexMap: Record<string, string> = {\n dropdown: 'dropdown',\n sticky: 'sticky',\n fixed: 'fixed',\n modalBackdrop: 'modal-backdrop',\n modal: 'modal',\n popover: 'popover',\n tooltip: 'tooltip'\n };\n\n Object.entries(zIndex).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n const cssKey = zIndexMap[key] || key;\n root.style.setProperty(`--studio-z-${cssKey}`, String(value));\n }\n });\n }\n\n private applyTokens(\n root: HTMLElement,\n prefix: string,\n tokens: Record<string, string | number>\n ): void {\n Object.entries(tokens).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n root.style.setProperty(`--${prefix}-${key}`, String(value));\n }\n });\n }\n}\n","import { EnvironmentProviders, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, inject } from '@angular/core';\nimport { STUDIO_CONFIG, StudioConfig } from './studio.config';\nimport { StudioConfigService } from './studio.service';\n\n/**\n * Provide Studio configuration for the application\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { provideStudioConfig } from '@eduboxpro/studio/config';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideStudioConfig({\n * theme: {\n * mode: 'light',\n * colors: {\n * primary: '#3b82f6'\n * }\n * }\n * })\n * ]\n * };\n * ```\n */\nexport function provideStudioConfig(config: StudioConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: STUDIO_CONFIG,\n useValue: config\n },\n {\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useValue: () => {\n const studioConfig = inject(StudioConfigService);\n const initialConfig = inject(STUDIO_CONFIG);\n studioConfig.configure(initialConfig);\n }\n }\n ]);\n}\n","/**\n * Configuration module\n * @module config\n */\n\nexport * from './studio.config';\nexport * from './studio.service';\nexport * from './provide-studio';\n","import { Component, ChangeDetectionStrategy, input, computed } from '@angular/core';\nimport { LucideAngularModule, icons } from 'lucide-angular';\n\n@Component({\n selector: 'studio-icon',\n standalone: true,\n imports: [LucideAngularModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[style.width.px]': 'size()',\n '[style.height.px]': 'size()',\n },\n template: `\n @if (lucideIcon(); as iconName) {\n <lucide-icon\n [name]=\"iconName\"\n [size]=\"size()\"\n [color]=\"computedColor()\"\n [strokeWidth]=\"strokeWidth()\"\n [absoluteStrokeWidth]=\"absoluteStrokeWidth()\"\n />\n }\n `,\n styles: [`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n `]\n})\nexport class IconComponent {\n name = input.required<string>();\n size = input<number>(24);\n color = input<'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'inherit' | string>('inherit');\n strokeWidth = input<number>(2);\n absoluteStrokeWidth = input<boolean>(false);\n\n protected readonly icons = icons;\n\n protected lucideIcon = computed(() => {\n const iconName = this.name();\n return iconName;\n });\n\n protected computedColor = computed(() => {\n const colorValue = this.color();\n\n const colorMap: Record<string, string> = {\n 'primary': 'var(--studio-primary)',\n 'secondary': 'var(--studio-secondary)',\n 'success': 'var(--studio-success)',\n 'error': 'var(--studio-error)',\n 'warning': 'var(--studio-warning)',\n 'inherit': 'currentColor'\n };\n\n return colorMap[colorValue] || colorValue;\n });\n\n protected hostClasses = computed(() => {\n return ['studio-icon'];\n });\n}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { LUCIDE_ICONS, LucideIconProvider } from 'lucide-angular';\nimport {\n ArrowRight,\n ArrowLeft,\n ChevronDown,\n ChevronUp,\n ChevronLeft,\n ChevronRight,\n Download,\n Upload,\n Mail,\n Phone,\n Heart,\n Star,\n Settings,\n User,\n Trash2,\n Edit,\n Plus,\n Minus,\n Check,\n X,\n Search,\n Filter,\n ExternalLink,\n Link,\n Copy,\n Share2,\n Home,\n Menu,\n MoreVertical,\n MoreHorizontal,\n Bell,\n Calendar,\n Clock,\n Eye,\n EyeOff,\n Lock,\n Unlock,\n LogIn,\n LogOut,\n AlertCircle,\n AlertTriangle,\n Info,\n CheckCircle,\n XCircle,\n HelpCircle,\n File,\n FileText,\n Folder,\n Image,\n Save,\n Printer,\n RefreshCw,\n RotateCw,\n Loader,\n Loader2\n} from 'lucide-angular';\n\n/**\n * Провайдер иконок для Studio\n * Регистрирует базовый набор часто используемых иконок\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { provideStudioIcons } from '@eduboxpro/studio';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideStudioIcons()\n * ]\n * };\n * ```\n *\n * Для добавления дополнительных иконок:\n * @example\n * ```typescript\n * import { LUCIDE_ICONS, LucideIconProvider } from 'lucide-angular';\n * import { Zap, Wifi } from 'lucide-angular';\n *\n * providers: [\n * provideStudioIcons(),\n * {\n * provide: LUCIDE_ICONS,\n * multi: true,\n * useValue: new LucideIconProvider({ Zap, Wifi })\n * }\n * ]\n * ```\n */\nexport function provideStudioIcons(): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: LUCIDE_ICONS,\n multi: true,\n useValue: new LucideIconProvider({\n ArrowRight,\n ArrowLeft,\n ChevronDown,\n ChevronUp,\n ChevronLeft,\n ChevronRight,\n Download,\n Upload,\n Mail,\n Phone,\n Heart,\n Star,\n Settings,\n User,\n Trash2,\n Edit,\n Plus,\n Minus,\n Check,\n X,\n Search,\n Filter,\n ExternalLink,\n Link,\n Copy,\n Share2,\n Home,\n Menu,\n MoreVertical,\n MoreHorizontal,\n Bell,\n Calendar,\n Clock,\n Eye,\n EyeOff,\n Lock,\n Unlock,\n LogIn,\n LogOut,\n AlertCircle,\n AlertTriangle,\n Info,\n CheckCircle,\n XCircle,\n HelpCircle,\n File,\n FileText,\n Folder,\n Image,\n Save,\n Printer,\n RefreshCw,\n RotateCw,\n Loader,\n Loader2\n })\n }\n ]);\n}\n","import { Component, input, output, computed, ChangeDetectionStrategy } from '@angular/core';\nimport { IconComponent } from '../icon';\n\n@Component({\n selector: 'studio-button',\n standalone: true,\n imports: [IconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[attr.disabled]': 'disabled() || loading() ? \"\" : null',\n '[attr.type]': 'type()',\n '(click)': 'handleClick($event)'\n },\n template: `\n <span class=\"studio-button__content\">\n @if (loading()) {\n <studio-icon\n name=\"loader-2\"\n [size]=\"iconSize()\"\n class=\"studio-button__spinner\"\n />\n }\n @if (!loading() && icon() && iconPosition() === 'left') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (iconPosition() !== 'only' && !loading()) {\n <ng-content />\n }\n @if (!loading() && icon() && iconPosition() === 'right') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!loading() && icon() && iconPosition() === 'only') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (loading() && iconPosition() === 'only') {\n <!-- Empty, spinner already shown -->\n } @else if (loading()) {\n <span>Loading...</span>\n }\n </span>\n `,\n styleUrl: './button.component.scss'\n})\nexport class ButtonComponent {\n variant = input<'solid' | 'outline' | 'ghost'>('solid');\n size = input<'sm' | 'md' | 'lg'>('md');\n color = input<'primary' | 'secondary' | 'success' | 'error' | 'warning'>('primary');\n disabled = input<boolean>(false);\n fullWidth = input<boolean>(false);\n loading = input<boolean>(false);\n type = input<'button' | 'submit' | 'reset'>('button');\n icon = input<string>();\n iconPosition = input<'left' | 'right' | 'only'>('left');\n\n clicked = output<MouseEvent>();\n\n protected iconSize = computed(() => {\n const sizeMap = { sm: 16, md: 18, lg: 20 };\n return sizeMap[this.size()];\n });\n\n protected hostClasses = computed(() => {\n return [\n 'studio-button',\n `studio-button--${this.variant()}`,\n `studio-button--${this.size()}`,\n `studio-button--${this.color()}`,\n this.fullWidth() ? 'studio-button--full' : '',\n this.loading() ? 'studio-button--loading' : '',\n this.iconPosition() === 'only' ? 'studio-button--icon-only' : ''\n ].filter(Boolean).join(' ');\n });\n\n protected handleClick(event: MouseEvent): void {\n if (this.disabled() || this.loading()) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n this.clicked.emit(event);\n }\n}\n","/**\n * Button component\n */\n\nexport * from './button.component';\n","/**\n * Primitives (Atoms)\n * Basic building blocks\n */\n\nexport * from './button';\nexport * from './icon';\n","/**\n * Composites (Molecules + Organisms)\n * Complex components built from primitives\n */\n\n// Export composite components here\n// Example: export * from './form-field';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Education components\n * Domain-specific components for educational platforms\n */\n\n// Export education components here\n// Example: export * from './course-card';\n// Example: export * from './lesson-viewer';\n// Example: export * from './quiz-builder';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Utilities\n * Helper functions, directives, pipes\n */\n\n// Export utilities here\n// Example: export * from './format-date.pipe';\n// Example: export * from './auto-focus.directive';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Public API Surface of @eduboxpro/studio\n */\n\n/* ========================================\n * Configuration\n * ======================================== */\nexport * from './lib/config';\n\n/* ========================================\n * Components\n * ======================================== */\nexport * from './lib/primitives';\nexport * from './lib/composites';\nexport * from './lib/education';\n\n/* ========================================\n * Utilities\n * ======================================== */\nexport * from './lib/utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eduboxpro-studio.mjs","sources":["../../../projects/studio/src/lib/config/studio.config.ts","../../../projects/studio/src/lib/config/studio.service.ts","../../../projects/studio/src/lib/config/provide-studio.ts","../../../projects/studio/src/lib/config/index.ts","../../../projects/studio/src/lib/primitives/icon/icon.component.ts","../../../projects/studio/src/lib/primitives/icon/icon.provider.ts","../../../projects/studio/src/lib/utils/url-validator.ts","../../../projects/studio/src/lib/utils/class-names.ts","../../../projects/studio/src/lib/utils/config-helpers.ts","../../../projects/studio/src/lib/utils/index.ts","../../../projects/studio/src/lib/primitives/badge/badge.component.ts","../../../projects/studio/src/lib/primitives/badge/index.ts","../../../projects/studio/src/lib/primitives/button/button.component.ts","../../../projects/studio/src/lib/primitives/button/index.ts","../../../projects/studio/src/lib/primitives/index.ts","../../../projects/studio/src/lib/composites/index.ts","../../../projects/studio/src/lib/education/index.ts","../../../projects/studio/src/public-api.ts","../../../projects/studio/src/eduboxpro-studio.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * Theme mode: light or dark\n */\nexport type ThemeMode = 'light' | 'dark';\n\n/**\n * Color configuration with hover and active states\n */\nexport interface ColorConfig {\n base?: string;\n hover?: string;\n active?: string;\n bg?: string;\n}\n\n/**\n * Theme configuration interface\n */\nexport interface StudioThemeConfig {\n /**\n * Theme mode (default: 'light')\n */\n mode?: ThemeMode;\n\n /**\n * Color tokens override with hover/active states\n */\n colors?: {\n primary?: ColorConfig | string;\n secondary?: ColorConfig | string;\n success?: ColorConfig | string;\n error?: ColorConfig | string;\n warning?: ColorConfig | string;\n info?: ColorConfig | string;\n bg?: {\n primary?: string;\n secondary?: string;\n tertiary?: string;\n };\n text?: {\n primary?: string;\n secondary?: string;\n tertiary?: string;\n inverse?: string;\n };\n border?: {\n primary?: string;\n secondary?: string;\n };\n };\n\n /**\n * Typography tokens override\n */\n typography?: {\n fontFamily?: string;\n fontMono?: string;\n fontSize?: {\n xs?: string;\n sm?: string;\n base?: string;\n lg?: string;\n xl?: string;\n '2xl'?: string;\n };\n fontWeight?: {\n normal?: number;\n medium?: number;\n semibold?: number;\n bold?: number;\n };\n lineHeight?: {\n tight?: number;\n normal?: number;\n relaxed?: number;\n };\n };\n\n /**\n * Spacing tokens override\n */\n spacing?: {\n xs?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n '2xl'?: string;\n };\n\n /**\n * Border radius tokens override\n */\n borderRadius?: {\n none?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n full?: string;\n };\n\n /**\n * Shadow tokens override\n */\n shadows?: {\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n };\n\n /**\n * Transition tokens override\n */\n transitions?: {\n fast?: string;\n base?: string;\n slow?: string;\n };\n\n /**\n * Z-index tokens override\n */\n zIndex?: {\n dropdown?: number;\n sticky?: number;\n fixed?: number;\n modalBackdrop?: number;\n modal?: number;\n popover?: number;\n tooltip?: number;\n };\n}\n\n/**\n * Button component defaults configuration\n */\nexport interface ButtonDefaultsConfig {\n variant?: 'solid' | 'outline' | 'ghost';\n size?: 'sm' | 'md' | 'lg';\n color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning';\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';\n shadow?: 'none' | 'sm' | 'md' | 'lg';\n compact?: boolean;\n}\n\n/**\n * Badge component defaults configuration\n */\nexport interface BadgeDefaultsConfig {\n variant?: 'solid' | 'outline' | 'soft' | 'dot';\n size?: 'sm' | 'md' | 'lg';\n color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'neutral';\n radius?: 'sm' | 'md' | 'lg' | 'full';\n}\n\n/**\n * Components defaults configuration\n */\nexport interface ComponentsConfig {\n /**\n * Button component defaults\n */\n button?: ButtonDefaultsConfig;\n\n /**\n * Badge component defaults\n */\n badge?: BadgeDefaultsConfig;\n\n // Future components\n // input?: InputDefaultsConfig;\n // card?: CardDefaultsConfig;\n}\n\n/**\n * Main Studio configuration interface\n */\nexport interface StudioConfig {\n /**\n * Theme configuration\n */\n theme?: StudioThemeConfig;\n\n /**\n * Components default values configuration\n */\n components?: ComponentsConfig;\n}\n\n/**\n * Injection token for Studio configuration\n */\nexport const STUDIO_CONFIG = new InjectionToken<StudioConfig>('STUDIO_CONFIG', {\n providedIn: 'root',\n factory: () => ({})\n});\n","import { Injectable, inject, signal, effect } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\nimport { StudioConfig, StudioThemeConfig, ThemeMode, ColorConfig } from './studio.config';\n\n@Injectable({ providedIn: 'root' })\nexport class StudioConfigService {\n private readonly document = inject(DOCUMENT);\n\n readonly config = signal<StudioConfig>({});\n readonly themeMode = signal<ThemeMode>('light');\n\n constructor() {\n effect(() => {\n this.applyTheme(this.config().theme);\n }, { allowSignalWrites: false });\n }\n\n configure(config: StudioConfig): void {\n this.config.set(config);\n if (config.theme?.mode) {\n this.setThemeMode(config.theme.mode);\n }\n }\n\n setThemeMode(mode: ThemeMode): void {\n this.themeMode.set(mode);\n this.document.documentElement.setAttribute('data-theme', mode);\n }\n\n toggleTheme(): void {\n const newMode = this.themeMode() === 'light' ? 'dark' : 'light';\n this.setThemeMode(newMode);\n }\n\n async loadFromBackend(organizationSlug: string): Promise<void> {\n try {\n const response = await fetch(`/api/organizations/${organizationSlug}/design-config`);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const config = await response.json();\n this.configure(config);\n } catch (error) {\n console.error('[Studio] Failed to load config from backend:', error);\n throw error;\n }\n }\n\n private applyTheme(theme?: StudioThemeConfig): void {\n if (!theme) return;\n\n const root = this.document.documentElement;\n\n // Apply colors\n if (theme.colors) {\n this.applyColorTokens(root, theme.colors);\n }\n\n // Apply typography\n if (theme.typography) {\n if (theme.typography.fontFamily) {\n root.style.setProperty('--studio-font-family', theme.typography.fontFamily);\n }\n if (theme.typography.fontMono) {\n root.style.setProperty('--studio-font-mono', theme.typography.fontMono);\n }\n if (theme.typography.fontSize) {\n this.applyTokens(root, 'studio-font-size', theme.typography.fontSize);\n }\n if (theme.typography.fontWeight) {\n this.applyTokens(root, 'studio-font-weight', theme.typography.fontWeight);\n }\n if (theme.typography.lineHeight) {\n this.applyTokens(root, 'studio-line-height', theme.typography.lineHeight);\n }\n }\n\n // Apply spacing\n if (theme.spacing) {\n this.applyTokens(root, 'studio-spacing', theme.spacing);\n }\n\n // Apply border radius\n if (theme.borderRadius) {\n this.applyTokens(root, 'studio-radius', theme.borderRadius);\n }\n\n // Apply shadows\n if (theme.shadows) {\n this.applyTokens(root, 'studio-shadow', theme.shadows);\n }\n\n // Apply transitions\n if (theme.transitions) {\n this.applyTokens(root, 'studio-transition', theme.transitions);\n }\n\n // Apply z-index\n if (theme.zIndex) {\n this.applyZIndexTokens(root, theme.zIndex);\n }\n }\n\n private applyColorTokens(\n root: HTMLElement,\n colors: NonNullable<StudioThemeConfig['colors']>\n ): void {\n // Brand colors with hover/active states\n const brandColors = ['primary', 'secondary', 'success', 'error', 'warning', 'info'] as const;\n\n brandColors.forEach(colorName => {\n const colorValue = colors[colorName];\n if (!colorValue) return;\n\n if (typeof colorValue === 'string') {\n root.style.setProperty(`--studio-${colorName}`, colorValue);\n } else {\n const config = colorValue as ColorConfig;\n if (config.base) {\n root.style.setProperty(`--studio-${colorName}`, config.base);\n }\n if (config.hover) {\n root.style.setProperty(`--studio-${colorName}-hover`, config.hover);\n }\n if (config.active) {\n root.style.setProperty(`--studio-${colorName}-active`, config.active);\n }\n if (config.bg) {\n root.style.setProperty(`--studio-${colorName}-bg`, config.bg);\n }\n }\n });\n\n // Background colors\n if (colors.bg) {\n this.applyTokens(root, 'studio-bg', colors.bg);\n }\n\n // Text colors\n if (colors.text) {\n this.applyTokens(root, 'studio-text', colors.text);\n }\n\n // Border colors\n if (colors.border) {\n this.applyTokens(root, 'studio-border', colors.border);\n }\n }\n\n private applyZIndexTokens(\n root: HTMLElement,\n zIndex: NonNullable<StudioThemeConfig['zIndex']>\n ): void {\n const zIndexMap: Record<string, string> = {\n dropdown: 'dropdown',\n sticky: 'sticky',\n fixed: 'fixed',\n modalBackdrop: 'modal-backdrop',\n modal: 'modal',\n popover: 'popover',\n tooltip: 'tooltip'\n };\n\n Object.entries(zIndex).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n const cssKey = zIndexMap[key] || key;\n root.style.setProperty(`--studio-z-${cssKey}`, String(value));\n }\n });\n }\n\n private applyTokens(\n root: HTMLElement,\n prefix: string,\n tokens: Record<string, string | number>\n ): void {\n Object.entries(tokens).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n root.style.setProperty(`--${prefix}-${key}`, String(value));\n }\n });\n }\n}\n","import { EnvironmentProviders, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, inject } from '@angular/core';\nimport { STUDIO_CONFIG, StudioConfig } from './studio.config';\nimport { StudioConfigService } from './studio.service';\n\n/**\n * Provide Studio configuration for the application\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { provideStudioConfig } from '@eduboxpro/studio/config';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideStudioConfig({\n * theme: {\n * mode: 'light',\n * colors: {\n * primary: '#3b82f6'\n * }\n * }\n * })\n * ]\n * };\n * ```\n */\nexport function provideStudioConfig(config: StudioConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: STUDIO_CONFIG,\n useValue: config\n },\n {\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useValue: () => {\n const studioConfig = inject(StudioConfigService);\n const initialConfig = inject(STUDIO_CONFIG);\n studioConfig.configure(initialConfig);\n }\n }\n ]);\n}\n","/**\n * Configuration module\n * @module config\n */\n\nexport * from './studio.config';\nexport * from './studio.service';\nexport * from './provide-studio';\n","import { Component, ChangeDetectionStrategy, input, computed } from '@angular/core';\nimport { LucideAngularModule, icons } from 'lucide-angular';\n\n@Component({\n selector: 'studio-icon',\n standalone: true,\n imports: [LucideAngularModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[style.width.px]': 'size()',\n '[style.height.px]': 'size()',\n },\n template: `\n @if (lucideIcon(); as iconName) {\n <lucide-icon\n [name]=\"iconName\"\n [size]=\"size()\"\n [color]=\"computedColor()\"\n [strokeWidth]=\"strokeWidth()\"\n [absoluteStrokeWidth]=\"absoluteStrokeWidth()\"\n />\n }\n `,\n styles: [`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n `]\n})\nexport class IconComponent {\n name = input.required<string>();\n size = input<number>(24);\n color = input<'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'inherit' | string>('inherit');\n strokeWidth = input<number>(2);\n absoluteStrokeWidth = input<boolean>(false);\n\n protected readonly icons = icons;\n\n protected lucideIcon = computed(() => {\n const iconName = this.name();\n return iconName;\n });\n\n protected computedColor = computed(() => {\n const colorValue = this.color();\n\n const colorMap: Record<string, string> = {\n 'primary': 'var(--studio-primary)',\n 'secondary': 'var(--studio-secondary)',\n 'success': 'var(--studio-success)',\n 'error': 'var(--studio-error)',\n 'warning': 'var(--studio-warning)',\n 'inherit': 'currentColor'\n };\n\n return colorMap[colorValue] || colorValue;\n });\n\n protected hostClasses = computed(() => {\n return ['studio-icon'];\n });\n}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { LUCIDE_ICONS, LucideIconProvider } from 'lucide-angular';\nimport {\n ArrowRight,\n ArrowLeft,\n ChevronDown,\n ChevronUp,\n ChevronLeft,\n ChevronRight,\n Download,\n Upload,\n Mail,\n Phone,\n Heart,\n Star,\n Settings,\n User,\n Trash2,\n Edit,\n Plus,\n Minus,\n Check,\n X,\n Search,\n Filter,\n ExternalLink,\n Link,\n Copy,\n Share2,\n Home,\n Menu,\n MoreVertical,\n MoreHorizontal,\n Bell,\n Calendar,\n Clock,\n Eye,\n EyeOff,\n Lock,\n Unlock,\n LogIn,\n LogOut,\n AlertCircle,\n AlertTriangle,\n Info,\n CheckCircle,\n XCircle,\n HelpCircle,\n File,\n FileText,\n Folder,\n Image,\n Save,\n Printer,\n RefreshCw,\n RotateCw,\n Loader,\n Loader2,\n ShoppingCart\n} from 'lucide-angular';\n\n/**\n * Провайдер иконок для Studio\n * Регистрирует базовый набор часто используемых иконок\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { provideStudioIcons } from '@eduboxpro/studio';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideStudioIcons()\n * ]\n * };\n * ```\n *\n * Для добавления дополнительных иконок:\n * @example\n * ```typescript\n * import { LUCIDE_ICONS, LucideIconProvider } from 'lucide-angular';\n * import { Zap, Wifi } from 'lucide-angular';\n *\n * providers: [\n * provideStudioIcons(),\n * {\n * provide: LUCIDE_ICONS,\n * multi: true,\n * useValue: new LucideIconProvider({ Zap, Wifi })\n * }\n * ]\n * ```\n */\nexport function provideStudioIcons(): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: LUCIDE_ICONS,\n multi: true,\n useValue: new LucideIconProvider({\n ArrowRight,\n ArrowLeft,\n ChevronDown,\n ChevronUp,\n ChevronLeft,\n ChevronRight,\n Download,\n Upload,\n Mail,\n Phone,\n Heart,\n Star,\n Settings,\n User,\n Trash2,\n Edit,\n Plus,\n Minus,\n Check,\n X,\n Search,\n Filter,\n ExternalLink,\n Link,\n Copy,\n Share2,\n Home,\n Menu,\n MoreVertical,\n MoreHorizontal,\n Bell,\n Calendar,\n Clock,\n Eye,\n EyeOff,\n Lock,\n Unlock,\n LogIn,\n LogOut,\n AlertCircle,\n AlertTriangle,\n Info,\n CheckCircle,\n XCircle,\n HelpCircle,\n File,\n FileText,\n Folder,\n Image,\n Save,\n Printer,\n RefreshCw,\n RotateCw,\n Loader,\n Loader2,\n ShoppingCart\n })\n }\n ]);\n}\n","/**\n * Проверяет безопасность URL для навигации\n *\n * @param url - URL для проверки\n * @returns true если URL безопасен (http/https или относительный)\n *\n * @example\n * ```typescript\n * isSafeUrl('https://example.com') // true\n * isSafeUrl('javascript:alert(1)') // false\n * isSafeUrl('/relative/path') // true\n * ```\n */\nexport function isSafeUrl(url: string): boolean {\n if (!url || typeof url !== 'string') {\n return false;\n }\n\n try {\n const parsed = new URL(url, window.location.origin);\n // Разрешаем только http(s) и относительные URL (пустой protocol)\n return ['http:', 'https:', ''].includes(parsed.protocol);\n } catch {\n // Невалидный URL\n return false;\n }\n}\n\n/**\n * Sanitize URL перед использованием в навигации\n *\n * @param url - URL для sanitization\n * @returns Безопасный URL или '#' если URL небезопасен\n *\n * @example\n * ```typescript\n * sanitizeUrl('https://example.com') // 'https://example.com'\n * sanitizeUrl('javascript:alert(1)') // '#' (с предупреждением в консоли)\n * ```\n */\nexport function sanitizeUrl(url: string): string {\n if (!isSafeUrl(url)) {\n console.warn(`[Studio] Unsafe URL blocked: ${url}`);\n return '#';\n }\n return url;\n}\n","/**\n * Объединяет CSS классы, игнорируя falsy значения\n *\n * @param classes - Массив классов (строки, undefined, null, false)\n * @returns Строка с объединенными классами\n *\n * @example\n * ```typescript\n * classNames('btn', 'btn-primary') // 'btn btn-primary'\n * classNames('btn', isActive && 'active') // 'btn active' если isActive=true, иначе 'btn'\n * classNames('btn', undefined, null, false, 'large') // 'btn large'\n * ```\n */\nexport function classNames(...classes: (string | false | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n","import { computed, Signal } from '@angular/core';\n\n/**\n * Создает computed signal с fallback chain: input → config → default\n *\n * Упрощает паттерн configurable inputs, убирая boilerplate код.\n *\n * @param inputSignal - Input signal от пользователя\n * @param configSignal - Config значение (может быть undefined)\n * @param defaultValue - Fallback значение\n * @returns Computed signal с resolved значением\n *\n * @example\n * ```typescript\n * export class ButtonComponent {\n * private defaults = computed(() => this.configService.config().components?.button);\n *\n * // Input\n * variantInput = input<Variant | undefined>(undefined, { alias: 'variant' });\n *\n * // Resolved value с config fallback\n * variant = withConfigDefault(\n * this.variantInput,\n * computed(() => this.defaults()?.variant),\n * 'solid'\n * );\n * }\n * ```\n */\nexport function withConfigDefault<T>(\n inputSignal: Signal<T | undefined>,\n configSignal: Signal<T | undefined>,\n defaultValue: T\n): Signal<T> {\n return computed(() => {\n const inputValue = inputSignal();\n if (inputValue !== undefined) return inputValue;\n\n const configValue = configSignal();\n if (configValue !== undefined) return configValue;\n\n return defaultValue;\n });\n}\n","/**\n * @eduboxpro/studio - Utilities\n *\n * Helper functions and utilities for the Studio library\n */\n\nexport * from './url-validator';\nexport * from './class-names';\nexport * from './config-helpers';\n","import { Component, input, output, computed, inject, ChangeDetectionStrategy } from '@angular/core';\nimport { IconComponent } from '../icon';\nimport { StudioConfigService } from '../../config';\nimport { sanitizeUrl, classNames, withConfigDefault } from '../../utils';\n\n@Component({\n selector: 'studio-badge',\n standalone: true,\n imports: [IconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[attr.disabled]': 'disabled() ? \"\" : null',\n '[attr.href]': 'href()',\n '[attr.target]': 'href() ? target() : null',\n '[attr.rel]': 'href() && target() === \"_blank\" ? \"noopener noreferrer\" : null',\n '[style.display]': 'isVisible() ? null : \"none\"',\n '(click)': 'handleClick($event)'\n },\n template: `\n <span class=\"studio-badge__content\">\n @if (dot()) {\n <span\n class=\"studio-badge__dot\"\n [class]=\"'studio-badge__dot--' + (dotColor() || color())\"\n ></span>\n }\n @if (icon() && iconPosition() === 'left') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n <span class=\"studio-badge__text\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <ng-content />\n }\n </span>\n @if (icon() && iconPosition() === 'right') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (removable()) {\n <button\n type=\"button\"\n class=\"studio-badge__remove\"\n (click)=\"handleRemove($event)\"\n aria-label=\"Remove\"\n >\n <studio-icon name=\"x\" [size]=\"iconSize()\" />\n </button>\n }\n </span>\n `,\n styleUrl: './badge.component.scss'\n})\nexport class BadgeComponent {\n private readonly configService = inject(StudioConfigService);\n private readonly badgeDefaults = computed(() => this.configService.config().components?.badge);\n\n // Appearance - inputs\n variantInput = input<'solid' | 'outline' | 'soft' | 'dot' | undefined>(undefined, { alias: 'variant' });\n sizeInput = input<'sm' | 'md' | 'lg' | undefined>(undefined, { alias: 'size' });\n colorInput = input<'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'neutral' | undefined>(undefined, { alias: 'color' });\n radiusInput = input<'sm' | 'md' | 'lg' | 'full' | undefined>(undefined, { alias: 'radius' });\n\n // Values with config defaults\n variant = withConfigDefault(this.variantInput, computed(() => this.badgeDefaults()?.variant), 'solid');\n size = withConfigDefault(this.sizeInput, computed(() => this.badgeDefaults()?.size), 'md');\n color = withConfigDefault(this.colorInput, computed(() => this.badgeDefaults()?.color), 'primary');\n radius = withConfigDefault(this.radiusInput, computed(() => this.badgeDefaults()?.radius), 'full');\n\n // Icon\n icon = input<string>();\n iconPosition = input<'left' | 'right'>('left');\n\n // Dot indicator\n dot = input<boolean>(false);\n dotColor = input<'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'neutral'>();\n\n // Removable\n removable = input<boolean>(false);\n removed = output<void>();\n\n // Clickable & Navigation\n href = input<string>();\n target = input<'_blank' | '_self' | '_parent' | '_top'>('_self');\n disabled = input<boolean>(false);\n clicked = output<MouseEvent>();\n\n // Number badge\n value = input<string | number>();\n max = input<number>();\n showZero = input<boolean>(true);\n\n // Typography\n uppercase = input<boolean>(false);\n bold = input<boolean>(false);\n\n // Animation\n pulse = input<boolean>(false);\n\n // Auto color (будет реализовано позже если нужно)\n autoColor = input<boolean>(false);\n\n protected iconSize = computed(() => {\n const sizeMap = { sm: 12, md: 14, lg: 16 };\n return sizeMap[this.size()];\n });\n\n protected displayValue = computed(() => {\n const val = this.value();\n if (val === undefined || val === null) return '';\n\n const numVal = typeof val === 'number' ? val : parseInt(val, 10);\n\n // Если это число\n if (!isNaN(numVal)) {\n // Не показывать 0 если showZero = false\n if (numVal === 0 && !this.showZero()) return '';\n\n // Показать max+ если превышает максимум\n const maxVal = this.max();\n if (maxVal !== undefined && numVal > maxVal) {\n return `${maxVal}+`;\n }\n\n return numVal.toString();\n }\n\n return val.toString();\n });\n\n protected isVisible = computed(() => {\n // Скрыть если значение 0 и showZero = false\n const val = this.value();\n if (val !== undefined && val !== null) {\n const numVal = typeof val === 'number' ? val : parseInt(val, 10);\n if (!isNaN(numVal) && numVal === 0 && !this.showZero()) {\n return false;\n }\n }\n return true;\n });\n\n protected hostClasses = computed(() => classNames(\n 'studio-badge',\n `studio-badge--${this.variant()}`,\n `studio-badge--${this.size()}`,\n `studio-badge--${this.color()}`,\n `studio-badge--radius-${this.radius()}`,\n this.disabled() && 'studio-badge--disabled',\n this.uppercase() && 'studio-badge--uppercase',\n this.bold() && 'studio-badge--bold',\n this.pulse() && 'studio-badge--pulse',\n this.href() && 'studio-badge--clickable'\n ));\n\n protected handleClick(event: MouseEvent): void {\n if (this.disabled()) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Handle link navigation\n const url = this.href();\n if (url) {\n const safeUrl = sanitizeUrl(url);\n if (safeUrl === '#') {\n // URL was blocked - don't navigate\n return;\n }\n\n const target = this.target();\n if (target === '_blank') {\n window.open(safeUrl, '_blank', 'noopener,noreferrer');\n } else {\n window.location.href = safeUrl;\n }\n }\n\n this.clicked.emit(event);\n }\n\n protected handleRemove(event: MouseEvent): void {\n event.preventDefault();\n event.stopPropagation();\n\n if (this.disabled()) return;\n\n this.removed.emit();\n }\n}\n","/**\n * Badge component\n */\n\nexport * from './badge.component';\n","import { Component, input, output, computed, inject, ChangeDetectionStrategy } from '@angular/core';\nimport { IconComponent } from '../icon';\nimport { StudioConfigService } from '../../config';\nimport { sanitizeUrl, classNames, withConfigDefault } from '../../utils';\n\n@Component({\n selector: 'studio-button',\n standalone: true,\n imports: [IconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[attr.disabled]': 'disabled() || loading() ? \"\" : null',\n '[attr.type]': 'href() ? null : type()',\n '[attr.href]': 'href()',\n '[attr.target]': 'href() ? target() : null',\n '[attr.rel]': 'href() && target() === \"_blank\" ? \"noopener noreferrer\" : null',\n '[attr.aria-label]': 'ariaLabel()',\n '(click)': 'handleClick($event)'\n },\n template: `\n <span class=\"studio-button__content\">\n @if (loading()) {\n <studio-icon\n name=\"loader-2\"\n [size]=\"iconSize()\"\n class=\"studio-button__spinner\"\n />\n }\n @if (!loading() && icon() && iconPosition() === 'left') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (iconPosition() !== 'only' && !loading()) {\n <ng-content />\n }\n @if (!loading() && icon() && iconPosition() === 'right') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (!loading() && icon() && iconPosition() === 'only') {\n <studio-icon [name]=\"icon()!\" [size]=\"iconSize()\" />\n }\n @if (loading() && iconPosition() === 'only') {\n <!-- Empty, spinner already shown -->\n } @else if (loading()) {\n <span>{{ loadingText() }}</span>\n }\n @if (badge() !== undefined && badge() !== null && badge() !== '') {\n <span class=\"studio-button__badge studio-button__badge--{{ badgeColor() }}\">\n {{ badge() }}\n </span>\n }\n </span>\n `,\n styleUrl: './button.component.scss'\n})\nexport class ButtonComponent {\n private readonly configService = inject(StudioConfigService);\n private readonly buttonDefaults = computed(() => this.configService.config().components?.button);\n\n // Appearance - inputs\n variantInput = input<'solid' | 'outline' | 'ghost' | undefined>(undefined, { alias: 'variant' });\n sizeInput = input<'sm' | 'md' | 'lg' | undefined>(undefined, { alias: 'size' });\n colorInput = input<'primary' | 'secondary' | 'success' | 'error' | 'warning' | undefined>(undefined, { alias: 'color' });\n radiusInput = input<'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | undefined>(undefined, { alias: 'radius' });\n shadowInput = input<'none' | 'sm' | 'md' | 'lg' | undefined>(undefined, { alias: 'shadow' });\n compactInput = input<boolean | undefined>(undefined, { alias: 'compact' });\n\n // Values with config defaults\n variant = withConfigDefault(this.variantInput, computed(() => this.buttonDefaults()?.variant), 'solid');\n size = withConfigDefault(this.sizeInput, computed(() => this.buttonDefaults()?.size), 'md');\n color = withConfigDefault(this.colorInput, computed(() => this.buttonDefaults()?.color), 'primary');\n radius = withConfigDefault(this.radiusInput, computed(() => this.buttonDefaults()?.radius), 'sm');\n shadow = withConfigDefault(this.shadowInput, computed(() => this.buttonDefaults()?.shadow), 'none');\n compact = withConfigDefault(this.compactInput, computed(() => this.buttonDefaults()?.compact), false);\n\n // State\n disabled = input<boolean>(false);\n loading = input<boolean>(false);\n loadingText = input<string>('Loading...');\n\n // Layout\n fullWidth = input<boolean>(false);\n\n // Button props\n type = input<'button' | 'submit' | 'reset'>('button');\n\n // Icon\n icon = input<string>();\n iconPosition = input<'left' | 'right' | 'only'>('left');\n\n // Link mode\n href = input<string>();\n target = input<'_blank' | '_self' | '_parent' | '_top'>('_self');\n\n // Badge\n badge = input<string | number>();\n badgeColor = input<'primary' | 'error' | 'warning'>('error');\n\n // Accessibility\n ariaLabel = input<string>();\n\n clicked = output<MouseEvent>();\n\n protected iconSize = computed(() => {\n const sizeMap = { sm: 16, md: 18, lg: 20 };\n return sizeMap[this.size()];\n });\n\n protected hostClasses = computed(() => classNames(\n 'studio-button',\n `studio-button--${this.variant()}`,\n `studio-button--${this.size()}`,\n `studio-button--${this.color()}`,\n `studio-button--radius-${this.radius()}`,\n `studio-button--shadow-${this.shadow()}`,\n this.compact() && 'studio-button--compact',\n this.fullWidth() && 'studio-button--full',\n this.loading() && 'studio-button--loading',\n this.iconPosition() === 'only' && 'studio-button--icon-only'\n ));\n\n protected handleClick(event: MouseEvent): void {\n if (this.disabled() || this.loading()) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Handle link navigation\n const url = this.href();\n if (url) {\n const safeUrl = sanitizeUrl(url);\n if (safeUrl === '#') {\n // URL was blocked - don't navigate\n return;\n }\n\n const target = this.target();\n if (target === '_blank') {\n window.open(safeUrl, '_blank', 'noopener,noreferrer');\n } else {\n window.location.href = safeUrl;\n }\n }\n\n this.clicked.emit(event);\n }\n}\n","/**\n * Button component\n */\n\nexport * from './button.component';\n","/**\n * Primitives (Atoms)\n * Basic building blocks\n */\n\nexport * from './badge';\nexport * from './button';\nexport * from './icon';\n","/**\n * Composites (Molecules + Organisms)\n * Complex components built from primitives\n */\n\n// Export composite components here\n// Example: export * from './form-field';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Education components\n * Domain-specific components for educational platforms\n */\n\n// Export education components here\n// Example: export * from './course-card';\n// Example: export * from './lesson-viewer';\n// Example: export * from './quiz-builder';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Public API Surface of @eduboxpro/studio\n */\n\n/* ========================================\n * Configuration\n * ======================================== */\nexport * from './lib/config';\n\n/* ========================================\n * Components\n * ======================================== */\nexport * from './lib/primitives';\nexport * from './lib/composites';\nexport * from './lib/education';\n\n/* ========================================\n * Utilities\n * ======================================== */\nexport * from './lib/utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { InjectionToken, EnvironmentProviders } from '@angular/core';
2
+ import { InjectionToken, EnvironmentProviders, Signal } from '@angular/core';
3
3
  import { icons } from 'lucide-angular';
4
4
 
5
5
  /**
@@ -127,6 +127,39 @@ interface StudioThemeConfig {
127
127
  tooltip?: number;
128
128
  };
129
129
  }
130
+ /**
131
+ * Button component defaults configuration
132
+ */
133
+ interface ButtonDefaultsConfig {
134
+ variant?: 'solid' | 'outline' | 'ghost';
135
+ size?: 'sm' | 'md' | 'lg';
136
+ color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning';
137
+ radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
138
+ shadow?: 'none' | 'sm' | 'md' | 'lg';
139
+ compact?: boolean;
140
+ }
141
+ /**
142
+ * Badge component defaults configuration
143
+ */
144
+ interface BadgeDefaultsConfig {
145
+ variant?: 'solid' | 'outline' | 'soft' | 'dot';
146
+ size?: 'sm' | 'md' | 'lg';
147
+ color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'neutral';
148
+ radius?: 'sm' | 'md' | 'lg' | 'full';
149
+ }
150
+ /**
151
+ * Components defaults configuration
152
+ */
153
+ interface ComponentsConfig {
154
+ /**
155
+ * Button component defaults
156
+ */
157
+ button?: ButtonDefaultsConfig;
158
+ /**
159
+ * Badge component defaults
160
+ */
161
+ badge?: BadgeDefaultsConfig;
162
+ }
130
163
  /**
131
164
  * Main Studio configuration interface
132
165
  */
@@ -135,6 +168,10 @@ interface StudioConfig {
135
168
  * Theme configuration
136
169
  */
137
170
  theme?: StudioThemeConfig;
171
+ /**
172
+ * Components default values configuration
173
+ */
174
+ components?: ComponentsConfig;
138
175
  }
139
176
  /**
140
177
  * Injection token for Studio configuration
@@ -182,22 +219,77 @@ declare class StudioConfigService {
182
219
  */
183
220
  declare function provideStudioConfig(config?: StudioConfig): EnvironmentProviders;
184
221
 
222
+ declare class BadgeComponent {
223
+ private readonly configService;
224
+ private readonly badgeDefaults;
225
+ variantInput: _angular_core.InputSignal<"solid" | "outline" | "soft" | "dot" | undefined>;
226
+ sizeInput: _angular_core.InputSignal<"sm" | "md" | "lg" | undefined>;
227
+ colorInput: _angular_core.InputSignal<"primary" | "secondary" | "success" | "error" | "warning" | "info" | "neutral" | undefined>;
228
+ radiusInput: _angular_core.InputSignal<"sm" | "md" | "lg" | "full" | undefined>;
229
+ variant: _angular_core.Signal<"solid" | "outline" | "soft" | "dot">;
230
+ size: _angular_core.Signal<"sm" | "md" | "lg">;
231
+ color: _angular_core.Signal<"primary" | "secondary" | "success" | "error" | "warning" | "info" | "neutral">;
232
+ radius: _angular_core.Signal<"sm" | "md" | "lg" | "full">;
233
+ icon: _angular_core.InputSignal<string | undefined>;
234
+ iconPosition: _angular_core.InputSignal<"left" | "right">;
235
+ dot: _angular_core.InputSignal<boolean>;
236
+ dotColor: _angular_core.InputSignal<"primary" | "secondary" | "success" | "error" | "warning" | "info" | "neutral" | undefined>;
237
+ removable: _angular_core.InputSignal<boolean>;
238
+ removed: _angular_core.OutputEmitterRef<void>;
239
+ href: _angular_core.InputSignal<string | undefined>;
240
+ target: _angular_core.InputSignal<"_blank" | "_self" | "_parent" | "_top">;
241
+ disabled: _angular_core.InputSignal<boolean>;
242
+ clicked: _angular_core.OutputEmitterRef<MouseEvent>;
243
+ value: _angular_core.InputSignal<string | number | undefined>;
244
+ max: _angular_core.InputSignal<number | undefined>;
245
+ showZero: _angular_core.InputSignal<boolean>;
246
+ uppercase: _angular_core.InputSignal<boolean>;
247
+ bold: _angular_core.InputSignal<boolean>;
248
+ pulse: _angular_core.InputSignal<boolean>;
249
+ autoColor: _angular_core.InputSignal<boolean>;
250
+ protected iconSize: _angular_core.Signal<number>;
251
+ protected displayValue: _angular_core.Signal<string>;
252
+ protected isVisible: _angular_core.Signal<boolean>;
253
+ protected hostClasses: _angular_core.Signal<string>;
254
+ protected handleClick(event: MouseEvent): void;
255
+ protected handleRemove(event: MouseEvent): void;
256
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BadgeComponent, never>;
257
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BadgeComponent, "studio-badge", never, { "variantInput": { "alias": "variant"; "required": false; "isSignal": true; }; "sizeInput": { "alias": "size"; "required": false; "isSignal": true; }; "colorInput": { "alias": "color"; "required": false; "isSignal": true; }; "radiusInput": { "alias": "radius"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconPosition": { "alias": "iconPosition"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; "dotColor": { "alias": "dotColor"; "required": false; "isSignal": true; }; "removable": { "alias": "removable"; "required": false; "isSignal": true; }; "href": { "alias": "href"; "required": false; "isSignal": true; }; "target": { "alias": "target"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "showZero": { "alias": "showZero"; "required": false; "isSignal": true; }; "uppercase": { "alias": "uppercase"; "required": false; "isSignal": true; }; "bold": { "alias": "bold"; "required": false; "isSignal": true; }; "pulse": { "alias": "pulse"; "required": false; "isSignal": true; }; "autoColor": { "alias": "autoColor"; "required": false; "isSignal": true; }; }, { "removed": "removed"; "clicked": "clicked"; }, never, ["*"], true, never>;
258
+ }
259
+
185
260
  declare class ButtonComponent {
186
- variant: _angular_core.InputSignal<"solid" | "outline" | "ghost">;
187
- size: _angular_core.InputSignal<"sm" | "lg" | "md">;
188
- color: _angular_core.InputSignal<"primary" | "secondary" | "success" | "error" | "warning">;
261
+ private readonly configService;
262
+ private readonly buttonDefaults;
263
+ variantInput: _angular_core.InputSignal<"solid" | "outline" | "ghost" | undefined>;
264
+ sizeInput: _angular_core.InputSignal<"sm" | "md" | "lg" | undefined>;
265
+ colorInput: _angular_core.InputSignal<"primary" | "secondary" | "success" | "error" | "warning" | undefined>;
266
+ radiusInput: _angular_core.InputSignal<"sm" | "md" | "lg" | "none" | "xl" | "full" | undefined>;
267
+ shadowInput: _angular_core.InputSignal<"sm" | "md" | "lg" | "none" | undefined>;
268
+ compactInput: _angular_core.InputSignal<boolean | undefined>;
269
+ variant: _angular_core.Signal<"solid" | "outline" | "ghost">;
270
+ size: _angular_core.Signal<"sm" | "md" | "lg">;
271
+ color: _angular_core.Signal<"primary" | "secondary" | "success" | "error" | "warning">;
272
+ radius: _angular_core.Signal<"sm" | "md" | "lg" | "none" | "xl" | "full">;
273
+ shadow: _angular_core.Signal<"sm" | "md" | "lg" | "none">;
274
+ compact: _angular_core.Signal<boolean>;
189
275
  disabled: _angular_core.InputSignal<boolean>;
190
- fullWidth: _angular_core.InputSignal<boolean>;
191
276
  loading: _angular_core.InputSignal<boolean>;
277
+ loadingText: _angular_core.InputSignal<string>;
278
+ fullWidth: _angular_core.InputSignal<boolean>;
192
279
  type: _angular_core.InputSignal<"button" | "submit" | "reset">;
193
280
  icon: _angular_core.InputSignal<string | undefined>;
194
281
  iconPosition: _angular_core.InputSignal<"left" | "right" | "only">;
282
+ href: _angular_core.InputSignal<string | undefined>;
283
+ target: _angular_core.InputSignal<"_blank" | "_self" | "_parent" | "_top">;
284
+ badge: _angular_core.InputSignal<string | number | undefined>;
285
+ badgeColor: _angular_core.InputSignal<"primary" | "error" | "warning">;
286
+ ariaLabel: _angular_core.InputSignal<string | undefined>;
195
287
  clicked: _angular_core.OutputEmitterRef<MouseEvent>;
196
288
  protected iconSize: _angular_core.Signal<number>;
197
289
  protected hostClasses: _angular_core.Signal<string>;
198
290
  protected handleClick(event: MouseEvent): void;
199
291
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ButtonComponent, never>;
200
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ButtonComponent, "studio-button", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconPosition": { "alias": "iconPosition"; "required": false; "isSignal": true; }; }, { "clicked": "clicked"; }, never, ["*"], true, never>;
292
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ButtonComponent, "studio-button", never, { "variantInput": { "alias": "variant"; "required": false; "isSignal": true; }; "sizeInput": { "alias": "size"; "required": false; "isSignal": true; }; "colorInput": { "alias": "color"; "required": false; "isSignal": true; }; "radiusInput": { "alias": "radius"; "required": false; "isSignal": true; }; "shadowInput": { "alias": "shadow"; "required": false; "isSignal": true; }; "compactInput": { "alias": "compact"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconPosition": { "alias": "iconPosition"; "required": false; "isSignal": true; }; "href": { "alias": "href"; "required": false; "isSignal": true; }; "target": { "alias": "target"; "required": false; "isSignal": true; }; "badge": { "alias": "badge"; "required": false; "isSignal": true; }; "badgeColor": { "alias": "badgeColor"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "clicked": "clicked"; }, never, ["*"], true, never>;
201
293
  }
202
294
 
203
295
  declare class IconComponent {
@@ -248,5 +340,77 @@ declare class IconComponent {
248
340
  */
249
341
  declare function provideStudioIcons(): EnvironmentProviders;
250
342
 
251
- export { ButtonComponent, IconComponent, STUDIO_CONFIG, StudioConfigService, provideStudioConfig, provideStudioIcons };
252
- export type { ColorConfig, StudioConfig, StudioThemeConfig, ThemeMode };
343
+ /**
344
+ * Проверяет безопасность URL для навигации
345
+ *
346
+ * @param url - URL для проверки
347
+ * @returns true если URL безопасен (http/https или относительный)
348
+ *
349
+ * @example
350
+ * ```typescript
351
+ * isSafeUrl('https://example.com') // true
352
+ * isSafeUrl('javascript:alert(1)') // false
353
+ * isSafeUrl('/relative/path') // true
354
+ * ```
355
+ */
356
+ declare function isSafeUrl(url: string): boolean;
357
+ /**
358
+ * Sanitize URL перед использованием в навигации
359
+ *
360
+ * @param url - URL для sanitization
361
+ * @returns Безопасный URL или '#' если URL небезопасен
362
+ *
363
+ * @example
364
+ * ```typescript
365
+ * sanitizeUrl('https://example.com') // 'https://example.com'
366
+ * sanitizeUrl('javascript:alert(1)') // '#' (с предупреждением в консоли)
367
+ * ```
368
+ */
369
+ declare function sanitizeUrl(url: string): string;
370
+
371
+ /**
372
+ * Объединяет CSS классы, игнорируя falsy значения
373
+ *
374
+ * @param classes - Массив классов (строки, undefined, null, false)
375
+ * @returns Строка с объединенными классами
376
+ *
377
+ * @example
378
+ * ```typescript
379
+ * classNames('btn', 'btn-primary') // 'btn btn-primary'
380
+ * classNames('btn', isActive && 'active') // 'btn active' если isActive=true, иначе 'btn'
381
+ * classNames('btn', undefined, null, false, 'large') // 'btn large'
382
+ * ```
383
+ */
384
+ declare function classNames(...classes: (string | false | undefined | null)[]): string;
385
+
386
+ /**
387
+ * Создает computed signal с fallback chain: input → config → default
388
+ *
389
+ * Упрощает паттерн configurable inputs, убирая boilerplate код.
390
+ *
391
+ * @param inputSignal - Input signal от пользователя
392
+ * @param configSignal - Config значение (может быть undefined)
393
+ * @param defaultValue - Fallback значение
394
+ * @returns Computed signal с resolved значением
395
+ *
396
+ * @example
397
+ * ```typescript
398
+ * export class ButtonComponent {
399
+ * private defaults = computed(() => this.configService.config().components?.button);
400
+ *
401
+ * // Input
402
+ * variantInput = input<Variant | undefined>(undefined, { alias: 'variant' });
403
+ *
404
+ * // Resolved value с config fallback
405
+ * variant = withConfigDefault(
406
+ * this.variantInput,
407
+ * computed(() => this.defaults()?.variant),
408
+ * 'solid'
409
+ * );
410
+ * }
411
+ * ```
412
+ */
413
+ declare function withConfigDefault<T>(inputSignal: Signal<T | undefined>, configSignal: Signal<T | undefined>, defaultValue: T): Signal<T>;
414
+
415
+ export { BadgeComponent, ButtonComponent, IconComponent, STUDIO_CONFIG, StudioConfigService, classNames, isSafeUrl, provideStudioConfig, provideStudioIcons, sanitizeUrl, withConfigDefault };
416
+ export type { BadgeDefaultsConfig, ButtonDefaultsConfig, ColorConfig, ComponentsConfig, StudioConfig, StudioThemeConfig, ThemeMode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eduboxpro/studio",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Modern Angular UI library for educational platforms with customizable design system",
5
5
  "keywords": [
6
6
  "angular",
@@ -19,8 +19,9 @@
19
19
  "url": "git+https://github.com/eduboxpro/studio.git"
20
20
  },
21
21
  "peerDependencies": {
22
- "@angular/common": "^20.3.0",
23
- "@angular/core": "^20.3.0"
22
+ "@angular/common": "^20.0.0",
23
+ "@angular/core": "^20.0.0",
24
+ "lucide-angular": "^0.468.0"
24
25
  },
25
26
  "sideEffects": [
26
27
  "*.css",
@@ -6,10 +6,10 @@
6
6
  */
7
7
 
8
8
  /* Design Tokens */
9
- @import 'tokens';
9
+ @forward 'tokens';
10
10
 
11
11
  /* CSS Reset */
12
- @import 'reset';
12
+ @forward 'reset';
13
13
 
14
- /* Mixins - import in component styles as needed */
15
- /* @import '@eduboxpro/studio/styles/mixins'; */
14
+ /* Mixins - use in component styles as needed */
15
+ /* @use '@eduboxpro/studio/styles/mixins'; */