@eduboxpro/studio 0.1.6 → 0.1.8

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.
@@ -1,8 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, signal, effect, Injectable, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, input, computed, ChangeDetectionStrategy, Component, output, viewChild, forwardRef, model } from '@angular/core';
3
- import { DOCUMENT } from '@angular/common';
2
+ import { InjectionToken, inject, signal, effect, Injectable, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, input, computed, ChangeDetectionStrategy, Component, output, ElementRef, forwardRef, viewChild, model } from '@angular/core';
3
+ import * as i1$1 from '@angular/common';
4
+ import { DOCUMENT, CommonModule } from '@angular/common';
4
5
  import * as i1 from 'lucide-angular';
5
- import { icons, LucideAngularModule, LucideIconProvider, LUCIDE_ICONS, Moon, Sun, 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
+ import { icons, LucideAngularModule, LucideIconProvider, LUCIDE_ICONS, Laptop, MessageSquare, List, Grid3x3, Strikethrough, Underline, Italic, Bold, AlignJustify, AlignRight, AlignCenter, AlignLeft, Moon, Sun, 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
7
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
7
8
 
8
9
  /**
@@ -442,7 +443,19 @@ function provideStudioIcons() {
442
443
  Loader2,
443
444
  ShoppingCart,
444
445
  Sun,
445
- Moon
446
+ Moon,
447
+ AlignLeft,
448
+ AlignCenter,
449
+ AlignRight,
450
+ AlignJustify,
451
+ Bold,
452
+ Italic,
453
+ Underline,
454
+ Strikethrough,
455
+ Grid3x3,
456
+ List,
457
+ MessageSquare,
458
+ Laptop
446
459
  })
447
460
  }
448
461
  ]);
@@ -868,6 +881,302 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
868
881
  * Button component
869
882
  */
870
883
 
884
+ class ButtonGroupComponent {
885
+ elementRef = inject(ElementRef);
886
+ configService = inject(StudioConfigService);
887
+ groupDefaults = computed(() => this.configService.config().components?.buttonGroup, ...(ngDevMode ? [{ debugName: "groupDefaults" }] : []));
888
+ orientationInput = input(undefined, ...(ngDevMode ? [{ debugName: "orientationInput", alias: 'orientation' }] : [{ alias: 'orientation' }]));
889
+ sizeInput = input(undefined, ...(ngDevMode ? [{ debugName: "sizeInput", alias: 'size' }] : [{ alias: 'size' }]));
890
+ variantInput = input(undefined, ...(ngDevMode ? [{ debugName: "variantInput", alias: 'variant' }] : [{ alias: 'variant' }]));
891
+ colorInput = input(undefined, ...(ngDevMode ? [{ debugName: "colorInput", alias: 'color' }] : [{ alias: 'color' }]));
892
+ radiusInput = input(undefined, ...(ngDevMode ? [{ debugName: "radiusInput", alias: 'radius' }] : [{ alias: 'radius' }]));
893
+ orientation = withConfigDefault(this.orientationInput, computed(() => this.groupDefaults()?.orientation), 'horizontal');
894
+ size = withConfigDefault(this.sizeInput, computed(() => this.groupDefaults()?.size), undefined);
895
+ variant = withConfigDefault(this.variantInput, computed(() => this.groupDefaults()?.variant), undefined);
896
+ color = withConfigDefault(this.colorInput, computed(() => this.groupDefaults()?.color), undefined);
897
+ radius = withConfigDefault(this.radiusInput, computed(() => this.groupDefaults()?.radius), undefined);
898
+ attached = input(false, ...(ngDevMode ? [{ debugName: "attached" }] : []));
899
+ fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : []));
900
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
901
+ spacing = input('sm', ...(ngDevMode ? [{ debugName: "spacing" }] : []));
902
+ align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : []));
903
+ ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : []));
904
+ role = input('group', ...(ngDevMode ? [{ debugName: "role" }] : []));
905
+ hostClasses = computed(() => classNames('studio-button-group', `studio-button-group--${this.orientation()}`, `studio-button-group--spacing-${this.spacing()}`, `studio-button-group--align-${this.align()}`, this.attached() && 'studio-button-group--attached', this.fullWidth() && 'studio-button-group--full', this.disabled() && 'studio-button-group--disabled'), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
906
+ constructor() {
907
+ effect(() => {
908
+ const isAttached = this.attached();
909
+ const hostElement = this.elementRef.nativeElement;
910
+ const buttonElements = hostElement.querySelectorAll('studio-button');
911
+ buttonElements.forEach((buttonEl, index) => {
912
+ const isFirst = index === 0;
913
+ const isLast = index === buttonElements.length - 1;
914
+ const isMiddle = !isFirst && !isLast;
915
+ if (isAttached) {
916
+ buttonEl.classList.add('studio-button-group__item--attached');
917
+ if (isFirst)
918
+ buttonEl.classList.add('studio-button-group__item--first');
919
+ if (isLast)
920
+ buttonEl.classList.add('studio-button-group__item--last');
921
+ if (isMiddle)
922
+ buttonEl.classList.add('studio-button-group__item--middle');
923
+ }
924
+ else {
925
+ buttonEl.classList.remove('studio-button-group__item--attached');
926
+ buttonEl.classList.remove('studio-button-group__item--first');
927
+ buttonEl.classList.remove('studio-button-group__item--last');
928
+ buttonEl.classList.remove('studio-button-group__item--middle');
929
+ }
930
+ });
931
+ });
932
+ }
933
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
934
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.12", type: ButtonGroupComponent, isStandalone: true, selector: "studio-button-group", inputs: { orientationInput: { classPropertyName: "orientationInput", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, sizeInput: { classPropertyName: "sizeInput", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variantInput: { classPropertyName: "variantInput", publicName: "variant", 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 }, attached: { classPropertyName: "attached", publicName: "attached", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, spacing: { classPropertyName: "spacing", publicName: "spacing", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.role": "role()", "attr.aria-label": "ariaLabel()" } }, ngImport: i0, template: `<ng-content select="studio-button" />`, isInline: true, styles: [":host{display:inline-flex;align-items:center;position:relative}:host(.studio-button-group--horizontal){flex-direction:row}:host(.studio-button-group--vertical){flex-direction:column}:host(.studio-button-group--spacing-none){gap:0}:host(.studio-button-group--spacing-xs){gap:var(--studio-spacing-xs)}:host(.studio-button-group--spacing-sm){gap:var(--studio-spacing-sm)}:host(.studio-button-group--spacing-md){gap:var(--studio-spacing-md)}:host(.studio-button-group--spacing-lg){gap:var(--studio-spacing-lg)}:host(.studio-button-group--align-start){justify-content:flex-start}:host(.studio-button-group--align-center){justify-content:center}:host(.studio-button-group--align-end){justify-content:flex-end}:host(.studio-button-group--align-stretch){align-items:stretch}:host(.studio-button-group--align-stretch) ::ng-deep studio-button{flex:1}:host(.studio-button-group--full){width:100%}:host(.studio-button-group--full) ::ng-deep studio-button{flex:1}:host(.studio-button-group--attached){gap:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--attached{margin:0;position:relative}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--middle{border-radius:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--first:not(.studio-button-group__item--last){border-top-right-radius:0;border-bottom-right-radius:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--last:not(.studio-button-group__item--first){border-top-left-radius:0;border-bottom-left-radius:0}:host(.studio-button-group--attached).studio-button-group--horizontal ::ng-deep studio-button.studio-button-group__item--attached:not(:last-child){border-right:1px solid rgba(0,0,0,.1)}:host(.studio-button-group--attached).studio-button-group--horizontal ::ng-deep studio-button.studio-button-group__item--attached.studio-button--outline:not(:last-child){margin-right:-1px}:host(.studio-button-group--vertical){align-items:stretch}:host(.studio-button-group--vertical) ::ng-deep studio-button{width:100%;justify-content:flex-start}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--first:not(.studio-button-group__item--last){border-top-right-radius:var(--studio-radius-sm);border-bottom-right-radius:0;border-top-left-radius:var(--studio-radius-sm);border-bottom-left-radius:0}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--last:not(.studio-button-group__item--first){border-top-left-radius:0;border-bottom-left-radius:var(--studio-radius-sm);border-top-right-radius:0;border-bottom-right-radius:var(--studio-radius-sm)}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--attached:not(:last-child){border-right:none;border-bottom:1px solid rgba(255,255,255,.2)}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--middle{border-radius:0}:host(.studio-button-group--vertical.studio-button-group--full) ::ng-deep studio-button{width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
935
+ }
936
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonGroupComponent, decorators: [{
937
+ type: Component,
938
+ args: [{ selector: 'studio-button-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
939
+ '[class]': 'hostClasses()',
940
+ '[attr.role]': 'role()',
941
+ '[attr.aria-label]': 'ariaLabel()'
942
+ }, template: `<ng-content select="studio-button" />`, styles: [":host{display:inline-flex;align-items:center;position:relative}:host(.studio-button-group--horizontal){flex-direction:row}:host(.studio-button-group--vertical){flex-direction:column}:host(.studio-button-group--spacing-none){gap:0}:host(.studio-button-group--spacing-xs){gap:var(--studio-spacing-xs)}:host(.studio-button-group--spacing-sm){gap:var(--studio-spacing-sm)}:host(.studio-button-group--spacing-md){gap:var(--studio-spacing-md)}:host(.studio-button-group--spacing-lg){gap:var(--studio-spacing-lg)}:host(.studio-button-group--align-start){justify-content:flex-start}:host(.studio-button-group--align-center){justify-content:center}:host(.studio-button-group--align-end){justify-content:flex-end}:host(.studio-button-group--align-stretch){align-items:stretch}:host(.studio-button-group--align-stretch) ::ng-deep studio-button{flex:1}:host(.studio-button-group--full){width:100%}:host(.studio-button-group--full) ::ng-deep studio-button{flex:1}:host(.studio-button-group--attached){gap:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--attached{margin:0;position:relative}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--middle{border-radius:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--first:not(.studio-button-group__item--last){border-top-right-radius:0;border-bottom-right-radius:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--last:not(.studio-button-group__item--first){border-top-left-radius:0;border-bottom-left-radius:0}:host(.studio-button-group--attached).studio-button-group--horizontal ::ng-deep studio-button.studio-button-group__item--attached:not(:last-child){border-right:1px solid rgba(0,0,0,.1)}:host(.studio-button-group--attached).studio-button-group--horizontal ::ng-deep studio-button.studio-button-group__item--attached.studio-button--outline:not(:last-child){margin-right:-1px}:host(.studio-button-group--vertical){align-items:stretch}:host(.studio-button-group--vertical) ::ng-deep studio-button{width:100%;justify-content:flex-start}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--first:not(.studio-button-group__item--last){border-top-right-radius:var(--studio-radius-sm);border-bottom-right-radius:0;border-top-left-radius:var(--studio-radius-sm);border-bottom-left-radius:0}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--last:not(.studio-button-group__item--first){border-top-left-radius:0;border-bottom-left-radius:var(--studio-radius-sm);border-top-right-radius:0;border-bottom-right-radius:var(--studio-radius-sm)}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--attached:not(:last-child){border-right:none;border-bottom:1px solid rgba(255,255,255,.2)}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--middle{border-radius:0}:host(.studio-button-group--vertical.studio-button-group--full) ::ng-deep studio-button{width:100%}\n"] }]
943
+ }], ctorParameters: () => [], propDecorators: { orientationInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], sizeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variantInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], colorInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], radiusInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], attached: [{ type: i0.Input, args: [{ isSignal: true, alias: "attached", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], spacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "spacing", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }] } });
944
+
945
+ /**
946
+ * Checkbox component for selecting boolean values
947
+ *
948
+ * @example
949
+ * <studio-checkbox
950
+ * [(ngModel)]="accepted"
951
+ * label="I accept terms and conditions"
952
+ * (changed)="onAccept($event)"
953
+ * />
954
+ */
955
+ class CheckboxComponent {
956
+ configService = inject(StudioConfigService);
957
+ checkboxDefaults = computed(() => this.configService.config().components?.checkbox, ...(ngDevMode ? [{ debugName: "checkboxDefaults" }] : []));
958
+ // ==========================================
959
+ // INPUTS - Appearance
960
+ // ==========================================
961
+ /**
962
+ * Size of the checkbox
963
+ */
964
+ size = input(this.checkboxDefaults()?.size ?? 'md', ...(ngDevMode ? [{ debugName: "size" }] : []));
965
+ /**
966
+ * Color scheme
967
+ */
968
+ color = input(this.checkboxDefaults()?.color ?? 'primary', ...(ngDevMode ? [{ debugName: "color" }] : []));
969
+ /**
970
+ * Visual variant
971
+ */
972
+ variant = input(this.checkboxDefaults()?.variant ?? 'default', ...(ngDevMode ? [{ debugName: "variant" }] : []));
973
+ /**
974
+ * Border radius
975
+ */
976
+ radius = input(this.checkboxDefaults()?.radius ?? 'sm', ...(ngDevMode ? [{ debugName: "radius" }] : []));
977
+ // ==========================================
978
+ // INPUTS - Labels & Description
979
+ // ==========================================
980
+ /**
981
+ * Label text
982
+ */
983
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
984
+ /**
985
+ * Label position relative to checkbox
986
+ */
987
+ labelPosition = input(this.checkboxDefaults()?.labelPosition ?? 'right', ...(ngDevMode ? [{ debugName: "labelPosition" }] : []));
988
+ /**
989
+ * Additional description text
990
+ */
991
+ description = input(...(ngDevMode ? [undefined, { debugName: "description" }] : []));
992
+ /**
993
+ * Helper text
994
+ */
995
+ hint = input(...(ngDevMode ? [undefined, { debugName: "hint" }] : []));
996
+ // ==========================================
997
+ // INPUTS - Validation
998
+ // ==========================================
999
+ /**
1000
+ * Required field
1001
+ */
1002
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
1003
+ /**
1004
+ * Error state
1005
+ */
1006
+ error = input(false, ...(ngDevMode ? [{ debugName: "error" }] : []));
1007
+ /**
1008
+ * Error message
1009
+ */
1010
+ errorMessage = input(...(ngDevMode ? [undefined, { debugName: "errorMessage" }] : []));
1011
+ // ==========================================
1012
+ // INPUTS - Behavior
1013
+ // ==========================================
1014
+ /**
1015
+ * Disabled state
1016
+ */
1017
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1018
+ /**
1019
+ * Readonly state
1020
+ */
1021
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
1022
+ /**
1023
+ * Indeterminate state (for "select all" checkboxes)
1024
+ */
1025
+ indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : []));
1026
+ /**
1027
+ * Name attribute for form control
1028
+ */
1029
+ name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
1030
+ /**
1031
+ * Tab index
1032
+ */
1033
+ tabIndex = input(0, ...(ngDevMode ? [{ debugName: "tabIndex" }] : []));
1034
+ /**
1035
+ * Value for checkbox groups
1036
+ */
1037
+ value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
1038
+ // ==========================================
1039
+ // OUTPUTS
1040
+ // ==========================================
1041
+ /**
1042
+ * Emitted when checkbox state changes
1043
+ */
1044
+ changed = output();
1045
+ // ==========================================
1046
+ // STATE
1047
+ // ==========================================
1048
+ /**
1049
+ * Internal checked state
1050
+ */
1051
+ internalChecked = signal(false, ...(ngDevMode ? [{ debugName: "internalChecked" }] : []));
1052
+ /**
1053
+ * Internal focus state
1054
+ */
1055
+ isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : []));
1056
+ /**
1057
+ * Unique ID for accessibility
1058
+ */
1059
+ checkboxId = signal(`studio-checkbox-${Math.random().toString(36).substr(2, 9)}`, ...(ngDevMode ? [{ debugName: "checkboxId" }] : []));
1060
+ // ==========================================
1061
+ // COMPUTED
1062
+ // ==========================================
1063
+ /**
1064
+ * Host CSS classes
1065
+ */
1066
+ hostClasses = computed(() => ({
1067
+ 'studio-checkbox-wrapper': true,
1068
+ [`studio-checkbox-wrapper--${this.size()}`]: true,
1069
+ 'studio-checkbox-wrapper--disabled': this.disabled(),
1070
+ 'studio-checkbox-wrapper--error': this.error(),
1071
+ 'studio-checkbox-wrapper--focused': this.isFocused(),
1072
+ 'studio-checkbox-wrapper--label-left': this.labelPosition() === 'left'
1073
+ }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
1074
+ /**
1075
+ * Checkbox element CSS classes
1076
+ */
1077
+ checkboxClasses = computed(() => ({
1078
+ 'studio-checkbox': true,
1079
+ [`studio-checkbox--${this.size()}`]: true,
1080
+ [`studio-checkbox--${this.color()}`]: true,
1081
+ [`studio-checkbox--${this.variant()}`]: true,
1082
+ [`studio-checkbox--radius-${this.radius()}`]: true,
1083
+ 'studio-checkbox--checked': this.internalChecked(),
1084
+ 'studio-checkbox--indeterminate': this.indeterminate(),
1085
+ 'studio-checkbox--disabled': this.disabled(),
1086
+ 'studio-checkbox--error': this.error()
1087
+ }), ...(ngDevMode ? [{ debugName: "checkboxClasses" }] : []));
1088
+ /**
1089
+ * Show error message
1090
+ */
1091
+ showError = computed(() => this.error() && this.errorMessage(), ...(ngDevMode ? [{ debugName: "showError" }] : []));
1092
+ /**
1093
+ * Show hint
1094
+ */
1095
+ showHint = computed(() => !this.error() && this.hint(), ...(ngDevMode ? [{ debugName: "showHint" }] : []));
1096
+ /**
1097
+ * ARIA checked state
1098
+ */
1099
+ ariaChecked = computed(() => {
1100
+ if (this.indeterminate())
1101
+ return 'mixed';
1102
+ return this.internalChecked() ? 'true' : 'false';
1103
+ }, ...(ngDevMode ? [{ debugName: "ariaChecked" }] : []));
1104
+ // ==========================================
1105
+ // CONTROL VALUE ACCESSOR
1106
+ // ==========================================
1107
+ onChange = () => { };
1108
+ onTouched = () => { };
1109
+ writeValue(value) {
1110
+ this.internalChecked.set(value ?? false);
1111
+ }
1112
+ registerOnChange(fn) {
1113
+ this.onChange = fn;
1114
+ }
1115
+ registerOnTouched(fn) {
1116
+ this.onTouched = fn;
1117
+ }
1118
+ setDisabledState(isDisabled) {
1119
+ // Disabled state is controlled via input
1120
+ }
1121
+ // ==========================================
1122
+ // METHODS
1123
+ // ==========================================
1124
+ /**
1125
+ * Handle checkbox toggle
1126
+ */
1127
+ handleChange(event) {
1128
+ if (this.disabled() || this.readonly()) {
1129
+ event.preventDefault();
1130
+ return;
1131
+ }
1132
+ const newValue = event.target.checked;
1133
+ this.internalChecked.set(newValue);
1134
+ this.onChange(newValue);
1135
+ this.changed.emit(newValue);
1136
+ }
1137
+ /**
1138
+ * Handle focus
1139
+ */
1140
+ handleFocus() {
1141
+ this.isFocused.set(true);
1142
+ }
1143
+ /**
1144
+ * Handle blur
1145
+ */
1146
+ handleBlur() {
1147
+ this.isFocused.set(false);
1148
+ this.onTouched();
1149
+ }
1150
+ /**
1151
+ * Handle label click
1152
+ */
1153
+ handleLabelClick(event) {
1154
+ if (this.disabled() || this.readonly()) {
1155
+ event.preventDefault();
1156
+ }
1157
+ }
1158
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: CheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1159
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: CheckboxComponent, isStandalone: true, selector: "studio-checkbox", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, radius: { classPropertyName: "radius", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, host: { properties: { "class": "hostClasses()", "attr.data-size": "size()", "attr.data-color": "color()", "attr.data-disabled": "disabled()", "attr.data-error": "error()" } }, providers: [{
1160
+ provide: NG_VALUE_ACCESSOR,
1161
+ useExisting: forwardRef(() => CheckboxComponent),
1162
+ multi: true
1163
+ }], ngImport: i0, template: "<label\n [for]=\"checkboxId()\"\n [ngClass]=\"hostClasses()\"\n (click)=\"handleLabelClick($event)\"\n>\n <!-- Checkbox input -->\n <input\n type=\"checkbox\"\n [id]=\"checkboxId()\"\n [name]=\"name()\"\n [checked]=\"internalChecked()\"\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [tabIndex]=\"tabIndex()\"\n [attr.aria-checked]=\"ariaChecked()\"\n [attr.aria-label]=\"label() || undefined\"\n [attr.aria-describedby]=\"showHint() || showError() ? checkboxId() + '-description' : undefined\"\n [attr.aria-invalid]=\"error()\"\n [attr.aria-required]=\"required()\"\n class=\"studio-checkbox__input\"\n (change)=\"handleChange($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n />\n\n <!-- Custom checkbox -->\n <span [ngClass]=\"checkboxClasses()\">\n <!-- Checkmark icon -->\n @if (internalChecked() && !indeterminate()) {\n <svg\n class=\"studio-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M13.3333 4L6 11.3333L2.66666 8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n }\n\n <!-- Indeterminate icon -->\n @if (indeterminate()) {\n <svg\n class=\"studio-checkbox__icon studio-checkbox__icon--indeterminate\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M4 8H12\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n }\n </span>\n\n <!-- Label content -->\n @if (label() || description()) {\n <span class=\"studio-checkbox__label-wrapper\">\n @if (label()) {\n <span class=\"studio-checkbox__label\">\n {{ label() }}\n @if (required()) {\n <span class=\"studio-checkbox__required\" aria-hidden=\"true\">*</span>\n }\n </span>\n }\n\n @if (description()) {\n <span class=\"studio-checkbox__description\">\n {{ description() }}\n </span>\n }\n </span>\n }\n</label>\n\n<!-- Helper text / Error message -->\n@if (showHint() || showError()) {\n <div\n [id]=\"checkboxId() + '-description'\"\n class=\"studio-checkbox__info\"\n >\n @if (showError()) {\n <span class=\"studio-checkbox__error\">\n {{ errorMessage() }}\n </span>\n }\n\n @if (showHint()) {\n <span class=\"studio-checkbox__hint\">\n {{ hint() }}\n </span>\n }\n </div>\n}\n", styles: [":host{display:inline-flex;flex-direction:column;font-family:var(--studio-font-family)!important}.studio-checkbox-wrapper{display:inline-flex;align-items:flex-start;gap:var(--studio-spacing-sm);cursor:pointer;-webkit-user-select:none;user-select:none;position:relative}.studio-checkbox-wrapper--label-left{flex-direction:row-reverse}.studio-checkbox-wrapper--disabled{cursor:not-allowed;opacity:.5}.studio-checkbox-wrapper--sm{font-size:var(--studio-font-size-sm)}.studio-checkbox-wrapper--md{font-size:var(--studio-font-size-base)}.studio-checkbox-wrapper--lg{font-size:var(--studio-font-size-lg)}.studio-checkbox__input{position:absolute;opacity:0;pointer-events:none;width:0;height:0}.studio-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;border:2px solid var(--studio-border-primary);background-color:var(--studio-bg-primary);transition:all var(--studio-transition-base)}.studio-checkbox--sm{width:1rem;height:1rem}.studio-checkbox--md{width:1.25rem;height:1.25rem}.studio-checkbox--lg{width:1.5rem;height:1.5rem}.studio-checkbox--radius-none{border-radius:0}.studio-checkbox--radius-sm{border-radius:var(--studio-radius-sm)}.studio-checkbox--radius-md{border-radius:var(--studio-radius-md)}.studio-checkbox--radius-lg{border-radius:var(--studio-radius-lg)}.studio-checkbox--radius-full{border-radius:var(--studio-radius-full)}.studio-checkbox--default.studio-checkbox--checked,.studio-checkbox--default.studio-checkbox--indeterminate{border-color:transparent}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--primary,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--primary{background-color:var(--studio-primary);color:var(--studio-text-inverse)}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--secondary,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--secondary{background-color:var(--studio-secondary);color:var(--studio-text-inverse)}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--success,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--success{background-color:var(--studio-success);color:var(--studio-text-inverse)}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--error,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--error{background-color:var(--studio-error);color:var(--studio-text-inverse)}.studio-checkbox--outlined.studio-checkbox--checked,.studio-checkbox--outlined.studio-checkbox--indeterminate{background-color:transparent}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--primary,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--primary{border-color:var(--studio-primary);color:var(--studio-primary)}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--secondary,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--secondary{border-color:var(--studio-secondary);color:var(--studio-secondary)}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--success,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--success{border-color:var(--studio-success);color:var(--studio-success)}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--error,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--error{border-color:var(--studio-error);color:var(--studio-error)}.studio-checkbox--filled.studio-checkbox--primary{background-color:var(--studio-primary-bg);border-color:var(--studio-primary-bg)}.studio-checkbox--filled.studio-checkbox--secondary{background-color:var(--studio-secondary-bg);border-color:var(--studio-secondary-bg)}.studio-checkbox--filled.studio-checkbox--success{background-color:var(--studio-success-bg);border-color:var(--studio-success-bg)}.studio-checkbox--filled.studio-checkbox--error{background-color:var(--studio-error-bg);border-color:var(--studio-error-bg)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--primary,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--primary{background-color:var(--studio-primary);border-color:var(--studio-primary);color:var(--studio-text-inverse)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--secondary,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--secondary{background-color:var(--studio-secondary);border-color:var(--studio-secondary);color:var(--studio-text-inverse)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--success,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--success{background-color:var(--studio-success);border-color:var(--studio-success);color:var(--studio-text-inverse)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--error,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--error{background-color:var(--studio-error);border-color:var(--studio-error);color:var(--studio-text-inverse)}.studio-checkbox--error:not(.studio-checkbox--checked):not(.studio-checkbox--indeterminate){border-color:var(--studio-error)}.studio-checkbox:hover:not(.studio-checkbox--disabled){border-color:var(--studio-border-secondary)}.studio-checkbox__input:focus-visible+.studio-checkbox{outline:2px solid var(--studio-primary);outline-offset:2px}.studio-checkbox__icon{width:100%;height:100%;opacity:0;transform:scale(.8);transition:all var(--studio-transition-fast)}.studio-checkbox--checked .studio-checkbox__icon,.studio-checkbox--indeterminate .studio-checkbox__icon{opacity:1;transform:scale(1)}.studio-checkbox__label-wrapper{display:flex;flex-direction:column;gap:var(--studio-spacing-xs)}.studio-checkbox__label{font-weight:var(--studio-font-weight-medium);color:var(--studio-text-primary);line-height:var(--studio-line-height-normal)}.studio-checkbox__description{font-size:var(--studio-font-size-sm);color:var(--studio-text-secondary);line-height:var(--studio-line-height-normal)}.studio-checkbox__required{color:var(--studio-error);margin-left:var(--studio-spacing-xs)}.studio-checkbox__info{display:flex;flex-direction:column;gap:var(--studio-spacing-xs);margin-top:var(--studio-spacing-xs);padding-left:calc(var(--studio-spacing-sm) + 1.25rem)}.studio-checkbox-wrapper--label-left+.studio-checkbox__info{padding-left:0;padding-right:calc(var(--studio-spacing-sm) + 1.25rem)}.studio-checkbox-wrapper--sm .studio-checkbox__info{padding-left:calc(var(--studio-spacing-sm) + 1rem)}.studio-checkbox-wrapper--sm.studio-checkbox-wrapper--label-left .studio-checkbox__info{padding-left:0;padding-right:calc(var(--studio-spacing-sm) + 1rem)}.studio-checkbox-wrapper--lg .studio-checkbox__info{padding-left:calc(var(--studio-spacing-sm) + 1.5rem)}.studio-checkbox-wrapper--lg.studio-checkbox-wrapper--label-left .studio-checkbox__info{padding-left:0;padding-right:calc(var(--studio-spacing-sm) + 1.5rem)}.studio-checkbox__hint{font-size:var(--studio-font-size-xs);color:var(--studio-text-secondary);line-height:var(--studio-line-height-normal)}.studio-checkbox__error{font-size:var(--studio-font-size-xs);color:var(--studio-error);line-height:var(--studio-line-height-normal)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
1164
+ }
1165
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: CheckboxComponent, decorators: [{
1166
+ type: Component,
1167
+ args: [{ selector: 'studio-checkbox', standalone: true, imports: [CommonModule], providers: [{
1168
+ provide: NG_VALUE_ACCESSOR,
1169
+ useExisting: forwardRef(() => CheckboxComponent),
1170
+ multi: true
1171
+ }], host: {
1172
+ '[class]': 'hostClasses()',
1173
+ '[attr.data-size]': 'size()',
1174
+ '[attr.data-color]': 'color()',
1175
+ '[attr.data-disabled]': 'disabled()',
1176
+ '[attr.data-error]': 'error()'
1177
+ }, template: "<label\n [for]=\"checkboxId()\"\n [ngClass]=\"hostClasses()\"\n (click)=\"handleLabelClick($event)\"\n>\n <!-- Checkbox input -->\n <input\n type=\"checkbox\"\n [id]=\"checkboxId()\"\n [name]=\"name()\"\n [checked]=\"internalChecked()\"\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [tabIndex]=\"tabIndex()\"\n [attr.aria-checked]=\"ariaChecked()\"\n [attr.aria-label]=\"label() || undefined\"\n [attr.aria-describedby]=\"showHint() || showError() ? checkboxId() + '-description' : undefined\"\n [attr.aria-invalid]=\"error()\"\n [attr.aria-required]=\"required()\"\n class=\"studio-checkbox__input\"\n (change)=\"handleChange($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n />\n\n <!-- Custom checkbox -->\n <span [ngClass]=\"checkboxClasses()\">\n <!-- Checkmark icon -->\n @if (internalChecked() && !indeterminate()) {\n <svg\n class=\"studio-checkbox__icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M13.3333 4L6 11.3333L2.66666 8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n }\n\n <!-- Indeterminate icon -->\n @if (indeterminate()) {\n <svg\n class=\"studio-checkbox__icon studio-checkbox__icon--indeterminate\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M4 8H12\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n }\n </span>\n\n <!-- Label content -->\n @if (label() || description()) {\n <span class=\"studio-checkbox__label-wrapper\">\n @if (label()) {\n <span class=\"studio-checkbox__label\">\n {{ label() }}\n @if (required()) {\n <span class=\"studio-checkbox__required\" aria-hidden=\"true\">*</span>\n }\n </span>\n }\n\n @if (description()) {\n <span class=\"studio-checkbox__description\">\n {{ description() }}\n </span>\n }\n </span>\n }\n</label>\n\n<!-- Helper text / Error message -->\n@if (showHint() || showError()) {\n <div\n [id]=\"checkboxId() + '-description'\"\n class=\"studio-checkbox__info\"\n >\n @if (showError()) {\n <span class=\"studio-checkbox__error\">\n {{ errorMessage() }}\n </span>\n }\n\n @if (showHint()) {\n <span class=\"studio-checkbox__hint\">\n {{ hint() }}\n </span>\n }\n </div>\n}\n", styles: [":host{display:inline-flex;flex-direction:column;font-family:var(--studio-font-family)!important}.studio-checkbox-wrapper{display:inline-flex;align-items:flex-start;gap:var(--studio-spacing-sm);cursor:pointer;-webkit-user-select:none;user-select:none;position:relative}.studio-checkbox-wrapper--label-left{flex-direction:row-reverse}.studio-checkbox-wrapper--disabled{cursor:not-allowed;opacity:.5}.studio-checkbox-wrapper--sm{font-size:var(--studio-font-size-sm)}.studio-checkbox-wrapper--md{font-size:var(--studio-font-size-base)}.studio-checkbox-wrapper--lg{font-size:var(--studio-font-size-lg)}.studio-checkbox__input{position:absolute;opacity:0;pointer-events:none;width:0;height:0}.studio-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;border:2px solid var(--studio-border-primary);background-color:var(--studio-bg-primary);transition:all var(--studio-transition-base)}.studio-checkbox--sm{width:1rem;height:1rem}.studio-checkbox--md{width:1.25rem;height:1.25rem}.studio-checkbox--lg{width:1.5rem;height:1.5rem}.studio-checkbox--radius-none{border-radius:0}.studio-checkbox--radius-sm{border-radius:var(--studio-radius-sm)}.studio-checkbox--radius-md{border-radius:var(--studio-radius-md)}.studio-checkbox--radius-lg{border-radius:var(--studio-radius-lg)}.studio-checkbox--radius-full{border-radius:var(--studio-radius-full)}.studio-checkbox--default.studio-checkbox--checked,.studio-checkbox--default.studio-checkbox--indeterminate{border-color:transparent}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--primary,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--primary{background-color:var(--studio-primary);color:var(--studio-text-inverse)}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--secondary,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--secondary{background-color:var(--studio-secondary);color:var(--studio-text-inverse)}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--success,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--success{background-color:var(--studio-success);color:var(--studio-text-inverse)}.studio-checkbox--default.studio-checkbox--checked.studio-checkbox--error,.studio-checkbox--default.studio-checkbox--indeterminate.studio-checkbox--error{background-color:var(--studio-error);color:var(--studio-text-inverse)}.studio-checkbox--outlined.studio-checkbox--checked,.studio-checkbox--outlined.studio-checkbox--indeterminate{background-color:transparent}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--primary,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--primary{border-color:var(--studio-primary);color:var(--studio-primary)}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--secondary,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--secondary{border-color:var(--studio-secondary);color:var(--studio-secondary)}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--success,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--success{border-color:var(--studio-success);color:var(--studio-success)}.studio-checkbox--outlined.studio-checkbox--checked.studio-checkbox--error,.studio-checkbox--outlined.studio-checkbox--indeterminate.studio-checkbox--error{border-color:var(--studio-error);color:var(--studio-error)}.studio-checkbox--filled.studio-checkbox--primary{background-color:var(--studio-primary-bg);border-color:var(--studio-primary-bg)}.studio-checkbox--filled.studio-checkbox--secondary{background-color:var(--studio-secondary-bg);border-color:var(--studio-secondary-bg)}.studio-checkbox--filled.studio-checkbox--success{background-color:var(--studio-success-bg);border-color:var(--studio-success-bg)}.studio-checkbox--filled.studio-checkbox--error{background-color:var(--studio-error-bg);border-color:var(--studio-error-bg)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--primary,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--primary{background-color:var(--studio-primary);border-color:var(--studio-primary);color:var(--studio-text-inverse)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--secondary,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--secondary{background-color:var(--studio-secondary);border-color:var(--studio-secondary);color:var(--studio-text-inverse)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--success,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--success{background-color:var(--studio-success);border-color:var(--studio-success);color:var(--studio-text-inverse)}.studio-checkbox--filled.studio-checkbox--checked.studio-checkbox--error,.studio-checkbox--filled.studio-checkbox--indeterminate.studio-checkbox--error{background-color:var(--studio-error);border-color:var(--studio-error);color:var(--studio-text-inverse)}.studio-checkbox--error:not(.studio-checkbox--checked):not(.studio-checkbox--indeterminate){border-color:var(--studio-error)}.studio-checkbox:hover:not(.studio-checkbox--disabled){border-color:var(--studio-border-secondary)}.studio-checkbox__input:focus-visible+.studio-checkbox{outline:2px solid var(--studio-primary);outline-offset:2px}.studio-checkbox__icon{width:100%;height:100%;opacity:0;transform:scale(.8);transition:all var(--studio-transition-fast)}.studio-checkbox--checked .studio-checkbox__icon,.studio-checkbox--indeterminate .studio-checkbox__icon{opacity:1;transform:scale(1)}.studio-checkbox__label-wrapper{display:flex;flex-direction:column;gap:var(--studio-spacing-xs)}.studio-checkbox__label{font-weight:var(--studio-font-weight-medium);color:var(--studio-text-primary);line-height:var(--studio-line-height-normal)}.studio-checkbox__description{font-size:var(--studio-font-size-sm);color:var(--studio-text-secondary);line-height:var(--studio-line-height-normal)}.studio-checkbox__required{color:var(--studio-error);margin-left:var(--studio-spacing-xs)}.studio-checkbox__info{display:flex;flex-direction:column;gap:var(--studio-spacing-xs);margin-top:var(--studio-spacing-xs);padding-left:calc(var(--studio-spacing-sm) + 1.25rem)}.studio-checkbox-wrapper--label-left+.studio-checkbox__info{padding-left:0;padding-right:calc(var(--studio-spacing-sm) + 1.25rem)}.studio-checkbox-wrapper--sm .studio-checkbox__info{padding-left:calc(var(--studio-spacing-sm) + 1rem)}.studio-checkbox-wrapper--sm.studio-checkbox-wrapper--label-left .studio-checkbox__info{padding-left:0;padding-right:calc(var(--studio-spacing-sm) + 1rem)}.studio-checkbox-wrapper--lg .studio-checkbox__info{padding-left:calc(var(--studio-spacing-sm) + 1.5rem)}.studio-checkbox-wrapper--lg.studio-checkbox-wrapper--label-left .studio-checkbox__info{padding-left:0;padding-right:calc(var(--studio-spacing-sm) + 1.5rem)}.studio-checkbox__hint{font-size:var(--studio-font-size-xs);color:var(--studio-text-secondary);line-height:var(--studio-line-height-normal)}.studio-checkbox__error{font-size:var(--studio-font-size-xs);color:var(--studio-error);line-height:var(--studio-line-height-normal)}\n"] }]
1178
+ }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
1179
+
871
1180
  /**
872
1181
  * Input component with form control support, variants, and accessibility
873
1182
  *
@@ -1138,11 +1447,518 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1138
1447
  * Switch component
1139
1448
  */
1140
1449
 
1450
+ /**
1451
+ * Textarea component for multi-line text input
1452
+ *
1453
+ * @example
1454
+ * <studio-textarea
1455
+ * [(ngModel)]="message"
1456
+ * label="Your message"
1457
+ * placeholder="Enter your message..."
1458
+ * [rows]="4"
1459
+ * />
1460
+ */
1461
+ class TextareaComponent {
1462
+ configService = inject(StudioConfigService);
1463
+ textareaDefaults = computed(() => this.configService.config().components?.textarea, ...(ngDevMode ? [{ debugName: "textareaDefaults" }] : []));
1464
+ variant = input(this.textareaDefaults()?.variant ?? 'outline', ...(ngDevMode ? [{ debugName: "variant" }] : []));
1465
+ size = input(this.textareaDefaults()?.size ?? 'md', ...(ngDevMode ? [{ debugName: "size" }] : []));
1466
+ color = input(this.textareaDefaults()?.color ?? 'primary', ...(ngDevMode ? [{ debugName: "color" }] : []));
1467
+ radius = input(this.textareaDefaults()?.radius ?? 'md', ...(ngDevMode ? [{ debugName: "radius" }] : []));
1468
+ // ==========================================
1469
+ // INPUTS - Labels & Description
1470
+ // ==========================================
1471
+ /**
1472
+ * Label text
1473
+ */
1474
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
1475
+ /**
1476
+ * Floating label (moves up when focused/filled)
1477
+ */
1478
+ floatingLabel = input(false, ...(ngDevMode ? [{ debugName: "floatingLabel" }] : []));
1479
+ /**
1480
+ * Placeholder text
1481
+ */
1482
+ placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : []));
1483
+ /**
1484
+ * Helper text
1485
+ */
1486
+ hint = input(...(ngDevMode ? [undefined, { debugName: "hint" }] : []));
1487
+ // ==========================================
1488
+ // INPUTS - Textarea Specific
1489
+ // ==========================================
1490
+ /**
1491
+ * Number of visible text rows
1492
+ */
1493
+ rows = input(this.textareaDefaults()?.rows ?? 3, ...(ngDevMode ? [{ debugName: "rows" }] : []));
1494
+ /**
1495
+ * Minimum rows for auto-resize
1496
+ */
1497
+ minRows = input(...(ngDevMode ? [undefined, { debugName: "minRows" }] : []));
1498
+ /**
1499
+ * Maximum rows for auto-resize
1500
+ */
1501
+ maxRows = input(...(ngDevMode ? [undefined, { debugName: "maxRows" }] : []));
1502
+ /**
1503
+ * Enable auto-resize based on content
1504
+ */
1505
+ autoResize = input(this.textareaDefaults()?.autoResize ?? false, ...(ngDevMode ? [{ debugName: "autoResize" }] : []));
1506
+ /**
1507
+ * Resize behavior
1508
+ */
1509
+ resize = input(this.textareaDefaults()?.resize ?? 'vertical', ...(ngDevMode ? [{ debugName: "resize" }] : []));
1510
+ // ==========================================
1511
+ // INPUTS - Character Count
1512
+ // ==========================================
1513
+ /**
1514
+ * Maximum character length
1515
+ */
1516
+ maxLength = input(...(ngDevMode ? [undefined, { debugName: "maxLength" }] : []));
1517
+ /**
1518
+ * Show character counter
1519
+ */
1520
+ showCharCount = input(this.textareaDefaults()?.showCharCount ?? false, ...(ngDevMode ? [{ debugName: "showCharCount" }] : []));
1521
+ /**
1522
+ * Character counter position
1523
+ */
1524
+ charCountPosition = input('bottom-right', ...(ngDevMode ? [{ debugName: "charCountPosition" }] : []));
1525
+ // ==========================================
1526
+ // INPUTS - Validation
1527
+ // ==========================================
1528
+ /**
1529
+ * Required field
1530
+ */
1531
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
1532
+ /**
1533
+ * Minimum character length
1534
+ */
1535
+ minLength = input(...(ngDevMode ? [undefined, { debugName: "minLength" }] : []));
1536
+ /**
1537
+ * Error state
1538
+ */
1539
+ error = input(false, ...(ngDevMode ? [{ debugName: "error" }] : []));
1540
+ /**
1541
+ * Error message
1542
+ */
1543
+ errorMessage = input(...(ngDevMode ? [undefined, { debugName: "errorMessage" }] : []));
1544
+ // ==========================================
1545
+ // INPUTS - Behavior
1546
+ // ==========================================
1547
+ /**
1548
+ * Disabled state
1549
+ */
1550
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1551
+ /**
1552
+ * Readonly state
1553
+ */
1554
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
1555
+ /**
1556
+ * Full width (100% of parent)
1557
+ */
1558
+ fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : []));
1559
+ /**
1560
+ * Name attribute for form control
1561
+ */
1562
+ name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
1563
+ /**
1564
+ * Autocomplete attribute
1565
+ */
1566
+ autocomplete = input(...(ngDevMode ? [undefined, { debugName: "autocomplete" }] : []));
1567
+ /**
1568
+ * Spellcheck attribute
1569
+ */
1570
+ spellcheck = input(true, ...(ngDevMode ? [{ debugName: "spellcheck" }] : []));
1571
+ /**
1572
+ * Show clear button
1573
+ */
1574
+ clearable = input(this.textareaDefaults()?.clearable ?? false, ...(ngDevMode ? [{ debugName: "clearable" }] : []));
1575
+ /**
1576
+ * Loading state
1577
+ */
1578
+ loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1579
+ // ==========================================
1580
+ // OUTPUTS
1581
+ // ==========================================
1582
+ /**
1583
+ * Emitted when value changes
1584
+ */
1585
+ changed = output();
1586
+ /**
1587
+ * Emitted on focus
1588
+ */
1589
+ focused = output();
1590
+ /**
1591
+ * Emitted on blur
1592
+ */
1593
+ blurred = output();
1594
+ /**
1595
+ * Emitted on key press
1596
+ */
1597
+ keyPressed = output();
1598
+ // ==========================================
1599
+ // STATE
1600
+ // ==========================================
1601
+ /**
1602
+ * Internal value
1603
+ */
1604
+ internalValue = signal('', ...(ngDevMode ? [{ debugName: "internalValue" }] : []));
1605
+ /**
1606
+ * Internal focus state
1607
+ */
1608
+ isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : []));
1609
+ /**
1610
+ * Unique ID for accessibility
1611
+ */
1612
+ textareaId = signal(`studio-textarea-${Math.random().toString(36).substr(2, 9)}`, ...(ngDevMode ? [{ debugName: "textareaId" }] : []));
1613
+ /**
1614
+ * Textarea element reference
1615
+ */
1616
+ textareaEl = viewChild('textarea', ...(ngDevMode ? [{ debugName: "textareaEl" }] : []));
1617
+ // ==========================================
1618
+ // COMPUTED
1619
+ // ==========================================
1620
+ hostClasses = computed(() => classNames('studio-textarea-wrapper', `studio-textarea-wrapper--${this.size()}`, `studio-textarea-wrapper--${this.variant()}`, this.disabled() && 'studio-textarea-wrapper--disabled', this.error() && 'studio-textarea-wrapper--error', this.isFocused() && 'studio-textarea-wrapper--focused', this.fullWidth() && 'studio-textarea-wrapper--full-width', this.floatingLabel() && 'studio-textarea-wrapper--floating-label'), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
1621
+ /**
1622
+ * Textarea element CSS classes
1623
+ */
1624
+ textareaClasses = computed(() => classNames('studio-textarea', `studio-textarea--${this.size()}`, `studio-textarea--${this.variant()}`, `studio-textarea--${this.color()}`, `studio-textarea--radius-${this.radius()}`, `studio-textarea--resize-${this.resize()}`, this.disabled() && 'studio-textarea--disabled', this.readonly() && 'studio-textarea--readonly', this.error() && 'studio-textarea--error', this.internalValue().length > 0 && 'studio-textarea--has-value', this.autoResize() && 'studio-textarea--auto-resize'), ...(ngDevMode ? [{ debugName: "textareaClasses" }] : []));
1625
+ /**
1626
+ * Show error message
1627
+ */
1628
+ showError = computed(() => this.error() && this.errorMessage(), ...(ngDevMode ? [{ debugName: "showError" }] : []));
1629
+ /**
1630
+ * Show hint
1631
+ */
1632
+ showHint = computed(() => !this.error() && this.hint(), ...(ngDevMode ? [{ debugName: "showHint" }] : []));
1633
+ /**
1634
+ * Character count text
1635
+ */
1636
+ charCountText = computed(() => {
1637
+ const length = this.internalValue().length;
1638
+ const max = this.maxLength();
1639
+ return max ? `${length}/${max}` : `${length}`;
1640
+ }, ...(ngDevMode ? [{ debugName: "charCountText" }] : []));
1641
+ /**
1642
+ * Is character limit exceeded
1643
+ */
1644
+ isCharLimitExceeded = computed(() => {
1645
+ const max = this.maxLength();
1646
+ return max ? this.internalValue().length > max : false;
1647
+ }, ...(ngDevMode ? [{ debugName: "isCharLimitExceeded" }] : []));
1648
+ /**
1649
+ * Computed placeholder (empty if floating label)
1650
+ */
1651
+ computedPlaceholder = computed(() => {
1652
+ if (this.floatingLabel()) {
1653
+ return '';
1654
+ }
1655
+ return this.placeholder();
1656
+ }, ...(ngDevMode ? [{ debugName: "computedPlaceholder" }] : []));
1657
+ /**
1658
+ * Show floating label in "up" position
1659
+ */
1660
+ showFloatingLabelUp = computed(() => {
1661
+ return this.floatingLabel() && (this.isFocused() || this.internalValue().length > 0);
1662
+ }, ...(ngDevMode ? [{ debugName: "showFloatingLabelUp" }] : []));
1663
+ // ==========================================
1664
+ // CONTROL VALUE ACCESSOR
1665
+ // ==========================================
1666
+ onChange = () => { };
1667
+ onTouched = () => { };
1668
+ writeValue(value) {
1669
+ this.internalValue.set(value ?? '');
1670
+ this.adjustHeightIfNeeded();
1671
+ }
1672
+ registerOnChange(fn) {
1673
+ this.onChange = fn;
1674
+ }
1675
+ registerOnTouched(fn) {
1676
+ this.onTouched = fn;
1677
+ }
1678
+ setDisabledState(isDisabled) {
1679
+ // Disabled state is controlled via input
1680
+ }
1681
+ // ==========================================
1682
+ // CONSTRUCTOR & EFFECTS
1683
+ // ==========================================
1684
+ constructor() {
1685
+ // Auto-resize effect
1686
+ effect(() => {
1687
+ if (this.autoResize()) {
1688
+ this.adjustHeightIfNeeded();
1689
+ }
1690
+ });
1691
+ }
1692
+ // ==========================================
1693
+ // METHODS
1694
+ // ==========================================
1695
+ /**
1696
+ * Handle textarea input
1697
+ */
1698
+ handleInput(event) {
1699
+ if (this.disabled() || this.readonly()) {
1700
+ return;
1701
+ }
1702
+ const newValue = event.target.value;
1703
+ this.internalValue.set(newValue);
1704
+ this.onChange(newValue);
1705
+ this.changed.emit(newValue);
1706
+ if (this.autoResize()) {
1707
+ this.adjustHeight(event.target);
1708
+ }
1709
+ }
1710
+ /**
1711
+ * Handle focus
1712
+ */
1713
+ handleFocus(event) {
1714
+ this.isFocused.set(true);
1715
+ this.focused.emit(event);
1716
+ }
1717
+ /**
1718
+ * Handle blur
1719
+ */
1720
+ handleBlur(event) {
1721
+ this.isFocused.set(false);
1722
+ this.onTouched();
1723
+ this.blurred.emit(event);
1724
+ }
1725
+ /**
1726
+ * Handle key press
1727
+ */
1728
+ handleKeyPress(event) {
1729
+ this.keyPressed.emit(event);
1730
+ }
1731
+ /**
1732
+ * Clear textarea value
1733
+ */
1734
+ handleClear() {
1735
+ if (this.disabled() || this.readonly()) {
1736
+ return;
1737
+ }
1738
+ this.internalValue.set('');
1739
+ this.onChange('');
1740
+ this.changed.emit('');
1741
+ // Focus textarea after clearing
1742
+ this.textareaEl()?.nativeElement.focus();
1743
+ }
1744
+ /**
1745
+ * Adjust textarea height for auto-resize
1746
+ */
1747
+ adjustHeightIfNeeded() {
1748
+ if (this.autoResize()) {
1749
+ setTimeout(() => {
1750
+ const textarea = this.textareaEl()?.nativeElement;
1751
+ if (textarea) {
1752
+ this.adjustHeight(textarea);
1753
+ }
1754
+ });
1755
+ }
1756
+ }
1757
+ /**
1758
+ * Adjust textarea height based on content
1759
+ */
1760
+ adjustHeight(textarea) {
1761
+ // Reset height to auto to get proper scrollHeight
1762
+ textarea.style.height = 'auto';
1763
+ const minRows = this.minRows() ?? this.rows();
1764
+ const maxRows = this.maxRows();
1765
+ // Calculate line height
1766
+ const lineHeight = parseInt(getComputedStyle(textarea).lineHeight);
1767
+ const padding = parseInt(getComputedStyle(textarea).paddingTop) +
1768
+ parseInt(getComputedStyle(textarea).paddingBottom);
1769
+ // Calculate min and max heights
1770
+ const minHeight = minRows * lineHeight + padding;
1771
+ const maxHeight = maxRows ? maxRows * lineHeight + padding : Infinity;
1772
+ // Set new height within bounds
1773
+ const newHeight = Math.max(minHeight, Math.min(textarea.scrollHeight, maxHeight));
1774
+ textarea.style.height = `${newHeight}px`;
1775
+ }
1776
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1777
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: TextareaComponent, isStandalone: true, selector: "studio-textarea", 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 }, radius: { classPropertyName: "radius", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, floatingLabel: { classPropertyName: "floatingLabel", publicName: "floatingLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, minRows: { classPropertyName: "minRows", publicName: "minRows", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, showCharCount: { classPropertyName: "showCharCount", publicName: "showCharCount", isSignal: true, isRequired: false, transformFunction: null }, charCountPosition: { classPropertyName: "charCountPosition", publicName: "charCountPosition", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, spellcheck: { classPropertyName: "spellcheck", publicName: "spellcheck", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed", focused: "focused", blurred: "blurred", keyPressed: "keyPressed" }, host: { properties: { "class": "hostClasses()", "attr.data-size": "size()", "attr.data-variant": "variant()", "attr.data-disabled": "disabled()", "attr.data-error": "error()", "attr.data-full-width": "fullWidth()" } }, providers: [{
1778
+ provide: NG_VALUE_ACCESSOR,
1779
+ useExisting: forwardRef(() => TextareaComponent),
1780
+ multi: true
1781
+ }], viewQueries: [{ propertyName: "textareaEl", first: true, predicate: ["textarea"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"studio-textarea-container\">\n <!-- Label (static or floating) -->\n @if (label() && !floatingLabel()) {\n <label\n [for]=\"textareaId()\"\n class=\"studio-textarea-label\"\n [class.studio-textarea-label--required]=\"required()\"\n >\n {{ label() }}\n @if (required()) {\n <span class=\"studio-textarea-label__required\">*</span>\n }\n </label>\n }\n\n <!-- Textarea wrapper -->\n <div class=\"studio-textarea-input-wrapper\">\n <!-- Floating label -->\n @if (floatingLabel() && label()) {\n <label\n [for]=\"textareaId()\"\n class=\"studio-textarea-label studio-textarea-label--floating\"\n [class.studio-textarea-label--floating-up]=\"showFloatingLabelUp()\"\n [class.studio-textarea-label--required]=\"required()\"\n >\n {{ label() }}\n @if (required()) {\n <span class=\"studio-textarea-label__required\">*</span>\n }\n </label>\n }\n\n <!-- Textarea element -->\n <textarea\n #textarea\n [id]=\"textareaId()\"\n [class]=\"textareaClasses()\"\n [value]=\"internalValue()\"\n [placeholder]=\"computedPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [rows]=\"rows()\"\n [attr.maxlength]=\"maxLength()\"\n [attr.minlength]=\"minLength()\"\n [required]=\"required()\"\n [name]=\"name()\"\n [autocomplete]=\"autocomplete()\"\n [spellcheck]=\"spellcheck()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"error()\"\n [attr.aria-describedby]=\"showHint() || showError() ? textareaId() + '-description' : undefined\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keypress)=\"handleKeyPress($event)\"\n ></textarea>\n\n <!-- Clear button -->\n @if (clearable() && internalValue().length > 0 && !disabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"studio-textarea-clear\"\n [attr.aria-label]=\"'Clear textarea'\"\n (click)=\"handleClear()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n\n <!-- Loading indicator -->\n @if (loading()) {\n <div class=\"studio-textarea-loading\">\n <svg\n class=\"studio-textarea-spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n </div>\n }\n\n <!-- Character counter -->\n @if (showCharCount()) {\n <div\n class=\"studio-textarea-char-count\"\n [class.studio-textarea-char-count--exceeded]=\"isCharLimitExceeded()\"\n [attr.data-position]=\"charCountPosition()\"\n >\n {{ charCountText() }}\n </div>\n }\n </div>\n\n <!-- Helper text / Error message -->\n @if (showError()) {\n <div\n class=\"studio-textarea-message studio-textarea-message--error\"\n [id]=\"textareaId() + '-description'\"\n role=\"alert\"\n >\n {{ errorMessage() }}\n </div>\n } @else if (showHint()) {\n <div\n class=\"studio-textarea-message studio-textarea-message--hint\"\n [id]=\"textareaId() + '-description'\"\n >\n {{ hint() }}\n </div>\n }\n</div>\n", styles: [":host{display:flex;flex-direction:column;gap:.375rem;font-family:var(--studio-font-family)}:host(.studio-textarea-wrapper--full-width){width:100%}.studio-textarea-label{display:block;font-size:.875rem;font-weight:var(--studio-font-weight-medium);color:var(--studio-text-primary);margin-bottom:.25rem}.studio-textarea-label__required{color:var(--studio-error);margin-left:.125rem}.studio-textarea-label--floating{position:absolute;top:.75rem;left:.75rem;pointer-events:none;background:transparent;padding:0 .25rem;z-index:1;transition:all .2s ease}.studio-textarea-label--floating-up{top:-.5rem;font-size:.75rem;background:var(--studio-background);color:var(--studio-primary)}.studio-textarea-input-wrapper{position:relative;display:flex;flex-direction:column;transition:all var(--studio-transition-fast)}.studio-textarea{width:100%;padding:.75rem;font-size:1rem;font-family:inherit;color:var(--studio-text-primary);background:transparent;border:none;outline:none;resize:vertical;transition:all var(--studio-transition-fast)}.studio-textarea::placeholder{color:var(--studio-text-tertiary)}.studio-textarea:disabled{cursor:not-allowed;opacity:.6}.studio-textarea:read-only{cursor:default}.studio-textarea-clear,.studio-textarea-loading{position:absolute;top:.5rem;right:.5rem;display:flex;align-items:center;justify-content:center}.studio-textarea-clear{padding:.25rem;background:none;border:none;color:var(--studio-text-secondary);cursor:pointer;border-radius:var(--studio-radius-sm);transition:all var(--studio-transition-fast)}.studio-textarea-clear:hover{background:var(--studio-background-hover);color:var(--studio-text-primary)}.studio-textarea-clear svg{width:1rem;height:1rem}.studio-textarea-spinner{width:1rem;height:1rem;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.studio-textarea-char-count{position:absolute;bottom:.5rem;font-size:.75rem;color:var(--studio-text-muted);pointer-events:none}.studio-textarea-char-count[data-position=bottom-right]{right:.75rem}.studio-textarea-char-count[data-position=bottom-left]{left:.75rem}.studio-textarea-char-count--exceeded{color:var(--studio-error);font-weight:500}.studio-textarea-message{font-size:.75rem;line-height:1.4}.studio-textarea-message--hint{color:var(--studio-text-secondary)}.studio-textarea-message--error{color:var(--studio-error)}:host(.studio-textarea-wrapper--outline) .studio-textarea-input-wrapper{border:1px solid var(--studio-border-primary);background:var(--studio-bg-primary);border-radius:var(--studio-radius-md)}:host(.studio-textarea-wrapper--outline) .studio-textarea-input-wrapper:hover:not(:has(.studio-textarea:disabled)){border-color:var(--studio-primary)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--focused) .studio-textarea-input-wrapper{border-color:var(--studio-primary);box-shadow:0 0 0 3px var(--studio-primary-bg)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--error) .studio-textarea-input-wrapper{border-color:var(--studio-error)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--error) .studio-textarea-input-wrapper:hover{border-color:var(--studio-error)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--disabled) .studio-textarea-input-wrapper{background:var(--studio-bg-secondary);border-color:var(--studio-border-secondary)}:host(.studio-textarea-wrapper--filled) .studio-textarea-input-wrapper{background:var(--studio-bg-secondary);border:none;border-bottom:2px solid var(--studio-border-primary);border-radius:var(--studio-radius-md) var(--studio-radius-md) 0 0}:host(.studio-textarea-wrapper--filled) .studio-textarea-input-wrapper:hover:not(:has(.studio-textarea:disabled)){background:var(--studio-bg-tertiary)}:host(.studio-textarea-wrapper--filled.studio-textarea-wrapper--focused) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-primary);background:var(--studio-bg-tertiary)}:host(.studio-textarea-wrapper--filled.studio-textarea-wrapper--error) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-error)}:host(.studio-textarea-wrapper--filled.studio-textarea-wrapper--disabled) .studio-textarea-input-wrapper{background:var(--studio-bg-secondary);opacity:.6}:host(.studio-textarea-wrapper--underline) .studio-textarea-input-wrapper{background:transparent;border:none;border-bottom:2px solid var(--studio-border-primary);border-radius:0}:host(.studio-textarea-wrapper--underline) .studio-textarea-input-wrapper .studio-textarea{padding-left:0;padding-right:0}:host(.studio-textarea-wrapper--underline) .studio-textarea-input-wrapper:hover:not(:has(.studio-textarea:disabled)){border-bottom-color:var(--studio-primary)}:host(.studio-textarea-wrapper--underline.studio-textarea-wrapper--focused) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-primary)}:host(.studio-textarea-wrapper--underline.studio-textarea-wrapper--error) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-error)}:host(.studio-textarea-wrapper--sm) .studio-textarea{padding:.5rem .75rem;font-size:.875rem}:host(.studio-textarea-wrapper--md) .studio-textarea{padding:.75rem;font-size:1rem}:host(.studio-textarea-wrapper--lg) .studio-textarea{padding:1rem;font-size:1.125rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1782
+ }
1783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: TextareaComponent, decorators: [{
1784
+ type: Component,
1785
+ args: [{ selector: 'studio-textarea', standalone: true, imports: [CommonModule], providers: [{
1786
+ provide: NG_VALUE_ACCESSOR,
1787
+ useExisting: forwardRef(() => TextareaComponent),
1788
+ multi: true
1789
+ }], host: {
1790
+ '[class]': 'hostClasses()',
1791
+ '[attr.data-size]': 'size()',
1792
+ '[attr.data-variant]': 'variant()',
1793
+ '[attr.data-disabled]': 'disabled()',
1794
+ '[attr.data-error]': 'error()',
1795
+ '[attr.data-full-width]': 'fullWidth()'
1796
+ }, template: "<div class=\"studio-textarea-container\">\n <!-- Label (static or floating) -->\n @if (label() && !floatingLabel()) {\n <label\n [for]=\"textareaId()\"\n class=\"studio-textarea-label\"\n [class.studio-textarea-label--required]=\"required()\"\n >\n {{ label() }}\n @if (required()) {\n <span class=\"studio-textarea-label__required\">*</span>\n }\n </label>\n }\n\n <!-- Textarea wrapper -->\n <div class=\"studio-textarea-input-wrapper\">\n <!-- Floating label -->\n @if (floatingLabel() && label()) {\n <label\n [for]=\"textareaId()\"\n class=\"studio-textarea-label studio-textarea-label--floating\"\n [class.studio-textarea-label--floating-up]=\"showFloatingLabelUp()\"\n [class.studio-textarea-label--required]=\"required()\"\n >\n {{ label() }}\n @if (required()) {\n <span class=\"studio-textarea-label__required\">*</span>\n }\n </label>\n }\n\n <!-- Textarea element -->\n <textarea\n #textarea\n [id]=\"textareaId()\"\n [class]=\"textareaClasses()\"\n [value]=\"internalValue()\"\n [placeholder]=\"computedPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [rows]=\"rows()\"\n [attr.maxlength]=\"maxLength()\"\n [attr.minlength]=\"minLength()\"\n [required]=\"required()\"\n [name]=\"name()\"\n [autocomplete]=\"autocomplete()\"\n [spellcheck]=\"spellcheck()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"error()\"\n [attr.aria-describedby]=\"showHint() || showError() ? textareaId() + '-description' : undefined\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keypress)=\"handleKeyPress($event)\"\n ></textarea>\n\n <!-- Clear button -->\n @if (clearable() && internalValue().length > 0 && !disabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"studio-textarea-clear\"\n [attr.aria-label]=\"'Clear textarea'\"\n (click)=\"handleClear()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n\n <!-- Loading indicator -->\n @if (loading()) {\n <div class=\"studio-textarea-loading\">\n <svg\n class=\"studio-textarea-spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n </div>\n }\n\n <!-- Character counter -->\n @if (showCharCount()) {\n <div\n class=\"studio-textarea-char-count\"\n [class.studio-textarea-char-count--exceeded]=\"isCharLimitExceeded()\"\n [attr.data-position]=\"charCountPosition()\"\n >\n {{ charCountText() }}\n </div>\n }\n </div>\n\n <!-- Helper text / Error message -->\n @if (showError()) {\n <div\n class=\"studio-textarea-message studio-textarea-message--error\"\n [id]=\"textareaId() + '-description'\"\n role=\"alert\"\n >\n {{ errorMessage() }}\n </div>\n } @else if (showHint()) {\n <div\n class=\"studio-textarea-message studio-textarea-message--hint\"\n [id]=\"textareaId() + '-description'\"\n >\n {{ hint() }}\n </div>\n }\n</div>\n", styles: [":host{display:flex;flex-direction:column;gap:.375rem;font-family:var(--studio-font-family)}:host(.studio-textarea-wrapper--full-width){width:100%}.studio-textarea-label{display:block;font-size:.875rem;font-weight:var(--studio-font-weight-medium);color:var(--studio-text-primary);margin-bottom:.25rem}.studio-textarea-label__required{color:var(--studio-error);margin-left:.125rem}.studio-textarea-label--floating{position:absolute;top:.75rem;left:.75rem;pointer-events:none;background:transparent;padding:0 .25rem;z-index:1;transition:all .2s ease}.studio-textarea-label--floating-up{top:-.5rem;font-size:.75rem;background:var(--studio-background);color:var(--studio-primary)}.studio-textarea-input-wrapper{position:relative;display:flex;flex-direction:column;transition:all var(--studio-transition-fast)}.studio-textarea{width:100%;padding:.75rem;font-size:1rem;font-family:inherit;color:var(--studio-text-primary);background:transparent;border:none;outline:none;resize:vertical;transition:all var(--studio-transition-fast)}.studio-textarea::placeholder{color:var(--studio-text-tertiary)}.studio-textarea:disabled{cursor:not-allowed;opacity:.6}.studio-textarea:read-only{cursor:default}.studio-textarea-clear,.studio-textarea-loading{position:absolute;top:.5rem;right:.5rem;display:flex;align-items:center;justify-content:center}.studio-textarea-clear{padding:.25rem;background:none;border:none;color:var(--studio-text-secondary);cursor:pointer;border-radius:var(--studio-radius-sm);transition:all var(--studio-transition-fast)}.studio-textarea-clear:hover{background:var(--studio-background-hover);color:var(--studio-text-primary)}.studio-textarea-clear svg{width:1rem;height:1rem}.studio-textarea-spinner{width:1rem;height:1rem;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.studio-textarea-char-count{position:absolute;bottom:.5rem;font-size:.75rem;color:var(--studio-text-muted);pointer-events:none}.studio-textarea-char-count[data-position=bottom-right]{right:.75rem}.studio-textarea-char-count[data-position=bottom-left]{left:.75rem}.studio-textarea-char-count--exceeded{color:var(--studio-error);font-weight:500}.studio-textarea-message{font-size:.75rem;line-height:1.4}.studio-textarea-message--hint{color:var(--studio-text-secondary)}.studio-textarea-message--error{color:var(--studio-error)}:host(.studio-textarea-wrapper--outline) .studio-textarea-input-wrapper{border:1px solid var(--studio-border-primary);background:var(--studio-bg-primary);border-radius:var(--studio-radius-md)}:host(.studio-textarea-wrapper--outline) .studio-textarea-input-wrapper:hover:not(:has(.studio-textarea:disabled)){border-color:var(--studio-primary)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--focused) .studio-textarea-input-wrapper{border-color:var(--studio-primary);box-shadow:0 0 0 3px var(--studio-primary-bg)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--error) .studio-textarea-input-wrapper{border-color:var(--studio-error)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--error) .studio-textarea-input-wrapper:hover{border-color:var(--studio-error)}:host(.studio-textarea-wrapper--outline.studio-textarea-wrapper--disabled) .studio-textarea-input-wrapper{background:var(--studio-bg-secondary);border-color:var(--studio-border-secondary)}:host(.studio-textarea-wrapper--filled) .studio-textarea-input-wrapper{background:var(--studio-bg-secondary);border:none;border-bottom:2px solid var(--studio-border-primary);border-radius:var(--studio-radius-md) var(--studio-radius-md) 0 0}:host(.studio-textarea-wrapper--filled) .studio-textarea-input-wrapper:hover:not(:has(.studio-textarea:disabled)){background:var(--studio-bg-tertiary)}:host(.studio-textarea-wrapper--filled.studio-textarea-wrapper--focused) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-primary);background:var(--studio-bg-tertiary)}:host(.studio-textarea-wrapper--filled.studio-textarea-wrapper--error) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-error)}:host(.studio-textarea-wrapper--filled.studio-textarea-wrapper--disabled) .studio-textarea-input-wrapper{background:var(--studio-bg-secondary);opacity:.6}:host(.studio-textarea-wrapper--underline) .studio-textarea-input-wrapper{background:transparent;border:none;border-bottom:2px solid var(--studio-border-primary);border-radius:0}:host(.studio-textarea-wrapper--underline) .studio-textarea-input-wrapper .studio-textarea{padding-left:0;padding-right:0}:host(.studio-textarea-wrapper--underline) .studio-textarea-input-wrapper:hover:not(:has(.studio-textarea:disabled)){border-bottom-color:var(--studio-primary)}:host(.studio-textarea-wrapper--underline.studio-textarea-wrapper--focused) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-primary)}:host(.studio-textarea-wrapper--underline.studio-textarea-wrapper--error) .studio-textarea-input-wrapper{border-bottom-color:var(--studio-error)}:host(.studio-textarea-wrapper--sm) .studio-textarea{padding:.5rem .75rem;font-size:.875rem}:host(.studio-textarea-wrapper--md) .studio-textarea{padding:.75rem;font-size:1rem}:host(.studio-textarea-wrapper--lg) .studio-textarea{padding:1rem;font-size:1.125rem}\n"] }]
1797
+ }], ctorParameters: () => [], 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 }] }], radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], floatingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatingLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], minRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRows", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], autoResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoResize", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], showCharCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCharCount", required: false }] }], charCountPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "charCountPosition", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], spellcheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellcheck", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }], focused: [{ type: i0.Output, args: ["focused"] }], blurred: [{ type: i0.Output, args: ["blurred"] }], keyPressed: [{ type: i0.Output, args: ["keyPressed"] }], textareaEl: [{ type: i0.ViewChild, args: ['textarea', { isSignal: true }] }] } });
1798
+
1141
1799
  /**
1142
1800
  * Primitives (Atoms)
1143
1801
  * Basic building blocks
1144
1802
  */
