@pegasusheavy/ngx-tailwindcss 0.3.6 → 0.4.0
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,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, makeEnvironmentProviders, inject, PLATFORM_ID, DestroyRef, signal, Injectable, APP_INITIALIZER, computed, LOCALE_ID, effect, ElementRef, Renderer2, booleanAttribute, HostListener, Input, Directive, numberAttribute, NgZone, EventEmitter, Output, ChangeDetectionStrategy, Component, HostBinding, forwardRef, ViewChild, input, output, ContentChildren, ContentChild, viewChild,
|
|
2
|
+
import { InjectionToken, makeEnvironmentProviders, inject, PLATFORM_ID, DestroyRef, signal, Injectable, APP_INITIALIZER, computed, LOCALE_ID, effect, ElementRef, Renderer2, booleanAttribute, HostListener, Input, Directive, numberAttribute, NgZone, EventEmitter, Output, ChangeDetectionStrategy, Component, HostBinding, forwardRef, ViewChild, input, output, ContentChildren, ContentChild, viewChild, contentChildren } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { DOCUMENT, isPlatformBrowser, CommonModule, NgStyle } from '@angular/common';
|
|
5
5
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
@@ -3848,8 +3848,8 @@ const BUTTON_VARIANTS = {
|
|
|
3848
3848
|
warning: 'bg-amber-500 hover:bg-amber-600 active:bg-amber-700 text-white shadow-sm hover:shadow focus-visible:ring-amber-500',
|
|
3849
3849
|
danger: 'bg-rose-600 hover:bg-rose-700 active:bg-rose-800 text-white shadow-sm hover:shadow focus-visible:ring-rose-500',
|
|
3850
3850
|
info: 'bg-cyan-600 hover:bg-cyan-700 active:bg-cyan-800 text-white shadow-sm hover:shadow focus-visible:ring-cyan-500',
|
|
3851
|
-
ghost: 'bg-transparent hover:bg-slate-100
|
|
3852
|
-
outline: 'bg-white
|
|
3851
|
+
ghost: 'bg-transparent hover:bg-slate-100 active:bg-slate-200 text-slate-700 focus-visible:ring-slate-500',
|
|
3852
|
+
outline: 'bg-white border-2 border-slate-500 hover:border-slate-600 hover:bg-slate-100 active:bg-slate-200 text-slate-800 shadow-sm focus-visible:ring-slate-500',
|
|
3853
3853
|
link: 'bg-transparent text-blue-600 hover:text-blue-700 hover:underline active:text-blue-800 focus-visible:ring-blue-500 p-0 shadow-none',
|
|
3854
3854
|
};
|
|
3855
3855
|
const BUTTON_SIZES = {
|
|
@@ -4307,7 +4307,7 @@ class TwInputComponent {
|
|
|
4307
4307
|
useExisting: forwardRef(() => TwInputComponent),
|
|
4308
4308
|
multi: true,
|
|
4309
4309
|
},
|
|
4310
|
-
], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }], ngImport: i0, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<div [class]=\"wrapperClasses()\">\n <!-- Prefix -->\n <ng-content select=\"[twInputPrefix]\"></ng-content>\n\n <!-- Input element -->\n <input\n #inputElement\n [id]=\"inputId\"\n [type]=\"type\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.aria-invalid]=\"hasError\"\n [attr.aria-describedby]=\"describedBy\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.inputmode]=\"inputmode\"\n [attr.pattern]=\"pattern\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [attr.step]=\"step\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus.emit($event)\"\n />\n\n <!-- Suffix -->\n <ng-content select=\"[twInputSuffix]\"></ng-content>\n\n <!-- Clear button -->\n @if (clearable && value && !disabled && !readonly) {\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-5 h-5 text-slate-400 hover:text-slate-600 transition-colors\"\n (click)=\"clear()\"\n aria-label=\"Clear input\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n }\n</div>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n<ng-content select=\"tw-hint, [twHint], tw-error, [twError]\"></ng-content>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4310
|
+
], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }], ngImport: i0, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<div [class]=\"wrapperClasses()\">\n <!-- Prefix -->\n <ng-content select=\"[twInputPrefix]\"></ng-content>\n\n <!-- Input element -->\n <input\n #inputElement\n [id]=\"inputId\"\n [type]=\"type\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.aria-invalid]=\"hasError\"\n [attr.aria-describedby]=\"describedBy\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.inputmode]=\"inputmode\"\n [attr.pattern]=\"pattern\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [attr.step]=\"step\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus.emit($event)\"\n />\n\n <!-- Suffix -->\n <ng-content select=\"[twInputSuffix]\"></ng-content>\n\n <!-- Clear button -->\n @if (clearable && value && !disabled && !readonly) {\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-5 h-5 text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300 transition-colors\"\n (click)=\"clear()\"\n aria-label=\"Clear input\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n }\n</div>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 dark:text-slate-400 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n<ng-content select=\"tw-hint, [twHint], tw-error, [twError]\"></ng-content>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4311
4311
|
}
|
|
4312
4312
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TwInputComponent, decorators: [{
|
|
4313
4313
|
type: Component,
|
|
@@ -4319,7 +4319,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
4319
4319
|
},
|
|
4320
4320
|
], host: {
|
|
4321
4321
|
class: 'block',
|
|
4322
|
-
}, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<div [class]=\"wrapperClasses()\">\n <!-- Prefix -->\n <ng-content select=\"[twInputPrefix]\"></ng-content>\n\n <!-- Input element -->\n <input\n #inputElement\n [id]=\"inputId\"\n [type]=\"type\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.aria-invalid]=\"hasError\"\n [attr.aria-describedby]=\"describedBy\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.inputmode]=\"inputmode\"\n [attr.pattern]=\"pattern\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [attr.step]=\"step\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus.emit($event)\"\n />\n\n <!-- Suffix -->\n <ng-content select=\"[twInputSuffix]\"></ng-content>\n\n <!-- Clear button -->\n @if (clearable && value && !disabled && !readonly) {\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-5 h-5 text-slate-400 hover:text-slate-600 transition-colors\"\n (click)=\"clear()\"\n aria-label=\"Clear input\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n }\n</div>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n<ng-content select=\"tw-hint, [twHint], tw-error, [twError]\"></ng-content>\n" }]
|
|
4322
|
+
}, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<div [class]=\"wrapperClasses()\">\n <!-- Prefix -->\n <ng-content select=\"[twInputPrefix]\"></ng-content>\n\n <!-- Input element -->\n <input\n #inputElement\n [id]=\"inputId\"\n [type]=\"type\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.aria-invalid]=\"hasError\"\n [attr.aria-describedby]=\"describedBy\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.inputmode]=\"inputmode\"\n [attr.pattern]=\"pattern\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [attr.step]=\"step\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus.emit($event)\"\n />\n\n <!-- Suffix -->\n <ng-content select=\"[twInputSuffix]\"></ng-content>\n\n <!-- Clear button -->\n @if (clearable && value && !disabled && !readonly) {\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-5 h-5 text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300 transition-colors\"\n (click)=\"clear()\"\n aria-label=\"Clear input\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n }\n</div>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 dark:text-slate-400 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n<ng-content select=\"tw-hint, [twHint], tw-error, [twError]\"></ng-content>\n" }]
|
|
4323
4323
|
}], propDecorators: { inputElement: [{
|
|
4324
4324
|
type: ViewChild,
|
|
4325
4325
|
args: ['inputElement']
|
|
@@ -4452,7 +4452,7 @@ class TwTextareaComponent {
|
|
|
4452
4452
|
useExisting: forwardRef(() => TwTextareaComponent),
|
|
4453
4453
|
multi: true,
|
|
4454
4454
|
},
|
|
4455
|
-
], viewQueries: [{ propertyName: "textareaElement", first: true, predicate: ["textareaElement"], descendants: true }], ngImport: i0, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<textarea\n #textareaElement\n [id]=\"inputId\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [rows]=\"rows\"\n [attr.aria-invalid]=\"hasError\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n></textarea>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n@if (maxlength && showCount) {\n <span class=\"block text-xs text-slate-400 mt-1 text-right\">\n {{ value.length }} / {{ maxlength }}\n </span>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4455
|
+
], viewQueries: [{ propertyName: "textareaElement", first: true, predicate: ["textareaElement"], descendants: true }], ngImport: i0, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<textarea\n #textareaElement\n [id]=\"inputId\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [rows]=\"rows\"\n [attr.aria-invalid]=\"hasError\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n></textarea>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 dark:text-slate-400 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n@if (maxlength && showCount) {\n <span class=\"block text-xs text-slate-400 mt-1 text-right\">\n {{ value.length }} / {{ maxlength }}\n </span>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4456
4456
|
}
|
|
4457
4457
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TwTextareaComponent, decorators: [{
|
|
4458
4458
|
type: Component,
|
|
@@ -4464,7 +4464,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
4464
4464
|
},
|
|
4465
4465
|
], host: {
|
|
4466
4466
|
class: 'block',
|
|
4467
|
-
}, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<textarea\n #textareaElement\n [id]=\"inputId\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [rows]=\"rows\"\n [attr.aria-invalid]=\"hasError\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n></textarea>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n@if (maxlength && showCount) {\n <span class=\"block text-xs text-slate-400 mt-1 text-right\">\n {{ value.length }} / {{ maxlength }}\n </span>\n}\n" }]
|
|
4467
|
+
}, template: "@if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5\">\n {{ label }}\n @if (required) {\n <span class=\"text-rose-500 ml-0.5\">*</span>\n }\n </label>\n}\n\n<textarea\n #textareaElement\n [id]=\"inputId\"\n [class]=\"computedClasses()\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [rows]=\"rows\"\n [attr.aria-invalid]=\"hasError\"\n [attr.minlength]=\"minlength\"\n [attr.maxlength]=\"maxlength\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n></textarea>\n\n@if (hint && !error) {\n <span class=\"block text-xs text-slate-500 dark:text-slate-400 mt-1.5\">{{ hint }}</span>\n}\n\n@if (error) {\n <span class=\"block text-xs text-rose-600 mt-1.5\" role=\"alert\">{{ error }}</span>\n}\n\n@if (maxlength && showCount) {\n <span class=\"block text-xs text-slate-400 mt-1 text-right\">\n {{ value.length }} / {{ maxlength }}\n </span>\n}\n" }]
|
|
4468
4468
|
}], propDecorators: { textareaElement: [{
|
|
4469
4469
|
type: ViewChild,
|
|
4470
4470
|
args: ['textareaElement']
|
|
@@ -9799,19 +9799,16 @@ class TwPaginationComponent {
|
|
|
9799
9799
|
const rightSiblingIndex = Math.min(current + siblings, total);
|
|
9800
9800
|
const showLeftEllipsis = leftSiblingIndex > 2;
|
|
9801
9801
|
const showRightEllipsis = rightSiblingIndex < total - 1;
|
|
9802
|
-
// Use unique ellipsis identifiers to avoid duplicate keys in @for tracking
|
|
9803
|
-
const LEFT_ELLIPSIS = '...left';
|
|
9804
|
-
const RIGHT_ELLIPSIS = '...right';
|
|
9805
9802
|
if (!showLeftEllipsis && showRightEllipsis) {
|
|
9806
9803
|
const leftRange = range(1, 3 + siblings * 2);
|
|
9807
|
-
return [...leftRange.map(String),
|
|
9804
|
+
return [...leftRange.map(String), '...', String(total)];
|
|
9808
9805
|
}
|
|
9809
9806
|
if (showLeftEllipsis && !showRightEllipsis) {
|
|
9810
9807
|
const rightRange = range(total - (3 + siblings * 2) + 1, total);
|
|
9811
|
-
return ['1',
|
|
9808
|
+
return ['1', '...', ...rightRange.map(String)];
|
|
9812
9809
|
}
|
|
9813
9810
|
const middleRange = range(leftSiblingIndex, rightSiblingIndex);
|
|
9814
|
-
return ['1',
|
|
9811
|
+
return ['1', '...', ...middleRange.map(String), '...', String(total)];
|
|
9815
9812
|
}, ...(ngDevMode ? [{ debugName: "visiblePages" }] : []));
|
|
9816
9813
|
goToPage(page) {
|
|
9817
9814
|
if (page >= 1 && page <= this.totalPagesValue() && page !== this._currentPage()) {
|
|
@@ -9886,11 +9883,11 @@ class TwPaginationComponent {
|
|
|
9886
9883
|
return baseClasses.join(' ');
|
|
9887
9884
|
}
|
|
9888
9885
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TwPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9889
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TwPaginationComponent, isStandalone: true, selector: "tw-pagination", inputs: { currentPage: "currentPage", totalPages: "totalPages", totalItems: "totalItems", itemsPerPage: "itemsPerPage", siblingCount: "siblingCount", size: "size", variant: "variant", showFirstLast: "showFirstLast" }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "@switch (variantValue()) {\n @case ('simple') {\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"simpleButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n >\n <svg\n class=\"w-5 h-5 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n Previous\n </button>\n <span class=\"text-sm text-slate-600\">\n Page {{ currentPageValue() }} of {{ totalPagesValue() }}\n </span>\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() >= totalPagesValue()\"\n [class]=\"simpleButtonClasses(currentPageValue() >= totalPagesValue())\"\n (click)=\"goToPage(currentPageValue() + 1)\"\n >\n Next\n <svg\n class=\"w-5 h-5 ml-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n }\n @default {\n <nav class=\"flex items-center gap-1\" aria-label=\"Pagination\">\n <!-- Previous -->\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"navButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n aria-label=\"Previous page\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n\n <!-- Page numbers -->\n @for (page of visiblePages(); track page) {\n @if (page
|
|
9886
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TwPaginationComponent, isStandalone: true, selector: "tw-pagination", inputs: { currentPage: "currentPage", totalPages: "totalPages", totalItems: "totalItems", itemsPerPage: "itemsPerPage", siblingCount: "siblingCount", size: "size", variant: "variant", showFirstLast: "showFirstLast" }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "@switch (variantValue()) {\n @case ('simple') {\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"simpleButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n >\n <svg\n class=\"w-5 h-5 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n Previous\n </button>\n <span class=\"text-sm text-slate-600\">\n Page {{ currentPageValue() }} of {{ totalPagesValue() }}\n </span>\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() >= totalPagesValue()\"\n [class]=\"simpleButtonClasses(currentPageValue() >= totalPagesValue())\"\n (click)=\"goToPage(currentPageValue() + 1)\"\n >\n Next\n <svg\n class=\"w-5 h-5 ml-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n }\n @default {\n <nav class=\"flex items-center gap-1\" aria-label=\"Pagination\">\n <!-- Previous -->\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"navButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n aria-label=\"Previous page\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n\n <!-- Page numbers -->\n @for (page of visiblePages(); track page) {\n @if (page === '...') {\n <span [class]=\"ellipsisClasses()\">...</span>\n } @else {\n <button\n type=\"button\"\n [class]=\"pageButtonClasses(+page === currentPageValue())\"\n [attr.aria-current]=\"+page === currentPageValue() ? 'page' : null\"\n (click)=\"goToPage(+page)\"\n >\n {{ page }}\n </button>\n }\n }\n\n <!-- Next -->\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() >= totalPagesValue()\"\n [class]=\"navButtonClasses(currentPageValue() >= totalPagesValue())\"\n (click)=\"goToPage(currentPageValue() + 1)\"\n aria-label=\"Next page\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </nav>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
9890
9887
|
}
|
|
9891
9888
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TwPaginationComponent, decorators: [{
|
|
9892
9889
|
type: Component,
|
|
9893
|
-
args: [{ selector: 'tw-pagination', standalone: true, imports: [CommonModule], template: "@switch (variantValue()) {\n @case ('simple') {\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"simpleButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n >\n <svg\n class=\"w-5 h-5 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n Previous\n </button>\n <span class=\"text-sm text-slate-600\">\n Page {{ currentPageValue() }} of {{ totalPagesValue() }}\n </span>\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() >= totalPagesValue()\"\n [class]=\"simpleButtonClasses(currentPageValue() >= totalPagesValue())\"\n (click)=\"goToPage(currentPageValue() + 1)\"\n >\n Next\n <svg\n class=\"w-5 h-5 ml-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n }\n @default {\n <nav class=\"flex items-center gap-1\" aria-label=\"Pagination\">\n <!-- Previous -->\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"navButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n aria-label=\"Previous page\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n\n <!-- Page numbers -->\n @for (page of visiblePages(); track page) {\n @if (page
|
|
9890
|
+
args: [{ selector: 'tw-pagination', standalone: true, imports: [CommonModule], template: "@switch (variantValue()) {\n @case ('simple') {\n <div class=\"flex items-center justify-between\">\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"simpleButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n >\n <svg\n class=\"w-5 h-5 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n Previous\n </button>\n <span class=\"text-sm text-slate-600\">\n Page {{ currentPageValue() }} of {{ totalPagesValue() }}\n </span>\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() >= totalPagesValue()\"\n [class]=\"simpleButtonClasses(currentPageValue() >= totalPagesValue())\"\n (click)=\"goToPage(currentPageValue() + 1)\"\n >\n Next\n <svg\n class=\"w-5 h-5 ml-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n }\n @default {\n <nav class=\"flex items-center gap-1\" aria-label=\"Pagination\">\n <!-- Previous -->\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() <= 1\"\n [class]=\"navButtonClasses(currentPageValue() <= 1)\"\n (click)=\"goToPage(currentPageValue() - 1)\"\n aria-label=\"Previous page\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n\n <!-- Page numbers -->\n @for (page of visiblePages(); track page) {\n @if (page === '...') {\n <span [class]=\"ellipsisClasses()\">...</span>\n } @else {\n <button\n type=\"button\"\n [class]=\"pageButtonClasses(+page === currentPageValue())\"\n [attr.aria-current]=\"+page === currentPageValue() ? 'page' : null\"\n (click)=\"goToPage(+page)\"\n >\n {{ page }}\n </button>\n }\n }\n\n <!-- Next -->\n <button\n type=\"button\"\n [disabled]=\"currentPageValue() >= totalPagesValue()\"\n [class]=\"navButtonClasses(currentPageValue() >= totalPagesValue())\"\n (click)=\"goToPage(currentPageValue() + 1)\"\n aria-label=\"Next page\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </nav>\n }\n}\n" }]
|
|
9894
9891
|
}], propDecorators: { currentPage: [{
|
|
9895
9892
|
type: Input
|
|
9896
9893
|
}], totalPages: [{
|
|
@@ -13210,8 +13207,6 @@ class TwVolumeDialComponent {
|
|
|
13210
13207
|
a11y = inject(MusicAccessibilityService);
|
|
13211
13208
|
dialSvg = viewChild('dialSvg', ...(ngDevMode ? [{ debugName: "dialSvg" }] : []));
|
|
13212
13209
|
// Inputs
|
|
13213
|
-
/** Initial/bound value - supports two-way binding with [(value)] */
|
|
13214
|
-
value = model(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
13215
13210
|
min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : []));
|
|
13216
13211
|
max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : []));
|
|
13217
13212
|
step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : []));
|
|
@@ -13238,8 +13233,10 @@ class TwVolumeDialComponent {
|
|
|
13238
13233
|
announceChanges = input(true, ...(ngDevMode ? [{ debugName: "announceChanges" }] : [])); // Announce value changes to screen readers
|
|
13239
13234
|
reducedMotion = input('auto', ...(ngDevMode ? [{ debugName: "reducedMotion" }] : [])); // Respect reduced motion preference
|
|
13240
13235
|
// Outputs
|
|
13241
|
-
|
|
13236
|
+
valueChange = output();
|
|
13242
13237
|
hapticTrigger = output(); // Haptic feedback trigger points
|
|
13238
|
+
// Internal state
|
|
13239
|
+
value = signal(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
13243
13240
|
isDragging = false;
|
|
13244
13241
|
startAngle = 0;
|
|
13245
13242
|
startValue = 0;
|
|
@@ -13490,6 +13487,7 @@ class TwVolumeDialComponent {
|
|
|
13490
13487
|
if (newValue !== this.value()) {
|
|
13491
13488
|
this.value.set(newValue);
|
|
13492
13489
|
this.onChangeFn(newValue);
|
|
13490
|
+
this.valueChange.emit(newValue);
|
|
13493
13491
|
// Announce to screen readers (debounced)
|
|
13494
13492
|
if (this.announceChanges()) {
|
|
13495
13493
|
this.a11y.announceValueChange(this.label() || 'Volume', this.displayValue(), this.unit());
|
|
@@ -13510,7 +13508,7 @@ class TwVolumeDialComponent {
|
|
|
13510
13508
|
// Disabled state is handled via input
|
|
13511
13509
|
}
|
|
13512
13510
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TwVolumeDialComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13513
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TwVolumeDialComponent, isStandalone: true, selector: "tw-volume-dial", inputs: {
|
|
13511
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TwVolumeDialComponent, isStandalone: true, selector: "tw-volume-dial", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, showTicks: { classPropertyName: "showTicks", publicName: "showTicks", isSignal: true, isRequired: false, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, showLedRing: { classPropertyName: "showLedRing", publicName: "showLedRing", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, centerDetent: { classPropertyName: "centerDetent", publicName: "centerDetent", isSignal: true, isRequired: false, transformFunction: null }, detentValue: { classPropertyName: "detentValue", publicName: "detentValue", isSignal: true, isRequired: false, transformFunction: null }, classOverride: { classPropertyName: "classOverride", publicName: "classOverride", isSignal: true, isRequired: false, transformFunction: null }, customSize: { classPropertyName: "customSize", publicName: "customSize", isSignal: true, isRequired: false, transformFunction: null }, customStrokeWidth: { classPropertyName: "customStrokeWidth", publicName: "customStrokeWidth", isSignal: true, isRequired: false, transformFunction: null }, hapticFeedback: { classPropertyName: "hapticFeedback", publicName: "hapticFeedback", isSignal: true, isRequired: false, transformFunction: null }, touchGuard: { classPropertyName: "touchGuard", publicName: "touchGuard", isSignal: true, isRequired: false, transformFunction: null }, minTouchDuration: { classPropertyName: "minTouchDuration", publicName: "minTouchDuration", isSignal: true, isRequired: false, transformFunction: null }, announceChanges: { classPropertyName: "announceChanges", publicName: "announceChanges", isSignal: true, isRequired: false, transformFunction: null }, reducedMotion: { classPropertyName: "reducedMotion", publicName: "reducedMotion", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", hapticTrigger: "hapticTrigger" }, host: { classAttribute: "inline-block" }, providers: [
|
|
13514
13512
|
{
|
|
13515
13513
|
provide: NG_VALUE_ACCESSOR,
|
|
13516
13514
|
useExisting: forwardRef(() => TwVolumeDialComponent),
|
|
@@ -13529,7 +13527,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
13529
13527
|
], host: {
|
|
13530
13528
|
class: 'inline-block',
|
|
13531
13529
|
}, template: "<div\n [class]=\"containerClasses()\"\n [style.width.px]=\"sizeConfig().size\"\n [style.height.px]=\"sizeConfig().size + (showValue() ? 24 : 0)\"\n>\n <!-- SVG Dial -->\n <svg\n #dialSvg\n [attr.width]=\"sizeConfig().size\"\n [attr.height]=\"sizeConfig().size\"\n [attr.viewBox]=\"'0 0 ' + sizeConfig().size + ' ' + sizeConfig().size\"\n class=\"cursor-pointer select-none\"\n [class.opacity-50]=\"disabled()\"\n [class.cursor-not-allowed]=\"disabled()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (keydown)=\"onKeyDown($event)\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n role=\"slider\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-label]=\"label() || 'Volume dial'\"\n [attr.aria-disabled]=\"disabled()\"\n >\n <!-- Track (background arc) -->\n <path\n [attr.d]=\"trackPath()\"\n fill=\"none\"\n [attr.stroke-width]=\"sizeConfig().strokeWidth\"\n [class]=\"variantConfig().track\"\n stroke-linecap=\"round\"\n />\n\n <!-- Fill (value arc) -->\n <path\n [attr.d]=\"fillPath()\"\n fill=\"none\"\n [attr.stroke-width]=\"sizeConfig().strokeWidth\"\n [class]=\"variantConfig().fill\"\n stroke-linecap=\"round\"\n />\n\n <!-- Tick marks -->\n @if (showTicks()) {\n @for (tick of tickMarks(); track tick.angle) {\n <line\n [attr.x1]=\"tick.x1\"\n [attr.y1]=\"tick.y1\"\n [attr.x2]=\"tick.x2\"\n [attr.y2]=\"tick.y2\"\n [class]=\"\n tick.isMajor\n ? 'stroke-slate-400 dark:stroke-slate-500'\n : 'stroke-slate-300 dark:stroke-slate-600'\n \"\n [attr.stroke-width]=\"tick.isMajor ? 2 : 1\"\n />\n }\n }\n\n <!-- Knob center -->\n <circle\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"knobRadius()\"\n [class]=\"variantConfig().knob\"\n stroke-width=\"2\"\n />\n\n <!-- Indicator line -->\n <line\n [attr.x1]=\"center()\"\n [attr.y1]=\"center()\"\n [attr.x2]=\"indicatorEnd().x\"\n [attr.y2]=\"indicatorEnd().y\"\n [class]=\"variantConfig().indicator\"\n [attr.stroke-width]=\"sizeConfig().strokeWidth - 1\"\n stroke-linecap=\"round\"\n />\n\n <!-- LED ring (for led variant) -->\n @if (variant() === 'led' && showLedRing()) {\n @for (led of ledSegments(); track led.index) {\n <circle\n [attr.cx]=\"led.x\"\n [attr.cy]=\"led.y\"\n [attr.r]=\"3\"\n [class]=\"led.active ? 'fill-emerald-400' : 'fill-slate-700'\"\n />\n }\n }\n </svg>\n\n <!-- Value display -->\n @if (showValue()) {\n <div [class]=\"valueClasses()\">{{ displayValue() }}{{ unit() }}</div>\n }\n\n <!-- Label -->\n @if (label() && showLabel()) {\n <div\n class=\"absolute -bottom-6 left-1/2 -translate-x-1/2 text-xs text-slate-500 dark:text-slate-400 whitespace-nowrap\"\n >\n {{ label() }}\n </div>\n }\n</div>\n" }]
|
|
13532
|
-
}], propDecorators: { dialSvg: [{ type: i0.ViewChild, args: ['dialSvg', { isSignal: true }] }],
|
|
13530
|
+
}], propDecorators: { dialSvg: [{ type: i0.ViewChild, args: ['dialSvg', { isSignal: true }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], showTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTicks", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], showLedRing: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLedRing", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], centerDetent: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerDetent", required: false }] }], detentValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "detentValue", required: false }] }], classOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "classOverride", required: false }] }], customSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "customSize", required: false }] }], customStrokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "customStrokeWidth", required: false }] }], hapticFeedback: [{ type: i0.Input, args: [{ isSignal: true, alias: "hapticFeedback", required: false }] }], touchGuard: [{ type: i0.Input, args: [{ isSignal: true, alias: "touchGuard", required: false }] }], minTouchDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTouchDuration", required: false }] }], announceChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "announceChanges", required: false }] }], reducedMotion: [{ type: i0.Input, args: [{ isSignal: true, alias: "reducedMotion", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], hapticTrigger: [{ type: i0.Output, args: ["hapticTrigger"] }] } });
|
|
13533
13531
|
|
|
13534
13532
|
// RMS calculation window size (samples)
|
|
13535
13533
|
const RMS_WINDOW_SIZE = 1024;
|
|
@@ -19135,7 +19133,7 @@ class TwChannelStripComponent {
|
|
|
19135
19133
|
useExisting: forwardRef(() => TwChannelStripComponent),
|
|
19136
19134
|
multi: true,
|
|
19137
19135
|
},
|
|
19138
|
-
], ngImport: i0, template: "<div [class]=\"containerClasses()\">\n <!-- Channel Label with Signal Indicator -->\n @if (showLabel()) {\n <div [class]=\"labelClasses()\" class=\"relative flex items-center justify-center gap-1\">\n <!-- Signal Present Indicator -->\n @if (showSignalIndicator()) {\n <div\n class=\"w-2 h-2 rounded-full transition-all duration-150\"\n [class.bg-green-500]=\"signalPresent()\"\n [class.shadow-[0_0_6px_rgba(34,197,94,0.8)]]=\"signalPresent()\"\n [class.bg-slate-600]=\"!signalPresent()\"\n title=\"Signal Present\"\n ></div>\n }\n <span class=\"text-slate-400\">{{ channelNumber() }}</span>\n <span class=\"text-white\">{{ label() }}</span>\n </div>\n }\n\n <!-- Input Gain Control -->\n @if (showInputGain()) {\n <div class=\"flex flex-col items-center gap-1\">\n <tw-volume-dial\n [ngModel]=\"inputGain()\"\n (ngModelChange)=\"onInputGainChange($event)\"\n [min]=\"-20\"\n [max]=\"20\"\n [step]=\"1\"\n [size]=\"size() === 'lg' ? 'sm' : 'xs'\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'minimal'\"\n [disabled]=\"disabled()\"\n [centerDetent]=\"true\"\n [detentValue]=\"0\"\n label=\"\"\n [showValue]=\"false\"\n ></tw-volume-dial>\n <span class=\"text-[9px] text-slate-500 font-mono\">{{ formatGain(inputGain()) }}dB</span>\n <span class=\"text-[8px] text-slate-600\">GAIN</span>\n </div>\n }\n\n <!-- Record Button -->\n @if (showRecord()) {\n <button\n type=\"button\"\n [class]=\"buttonSize()\"\n class=\"rounded-full flex items-center justify-center font-bold transition-all\"\n [class.bg-red-600]=\"record()\"\n [class.text-white]=\"record()\"\n [class.bg-slate-700]=\"!record()\"\n [class.text-slate-400]=\"!record()\"\n [class.hover:bg-red-500]=\"!record()\"\n [class.animate-pulse]=\"record()\"\n [disabled]=\"disabled()\"\n (click)=\"toggleRecord()\"\n title=\"Record Arm\"\n >\n R\n </button>\n }\n\n <!-- Aux Send Knobs -->\n @if (showAuxSends()) {\n <div class=\"flex flex-col gap-1 w-full border-t border-slate-700/50 pt-2\">\n <span class=\"text-[8px] text-slate-500 text-center\">SENDS</span>\n <div\n class=\"grid gap-1\"\n [class.grid-cols-2]=\"auxSendCount() > 2\"\n [class.grid-cols-1]=\"auxSendCount() <= 2\"\n >\n @for (aux of auxSendArray(); track aux.index) {\n <div class=\"flex flex-col items-center\">\n <tw-volume-dial\n [ngModel]=\"aux.value\"\n (ngModelChange)=\"onAuxSendChange(aux.index, $event)\"\n [min]=\"0\"\n [max]=\"100\"\n [step]=\"1\"\n size=\"xs\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'minimal'\"\n [disabled]=\"disabled() || mute()\"\n label=\"\"\n [showValue]=\"false\"\n ></tw-volume-dial>\n <span class=\"text-[8px] text-slate-500 truncate max-w-full\">{{ aux.label }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- VU Meter -->\n @if (showMeter()) {\n <div class=\"flex-1 flex items-center justify-center py-1\">\n @if (stereo()) {\n <tw-vu-meter\n [leftValue]=\"meterLevel()\"\n [rightValue]=\"meterLevelRight()\"\n [stereo]=\"true\"\n [segmentCount]=\"size() === 'sm' ? 8 : 12\"\n [height]=\"size() === 'sm' ? 60 : size() === 'lg' ? 100 : 80\"\n variant=\"led\"\n ></tw-vu-meter>\n } @else {\n <tw-vu-meter\n [value]=\"meterLevel()\"\n [segmentCount]=\"size() === 'sm' ? 8 : 12\"\n [height]=\"size() === 'sm' ? 60 : size() === 'lg' ? 100 : 80\"\n variant=\"led\"\n ></tw-vu-meter>\n }\n </div>\n }\n\n <!-- Volume Fader / Dial -->\n <tw-volume-dial\n [ngModel]=\"volume()\"\n (ngModelChange)=\"onVolumeChange($event)\"\n [min]=\"0\"\n [max]=\"100\"\n [step]=\"1\"\n [size]=\"dialSize()\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'modern'\"\n [disabled]=\"disabled() || mute()\"\n label=\"\"\n [showValue]=\"size() !== 'sm'\"\n ></tw-volume-dial>\n\n <!-- Pan Control -->\n @if (showPan()) {\n <tw-volume-dial\n [ngModel]=\"pan()\"\n (ngModelChange)=\"onPanChange($event)\"\n [min]=\"-100\"\n [max]=\"100\"\n [step]=\"1\"\n [size]=\"size() === 'lg' ? 'md' : 'sm'\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'minimal'\"\n [disabled]=\"disabled()\"\n [centerDetent]=\"true\"\n [detentValue]=\"0\"\n label=\"\"\n [showValue]=\"false\"\n ></tw-volume-dial>\n <span class=\"text-[10px] text-slate-500\">PAN</span>\n }\n\n <!-- Mute / Solo Buttons -->\n @if (showMuteSolo()) {\n <div class=\"flex gap-1\">\n <button\n type=\"button\"\n [class]=\"buttonSize()\"\n class=\"rounded flex items-center justify-center font-bold transition-all\"\n [class.bg-amber-500]=\"mute()\"\n [class.text-black]=\"mute()\"\n [class.bg-slate-700]=\"!mute()\"\n [class.text-slate-400]=\"!mute()\"\n [class.hover:bg-amber-400]=\"!mute()\"\n [disabled]=\"disabled()\"\n (click)=\"toggleMute()\"\n title=\"Mute\"\n >\n M\n </button>\n <button\n type=\"button\"\n [class]=\"buttonSize()\"\n class=\"rounded flex items-center justify-center font-bold transition-all\"\n [class.bg-green-500]=\"solo()\"\n [class.text-black]=\"solo()\"\n [class.bg-slate-700]=\"!solo()\"\n [class.text-slate-400]=\"!solo()\"\n [class.hover:bg-green-400]=\"!solo()\"\n [disabled]=\"disabled()\"\n (click)=\"toggleSolo()\"\n title=\"Solo\"\n >\n S\n </button>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TwVolumeDialComponent, selector: "tw-volume-dial", inputs: ["
|
|
19136
|
+
], ngImport: i0, template: "<div [class]=\"containerClasses()\">\n <!-- Channel Label with Signal Indicator -->\n @if (showLabel()) {\n <div [class]=\"labelClasses()\" class=\"relative flex items-center justify-center gap-1\">\n <!-- Signal Present Indicator -->\n @if (showSignalIndicator()) {\n <div\n class=\"w-2 h-2 rounded-full transition-all duration-150\"\n [class.bg-green-500]=\"signalPresent()\"\n [class.shadow-[0_0_6px_rgba(34,197,94,0.8)]]=\"signalPresent()\"\n [class.bg-slate-600]=\"!signalPresent()\"\n title=\"Signal Present\"\n ></div>\n }\n <span class=\"text-slate-400\">{{ channelNumber() }}</span>\n <span class=\"text-white\">{{ label() }}</span>\n </div>\n }\n\n <!-- Input Gain Control -->\n @if (showInputGain()) {\n <div class=\"flex flex-col items-center gap-1\">\n <tw-volume-dial\n [ngModel]=\"inputGain()\"\n (ngModelChange)=\"onInputGainChange($event)\"\n [min]=\"-20\"\n [max]=\"20\"\n [step]=\"1\"\n [size]=\"size() === 'lg' ? 'sm' : 'xs'\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'minimal'\"\n [disabled]=\"disabled()\"\n [centerDetent]=\"true\"\n [detentValue]=\"0\"\n label=\"\"\n [showValue]=\"false\"\n ></tw-volume-dial>\n <span class=\"text-[9px] text-slate-500 font-mono\">{{ formatGain(inputGain()) }}dB</span>\n <span class=\"text-[8px] text-slate-600\">GAIN</span>\n </div>\n }\n\n <!-- Record Button -->\n @if (showRecord()) {\n <button\n type=\"button\"\n [class]=\"buttonSize()\"\n class=\"rounded-full flex items-center justify-center font-bold transition-all\"\n [class.bg-red-600]=\"record()\"\n [class.text-white]=\"record()\"\n [class.bg-slate-700]=\"!record()\"\n [class.text-slate-400]=\"!record()\"\n [class.hover:bg-red-500]=\"!record()\"\n [class.animate-pulse]=\"record()\"\n [disabled]=\"disabled()\"\n (click)=\"toggleRecord()\"\n title=\"Record Arm\"\n >\n R\n </button>\n }\n\n <!-- Aux Send Knobs -->\n @if (showAuxSends()) {\n <div class=\"flex flex-col gap-1 w-full border-t border-slate-700/50 pt-2\">\n <span class=\"text-[8px] text-slate-500 text-center\">SENDS</span>\n <div\n class=\"grid gap-1\"\n [class.grid-cols-2]=\"auxSendCount() > 2\"\n [class.grid-cols-1]=\"auxSendCount() <= 2\"\n >\n @for (aux of auxSendArray(); track aux.index) {\n <div class=\"flex flex-col items-center\">\n <tw-volume-dial\n [ngModel]=\"aux.value\"\n (ngModelChange)=\"onAuxSendChange(aux.index, $event)\"\n [min]=\"0\"\n [max]=\"100\"\n [step]=\"1\"\n size=\"xs\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'minimal'\"\n [disabled]=\"disabled() || mute()\"\n label=\"\"\n [showValue]=\"false\"\n ></tw-volume-dial>\n <span class=\"text-[8px] text-slate-500 truncate max-w-full\">{{ aux.label }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- VU Meter -->\n @if (showMeter()) {\n <div class=\"flex-1 flex items-center justify-center py-1\">\n @if (stereo()) {\n <tw-vu-meter\n [leftValue]=\"meterLevel()\"\n [rightValue]=\"meterLevelRight()\"\n [stereo]=\"true\"\n [segmentCount]=\"size() === 'sm' ? 8 : 12\"\n [height]=\"size() === 'sm' ? 60 : size() === 'lg' ? 100 : 80\"\n variant=\"led\"\n ></tw-vu-meter>\n } @else {\n <tw-vu-meter\n [value]=\"meterLevel()\"\n [segmentCount]=\"size() === 'sm' ? 8 : 12\"\n [height]=\"size() === 'sm' ? 60 : size() === 'lg' ? 100 : 80\"\n variant=\"led\"\n ></tw-vu-meter>\n }\n </div>\n }\n\n <!-- Volume Fader / Dial -->\n <tw-volume-dial\n [ngModel]=\"volume()\"\n (ngModelChange)=\"onVolumeChange($event)\"\n [min]=\"0\"\n [max]=\"100\"\n [step]=\"1\"\n [size]=\"dialSize()\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'modern'\"\n [disabled]=\"disabled() || mute()\"\n label=\"\"\n [showValue]=\"size() !== 'sm'\"\n ></tw-volume-dial>\n\n <!-- Pan Control -->\n @if (showPan()) {\n <tw-volume-dial\n [ngModel]=\"pan()\"\n (ngModelChange)=\"onPanChange($event)\"\n [min]=\"-100\"\n [max]=\"100\"\n [step]=\"1\"\n [size]=\"size() === 'lg' ? 'md' : 'sm'\"\n [variant]=\"variant() === 'vintage' ? 'vintage' : 'minimal'\"\n [disabled]=\"disabled()\"\n [centerDetent]=\"true\"\n [detentValue]=\"0\"\n label=\"\"\n [showValue]=\"false\"\n ></tw-volume-dial>\n <span class=\"text-[10px] text-slate-500\">PAN</span>\n }\n\n <!-- Mute / Solo Buttons -->\n @if (showMuteSolo()) {\n <div class=\"flex gap-1\">\n <button\n type=\"button\"\n [class]=\"buttonSize()\"\n class=\"rounded flex items-center justify-center font-bold transition-all\"\n [class.bg-amber-500]=\"mute()\"\n [class.text-black]=\"mute()\"\n [class.bg-slate-700]=\"!mute()\"\n [class.text-slate-400]=\"!mute()\"\n [class.hover:bg-amber-400]=\"!mute()\"\n [disabled]=\"disabled()\"\n (click)=\"toggleMute()\"\n title=\"Mute\"\n >\n M\n </button>\n <button\n type=\"button\"\n [class]=\"buttonSize()\"\n class=\"rounded flex items-center justify-center font-bold transition-all\"\n [class.bg-green-500]=\"solo()\"\n [class.text-black]=\"solo()\"\n [class.bg-slate-700]=\"!solo()\"\n [class.text-slate-400]=\"!solo()\"\n [class.hover:bg-green-400]=\"!solo()\"\n [disabled]=\"disabled()\"\n (click)=\"toggleSolo()\"\n title=\"Solo\"\n >\n S\n </button>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TwVolumeDialComponent, selector: "tw-volume-dial", inputs: ["min", "max", "step", "variant", "size", "disabled", "showValue", "showTicks", "showLabel", "showLedRing", "label", "unit", "centerDetent", "detentValue", "classOverride", "customSize", "customStrokeWidth", "hapticFeedback", "touchGuard", "minTouchDuration", "announceChanges", "reducedMotion"], outputs: ["valueChange", "hapticTrigger"] }, { kind: "component", type: TwVuMeterComponent, selector: "tw-vu-meter", inputs: ["value", "leftValue", "rightValue", "min", "max", "stereo", "variant", "orientation", "meterMode", "segmentCount", "height", "width", "barWidth", "gapSize", "rmsDecayRate", "customHeight", "customWidth", "customBarWidth", "customGapSize", "showPeak", "peakHoldTime", "peakDecayRate", "showClip", "clipThreshold", "showScale", "showChannelLabels", "label", "labelPosition", "yellowThreshold", "redThreshold", "classOverride"], outputs: ["clipDetected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
19139
19137
|
}
|
|
19140
19138
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TwChannelStripComponent, decorators: [{
|
|
19141
19139
|
type: Component,
|
|
@@ -32083,6 +32081,17 @@ const TW_MUSIC_COMPONENTS = [
|
|
|
32083
32081
|
// Convenience array for directives only
|
|
32084
32082
|
const TW_MUSIC_DIRECTIVES = [TwTouchGuardDirective, TwMidiLearnDirective];
|
|
32085
32083
|
|
|
32084
|
+
/**
|
|
32085
|
+
* Utility for truly dynamic imports that bundlers cannot statically analyze.
|
|
32086
|
+
* This prevents build errors when optional peer dependencies (Tauri/Electron) are not installed.
|
|
32087
|
+
*/
|
|
32088
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32089
|
+
function dynamicImport(modulePath) {
|
|
32090
|
+
// Use Function constructor to hide the import from static analysis
|
|
32091
|
+
// This prevents bundlers from trying to resolve these modules at build time
|
|
32092
|
+
return new Function('modulePath', 'return import(modulePath)')(modulePath);
|
|
32093
|
+
}
|
|
32094
|
+
|
|
32086
32095
|
/**
|
|
32087
32096
|
* Service for detecting and interacting with the native platform
|
|
32088
32097
|
* Supports Tauri, Electron, and web browsers
|
|
@@ -32131,7 +32140,7 @@ class NativeAppPlatformService {
|
|
|
32131
32140
|
return 'web';
|
|
32132
32141
|
}
|
|
32133
32142
|
checkTauri() {
|
|
32134
|
-
return
|
|
32143
|
+
return false; // Tauri support disabled
|
|
32135
32144
|
}
|
|
32136
32145
|
checkElectron() {
|
|
32137
32146
|
return (typeof window !== 'undefined' &&
|
|
@@ -32170,18 +32179,12 @@ class NativeAppPlatformService {
|
|
|
32170
32179
|
// Window control methods
|
|
32171
32180
|
async minimize() {
|
|
32172
32181
|
if (this._isTauri()) {
|
|
32173
|
-
|
|
32174
|
-
|
|
32175
|
-
const win = tauriWindow.getCurrentWindow();
|
|
32176
|
-
await win.minimize();
|
|
32177
|
-
}
|
|
32178
|
-
catch (e) {
|
|
32179
|
-
console.warn('Tauri minimize failed:', e);
|
|
32180
|
-
}
|
|
32182
|
+
// Tauri support disabled
|
|
32183
|
+
return;
|
|
32181
32184
|
}
|
|
32182
32185
|
else if (this._isElectron()) {
|
|
32183
32186
|
try {
|
|
32184
|
-
const electron = await
|
|
32187
|
+
const electron = await dynamicImport('electron');
|
|
32185
32188
|
electron.ipcRenderer.send('window-minimize');
|
|
32186
32189
|
}
|
|
32187
32190
|
catch (e) {
|
|
@@ -32193,7 +32196,7 @@ class NativeAppPlatformService {
|
|
|
32193
32196
|
async maximize() {
|
|
32194
32197
|
if (this._isTauri()) {
|
|
32195
32198
|
try {
|
|
32196
|
-
const tauriWindow = await
|
|
32199
|
+
const tauriWindow = await dynamicImport('@tauri-apps/api/window');
|
|
32197
32200
|
const win = tauriWindow.getCurrentWindow();
|
|
32198
32201
|
if (await win.isMaximized()) {
|
|
32199
32202
|
await win.unmaximize();
|
|
@@ -32210,7 +32213,7 @@ class NativeAppPlatformService {
|
|
|
32210
32213
|
}
|
|
32211
32214
|
else if (this._isElectron()) {
|
|
32212
32215
|
try {
|
|
32213
|
-
const electron = await
|
|
32216
|
+
const electron = await dynamicImport('electron');
|
|
32214
32217
|
electron.ipcRenderer.send('window-maximize');
|
|
32215
32218
|
}
|
|
32216
32219
|
catch (e) {
|
|
@@ -32221,7 +32224,7 @@ class NativeAppPlatformService {
|
|
|
32221
32224
|
async close() {
|
|
32222
32225
|
if (this._isTauri()) {
|
|
32223
32226
|
try {
|
|
32224
|
-
const tauriWindow = await
|
|
32227
|
+
const tauriWindow = await dynamicImport('@tauri-apps/api/window');
|
|
32225
32228
|
const win = tauriWindow.getCurrentWindow();
|
|
32226
32229
|
await win.close();
|
|
32227
32230
|
}
|
|
@@ -32231,7 +32234,7 @@ class NativeAppPlatformService {
|
|
|
32231
32234
|
}
|
|
32232
32235
|
else if (this._isElectron()) {
|
|
32233
32236
|
try {
|
|
32234
|
-
const electron = await
|
|
32237
|
+
const electron = await dynamicImport('electron');
|
|
32235
32238
|
electron.ipcRenderer.send('window-close');
|
|
32236
32239
|
}
|
|
32237
32240
|
catch (e) {
|
|
@@ -32245,7 +32248,7 @@ class NativeAppPlatformService {
|
|
|
32245
32248
|
async toggleFullscreen() {
|
|
32246
32249
|
if (this._isTauri()) {
|
|
32247
32250
|
try {
|
|
32248
|
-
const tauriWindow = await
|
|
32251
|
+
const tauriWindow = await dynamicImport('@tauri-apps/api/window');
|
|
32249
32252
|
const win = tauriWindow.getCurrentWindow();
|
|
32250
32253
|
if (await win.isFullscreen()) {
|
|
32251
32254
|
await win.setFullscreen(false);
|
|
@@ -32260,7 +32263,7 @@ class NativeAppPlatformService {
|
|
|
32260
32263
|
}
|
|
32261
32264
|
else if (this._isElectron()) {
|
|
32262
32265
|
try {
|
|
32263
|
-
const electron = await
|
|
32266
|
+
const electron = await dynamicImport('electron');
|
|
32264
32267
|
electron.ipcRenderer.send('window-fullscreen');
|
|
32265
32268
|
}
|
|
32266
32269
|
catch (e) {
|
|
@@ -32279,7 +32282,7 @@ class NativeAppPlatformService {
|
|
|
32279
32282
|
async setTitle(title) {
|
|
32280
32283
|
if (this._isTauri()) {
|
|
32281
32284
|
try {
|
|
32282
|
-
const tauriWindow = await
|
|
32285
|
+
const tauriWindow = await dynamicImport('@tauri-apps/api/window');
|
|
32283
32286
|
const win = tauriWindow.getCurrentWindow();
|
|
32284
32287
|
await win.setTitle(title);
|
|
32285
32288
|
}
|
|
@@ -32289,7 +32292,7 @@ class NativeAppPlatformService {
|
|
|
32289
32292
|
}
|
|
32290
32293
|
else if (this._isElectron()) {
|
|
32291
32294
|
try {
|
|
32292
|
-
const electron = await
|
|
32295
|
+
const electron = await dynamicImport('electron');
|
|
32293
32296
|
electron.ipcRenderer.send('window-set-title', title);
|
|
32294
32297
|
}
|
|
32295
32298
|
catch (e) {
|
|
@@ -40180,7 +40183,7 @@ class TwTerminalComponent {
|
|
|
40180
40183
|
// Computed classes
|
|
40181
40184
|
containerClasses = computed(() => {
|
|
40182
40185
|
const variant = this.variant();
|
|
40183
|
-
const base = 'flex flex-col h-full overflow-hidden';
|
|
40186
|
+
const base = 'flex flex-col h-full overflow-hidden rounded-lg';
|
|
40184
40187
|
const variantClasses = {
|
|
40185
40188
|
default: 'bg-gray-900 text-gray-100',
|
|
40186
40189
|
dark: 'bg-black text-gray-200',
|
|
@@ -40339,7 +40342,7 @@ class TwTerminalComponent {
|
|
|
40339
40342
|
<!-- Input area -->
|
|
40340
40343
|
@if (showInput()) {
|
|
40341
40344
|
<div
|
|
40342
|
-
class="flex items-center gap-2 px-4 py-2 border-t border-gray-700 bg-gray-800"
|
|
40345
|
+
class="flex items-center gap-2 px-4 py-2 border-t border-gray-700 bg-gray-800 rounded-b-lg"
|
|
40343
40346
|
>
|
|
40344
40347
|
<span class="text-green-400 font-mono">{{ prompt() }}</span>
|
|
40345
40348
|
<input
|
|
@@ -40437,7 +40440,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
40437
40440
|
<!-- Input area -->
|
|
40438
40441
|
@if (showInput()) {
|
|
40439
40442
|
<div
|
|
40440
|
-
class="flex items-center gap-2 px-4 py-2 border-t border-gray-700 bg-gray-800"
|
|
40443
|
+
class="flex items-center gap-2 px-4 py-2 border-t border-gray-700 bg-gray-800 rounded-b-lg"
|
|
40441
40444
|
>
|
|
40442
40445
|
<span class="text-green-400 font-mono">{{ prompt() }}</span>
|
|
40443
40446
|
<input
|
|
@@ -40567,7 +40570,7 @@ class TwLogViewerComponent {
|
|
|
40567
40570
|
}
|
|
40568
40571
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TwLogViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
40569
40572
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TwLogViewerComponent, isStandalone: true, selector: "tw-log-viewer", inputs: { entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: false, transformFunction: null }, showSource: { classPropertyName: "showSource", publicName: "showSource", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entrySelect: "entrySelect", clearLogs: "clearLogs", exportClick: "exportClick" }, host: { classAttribute: "tw-log-viewer block" }, ngImport: i0, template: `
|
|
40570
|
-
<div class="flex flex-col h-full bg-white dark:bg-gray-900 overflow-hidden">
|
|
40573
|
+
<div class="flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg overflow-hidden">
|
|
40571
40574
|
<!-- Toolbar -->
|
|
40572
40575
|
<div
|
|
40573
40576
|
class="flex items-center gap-2 px-3 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800"
|
|
@@ -40717,7 +40720,7 @@ class TwLogViewerComponent {
|
|
|
40717
40720
|
|
|
40718
40721
|
<!-- Status bar -->
|
|
40719
40722
|
<div
|
|
40720
|
-
class="flex items-center justify-between px-3 py-1.5 text-xs text-gray-500 dark:text-gray-400 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800"
|
|
40723
|
+
class="flex items-center justify-between px-3 py-1.5 text-xs text-gray-500 dark:text-gray-400 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 rounded-b-lg"
|
|
40721
40724
|
>
|
|
40722
40725
|
<span>{{ filteredEntries().length }} / {{ entries().length }} entries</span>
|
|
40723
40726
|
<span>
|
|
@@ -40738,7 +40741,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
40738
40741
|
standalone: true,
|
|
40739
40742
|
imports: [CommonModule, FormsModule],
|
|
40740
40743
|
template: `
|
|
40741
|
-
<div class="flex flex-col h-full bg-white dark:bg-gray-900 overflow-hidden">
|
|
40744
|
+
<div class="flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg overflow-hidden">
|
|
40742
40745
|
<!-- Toolbar -->
|
|
40743
40746
|
<div
|
|
40744
40747
|
class="flex items-center gap-2 px-3 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800"
|
|
@@ -40888,7 +40891,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
40888
40891
|
|
|
40889
40892
|
<!-- Status bar -->
|
|
40890
40893
|
<div
|
|
40891
|
-
class="flex items-center justify-between px-3 py-1.5 text-xs text-gray-500 dark:text-gray-400 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800"
|
|
40894
|
+
class="flex items-center justify-between px-3 py-1.5 text-xs text-gray-500 dark:text-gray-400 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 rounded-b-lg"
|
|
40892
40895
|
>
|
|
40893
40896
|
<span>{{ filteredEntries().length }} / {{ entries().length }} entries</span>
|
|
40894
40897
|
<span>
|
|
@@ -43054,7 +43057,7 @@ class NativeStorageService {
|
|
|
43054
43057
|
}
|
|
43055
43058
|
if (this.platformService.isElectron()) {
|
|
43056
43059
|
try {
|
|
43057
|
-
const electron = await
|
|
43060
|
+
const electron = await dynamicImport('electron');
|
|
43058
43061
|
return electron.ipcRenderer.invoke('secure-storage-get', key);
|
|
43059
43062
|
}
|
|
43060
43063
|
catch (err) {
|
|
@@ -43081,7 +43084,7 @@ class NativeStorageService {
|
|
|
43081
43084
|
}
|
|
43082
43085
|
if (this.platformService.isElectron()) {
|
|
43083
43086
|
try {
|
|
43084
|
-
const electron = await
|
|
43087
|
+
const electron = await dynamicImport('electron');
|
|
43085
43088
|
await electron.ipcRenderer.invoke('secure-storage-set', key, value);
|
|
43086
43089
|
}
|
|
43087
43090
|
catch (err) {
|
|
@@ -43108,7 +43111,7 @@ class NativeStorageService {
|
|
|
43108
43111
|
}
|
|
43109
43112
|
if (this.platformService.isElectron()) {
|
|
43110
43113
|
try {
|
|
43111
|
-
const electron = await
|
|
43114
|
+
const electron = await dynamicImport('electron');
|
|
43112
43115
|
await electron.ipcRenderer.invoke('secure-storage-remove', key);
|
|
43113
43116
|
}
|
|
43114
43117
|
catch (err) {
|
|
@@ -43247,7 +43250,7 @@ class NativeIpcService {
|
|
|
43247
43250
|
async invoke(command, payload) {
|
|
43248
43251
|
if (this.platformService.isTauri()) {
|
|
43249
43252
|
try {
|
|
43250
|
-
const tauriCore = (await
|
|
43253
|
+
const tauriCore = (await dynamicImport('@tauri-apps/api/core'));
|
|
43251
43254
|
const data = await tauriCore.invoke(command, payload);
|
|
43252
43255
|
return { success: true, data };
|
|
43253
43256
|
}
|
|
@@ -43257,7 +43260,7 @@ class NativeIpcService {
|
|
|
43257
43260
|
}
|
|
43258
43261
|
if (this.platformService.isElectron()) {
|
|
43259
43262
|
try {
|
|
43260
|
-
const electron = await
|
|
43263
|
+
const electron = await dynamicImport('electron');
|
|
43261
43264
|
const data = await electron.ipcRenderer.invoke(command, payload);
|
|
43262
43265
|
return { success: true, data };
|
|
43263
43266
|
}
|
|
@@ -43273,7 +43276,7 @@ class NativeIpcService {
|
|
|
43273
43276
|
async send(channel, payload) {
|
|
43274
43277
|
if (this.platformService.isTauri()) {
|
|
43275
43278
|
try {
|
|
43276
|
-
const tauriEvent = (await
|
|
43279
|
+
const tauriEvent = (await dynamicImport('@tauri-apps/api/event'));
|
|
43277
43280
|
await tauriEvent.emit(channel, payload);
|
|
43278
43281
|
}
|
|
43279
43282
|
catch (e) {
|
|
@@ -43283,7 +43286,7 @@ class NativeIpcService {
|
|
|
43283
43286
|
}
|
|
43284
43287
|
if (this.platformService.isElectron()) {
|
|
43285
43288
|
try {
|
|
43286
|
-
const electron = await
|
|
43289
|
+
const electron = await dynamicImport('electron');
|
|
43287
43290
|
electron.ipcRenderer.send(channel, payload);
|
|
43288
43291
|
}
|
|
43289
43292
|
catch (e) {
|
|
@@ -43305,7 +43308,7 @@ class NativeIpcService {
|
|
|
43305
43308
|
// Platform-specific setup
|
|
43306
43309
|
if (this.platformService.isTauri()) {
|
|
43307
43310
|
try {
|
|
43308
|
-
const tauriEvent = (await
|
|
43311
|
+
const tauriEvent = (await dynamicImport('@tauri-apps/api/event'));
|
|
43309
43312
|
const unlisten = await tauriEvent.listen(channel, (event) => {
|
|
43310
43313
|
this.ngZone.run(() => {
|
|
43311
43314
|
callback(event.payload);
|
|
@@ -43320,7 +43323,7 @@ class NativeIpcService {
|
|
|
43320
43323
|
}
|
|
43321
43324
|
if (this.platformService.isElectron()) {
|
|
43322
43325
|
try {
|
|
43323
|
-
const electron = await
|
|
43326
|
+
const electron = await dynamicImport('electron');
|
|
43324
43327
|
const handler = (_event, data) => {
|
|
43325
43328
|
this.ngZone.run(() => {
|
|
43326
43329
|
callback(data);
|
|
@@ -43352,7 +43355,7 @@ class NativeIpcService {
|
|
|
43352
43355
|
async once(channel, callback) {
|
|
43353
43356
|
if (this.platformService.isTauri()) {
|
|
43354
43357
|
try {
|
|
43355
|
-
const tauriEvent = (await
|
|
43358
|
+
const tauriEvent = (await dynamicImport('@tauri-apps/api/event'));
|
|
43356
43359
|
await tauriEvent.once(channel, (event) => {
|
|
43357
43360
|
this.ngZone.run(() => {
|
|
43358
43361
|
callback(event.payload);
|
|
@@ -43366,7 +43369,7 @@ class NativeIpcService {
|
|
|
43366
43369
|
}
|
|
43367
43370
|
if (this.platformService.isElectron()) {
|
|
43368
43371
|
try {
|
|
43369
|
-
const electron = await
|
|
43372
|
+
const electron = await dynamicImport('electron');
|
|
43370
43373
|
electron.ipcRenderer.once(channel, (_event, data) => {
|
|
43371
43374
|
this.ngZone.run(() => {
|
|
43372
43375
|
callback(data);
|
|
@@ -43424,149 +43427,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
43424
43427
|
args: [{ providedIn: 'root' }]
|
|
43425
43428
|
}], ctorParameters: () => [] });
|
|
43426
43429
|
|
|
43427
|
-
/**
|
|
43428
|
-
* Dynamic import utilities that prevent bundlers from analyzing/resolving the imports at build time.
|
|
43429
|
-
*
|
|
43430
|
-
* The trick is to use a variable for the module specifier, which makes it impossible for bundlers
|
|
43431
|
-
* to statically analyze the import. This is intentional for optional dependencies like Electron and Tauri.
|
|
43432
|
-
*/
|
|
43433
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
43434
|
-
/**
|
|
43435
|
-
* Creates a dynamic import function that bundlers cannot statically analyze.
|
|
43436
|
-
* This prevents build errors for optional dependencies that may not be installed.
|
|
43437
|
-
*/
|
|
43438
|
-
function createDynamicImport() {
|
|
43439
|
-
// Use Function constructor to create import at runtime, preventing static analysis
|
|
43440
|
-
return new Function('modulePath', 'return import(modulePath)');
|
|
43441
|
-
}
|
|
43442
|
-
const dynamicImport = createDynamicImport();
|
|
43443
|
-
/**
|
|
43444
|
-
* Dynamically import the Electron module.
|
|
43445
|
-
* This will only work at runtime when running in an Electron context.
|
|
43446
|
-
* Returns null if Electron is not available.
|
|
43447
|
-
*/
|
|
43448
|
-
async function importElectron() {
|
|
43449
|
-
try {
|
|
43450
|
-
const electron = await dynamicImport('electron');
|
|
43451
|
-
return electron;
|
|
43452
|
-
}
|
|
43453
|
-
catch {
|
|
43454
|
-
return null;
|
|
43455
|
-
}
|
|
43456
|
-
}
|
|
43457
|
-
/**
|
|
43458
|
-
* Dynamically import Tauri dialog plugin.
|
|
43459
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43460
|
-
* Returns null if Tauri dialog is not available.
|
|
43461
|
-
*/
|
|
43462
|
-
async function importTauriDialog() {
|
|
43463
|
-
try {
|
|
43464
|
-
const dialog = await dynamicImport('@tauri-apps/plugin-dialog');
|
|
43465
|
-
return dialog;
|
|
43466
|
-
}
|
|
43467
|
-
catch {
|
|
43468
|
-
return null;
|
|
43469
|
-
}
|
|
43470
|
-
}
|
|
43471
|
-
/**
|
|
43472
|
-
* Dynamically import Tauri notification plugin.
|
|
43473
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43474
|
-
* Returns null if Tauri notification is not available.
|
|
43475
|
-
*/
|
|
43476
|
-
async function importTauriNotification() {
|
|
43477
|
-
try {
|
|
43478
|
-
const notification = await dynamicImport('@tauri-apps/plugin-notification');
|
|
43479
|
-
return notification;
|
|
43480
|
-
}
|
|
43481
|
-
catch {
|
|
43482
|
-
return null;
|
|
43483
|
-
}
|
|
43484
|
-
}
|
|
43485
|
-
/**
|
|
43486
|
-
* Dynamically import Tauri process plugin.
|
|
43487
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43488
|
-
* Returns null if Tauri process is not available.
|
|
43489
|
-
*/
|
|
43490
|
-
async function importTauriProcess() {
|
|
43491
|
-
try {
|
|
43492
|
-
const process = await dynamicImport('@tauri-apps/plugin-process');
|
|
43493
|
-
return process;
|
|
43494
|
-
}
|
|
43495
|
-
catch {
|
|
43496
|
-
return null;
|
|
43497
|
-
}
|
|
43498
|
-
}
|
|
43499
|
-
/**
|
|
43500
|
-
* Dynamically import Tauri updater plugin.
|
|
43501
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43502
|
-
* Returns null if Tauri updater is not available.
|
|
43503
|
-
*/
|
|
43504
|
-
async function importTauriUpdater() {
|
|
43505
|
-
try {
|
|
43506
|
-
const updater = await dynamicImport('@tauri-apps/plugin-updater');
|
|
43507
|
-
return updater;
|
|
43508
|
-
}
|
|
43509
|
-
catch {
|
|
43510
|
-
return null;
|
|
43511
|
-
}
|
|
43512
|
-
}
|
|
43513
|
-
/**
|
|
43514
|
-
* Dynamically import Tauri app API.
|
|
43515
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43516
|
-
* Returns null if Tauri app is not available.
|
|
43517
|
-
*/
|
|
43518
|
-
async function importTauriApp() {
|
|
43519
|
-
try {
|
|
43520
|
-
const app = await dynamicImport('@tauri-apps/api/app');
|
|
43521
|
-
return app;
|
|
43522
|
-
}
|
|
43523
|
-
catch {
|
|
43524
|
-
return null;
|
|
43525
|
-
}
|
|
43526
|
-
}
|
|
43527
|
-
/**
|
|
43528
|
-
* Dynamically import Tauri menu API.
|
|
43529
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43530
|
-
* Returns null if Tauri menu is not available.
|
|
43531
|
-
*/
|
|
43532
|
-
async function importTauriMenu() {
|
|
43533
|
-
try {
|
|
43534
|
-
const menu = await dynamicImport('@tauri-apps/api/menu');
|
|
43535
|
-
return menu;
|
|
43536
|
-
}
|
|
43537
|
-
catch {
|
|
43538
|
-
return null;
|
|
43539
|
-
}
|
|
43540
|
-
}
|
|
43541
|
-
/**
|
|
43542
|
-
* Dynamically import Tauri tray API.
|
|
43543
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43544
|
-
* Returns null if Tauri tray is not available.
|
|
43545
|
-
*/
|
|
43546
|
-
async function importTauriTray() {
|
|
43547
|
-
try {
|
|
43548
|
-
const tray = await dynamicImport('@tauri-apps/api/tray');
|
|
43549
|
-
return tray;
|
|
43550
|
-
}
|
|
43551
|
-
catch {
|
|
43552
|
-
return null;
|
|
43553
|
-
}
|
|
43554
|
-
}
|
|
43555
|
-
/**
|
|
43556
|
-
* Dynamically import Tauri window API.
|
|
43557
|
-
* This will only work at runtime when running in a Tauri context.
|
|
43558
|
-
* Returns null if Tauri window is not available.
|
|
43559
|
-
*/
|
|
43560
|
-
async function importTauriWindow() {
|
|
43561
|
-
try {
|
|
43562
|
-
const window = await dynamicImport('@tauri-apps/api/window');
|
|
43563
|
-
return window;
|
|
43564
|
-
}
|
|
43565
|
-
catch {
|
|
43566
|
-
return null;
|
|
43567
|
-
}
|
|
43568
|
-
}
|
|
43569
|
-
|
|
43570
43430
|
const PLATFORM_TAURI$4 = 'tauri';
|
|
43571
43431
|
const PLATFORM_ELECTRON$4 = 'electron';
|
|
43572
43432
|
class FilePickerService {
|
|
@@ -43609,14 +43469,12 @@ class FilePickerService {
|
|
|
43609
43469
|
}
|
|
43610
43470
|
async openFileTauri(options) {
|
|
43611
43471
|
try {
|
|
43612
|
-
const
|
|
43613
|
-
if (!dialog)
|
|
43614
|
-
return null;
|
|
43472
|
+
const { open } = await dynamicImport('@tauri-apps/plugin-dialog');
|
|
43615
43473
|
const filters = options.filters?.map(f => ({
|
|
43616
43474
|
name: f.name,
|
|
43617
43475
|
extensions: f.extensions,
|
|
43618
43476
|
}));
|
|
43619
|
-
const result = await
|
|
43477
|
+
const result = await open({
|
|
43620
43478
|
title: options.title,
|
|
43621
43479
|
defaultPath: options.defaultPath,
|
|
43622
43480
|
filters,
|
|
@@ -43640,10 +43498,8 @@ class FilePickerService {
|
|
|
43640
43498
|
}
|
|
43641
43499
|
async openFileElectron(options) {
|
|
43642
43500
|
try {
|
|
43643
|
-
const
|
|
43644
|
-
|
|
43645
|
-
return null;
|
|
43646
|
-
const result = await electron.ipcRenderer.invoke('show-open-dialog', {
|
|
43501
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43502
|
+
const result = await ipcRenderer.invoke('show-open-dialog', {
|
|
43647
43503
|
title: options.title,
|
|
43648
43504
|
defaultPath: options.defaultPath,
|
|
43649
43505
|
properties: [
|
|
@@ -43703,14 +43559,12 @@ class FilePickerService {
|
|
|
43703
43559
|
}
|
|
43704
43560
|
async saveFileTauri(options) {
|
|
43705
43561
|
try {
|
|
43706
|
-
const
|
|
43707
|
-
if (!dialog)
|
|
43708
|
-
return null;
|
|
43562
|
+
const { save } = await dynamicImport('@tauri-apps/plugin-dialog');
|
|
43709
43563
|
const filters = options.filters?.map(f => ({
|
|
43710
43564
|
name: f.name,
|
|
43711
43565
|
extensions: f.extensions,
|
|
43712
43566
|
}));
|
|
43713
|
-
const result = await
|
|
43567
|
+
const result = await save({
|
|
43714
43568
|
title: options.title,
|
|
43715
43569
|
defaultPath: options.defaultPath,
|
|
43716
43570
|
filters,
|
|
@@ -43724,10 +43578,8 @@ class FilePickerService {
|
|
|
43724
43578
|
}
|
|
43725
43579
|
async saveFileElectron(options) {
|
|
43726
43580
|
try {
|
|
43727
|
-
const
|
|
43728
|
-
|
|
43729
|
-
return null;
|
|
43730
|
-
const result = await electron.ipcRenderer.invoke('show-save-dialog', {
|
|
43581
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43582
|
+
const result = await ipcRenderer.invoke('show-save-dialog', {
|
|
43731
43583
|
title: options.title,
|
|
43732
43584
|
defaultPath: options.defaultPath,
|
|
43733
43585
|
filters: options.filters?.map(f => ({
|
|
@@ -43751,10 +43603,8 @@ class FilePickerService {
|
|
|
43751
43603
|
}
|
|
43752
43604
|
async selectDirectoryTauri(options) {
|
|
43753
43605
|
try {
|
|
43754
|
-
const
|
|
43755
|
-
|
|
43756
|
-
return null;
|
|
43757
|
-
const result = await dialog.open({
|
|
43606
|
+
const { open } = await dynamicImport('@tauri-apps/plugin-dialog');
|
|
43607
|
+
const result = await open({
|
|
43758
43608
|
title: options.title,
|
|
43759
43609
|
defaultPath: options.defaultPath,
|
|
43760
43610
|
directory: true,
|
|
@@ -43770,10 +43620,8 @@ class FilePickerService {
|
|
|
43770
43620
|
}
|
|
43771
43621
|
async selectDirectoryElectron(options) {
|
|
43772
43622
|
try {
|
|
43773
|
-
const
|
|
43774
|
-
|
|
43775
|
-
return null;
|
|
43776
|
-
const result = await electron.ipcRenderer.invoke('show-open-dialog', {
|
|
43623
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43624
|
+
const result = await ipcRenderer.invoke('show-open-dialog', {
|
|
43777
43625
|
title: options.title,
|
|
43778
43626
|
defaultPath: options.defaultPath,
|
|
43779
43627
|
properties: ['openDirectory'],
|
|
@@ -43861,8 +43709,8 @@ class SystemTrayService {
|
|
|
43861
43709
|
await tray.setIcon(icon);
|
|
43862
43710
|
}
|
|
43863
43711
|
else if (platform === PLATFORM_ELECTRON$3) {
|
|
43864
|
-
const
|
|
43865
|
-
|
|
43712
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43713
|
+
ipcRenderer.send('tray-set-icon', icon);
|
|
43866
43714
|
}
|
|
43867
43715
|
}
|
|
43868
43716
|
async setTooltip(tooltip) {
|
|
@@ -43872,8 +43720,8 @@ class SystemTrayService {
|
|
|
43872
43720
|
await tray.setTooltip(tooltip);
|
|
43873
43721
|
}
|
|
43874
43722
|
else if (platform === PLATFORM_ELECTRON$3) {
|
|
43875
|
-
const
|
|
43876
|
-
|
|
43723
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43724
|
+
ipcRenderer.send('tray-set-tooltip', tooltip);
|
|
43877
43725
|
}
|
|
43878
43726
|
}
|
|
43879
43727
|
async setMenu(menu) {
|
|
@@ -43882,8 +43730,8 @@ class SystemTrayService {
|
|
|
43882
43730
|
await this.setTauriMenu(menu);
|
|
43883
43731
|
}
|
|
43884
43732
|
else if (platform === PLATFORM_ELECTRON$3) {
|
|
43885
|
-
const
|
|
43886
|
-
|
|
43733
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43734
|
+
ipcRenderer.send('tray-set-menu', this.convertMenuForElectron(menu));
|
|
43887
43735
|
}
|
|
43888
43736
|
}
|
|
43889
43737
|
async destroy() {
|
|
@@ -43892,16 +43740,14 @@ class SystemTrayService {
|
|
|
43892
43740
|
this.trayInstance = null;
|
|
43893
43741
|
}
|
|
43894
43742
|
else if (platform === PLATFORM_ELECTRON$3) {
|
|
43895
|
-
const
|
|
43896
|
-
|
|
43743
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43744
|
+
ipcRenderer.send('tray-destroy');
|
|
43897
43745
|
}
|
|
43898
43746
|
this.isVisible.set(false);
|
|
43899
43747
|
}
|
|
43900
43748
|
async createTauriTray(config) {
|
|
43901
43749
|
try {
|
|
43902
|
-
const tauriTray = await
|
|
43903
|
-
if (!tauriTray)
|
|
43904
|
-
return false;
|
|
43750
|
+
const tauriTray = await dynamicImport('@tauri-apps/api/tray');
|
|
43905
43751
|
this.trayInstance = await tauriTray.TrayIcon.new({
|
|
43906
43752
|
icon: config.icon,
|
|
43907
43753
|
tooltip: config.tooltip,
|
|
@@ -43920,10 +43766,8 @@ class SystemTrayService {
|
|
|
43920
43766
|
}
|
|
43921
43767
|
async createElectronTray(config) {
|
|
43922
43768
|
try {
|
|
43923
|
-
const
|
|
43924
|
-
|
|
43925
|
-
return false;
|
|
43926
|
-
await electron.ipcRenderer.invoke('tray-create', {
|
|
43769
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43770
|
+
await ipcRenderer.invoke('tray-create', {
|
|
43927
43771
|
icon: config.icon,
|
|
43928
43772
|
tooltip: config.tooltip,
|
|
43929
43773
|
menu: config.menu ? this.convertMenuForElectron(config.menu) : undefined,
|
|
@@ -43938,9 +43782,7 @@ class SystemTrayService {
|
|
|
43938
43782
|
}
|
|
43939
43783
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43940
43784
|
async buildTauriMenu(items) {
|
|
43941
|
-
const tauriMenu = await
|
|
43942
|
-
if (!tauriMenu)
|
|
43943
|
-
return null;
|
|
43785
|
+
const tauriMenu = await dynamicImport('@tauri-apps/api/menu');
|
|
43944
43786
|
const { Menu, MenuItem, Submenu } = tauriMenu;
|
|
43945
43787
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43946
43788
|
const menuItems = [];
|
|
@@ -44027,9 +43869,7 @@ class NativeNotificationsService {
|
|
|
44027
43869
|
const platform = this.platformService.platform();
|
|
44028
43870
|
if (platform === PLATFORM_TAURI$2) {
|
|
44029
43871
|
try {
|
|
44030
|
-
const notification = await
|
|
44031
|
-
if (!notification)
|
|
44032
|
-
return false;
|
|
43872
|
+
const notification = await dynamicImport('@tauri-apps/plugin-notification');
|
|
44033
43873
|
let granted = await notification.isPermissionGranted();
|
|
44034
43874
|
if (!granted) {
|
|
44035
43875
|
const result = await notification.requestPermission();
|
|
@@ -44080,8 +43920,8 @@ class NativeNotificationsService {
|
|
|
44080
43920
|
}
|
|
44081
43921
|
else if (platform === PLATFORM_ELECTRON$2) {
|
|
44082
43922
|
try {
|
|
44083
|
-
const
|
|
44084
|
-
|
|
43923
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
43924
|
+
ipcRenderer.send('set-badge-count', count);
|
|
44085
43925
|
}
|
|
44086
43926
|
catch (error) {
|
|
44087
43927
|
console.error('Failed to set Electron badge count:', error);
|
|
@@ -44101,9 +43941,7 @@ class NativeNotificationsService {
|
|
|
44101
43941
|
}
|
|
44102
43942
|
async showTauriNotification(options) {
|
|
44103
43943
|
try {
|
|
44104
|
-
const notification = await
|
|
44105
|
-
if (!notification)
|
|
44106
|
-
return null;
|
|
43944
|
+
const notification = await dynamicImport('@tauri-apps/plugin-notification');
|
|
44107
43945
|
const id = `notification-${Date.now()}`;
|
|
44108
43946
|
await notification.sendNotification({
|
|
44109
43947
|
title: options.title,
|
|
@@ -44119,11 +43957,9 @@ class NativeNotificationsService {
|
|
|
44119
43957
|
}
|
|
44120
43958
|
async showElectronNotification(options) {
|
|
44121
43959
|
try {
|
|
44122
|
-
const
|
|
44123
|
-
if (!electron?.ipcRenderer)
|
|
44124
|
-
return null;
|
|
43960
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44125
43961
|
const id = `notification-${Date.now()}`;
|
|
44126
|
-
await
|
|
43962
|
+
await ipcRenderer.invoke('show-notification', {
|
|
44127
43963
|
title: options.title,
|
|
44128
43964
|
body: options.body,
|
|
44129
43965
|
icon: options.icon,
|
|
@@ -44185,16 +44021,11 @@ class DockService {
|
|
|
44185
44021
|
const platform = this.platformService.platform();
|
|
44186
44022
|
if (platform === PLATFORM_TAURI$1) {
|
|
44187
44023
|
try {
|
|
44188
|
-
const
|
|
44189
|
-
|
|
44190
|
-
|
|
44191
|
-
|
|
44192
|
-
|
|
44193
|
-
const currentTitle = await appWindow.title();
|
|
44194
|
-
// Remove any existing badge from title (e.g., "App (3)" -> "App")
|
|
44195
|
-
const baseTitle = currentTitle.replace(/\s*\(\d+\)\s*$/, '');
|
|
44196
|
-
const newTitle = text ? `${baseTitle} (${text})` : baseTitle;
|
|
44197
|
-
await appWindow.setTitle(newTitle);
|
|
44024
|
+
const { getCurrentWindow } = await dynamicImport('@tauri-apps/api/window');
|
|
44025
|
+
// Tauri doesn't have direct dock badge API, use window title instead
|
|
44026
|
+
const appWindow = getCurrentWindow();
|
|
44027
|
+
// Badge functionality varies by platform in Tauri
|
|
44028
|
+
console.warn('Dock badge not directly supported in Tauri, consider using notifications');
|
|
44198
44029
|
}
|
|
44199
44030
|
catch (error) {
|
|
44200
44031
|
console.error('Failed to set Tauri dock badge:', error);
|
|
@@ -44202,8 +44033,8 @@ class DockService {
|
|
|
44202
44033
|
}
|
|
44203
44034
|
else if (platform === PLATFORM_ELECTRON$1) {
|
|
44204
44035
|
try {
|
|
44205
|
-
const
|
|
44206
|
-
|
|
44036
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44037
|
+
ipcRenderer.send('set-dock-badge', text);
|
|
44207
44038
|
}
|
|
44208
44039
|
catch (error) {
|
|
44209
44040
|
console.error('Failed to set Electron dock badge:', error);
|
|
@@ -44223,10 +44054,10 @@ class DockService {
|
|
|
44223
44054
|
const platform = this.platformService.platform();
|
|
44224
44055
|
if (platform === PLATFORM_ELECTRON$1) {
|
|
44225
44056
|
try {
|
|
44226
|
-
const
|
|
44057
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44227
44058
|
// Progress should be between 0 and 1, or -1 to clear
|
|
44228
44059
|
const normalizedProgress = progress < 0 ? -1 : Math.min(1, Math.max(0, progress / 100));
|
|
44229
|
-
|
|
44060
|
+
ipcRenderer.send('set-progress', normalizedProgress);
|
|
44230
44061
|
}
|
|
44231
44062
|
catch (error) {
|
|
44232
44063
|
console.error('Failed to set Electron progress:', error);
|
|
@@ -44247,10 +44078,8 @@ class DockService {
|
|
|
44247
44078
|
const platform = this.platformService.platform();
|
|
44248
44079
|
if (platform === PLATFORM_ELECTRON$1) {
|
|
44249
44080
|
try {
|
|
44250
|
-
const
|
|
44251
|
-
|
|
44252
|
-
return -1;
|
|
44253
|
-
return await electron.ipcRenderer.invoke('dock-bounce', type);
|
|
44081
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44082
|
+
return await ipcRenderer.invoke('dock-bounce', type);
|
|
44254
44083
|
}
|
|
44255
44084
|
catch (error) {
|
|
44256
44085
|
console.error('Failed to bounce Electron dock:', error);
|
|
@@ -44266,8 +44095,8 @@ class DockService {
|
|
|
44266
44095
|
const platform = this.platformService.platform();
|
|
44267
44096
|
if (platform === PLATFORM_ELECTRON$1) {
|
|
44268
44097
|
try {
|
|
44269
|
-
const
|
|
44270
|
-
|
|
44098
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44099
|
+
ipcRenderer.send('cancel-dock-bounce', id);
|
|
44271
44100
|
}
|
|
44272
44101
|
catch (error) {
|
|
44273
44102
|
console.error('Failed to cancel Electron dock bounce:', error);
|
|
@@ -44281,8 +44110,8 @@ class DockService {
|
|
|
44281
44110
|
const platform = this.platformService.platform();
|
|
44282
44111
|
if (platform === PLATFORM_ELECTRON$1) {
|
|
44283
44112
|
try {
|
|
44284
|
-
const
|
|
44285
|
-
|
|
44113
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44114
|
+
ipcRenderer.send('set-dock-menu', this.convertMenuForElectron(items));
|
|
44286
44115
|
}
|
|
44287
44116
|
catch (error) {
|
|
44288
44117
|
console.error('Failed to set Electron dock menu:', error);
|
|
@@ -44296,8 +44125,8 @@ class DockService {
|
|
|
44296
44125
|
const platform = this.platformService.platform();
|
|
44297
44126
|
if (platform === PLATFORM_ELECTRON$1) {
|
|
44298
44127
|
try {
|
|
44299
|
-
const
|
|
44300
|
-
|
|
44128
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44129
|
+
ipcRenderer.send('show-dock');
|
|
44301
44130
|
}
|
|
44302
44131
|
catch (error) {
|
|
44303
44132
|
console.error('Failed to show Electron dock:', error);
|
|
@@ -44311,8 +44140,8 @@ class DockService {
|
|
|
44311
44140
|
const platform = this.platformService.platform();
|
|
44312
44141
|
if (platform === PLATFORM_ELECTRON$1) {
|
|
44313
44142
|
try {
|
|
44314
|
-
const
|
|
44315
|
-
|
|
44143
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44144
|
+
ipcRenderer.send('hide-dock');
|
|
44316
44145
|
}
|
|
44317
44146
|
catch (error) {
|
|
44318
44147
|
console.error('Failed to hide Electron dock:', error);
|
|
@@ -44326,10 +44155,8 @@ class DockService {
|
|
|
44326
44155
|
const platform = this.platformService.platform();
|
|
44327
44156
|
if (platform === PLATFORM_TAURI$1) {
|
|
44328
44157
|
try {
|
|
44329
|
-
const
|
|
44330
|
-
|
|
44331
|
-
return;
|
|
44332
|
-
const appWindow = tauriWindow.getCurrentWindow();
|
|
44158
|
+
const { getCurrentWindow } = await dynamicImport('@tauri-apps/api/window');
|
|
44159
|
+
const appWindow = getCurrentWindow();
|
|
44333
44160
|
await appWindow.requestUserAttention(flash ? 2 : null); // 2 = Informational
|
|
44334
44161
|
}
|
|
44335
44162
|
catch (error) {
|
|
@@ -44338,8 +44165,8 @@ class DockService {
|
|
|
44338
44165
|
}
|
|
44339
44166
|
else if (platform === PLATFORM_ELECTRON$1) {
|
|
44340
44167
|
try {
|
|
44341
|
-
const
|
|
44342
|
-
|
|
44168
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44169
|
+
ipcRenderer.send('flash-frame', flash);
|
|
44343
44170
|
}
|
|
44344
44171
|
catch (error) {
|
|
44345
44172
|
console.error('Failed to flash Electron frame:', error);
|
|
@@ -44474,26 +44301,24 @@ class UpdateService {
|
|
|
44474
44301
|
}
|
|
44475
44302
|
async setupElectronListeners() {
|
|
44476
44303
|
try {
|
|
44477
|
-
const
|
|
44478
|
-
|
|
44479
|
-
return;
|
|
44480
|
-
electron.ipcRenderer.on('update-available', (_event, info) => {
|
|
44304
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44305
|
+
ipcRenderer.on('update-available', (_event, info) => {
|
|
44481
44306
|
this.status.set('available');
|
|
44482
44307
|
this.updateInfo.set(info);
|
|
44483
44308
|
this.updateAvailable$.next(info);
|
|
44484
44309
|
});
|
|
44485
|
-
|
|
44310
|
+
ipcRenderer.on('update-not-available', () => {
|
|
44486
44311
|
this.status.set('not-available');
|
|
44487
44312
|
});
|
|
44488
|
-
|
|
44313
|
+
ipcRenderer.on('download-progress', (_event, progress) => {
|
|
44489
44314
|
this.progress.set(progress);
|
|
44490
44315
|
this.downloadProgress$.next(progress);
|
|
44491
44316
|
});
|
|
44492
|
-
|
|
44317
|
+
ipcRenderer.on('update-downloaded', () => {
|
|
44493
44318
|
this.status.set('downloaded');
|
|
44494
44319
|
this.updateDownloaded$.next();
|
|
44495
44320
|
});
|
|
44496
|
-
|
|
44321
|
+
ipcRenderer.on('update-error', (_event, error) => {
|
|
44497
44322
|
this.status.set('error');
|
|
44498
44323
|
this.error.set(error);
|
|
44499
44324
|
this.updateError$.next(error);
|
|
@@ -44504,10 +44329,8 @@ class UpdateService {
|
|
|
44504
44329
|
}
|
|
44505
44330
|
}
|
|
44506
44331
|
async checkTauriUpdates() {
|
|
44507
|
-
const updater = await
|
|
44508
|
-
const app = await
|
|
44509
|
-
if (!updater || !app)
|
|
44510
|
-
return null;
|
|
44332
|
+
const updater = await dynamicImport('@tauri-apps/plugin-updater');
|
|
44333
|
+
const app = await dynamicImport('@tauri-apps/api/app');
|
|
44511
44334
|
const currentVersion = await app.getVersion();
|
|
44512
44335
|
const update = await updater.check();
|
|
44513
44336
|
if (update?.available) {
|
|
@@ -44526,10 +44349,8 @@ class UpdateService {
|
|
|
44526
44349
|
return null;
|
|
44527
44350
|
}
|
|
44528
44351
|
async checkElectronUpdates() {
|
|
44529
|
-
const
|
|
44530
|
-
|
|
44531
|
-
return null;
|
|
44532
|
-
const result = (await electron.ipcRenderer.invoke('check-for-updates'));
|
|
44352
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44353
|
+
const result = (await ipcRenderer.invoke('check-for-updates'));
|
|
44533
44354
|
if (result?.updateAvailable) {
|
|
44534
44355
|
const info = {
|
|
44535
44356
|
currentVersion: result.currentVersion || '',
|
|
@@ -44546,12 +44367,10 @@ class UpdateService {
|
|
|
44546
44367
|
return null;
|
|
44547
44368
|
}
|
|
44548
44369
|
async downloadTauriUpdate() {
|
|
44549
|
-
const updater = await
|
|
44550
|
-
if (!updater)
|
|
44551
|
-
return;
|
|
44370
|
+
const updater = await dynamicImport('@tauri-apps/plugin-updater');
|
|
44552
44371
|
const update = await updater.check();
|
|
44553
44372
|
if (update?.available) {
|
|
44554
|
-
await update.downloadAndInstall(event => {
|
|
44373
|
+
await update.downloadAndInstall((event) => {
|
|
44555
44374
|
if (event.event === 'Started') {
|
|
44556
44375
|
const total = event.data?.contentLength || 0;
|
|
44557
44376
|
this.progress.set({ percent: 0, bytesDownloaded: 0, bytesTotal: total });
|
|
@@ -44578,16 +44397,16 @@ class UpdateService {
|
|
|
44578
44397
|
}
|
|
44579
44398
|
}
|
|
44580
44399
|
async downloadElectronUpdate() {
|
|
44581
|
-
const
|
|
44582
|
-
|
|
44400
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44401
|
+
ipcRenderer.send('download-update');
|
|
44583
44402
|
}
|
|
44584
44403
|
async installTauriUpdate() {
|
|
44585
|
-
const process = await
|
|
44586
|
-
await process
|
|
44404
|
+
const process = await dynamicImport('@tauri-apps/plugin-process');
|
|
44405
|
+
await process.relaunch();
|
|
44587
44406
|
}
|
|
44588
44407
|
async installElectronUpdate() {
|
|
44589
|
-
const
|
|
44590
|
-
|
|
44408
|
+
const { ipcRenderer } = await dynamicImport('electron');
|
|
44409
|
+
ipcRenderer.send('quit-and-install');
|
|
44591
44410
|
}
|
|
44592
44411
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UpdateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
44593
44412
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UpdateService, providedIn: 'root' });
|