1145
1803
 
1804
+ class ButtonToggleGroupComponent {
1805
+ configService = inject(StudioConfigService);
1806
+ toggleGroupDefaults = computed(() => this.configService.config().components?.buttonToggleGroup, ...(ngDevMode ? [{ debugName: "toggleGroupDefaults" }] : []));
1807
+ onChange = () => { };
1808
+ onTouched = () => { };
1809
+ value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
1810
+ options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
1811
+ multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
1812
+ allowEmpty = input(true, ...(ngDevMode ? [{ debugName: "allowEmpty" }] : []));
1813
+ orientationInput = input(undefined, ...(ngDevMode ? [{ debugName: "orientationInput", alias: 'orientation' }] : [{ alias: 'orientation' }]));
1814
+ sizeInput = input(undefined, ...(ngDevMode ? [{ debugName: "sizeInput", alias: 'size' }] : [{ alias: 'size' }]));
1815
+ variantInput = input(undefined, ...(ngDevMode ? [{ debugName: "variantInput", alias: 'variant' }] : [{ alias: 'variant' }]));
1816
+ colorInput = input(undefined, ...(ngDevMode ? [{ debugName: "colorInput", alias: 'color' }] : [{ alias: 'color' }]));
1817
+ radiusInput = input(undefined, ...(ngDevMode ? [{ debugName: "radiusInput", alias: 'radius' }] : [{ alias: 'radius' }]));
1818
+ shadowInput = input(undefined, ...(ngDevMode ? [{ debugName: "shadowInput", alias: 'shadow' }] : [{ alias: 'shadow' }]));
1819
+ orientation = withConfigDefault(this.orientationInput, computed(() => this.toggleGroupDefaults()?.orientation), 'horizontal');
1820
+ size = withConfigDefault(this.sizeInput, computed(() => this.toggleGroupDefaults()?.size), 'md');
1821
+ variant = withConfigDefault(this.variantInput, computed(() => this.toggleGroupDefaults()?.variant), 'outline');
1822
+ color = withConfigDefault(this.colorInput, computed(() => this.toggleGroupDefaults()?.color), 'primary');
1823
+ radius = withConfigDefault(this.radiusInput, computed(() => this.toggleGroupDefaults()?.radius), 'sm');
1824
+ shadow = withConfigDefault(this.shadowInput, computed(() => this.toggleGroupDefaults()?.shadow), 'none');
1825
+ attached = input(true, ...(ngDevMode ? [{ debugName: "attached" }] : []));
1826
+ fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : []));
1827
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1828
+ spacing = input('sm', ...(ngDevMode ? [{ debugName: "spacing" }] : []));
1829
+ align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : []));
1830
+ showIcons = input(true, ...(ngDevMode ? [{ debugName: "showIcons" }] : []));
1831
+ iconPosition = input('left', ...(ngDevMode ? [{ debugName: "iconPosition" }] : []));
1832
+ ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : []));
1833
+ valueChange = output();
1834
+ hostClasses = computed(() => classNames('studio-button-toggle-group', this.disabled() && 'studio-button-toggle-group--disabled'), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
1835
+ isSelected(optionValue) {
1836
+ const currentValue = this.value();
1837
+ if (this.multiple()) {
1838
+ return Array.isArray(currentValue) && currentValue.includes(optionValue);
1839
+ }
1840
+ return currentValue === optionValue;
1841
+ }
1842
+ handleToggle(optionValue) {
1843
+ if (this.disabled())
1844
+ return;
1845
+ let newValue;
1846
+ if (this.multiple()) {
1847
+ const currentArray = Array.isArray(this.value()) ? this.value() : [];
1848
+ const index = currentArray.indexOf(optionValue);
1849
+ if (index > -1) {
1850
+ if (!this.allowEmpty() && currentArray.length === 1) {
1851
+ return;
1852
+ }
1853
+ newValue = currentArray.filter(v => v !== optionValue);
1854
+ }
1855
+ else {
1856
+ newValue = [...currentArray, optionValue];
1857
+ }
1858
+ }
1859
+ else {
1860
+ const currentValue = this.value();
1861
+ if (currentValue === optionValue && !this.allowEmpty()) {
1862
+ return;
1863
+ }
1864
+ newValue = currentValue === optionValue ? (this.allowEmpty() ? '' : optionValue) : optionValue;
1865
+ }
1866
+ this.value.set(newValue);
1867
+ this.onChange(newValue);
1868
+ this.onTouched();
1869
+ this.valueChange.emit(newValue);
1870
+ }
1871
+ writeValue(val) {
1872
+ if (val !== undefined && val !== null) {
1873
+ this.value.set(val);
1874
+ }
1875
+ else {
1876
+ this.value.set(this.multiple() ? [] : '');
1877
+ }
1878
+ }
1879
+ registerOnChange(fn) {
1880
+ this.onChange = fn;
1881
+ }
1882
+ registerOnTouched(fn) {
1883
+ this.onTouched = fn;
1884
+ }
1885
+ setDisabledState(isDisabled) {
1886
+ // disabled handled via input signal
1887
+ }
1888
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonToggleGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1889
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: ButtonToggleGroupComponent, isStandalone: true, selector: "studio-button-toggle-group", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, allowEmpty: { classPropertyName: "allowEmpty", publicName: "allowEmpty", isSignal: true, isRequired: false, transformFunction: null }, orientationInput: { classPropertyName: "orientationInput", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, sizeInput: { classPropertyName: "sizeInput", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variantInput: { classPropertyName: "variantInput", publicName: "variant", 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 }, attached: { classPropertyName: "attached", publicName: "attached", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, spacing: { classPropertyName: "spacing", publicName: "spacing", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, showIcons: { classPropertyName: "showIcons", publicName: "showIcons", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", valueChange: "valueChange" }, host: { properties: { "class": "hostClasses()" } }, providers: [
1890
+ {
1891
+ provide: NG_VALUE_ACCESSOR,
1892
+ useExisting: forwardRef(() => ButtonToggleGroupComponent),
1893
+ multi: true
1894
+ }
1895
+ ], ngImport: i0, template: `
1896
+ <studio-button-group
1897
+ [orientation]="orientation()"
1898
+ [attached]="attached()"
1899
+ [fullWidth]="fullWidth()"
1900
+ [spacing]="spacing()"
1901
+ [align]="align()"
1902
+ [ariaLabel]="ariaLabel()">
1903
+ @for (option of options(); track option.value) {
1904
+ <studio-button
1905
+ [variant]="isSelected(option.value) ? 'solid' : variant()"
1906
+ [size]="size()"
1907
+ [color]="isSelected(option.value) ? color() : 'secondary'"
1908
+ [radius]="radius()"
1909
+ [shadow]="shadow()"
1910
+ [disabled]="disabled() || option.disabled || false"
1911
+ [icon]="showIcons() ? option.icon : undefined"
1912
+ [iconPosition]="iconPosition()"
1913
+ [ariaLabel]="option.ariaLabel"
1914
+ (clicked)="handleToggle(option.value)">
1915
+ @if (iconPosition() !== 'only') {
1916
+ {{ option.label }}
1917
+ }
1918
+ </studio-button>
1919
+ }
1920
+ </studio-button-group>
1921
+ `, isInline: true, styles: [":host{display:inline-block}:host(.studio-button-toggle-group--disabled){opacity:.6;pointer-events:none}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "studio-button", inputs: ["variant", "size", "color", "radius", "shadow", "compact", "disabled", "loading", "loadingText", "fullWidth", "type", "icon", "iconPosition", "href", "target", "badge", "badgeColor", "ariaLabel"], outputs: ["clicked"] }, { kind: "component", type: ButtonGroupComponent, selector: "studio-button-group", inputs: ["orientation", "size", "variant", "color", "radius", "attached", "fullWidth", "disabled", "spacing", "align", "ariaLabel", "role"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1922
+ }
1923
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonToggleGroupComponent, decorators: [{
1924
+ type: Component,
1925
+ args: [{ selector: 'studio-button-toggle-group', standalone: true, imports: [ButtonComponent, ButtonGroupComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
1926
+ {
1927
+ provide: NG_VALUE_ACCESSOR,
1928
+ useExisting: forwardRef(() => ButtonToggleGroupComponent),
1929
+ multi: true
1930
+ }
1931
+ ], host: {
1932
+ '[class]': 'hostClasses()'
1933
+ }, template: `
1934
+ <studio-button-group
1935
+ [orientation]="orientation()"
1936
+ [attached]="attached()"
1937
+ [fullWidth]="fullWidth()"
1938
+ [spacing]="spacing()"
1939
+ [align]="align()"
1940
+ [ariaLabel]="ariaLabel()">
1941
+ @for (option of options(); track option.value) {
1942
+ <studio-button
1943
+ [variant]="isSelected(option.value) ? 'solid' : variant()"
1944
+ [size]="size()"
1945
+ [color]="isSelected(option.value) ? color() : 'secondary'"
1946
+ [radius]="radius()"
1947
+ [shadow]="shadow()"
1948
+ [disabled]="disabled() || option.disabled || false"
1949
+ [icon]="showIcons() ? option.icon : undefined"
1950
+ [iconPosition]="iconPosition()"
1951
+ [ariaLabel]="option.ariaLabel"
1952
+ (clicked)="handleToggle(option.value)">
1953
+ @if (iconPosition() !== 'only') {
1954
+ {{ option.label }}
1955
+ }
1956
+ </studio-button>
1957
+ }
1958
+ </studio-button-group>
1959
+ `, styles: [":host{display:inline-block}:host(.studio-button-toggle-group--disabled){opacity:.6;pointer-events:none}\n"] }]
1960
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], allowEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowEmpty", required: false }] }], orientationInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], sizeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variantInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", 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 }] }], attached: [{ type: i0.Input, args: [{ isSignal: true, alias: "attached", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], spacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "spacing", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], showIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcons", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
1961
+
1146
1962
  /**
1147
1963
  * Theme toggle switch with sun/moon icons
1148
1964
  *
@@ -1244,5 +2060,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1244
2060
  * Generated bundle index. Do not edit.
1245
2061
  */
1246
2062
 
1247
- export { BadgeComponent, ButtonComponent, IconComponent, InputComponent, STUDIO_CONFIG, StudioConfigService, SwitchComponent, ThemeSwitchComponent, classNames, isSafeUrl, loadGoogleFont, loadGoogleFonts, provideStudioConfig, provideStudioIcons, sanitizeUrl, withConfigDefault };
2063
+ export { BadgeComponent, ButtonComponent, ButtonGroupComponent, ButtonToggleGroupComponent, CheckboxComponent, IconComponent, InputComponent, STUDIO_CONFIG, StudioConfigService, SwitchComponent, TextareaComponent, ThemeSwitchComponent, classNames, isSafeUrl, loadGoogleFont, loadGoogleFonts, provideStudioConfig, provideStudioIcons, sanitizeUrl, withConfigDefault };
1248
2064
  //# sourceMappingURL=eduboxpro-studio.mjs.map