@tolle_/tolle-ui 0.0.29-beta → 0.0.31-beta
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.
- package/esm2022/lib/accordion-item.component.mjs +60 -17
- package/esm2022/lib/accordion.component.mjs +17 -12
- package/esm2022/lib/alert.component.mjs +36 -24
- package/esm2022/lib/calendar.component.mjs +2 -5
- package/esm2022/lib/date-picker.component.mjs +1 -1
- package/esm2022/lib/segment.component.mjs +192 -0
- package/esm2022/lib/sidebar.component.mjs +433 -0
- package/esm2022/public-api.mjs +3 -1
- package/fesm2022/tolle-ui.mjs +727 -55
- package/fesm2022/tolle-ui.mjs.map +1 -1
- package/lib/accordion.component.d.ts +1 -0
- package/lib/alert.component.d.ts +2 -3
- package/lib/button.component.d.ts +2 -2
- package/lib/segment.component.d.ts +38 -0
- package/lib/sidebar.component.d.ts +37 -0
- package/package.json +1 -1
- package/public-api.d.ts +2 -0
package/fesm2022/tolle-ui.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Component, Input, forwardRef, ViewChild, Injectable, Optional, HostListener, ContentChildren, EventEmitter, Output, Directive, inject, PLATFORM_ID, Inject, InjectionToken, APP_INITIALIZER, ChangeDetectorRef, ChangeDetectionStrategy, TemplateRef, Injector, HostBinding } from '@angular/core';
|
|
4
|
+
import { Component, Input, forwardRef, ViewChild, Injectable, Optional, HostListener, ContentChildren, EventEmitter, Output, Directive, inject, PLATFORM_ID, Inject, InjectionToken, APP_INITIALIZER, ChangeDetectorRef, ChangeDetectionStrategy, TemplateRef, Injector, HostBinding, ViewChildren } from '@angular/core';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
6
6
|
import { CommonModule, isPlatformBrowser, DOCUMENT, NgIf, NgTemplateOutlet } from '@angular/common';
|
|
7
7
|
import { cva } from 'class-variance-authority';
|
|
@@ -10,9 +10,12 @@ import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
|
10
10
|
import { autoUpdate, computePosition, offset, flip, shift, size } from '@floating-ui/dom';
|
|
11
11
|
import { Subject, Subscription, BehaviorSubject } from 'rxjs';
|
|
12
12
|
import { format, startOfWeek, startOfMonth, endOfWeek, endOfMonth, eachDayOfInterval, subMonths, subYears, addMonths, addYears, setMonth, setYear, isSameDay, isToday, isSameMonth, isBefore, startOfDay, parse, isValid, isWithinInterval } from 'date-fns';
|
|
13
|
+
import { trigger, state, style, transition, animate } from '@angular/animations';
|
|
13
14
|
import * as i1$1 from '@angular/cdk/overlay';
|
|
14
15
|
import { OverlayConfig } from '@angular/cdk/overlay';
|
|
15
16
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
17
|
+
import * as i1$2 from '@angular/router';
|
|
18
|
+
import { RouterModule } from '@angular/router';
|
|
16
19
|
|
|
17
20
|
function cn(...inputs) {
|
|
18
21
|
return twMerge(clsx(inputs));
|
|
@@ -2563,10 +2566,7 @@ class CalendarComponent {
|
|
|
2563
2566
|
if (this.minDate && isBefore(date, this.minDate)) {
|
|
2564
2567
|
return true;
|
|
2565
2568
|
}
|
|
2566
|
-
|
|
2567
|
-
return true;
|
|
2568
|
-
}
|
|
2569
|
-
return false;
|
|
2569
|
+
return !!(this.maxDate && isBefore(this.maxDate, date));
|
|
2570
2570
|
}
|
|
2571
2571
|
isTodayDisabled() {
|
|
2572
2572
|
return this.isDateDisabled(new Date());
|
|
@@ -4170,21 +4170,42 @@ class AccordionItemComponent {
|
|
|
4170
4170
|
<button
|
|
4171
4171
|
type="button"
|
|
4172
4172
|
(click)="toggle()"
|
|
4173
|
-
|
|
4173
|
+
[attr.aria-expanded]="isOpen"
|
|
4174
4174
|
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
4175
|
+
class="flex flex-1 items-center justify-between py-4 font-medium transition-all group [&[data-state=open]>i]:rotate-180"
|
|
4175
4176
|
>
|
|
4176
|
-
<span class="text-left">{{ title }}</span>
|
|
4177
|
-
<i class="ri-arrow-down-s-line text-muted-foreground transition-transform"></i>
|
|
4177
|
+
<span class="text-left group-hover:underline">{{ title }}</span>
|
|
4178
|
+
<i class="ri-arrow-down-s-line text-muted-foreground text-lg transition-transform duration-200 hover:no-underline"></i>
|
|
4178
4179
|
</button>
|
|
4179
4180
|
|
|
4180
4181
|
<div
|
|
4181
|
-
|
|
4182
|
-
class="
|
|
4183
|
-
|
|
4184
|
-
|
|
4182
|
+
[@expandCollapse]="isOpen ? 'expanded' : 'collapsed'"
|
|
4183
|
+
class="overflow-hidden">
|
|
4184
|
+
<div class="pb-4 pt-0 text-sm text-muted-foreground">
|
|
4185
|
+
<ng-content></ng-content>
|
|
4186
|
+
</div>
|
|
4185
4187
|
</div>
|
|
4186
4188
|
</div>
|
|
4187
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }
|
|
4189
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], animations: [
|
|
4190
|
+
trigger('expandCollapse', [
|
|
4191
|
+
state('collapsed', style({
|
|
4192
|
+
height: '0px',
|
|
4193
|
+
opacity: '0',
|
|
4194
|
+
overflow: 'hidden',
|
|
4195
|
+
visibility: 'hidden'
|
|
4196
|
+
})),
|
|
4197
|
+
state('expanded', style({
|
|
4198
|
+
height: '*', // "Star" means actual content height
|
|
4199
|
+
opacity: '1',
|
|
4200
|
+
overflow: 'hidden',
|
|
4201
|
+
visibility: 'visible'
|
|
4202
|
+
})),
|
|
4203
|
+
// Use cubic-bezier to match Tailwind/shadcn-ui default ease
|
|
4204
|
+
transition('collapsed <=> expanded', [
|
|
4205
|
+
animate('300ms cubic-bezier(0.87, 0, 0.13, 1)')
|
|
4206
|
+
])
|
|
4207
|
+
])
|
|
4208
|
+
] });
|
|
4188
4209
|
}
|
|
4189
4210
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccordionItemComponent, decorators: [{
|
|
4190
4211
|
type: Component,
|
|
@@ -4192,23 +4213,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4192
4213
|
selector: 'tolle-accordion-item',
|
|
4193
4214
|
standalone: true,
|
|
4194
4215
|
imports: [CommonModule],
|
|
4216
|
+
animations: [
|
|
4217
|
+
trigger('expandCollapse', [
|
|
4218
|
+
state('collapsed', style({
|
|
4219
|
+
height: '0px',
|
|
4220
|
+
opacity: '0',
|
|
4221
|
+
overflow: 'hidden',
|
|
4222
|
+
visibility: 'hidden'
|
|
4223
|
+
})),
|
|
4224
|
+
state('expanded', style({
|
|
4225
|
+
height: '*', // "Star" means actual content height
|
|
4226
|
+
opacity: '1',
|
|
4227
|
+
overflow: 'hidden',
|
|
4228
|
+
visibility: 'visible'
|
|
4229
|
+
})),
|
|
4230
|
+
// Use cubic-bezier to match Tailwind/shadcn-ui default ease
|
|
4231
|
+
transition('collapsed <=> expanded', [
|
|
4232
|
+
animate('300ms cubic-bezier(0.87, 0, 0.13, 1)')
|
|
4233
|
+
])
|
|
4234
|
+
])
|
|
4235
|
+
],
|
|
4195
4236
|
template: `
|
|
4196
4237
|
<div [class]="cn('flex flex-col border-b border-border', class)">
|
|
4197
4238
|
<button
|
|
4198
4239
|
type="button"
|
|
4199
4240
|
(click)="toggle()"
|
|
4200
|
-
|
|
4241
|
+
[attr.aria-expanded]="isOpen"
|
|
4201
4242
|
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
4243
|
+
class="flex flex-1 items-center justify-between py-4 font-medium transition-all group [&[data-state=open]>i]:rotate-180"
|
|
4202
4244
|
>
|
|
4203
|
-
<span class="text-left">{{ title }}</span>
|
|
4204
|
-
<i class="ri-arrow-down-s-line text-muted-foreground transition-transform"></i>
|
|
4245
|
+
<span class="text-left group-hover:underline">{{ title }}</span>
|
|
4246
|
+
<i class="ri-arrow-down-s-line text-muted-foreground text-lg transition-transform duration-200 hover:no-underline"></i>
|
|
4205
4247
|
</button>
|
|
4206
4248
|
|
|
4207
4249
|
<div
|
|
4208
|
-
|
|
4209
|
-
class="
|
|
4210
|
-
|
|
4211
|
-
|
|
4250
|
+
[@expandCollapse]="isOpen ? 'expanded' : 'collapsed'"
|
|
4251
|
+
class="overflow-hidden">
|
|
4252
|
+
<div class="pb-4 pt-0 text-sm text-muted-foreground">
|
|
4253
|
+
<ng-content></ng-content>
|
|
4254
|
+
</div>
|
|
4212
4255
|
</div>
|
|
4213
4256
|
</div>
|
|
4214
4257
|
`
|
|
@@ -4226,31 +4269,36 @@ class AccordionComponent {
|
|
|
4226
4269
|
class = '';
|
|
4227
4270
|
items;
|
|
4228
4271
|
ngAfterContentInit() {
|
|
4272
|
+
// 1. Assign IDs and Listeners on load
|
|
4273
|
+
this.initItems();
|
|
4274
|
+
// 2. Re-init if items change dynamically (optional but good for robustness)
|
|
4275
|
+
this.items.changes.subscribe(() => this.initItems());
|
|
4276
|
+
}
|
|
4277
|
+
initItems() {
|
|
4229
4278
|
this.items.forEach((item, index) => {
|
|
4230
|
-
//
|
|
4279
|
+
// Auto-assign ID if missing
|
|
4231
4280
|
if (item.id === undefined)
|
|
4232
|
-
item.id = index
|
|
4233
|
-
//
|
|
4281
|
+
item.id = `accordion-item-${index}`;
|
|
4282
|
+
// Set up the toggle bridge
|
|
4234
4283
|
item.onToggle = (id) => this.handleToggle(id);
|
|
4235
4284
|
});
|
|
4236
4285
|
}
|
|
4237
4286
|
handleToggle(selectedId) {
|
|
4238
4287
|
this.items.forEach(item => {
|
|
4239
4288
|
if (item.id === selectedId) {
|
|
4289
|
+
// Toggle the clicked item
|
|
4240
4290
|
item.isOpen = !item.isOpen;
|
|
4241
4291
|
}
|
|
4242
|
-
else {
|
|
4243
|
-
//
|
|
4244
|
-
|
|
4245
|
-
item.isOpen = false;
|
|
4246
|
-
}
|
|
4292
|
+
else if (this.type === 'single') {
|
|
4293
|
+
// Close others if in single mode
|
|
4294
|
+
item.isOpen = false;
|
|
4247
4295
|
}
|
|
4248
4296
|
});
|
|
4249
4297
|
}
|
|
4250
4298
|
cn = cn;
|
|
4251
4299
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4252
4300
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: AccordionComponent, isStandalone: true, selector: "tolle-accordion", inputs: { type: "type", class: "class" }, queries: [{ propertyName: "items", predicate: AccordionItemComponent }], ngImport: i0, template: `
|
|
4253
|
-
<div [class]="cn('w-full
|
|
4301
|
+
<div [class]="cn('w-full', class)">
|
|
4254
4302
|
<ng-content></ng-content>
|
|
4255
4303
|
</div>
|
|
4256
4304
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
@@ -4260,9 +4308,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4260
4308
|
args: [{
|
|
4261
4309
|
selector: 'tolle-accordion',
|
|
4262
4310
|
standalone: true,
|
|
4263
|
-
imports: [CommonModule],
|
|
4311
|
+
imports: [CommonModule], // No AccordionItemComponent import needed here if projected via ng-content
|
|
4264
4312
|
template: `
|
|
4265
|
-
<div [class]="cn('w-full
|
|
4313
|
+
<div [class]="cn('w-full', class)">
|
|
4266
4314
|
<ng-content></ng-content>
|
|
4267
4315
|
</div>
|
|
4268
4316
|
`
|
|
@@ -5474,13 +5522,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
5474
5522
|
type: Input
|
|
5475
5523
|
}] } });
|
|
5476
5524
|
|
|
5477
|
-
const alertVariants = cva("relative w-full rounded-lg border p-4
|
|
5525
|
+
const alertVariants = cva("relative w-full rounded-lg border p-4 [&>i+div]:translate-y-[-3px] [&>i]:absolute [&>i]:left-4 [&>i]:top-4 [&>i]:text-foreground [&>i~div]:pl-7", {
|
|
5478
5526
|
variants: {
|
|
5479
5527
|
variant: {
|
|
5480
5528
|
default: "bg-background text-foreground",
|
|
5481
|
-
destructive: "border-
|
|
5482
|
-
success: "border-emerald-500/50 text-emerald-700 dark:
|
|
5483
|
-
warning: "border-amber-500/50 text-amber-700 dark:
|
|
5529
|
+
destructive: "border-red-500/50 text-red-500 dark:border-red-500 [&>i]:text-red-500",
|
|
5530
|
+
success: "border-emerald-500/50 text-emerald-700 dark:border-emerald-500 [&>i]:text-emerald-600 dark:text-emerald-400",
|
|
5531
|
+
warning: "border-amber-500/50 text-amber-700 dark:border-amber-500 [&>i]:text-amber-600 dark:text-amber-400",
|
|
5532
|
+
info: "border-blue-500/50 text-blue-700 dark:border-blue-500 [&>i]:text-blue-600 dark:text-blue-400",
|
|
5484
5533
|
},
|
|
5485
5534
|
},
|
|
5486
5535
|
defaultVariants: {
|
|
@@ -5494,24 +5543,18 @@ class AlertComponent {
|
|
|
5494
5543
|
dismissible = false;
|
|
5495
5544
|
onClose = new EventEmitter();
|
|
5496
5545
|
dismissed = false;
|
|
5497
|
-
isDismissing = false;
|
|
5498
5546
|
alertVariants = alertVariants;
|
|
5499
5547
|
cn = cn;
|
|
5500
5548
|
dismiss() {
|
|
5501
|
-
this.
|
|
5502
|
-
|
|
5503
|
-
setTimeout(() => {
|
|
5504
|
-
this.dismissed = true;
|
|
5505
|
-
this.onClose.emit();
|
|
5506
|
-
}, 300);
|
|
5549
|
+
this.dismissed = true;
|
|
5550
|
+
this.onClose.emit();
|
|
5507
5551
|
}
|
|
5508
5552
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5509
5553
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: AlertComponent, isStandalone: true, selector: "tolle-alert", inputs: { variant: "variant", title: "title", class: "class", dismissible: "dismissible" }, outputs: { onClose: "onClose" }, ngImport: i0, template: `
|
|
5510
5554
|
<div
|
|
5511
5555
|
*ngIf="!dismissed"
|
|
5556
|
+
@fade
|
|
5512
5557
|
[class]="cn(alertVariants({ variant }), class)"
|
|
5513
|
-
[class.opacity-0]="isDismissing"
|
|
5514
|
-
[class.scale-95]="isDismissing"
|
|
5515
5558
|
role="alert"
|
|
5516
5559
|
>
|
|
5517
5560
|
<ng-content select="[icon]"></ng-content>
|
|
@@ -5519,22 +5562,30 @@ class AlertComponent {
|
|
|
5519
5562
|
<button
|
|
5520
5563
|
*ngIf="dismissible"
|
|
5521
5564
|
(click)="dismiss()"
|
|
5522
|
-
class="absolute right-2 top-2 rounded-md p-1
|
|
5523
|
-
|
|
5565
|
+
class="absolute right-2 top-2 rounded-md p-1 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
|
5566
|
+
type="button"
|
|
5524
5567
|
>
|
|
5525
5568
|
<i class="ri-close-line text-lg"></i>
|
|
5569
|
+
<span class="sr-only">Close</span>
|
|
5526
5570
|
</button>
|
|
5527
5571
|
|
|
5528
5572
|
<div>
|
|
5529
5573
|
<h5 *ngIf="title" class="mb-1 font-medium leading-none tracking-tight">
|
|
5530
5574
|
{{ title }}
|
|
5531
5575
|
</h5>
|
|
5532
|
-
<div class="text-sm [&_p]:leading-relaxed">
|
|
5576
|
+
<div class="text-sm [&_p]:leading-relaxed opacity-90">
|
|
5533
5577
|
<ng-content></ng-content>
|
|
5534
5578
|
</div>
|
|
5535
5579
|
</div>
|
|
5536
5580
|
</div>
|
|
5537
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }]
|
|
5581
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], animations: [
|
|
5582
|
+
trigger('fade', [
|
|
5583
|
+
transition(':leave', [
|
|
5584
|
+
style({ opacity: 1, transform: 'scale(1)' }),
|
|
5585
|
+
animate('300ms ease-in-out', style({ opacity: 0, transform: 'scale(0.95)', height: 0, margin: 0, padding: 0 }))
|
|
5586
|
+
])
|
|
5587
|
+
])
|
|
5588
|
+
] });
|
|
5538
5589
|
}
|
|
5539
5590
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AlertComponent, decorators: [{
|
|
5540
5591
|
type: Component,
|
|
@@ -5542,12 +5593,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
5542
5593
|
selector: 'tolle-alert',
|
|
5543
5594
|
standalone: true,
|
|
5544
5595
|
imports: [CommonModule],
|
|
5596
|
+
animations: [
|
|
5597
|
+
trigger('fade', [
|
|
5598
|
+
transition(':leave', [
|
|
5599
|
+
style({ opacity: 1, transform: 'scale(1)' }),
|
|
5600
|
+
animate('300ms ease-in-out', style({ opacity: 0, transform: 'scale(0.95)', height: 0, margin: 0, padding: 0 }))
|
|
5601
|
+
])
|
|
5602
|
+
])
|
|
5603
|
+
],
|
|
5545
5604
|
template: `
|
|
5546
5605
|
<div
|
|
5547
5606
|
*ngIf="!dismissed"
|
|
5607
|
+
@fade
|
|
5548
5608
|
[class]="cn(alertVariants({ variant }), class)"
|
|
5549
|
-
[class.opacity-0]="isDismissing"
|
|
5550
|
-
[class.scale-95]="isDismissing"
|
|
5551
5609
|
role="alert"
|
|
5552
5610
|
>
|
|
5553
5611
|
<ng-content select="[icon]"></ng-content>
|
|
@@ -5555,22 +5613,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
5555
5613
|
<button
|
|
5556
5614
|
*ngIf="dismissible"
|
|
5557
5615
|
(click)="dismiss()"
|
|
5558
|
-
class="absolute right-2 top-2 rounded-md p-1
|
|
5559
|
-
|
|
5616
|
+
class="absolute right-2 top-2 rounded-md p-1 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
|
5617
|
+
type="button"
|
|
5560
5618
|
>
|
|
5561
5619
|
<i class="ri-close-line text-lg"></i>
|
|
5620
|
+
<span class="sr-only">Close</span>
|
|
5562
5621
|
</button>
|
|
5563
5622
|
|
|
5564
5623
|
<div>
|
|
5565
5624
|
<h5 *ngIf="title" class="mb-1 font-medium leading-none tracking-tight">
|
|
5566
5625
|
{{ title }}
|
|
5567
5626
|
</h5>
|
|
5568
|
-
<div class="text-sm [&_p]:leading-relaxed">
|
|
5627
|
+
<div class="text-sm [&_p]:leading-relaxed opacity-90">
|
|
5569
5628
|
<ng-content></ng-content>
|
|
5570
5629
|
</div>
|
|
5571
5630
|
</div>
|
|
5572
5631
|
</div>
|
|
5573
|
-
|
|
5632
|
+
`
|
|
5574
5633
|
}]
|
|
5575
5634
|
}], propDecorators: { variant: [{
|
|
5576
5635
|
type: Input
|
|
@@ -6447,6 +6506,619 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6447
6506
|
type: Input
|
|
6448
6507
|
}] } });
|
|
6449
6508
|
|
|
6509
|
+
class SegmentedComponent {
|
|
6510
|
+
cdr;
|
|
6511
|
+
items = [];
|
|
6512
|
+
class = '';
|
|
6513
|
+
disabled = false;
|
|
6514
|
+
itemTemplate; // Allow custom content
|
|
6515
|
+
value = null;
|
|
6516
|
+
gliderLeft = 0;
|
|
6517
|
+
gliderWidth = 0;
|
|
6518
|
+
hasValue = false;
|
|
6519
|
+
itemElements;
|
|
6520
|
+
onChange = () => { };
|
|
6521
|
+
onTouched = () => { };
|
|
6522
|
+
constructor(cdr) {
|
|
6523
|
+
this.cdr = cdr;
|
|
6524
|
+
}
|
|
6525
|
+
ngAfterViewInit() {
|
|
6526
|
+
setTimeout(() => this.updateGlider());
|
|
6527
|
+
}
|
|
6528
|
+
ngOnChanges(changes) {
|
|
6529
|
+
// Recalculate if items change or if value changes externally
|
|
6530
|
+
if (changes['items'] && !changes['items'].firstChange) {
|
|
6531
|
+
setTimeout(() => this.updateGlider());
|
|
6532
|
+
}
|
|
6533
|
+
}
|
|
6534
|
+
select(val) {
|
|
6535
|
+
if (this.disabled)
|
|
6536
|
+
return;
|
|
6537
|
+
const item = this.items.find(i => i.value === val);
|
|
6538
|
+
if (item?.disabled)
|
|
6539
|
+
return;
|
|
6540
|
+
this.value = val;
|
|
6541
|
+
this.onChange(val);
|
|
6542
|
+
this.onTouched();
|
|
6543
|
+
this.updateGlider();
|
|
6544
|
+
}
|
|
6545
|
+
updateGlider() {
|
|
6546
|
+
if (!this.itemElements || !this.items.length)
|
|
6547
|
+
return;
|
|
6548
|
+
const index = this.items.findIndex(i => i.value === this.value);
|
|
6549
|
+
if (index === -1) {
|
|
6550
|
+
this.hasValue = false;
|
|
6551
|
+
this.gliderWidth = 0;
|
|
6552
|
+
return;
|
|
6553
|
+
}
|
|
6554
|
+
const activeElement = this.itemElements.get(index)?.nativeElement;
|
|
6555
|
+
if (activeElement) {
|
|
6556
|
+
this.hasValue = true;
|
|
6557
|
+
this.gliderLeft = activeElement.offsetLeft;
|
|
6558
|
+
this.gliderWidth = activeElement.offsetWidth;
|
|
6559
|
+
this.cdr.detectChanges();
|
|
6560
|
+
}
|
|
6561
|
+
}
|
|
6562
|
+
// CVA Implementation
|
|
6563
|
+
writeValue(val) {
|
|
6564
|
+
this.value = val;
|
|
6565
|
+
setTimeout(() => this.updateGlider());
|
|
6566
|
+
}
|
|
6567
|
+
registerOnChange(fn) { this.onChange = fn; }
|
|
6568
|
+
registerOnTouched(fn) { this.onTouched = fn; }
|
|
6569
|
+
setDisabledState(isDisabled) {
|
|
6570
|
+
this.disabled = isDisabled;
|
|
6571
|
+
this.cdr.markForCheck();
|
|
6572
|
+
}
|
|
6573
|
+
cn = cn;
|
|
6574
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SegmentedComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
6575
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SegmentedComponent, isStandalone: true, selector: "tolle-segment", inputs: { items: "items", class: "class", disabled: "disabled", itemTemplate: "itemTemplate" }, providers: [
|
|
6576
|
+
{
|
|
6577
|
+
provide: NG_VALUE_ACCESSOR,
|
|
6578
|
+
useExisting: forwardRef(() => SegmentedComponent),
|
|
6579
|
+
multi: true
|
|
6580
|
+
}
|
|
6581
|
+
], viewQueries: [{ propertyName: "itemElements", predicate: ["itemEls"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
6582
|
+
<div
|
|
6583
|
+
#container
|
|
6584
|
+
[class]="cn(
|
|
6585
|
+
'relative flex items-center p-1 bg-muted rounded-lg select-none w-full gap-1',
|
|
6586
|
+
class
|
|
6587
|
+
)"
|
|
6588
|
+
role="tablist"
|
|
6589
|
+
>
|
|
6590
|
+
<div
|
|
6591
|
+
class="absolute top-1 bottom-1 bg-background shadow-sm rounded-md transition-all duration-300 ease-[cubic-bezier(0.2,0.0,0.2,1)]"
|
|
6592
|
+
[style.left.px]="gliderLeft"
|
|
6593
|
+
[style.width.px]="gliderWidth"
|
|
6594
|
+
[class.opacity-0]="!hasValue"
|
|
6595
|
+
></div>
|
|
6596
|
+
|
|
6597
|
+
<button
|
|
6598
|
+
*ngFor="let item of items"
|
|
6599
|
+
#itemEls
|
|
6600
|
+
type="button"
|
|
6601
|
+
role="tab"
|
|
6602
|
+
[disabled]="item.disabled || disabled"
|
|
6603
|
+
[attr.aria-selected]="value === item.value"
|
|
6604
|
+
(click)="select(item.value)"
|
|
6605
|
+
[class]="cn(
|
|
6606
|
+
'relative z-10 flex-1 px-3 py-1.5 text-sm font-medium transition-colors duration-200 rounded-md text-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
6607
|
+
'flex items-center justify-center gap-2',
|
|
6608
|
+
value === item.value
|
|
6609
|
+
? 'text-foreground'
|
|
6610
|
+
: 'text-muted-foreground hover:text-foreground/70',
|
|
6611
|
+
item.disabled && 'opacity-50 cursor-not-allowed',
|
|
6612
|
+
item.class
|
|
6613
|
+
)"
|
|
6614
|
+
>
|
|
6615
|
+
<ng-container *ngIf="itemTemplate; else defaultContent">
|
|
6616
|
+
<ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: item, selected: value === item.value }">
|
|
6617
|
+
</ng-container>
|
|
6618
|
+
</ng-container>
|
|
6619
|
+
|
|
6620
|
+
<ng-template #defaultContent>
|
|
6621
|
+
<i *ngIf="item.icon" [class]="item.icon"></i>
|
|
6622
|
+
<span class="truncate">{{ item.label }}</span>
|
|
6623
|
+
</ng-template>
|
|
6624
|
+
</button>
|
|
6625
|
+
</div>
|
|
6626
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }] });
|
|
6627
|
+
}
|
|
6628
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SegmentedComponent, decorators: [{
|
|
6629
|
+
type: Component,
|
|
6630
|
+
args: [{ selector: 'tolle-segment', standalone: true, imports: [CommonModule, FormsModule], providers: [
|
|
6631
|
+
{
|
|
6632
|
+
provide: NG_VALUE_ACCESSOR,
|
|
6633
|
+
useExisting: forwardRef(() => SegmentedComponent),
|
|
6634
|
+
multi: true
|
|
6635
|
+
}
|
|
6636
|
+
], template: `
|
|
6637
|
+
<div
|
|
6638
|
+
#container
|
|
6639
|
+
[class]="cn(
|
|
6640
|
+
'relative flex items-center p-1 bg-muted rounded-lg select-none w-full gap-1',
|
|
6641
|
+
class
|
|
6642
|
+
)"
|
|
6643
|
+
role="tablist"
|
|
6644
|
+
>
|
|
6645
|
+
<div
|
|
6646
|
+
class="absolute top-1 bottom-1 bg-background shadow-sm rounded-md transition-all duration-300 ease-[cubic-bezier(0.2,0.0,0.2,1)]"
|
|
6647
|
+
[style.left.px]="gliderLeft"
|
|
6648
|
+
[style.width.px]="gliderWidth"
|
|
6649
|
+
[class.opacity-0]="!hasValue"
|
|
6650
|
+
></div>
|
|
6651
|
+
|
|
6652
|
+
<button
|
|
6653
|
+
*ngFor="let item of items"
|
|
6654
|
+
#itemEls
|
|
6655
|
+
type="button"
|
|
6656
|
+
role="tab"
|
|
6657
|
+
[disabled]="item.disabled || disabled"
|
|
6658
|
+
[attr.aria-selected]="value === item.value"
|
|
6659
|
+
(click)="select(item.value)"
|
|
6660
|
+
[class]="cn(
|
|
6661
|
+
'relative z-10 flex-1 px-3 py-1.5 text-sm font-medium transition-colors duration-200 rounded-md text-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
6662
|
+
'flex items-center justify-center gap-2',
|
|
6663
|
+
value === item.value
|
|
6664
|
+
? 'text-foreground'
|
|
6665
|
+
: 'text-muted-foreground hover:text-foreground/70',
|
|
6666
|
+
item.disabled && 'opacity-50 cursor-not-allowed',
|
|
6667
|
+
item.class
|
|
6668
|
+
)"
|
|
6669
|
+
>
|
|
6670
|
+
<ng-container *ngIf="itemTemplate; else defaultContent">
|
|
6671
|
+
<ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: item, selected: value === item.value }">
|
|
6672
|
+
</ng-container>
|
|
6673
|
+
</ng-container>
|
|
6674
|
+
|
|
6675
|
+
<ng-template #defaultContent>
|
|
6676
|
+
<i *ngIf="item.icon" [class]="item.icon"></i>
|
|
6677
|
+
<span class="truncate">{{ item.label }}</span>
|
|
6678
|
+
</ng-template>
|
|
6679
|
+
</button>
|
|
6680
|
+
</div>
|
|
6681
|
+
`, styles: [":host{display:block}\n"] }]
|
|
6682
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { items: [{
|
|
6683
|
+
type: Input
|
|
6684
|
+
}], class: [{
|
|
6685
|
+
type: Input
|
|
6686
|
+
}], disabled: [{
|
|
6687
|
+
type: Input
|
|
6688
|
+
}], itemTemplate: [{
|
|
6689
|
+
type: Input
|
|
6690
|
+
}], itemElements: [{
|
|
6691
|
+
type: ViewChildren,
|
|
6692
|
+
args: ['itemEls']
|
|
6693
|
+
}] } });
|
|
6694
|
+
|
|
6695
|
+
class SidebarComponent {
|
|
6696
|
+
items = [];
|
|
6697
|
+
collapsed = false;
|
|
6698
|
+
class = '';
|
|
6699
|
+
expandedParents = new Set();
|
|
6700
|
+
expandedChildren = new Set();
|
|
6701
|
+
cn = cn;
|
|
6702
|
+
ngOnChanges(changes) {
|
|
6703
|
+
if (changes['collapsed'] && this.collapsed) {
|
|
6704
|
+
this.collapseAll();
|
|
6705
|
+
return;
|
|
6706
|
+
}
|
|
6707
|
+
if (changes['items']) {
|
|
6708
|
+
this.initializeState();
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6711
|
+
// --- STATE INIT ---
|
|
6712
|
+
initializeState() {
|
|
6713
|
+
this.collapseAll();
|
|
6714
|
+
if (!this.items)
|
|
6715
|
+
return;
|
|
6716
|
+
this.items.forEach((group, gIndex) => {
|
|
6717
|
+
group.items.forEach((item, iIndex) => {
|
|
6718
|
+
const parentId = this.getParentId(group, item, gIndex, iIndex);
|
|
6719
|
+
if (item.expanded) {
|
|
6720
|
+
this.expandedParents.add(parentId);
|
|
6721
|
+
}
|
|
6722
|
+
if (item.items) {
|
|
6723
|
+
item.items.forEach((subItem, sIndex) => {
|
|
6724
|
+
if (subItem.expanded) {
|
|
6725
|
+
const childId = this.getChildId(group, item, subItem, gIndex, iIndex, sIndex);
|
|
6726
|
+
this.expandedChildren.add(childId);
|
|
6727
|
+
this.expandedParents.add(parentId);
|
|
6728
|
+
}
|
|
6729
|
+
});
|
|
6730
|
+
}
|
|
6731
|
+
});
|
|
6732
|
+
});
|
|
6733
|
+
}
|
|
6734
|
+
// --- ID GENERATORS (Now using Group Index correctly) ---
|
|
6735
|
+
getGroupId(group, index) {
|
|
6736
|
+
return group.id || group.title || `g-${index}`;
|
|
6737
|
+
}
|
|
6738
|
+
getParentId(group, item, gIndex, iIndex) {
|
|
6739
|
+
const groupId = this.getGroupId(group, gIndex);
|
|
6740
|
+
const itemId = item.id || item.title || `p-${iIndex}`;
|
|
6741
|
+
return `${groupId}__${itemId}`;
|
|
6742
|
+
}
|
|
6743
|
+
getChildId(group, parent, subItem, gIndex, iIndex, sIndex) {
|
|
6744
|
+
const parentId = this.getParentId(group, parent, gIndex, iIndex);
|
|
6745
|
+
const subItemId = subItem.id || subItem.title || `c-${sIndex}`;
|
|
6746
|
+
return `${parentId}__${subItemId}`;
|
|
6747
|
+
}
|
|
6748
|
+
// --- ACTIONS ---
|
|
6749
|
+
toggleParent(group, item, gIndex, iIndex) {
|
|
6750
|
+
if (this.collapsed)
|
|
6751
|
+
return;
|
|
6752
|
+
const id = this.getParentId(group, item, gIndex, iIndex);
|
|
6753
|
+
// Create new Set reference to ensure Change Detection triggers
|
|
6754
|
+
const newSet = new Set(this.expandedParents);
|
|
6755
|
+
if (newSet.has(id)) {
|
|
6756
|
+
newSet.delete(id);
|
|
6757
|
+
}
|
|
6758
|
+
else {
|
|
6759
|
+
newSet.add(id);
|
|
6760
|
+
}
|
|
6761
|
+
this.expandedParents = newSet;
|
|
6762
|
+
}
|
|
6763
|
+
toggleChild(group, parent, subItem, gIndex, iIndex, sIndex) {
|
|
6764
|
+
const id = this.getChildId(group, parent, subItem, gIndex, iIndex, sIndex);
|
|
6765
|
+
// Create new Set reference
|
|
6766
|
+
const newSet = new Set(this.expandedChildren);
|
|
6767
|
+
if (newSet.has(id)) {
|
|
6768
|
+
newSet.delete(id);
|
|
6769
|
+
}
|
|
6770
|
+
else {
|
|
6771
|
+
newSet.add(id);
|
|
6772
|
+
}
|
|
6773
|
+
this.expandedChildren = newSet;
|
|
6774
|
+
}
|
|
6775
|
+
collapseAll() {
|
|
6776
|
+
this.expandedParents = new Set();
|
|
6777
|
+
this.expandedChildren = new Set();
|
|
6778
|
+
}
|
|
6779
|
+
// --- TEMPLATE HELPERS ---
|
|
6780
|
+
isParentExpanded(group, item, gIndex, iIndex) {
|
|
6781
|
+
return this.expandedParents.has(this.getParentId(group, item, gIndex, iIndex));
|
|
6782
|
+
}
|
|
6783
|
+
isChildExpanded(group, parent, subItem, gIndex, iIndex, sIndex) {
|
|
6784
|
+
return this.expandedChildren.has(this.getChildId(group, parent, subItem, gIndex, iIndex, sIndex));
|
|
6785
|
+
}
|
|
6786
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6787
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SidebarComponent, isStandalone: true, selector: "tolle-sidebar", inputs: { items: "items", collapsed: "collapsed", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
|
|
6788
|
+
<aside [class]="cn(
|
|
6789
|
+
'flex flex-col h-full border-r bg-background transition-[width] duration-300 ease-in-out shrink-0 overflow-hidden',
|
|
6790
|
+
collapsed ? 'w-16' : 'w-64',
|
|
6791
|
+
class
|
|
6792
|
+
)">
|
|
6793
|
+
<div class="flex h-14 shrink-0 items-center border-b px-3 overflow-hidden whitespace-nowrap">
|
|
6794
|
+
<ng-content select="[header]"></ng-content>
|
|
6795
|
+
</div>
|
|
6796
|
+
|
|
6797
|
+
<div class="flex-1 min-h-0 overflow-y-auto overflow-x-hidden py-4 px-3 custom-scrollbar">
|
|
6798
|
+
|
|
6799
|
+
@for (group of items; track group.id || group.title || $index; let gIndex = $index) {
|
|
6800
|
+
<div class="mb-6">
|
|
6801
|
+
|
|
6802
|
+
<div [class]="cn(
|
|
6803
|
+
'mb-2 px-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground/70 transition-all duration-200 overflow-hidden',
|
|
6804
|
+
collapsed ? 'opacity-0 h-0 mb-0 px-0' : 'opacity-100 h-auto'
|
|
6805
|
+
)">
|
|
6806
|
+
{{ group.title }}
|
|
6807
|
+
</div>
|
|
6808
|
+
|
|
6809
|
+
<div class="flex flex-col gap-1">
|
|
6810
|
+
@for (item of group.items; track item.id || item.title || $index; let i = $index) {
|
|
6811
|
+
|
|
6812
|
+
@if (item.items && item.items.length) {
|
|
6813
|
+
<div class="relative">
|
|
6814
|
+
<button
|
|
6815
|
+
type="button"
|
|
6816
|
+
(click)="toggleParent(group, item, gIndex, i)"
|
|
6817
|
+
[disabled]="collapsed"
|
|
6818
|
+
[attr.aria-expanded]="isParentExpanded(group, item, gIndex, i)"
|
|
6819
|
+
[class]="cn(
|
|
6820
|
+
'group w-full relative flex items-center rounded-md px-3 py-2 text-sm font-medium transition-colors',
|
|
6821
|
+
'hover:bg-accent hover:text-accent-foreground',
|
|
6822
|
+
isParentExpanded(group, item, gIndex, i) ? 'text-foreground bg-accent/50' : 'text-muted-foreground',
|
|
6823
|
+
collapsed ? 'justify-center' : 'justify-start'
|
|
6824
|
+
)"
|
|
6825
|
+
>
|
|
6826
|
+
<i [class]="cn(
|
|
6827
|
+
item.icon || 'ri-circle-fill',
|
|
6828
|
+
'h-4 w-4 text-lg shrink-0 transition-transform',
|
|
6829
|
+
!collapsed && 'group-hover:scale-110'
|
|
6830
|
+
)"></i>
|
|
6831
|
+
|
|
6832
|
+
<span [class]="cn(
|
|
6833
|
+
'truncate transition-all duration-300',
|
|
6834
|
+
collapsed ? 'opacity-0 w-0 ml-0' : 'opacity-100 w-auto ml-3'
|
|
6835
|
+
)">
|
|
6836
|
+
{{ item.title }}
|
|
6837
|
+
</span>
|
|
6838
|
+
|
|
6839
|
+
@if (!collapsed) {
|
|
6840
|
+
<i [class]="cn(
|
|
6841
|
+
'ri-arrow-down-s-line ml-auto transition-transform duration-300',
|
|
6842
|
+
isParentExpanded(group, item, gIndex, i) ? 'rotate-180' : ''
|
|
6843
|
+
)"></i>
|
|
6844
|
+
}
|
|
6845
|
+
</button>
|
|
6846
|
+
|
|
6847
|
+
<div [class]="cn(
|
|
6848
|
+
'grid transition-[grid-template-rows] duration-300 ease-in-out',
|
|
6849
|
+
isParentExpanded(group, item, gIndex, i) && !collapsed ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'
|
|
6850
|
+
)">
|
|
6851
|
+
<div class="overflow-hidden">
|
|
6852
|
+
<div class="flex flex-col gap-1 mt-1 ml-4 border-l border-border/50 pl-2">
|
|
6853
|
+
|
|
6854
|
+
@for (subItem of item.items; track subItem.id || subItem.title || $index; let j = $index) {
|
|
6855
|
+
|
|
6856
|
+
@if (subItem.items && subItem.items.length) {
|
|
6857
|
+
<div class="relative">
|
|
6858
|
+
<button
|
|
6859
|
+
type="button"
|
|
6860
|
+
(click)="toggleChild(group, item, subItem, gIndex, i, j); $event.stopPropagation()"
|
|
6861
|
+
[class]="cn(
|
|
6862
|
+
'group w-full relative flex items-center rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
|
|
6863
|
+
'hover:bg-accent hover:text-accent-foreground text-muted-foreground',
|
|
6864
|
+
isChildExpanded(group, item, subItem, gIndex, i, j) ? 'text-foreground bg-accent/30' : ''
|
|
6865
|
+
)"
|
|
6866
|
+
>
|
|
6867
|
+
<span class="w-1.5 h-1.5 rounded-full bg-border shrink-0"></span>
|
|
6868
|
+
<span class="ml-2 truncate">{{ subItem.title }}</span>
|
|
6869
|
+
<i [class]="cn(
|
|
6870
|
+
'ri-arrow-right-s-line ml-auto transition-transform duration-300 text-xs',
|
|
6871
|
+
isChildExpanded(group, item, subItem, gIndex, i, j) ? 'rotate-90' : ''
|
|
6872
|
+
)"></i>
|
|
6873
|
+
</button>
|
|
6874
|
+
|
|
6875
|
+
<div [class]="cn(
|
|
6876
|
+
'grid transition-[grid-template-rows] duration-300 ease-in-out',
|
|
6877
|
+
isChildExpanded(group, item, subItem, gIndex, i, j) ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'
|
|
6878
|
+
)">
|
|
6879
|
+
<div class="overflow-hidden">
|
|
6880
|
+
<div class="flex flex-col gap-1 mt-1 ml-4 border-l border-border/30 pl-2">
|
|
6881
|
+
@for (grandChild of subItem.items; track grandChild.title) {
|
|
6882
|
+
<a
|
|
6883
|
+
[routerLink]="grandChild.url"
|
|
6884
|
+
routerLinkActive="bg-accent/50 text-accent-foreground"
|
|
6885
|
+
[routerLinkActiveOptions]="{ exact: true }"
|
|
6886
|
+
class="flex items-center gap-2 hover:no-underline rounded-md px-3 py-1.5 text-sm transition-colors hover:bg-accent hover:text-accent-foreground text-muted-foreground whitespace-nowrap"
|
|
6887
|
+
>
|
|
6888
|
+
<span class="w-1.5 h-1.5 rounded-full bg-border/70 shrink-0"></span>
|
|
6889
|
+
<span class="truncate">{{ grandChild.title }}</span>
|
|
6890
|
+
</a>
|
|
6891
|
+
}
|
|
6892
|
+
</div>
|
|
6893
|
+
</div>
|
|
6894
|
+
</div>
|
|
6895
|
+
</div>
|
|
6896
|
+
}
|
|
6897
|
+
@else {
|
|
6898
|
+
<a
|
|
6899
|
+
[routerLink]="subItem.url"
|
|
6900
|
+
routerLinkActive="bg-accent/50 text-accent-foreground"
|
|
6901
|
+
[routerLinkActiveOptions]="{ exact: true }"
|
|
6902
|
+
class="flex items-center gap-2 hover:no-underline rounded-md px-3 py-1.5 text-sm transition-colors hover:bg-accent hover:text-accent-foreground text-muted-foreground whitespace-nowrap"
|
|
6903
|
+
>
|
|
6904
|
+
<span class="w-1.5 h-1.5 rounded-full bg-border shrink-0"></span>
|
|
6905
|
+
<span class="truncate">{{ subItem.title }}</span>
|
|
6906
|
+
</a>
|
|
6907
|
+
}
|
|
6908
|
+
}
|
|
6909
|
+
</div>
|
|
6910
|
+
</div>
|
|
6911
|
+
</div>
|
|
6912
|
+
</div>
|
|
6913
|
+
}
|
|
6914
|
+
@else {
|
|
6915
|
+
<a
|
|
6916
|
+
[routerLink]="item.url"
|
|
6917
|
+
routerLinkActive="bg-primary/10 text-primary"
|
|
6918
|
+
[routerLinkActiveOptions]="{ exact: true }"
|
|
6919
|
+
[class]="cn(
|
|
6920
|
+
'group relative hover:no-underline flex items-center rounded-md px-3 py-2 text-sm font-medium transition-colors',
|
|
6921
|
+
'hover:bg-accent hover:text-accent-foreground text-muted-foreground',
|
|
6922
|
+
collapsed ? 'justify-center' : 'justify-start'
|
|
6923
|
+
)"
|
|
6924
|
+
>
|
|
6925
|
+
<i [class]="cn(
|
|
6926
|
+
item.icon || 'ri-circle-fill',
|
|
6927
|
+
'h-4 w-4 text-lg shrink-0 transition-transform',
|
|
6928
|
+
!collapsed && 'group-hover:scale-110'
|
|
6929
|
+
)"></i>
|
|
6930
|
+
<span [class]="cn(
|
|
6931
|
+
'truncate transition-all duration-300',
|
|
6932
|
+
collapsed ? 'opacity-0 w-0 ml-0' : 'opacity-100 w-auto ml-3'
|
|
6933
|
+
)">
|
|
6934
|
+
{{ item.title }}
|
|
6935
|
+
</span>
|
|
6936
|
+
</a>
|
|
6937
|
+
}
|
|
6938
|
+
}
|
|
6939
|
+
</div>
|
|
6940
|
+
</div>
|
|
6941
|
+
}
|
|
6942
|
+
</div>
|
|
6943
|
+
|
|
6944
|
+
<div class="border-t shrink-0 p-3 overflow-hidden whitespace-nowrap">
|
|
6945
|
+
<ng-content select="[footer]"></ng-content>
|
|
6946
|
+
</div>
|
|
6947
|
+
</aside>
|
|
6948
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:rgba(156,163,175,.3) transparent}.custom-scrollbar::-webkit-scrollbar{width:4px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background-color:#9ca3af4d;border-radius:20px}button:disabled{cursor:not-allowed;opacity:.6}*{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ml-4{margin-left:1rem}.border-l{border-left-width:1px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
|
|
6949
|
+
}
|
|
6950
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SidebarComponent, decorators: [{
|
|
6951
|
+
type: Component,
|
|
6952
|
+
args: [{ selector: 'tolle-sidebar', standalone: true, imports: [CommonModule, RouterModule], template: `
|
|
6953
|
+
<aside [class]="cn(
|
|
6954
|
+
'flex flex-col h-full border-r bg-background transition-[width] duration-300 ease-in-out shrink-0 overflow-hidden',
|
|
6955
|
+
collapsed ? 'w-16' : 'w-64',
|
|
6956
|
+
class
|
|
6957
|
+
)">
|
|
6958
|
+
<div class="flex h-14 shrink-0 items-center border-b px-3 overflow-hidden whitespace-nowrap">
|
|
6959
|
+
<ng-content select="[header]"></ng-content>
|
|
6960
|
+
</div>
|
|
6961
|
+
|
|
6962
|
+
<div class="flex-1 min-h-0 overflow-y-auto overflow-x-hidden py-4 px-3 custom-scrollbar">
|
|
6963
|
+
|
|
6964
|
+
@for (group of items; track group.id || group.title || $index; let gIndex = $index) {
|
|
6965
|
+
<div class="mb-6">
|
|
6966
|
+
|
|
6967
|
+
<div [class]="cn(
|
|
6968
|
+
'mb-2 px-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground/70 transition-all duration-200 overflow-hidden',
|
|
6969
|
+
collapsed ? 'opacity-0 h-0 mb-0 px-0' : 'opacity-100 h-auto'
|
|
6970
|
+
)">
|
|
6971
|
+
{{ group.title }}
|
|
6972
|
+
</div>
|
|
6973
|
+
|
|
6974
|
+
<div class="flex flex-col gap-1">
|
|
6975
|
+
@for (item of group.items; track item.id || item.title || $index; let i = $index) {
|
|
6976
|
+
|
|
6977
|
+
@if (item.items && item.items.length) {
|
|
6978
|
+
<div class="relative">
|
|
6979
|
+
<button
|
|
6980
|
+
type="button"
|
|
6981
|
+
(click)="toggleParent(group, item, gIndex, i)"
|
|
6982
|
+
[disabled]="collapsed"
|
|
6983
|
+
[attr.aria-expanded]="isParentExpanded(group, item, gIndex, i)"
|
|
6984
|
+
[class]="cn(
|
|
6985
|
+
'group w-full relative flex items-center rounded-md px-3 py-2 text-sm font-medium transition-colors',
|
|
6986
|
+
'hover:bg-accent hover:text-accent-foreground',
|
|
6987
|
+
isParentExpanded(group, item, gIndex, i) ? 'text-foreground bg-accent/50' : 'text-muted-foreground',
|
|
6988
|
+
collapsed ? 'justify-center' : 'justify-start'
|
|
6989
|
+
)"
|
|
6990
|
+
>
|
|
6991
|
+
<i [class]="cn(
|
|
6992
|
+
item.icon || 'ri-circle-fill',
|
|
6993
|
+
'h-4 w-4 text-lg shrink-0 transition-transform',
|
|
6994
|
+
!collapsed && 'group-hover:scale-110'
|
|
6995
|
+
)"></i>
|
|
6996
|
+
|
|
6997
|
+
<span [class]="cn(
|
|
6998
|
+
'truncate transition-all duration-300',
|
|
6999
|
+
collapsed ? 'opacity-0 w-0 ml-0' : 'opacity-100 w-auto ml-3'
|
|
7000
|
+
)">
|
|
7001
|
+
{{ item.title }}
|
|
7002
|
+
</span>
|
|
7003
|
+
|
|
7004
|
+
@if (!collapsed) {
|
|
7005
|
+
<i [class]="cn(
|
|
7006
|
+
'ri-arrow-down-s-line ml-auto transition-transform duration-300',
|
|
7007
|
+
isParentExpanded(group, item, gIndex, i) ? 'rotate-180' : ''
|
|
7008
|
+
)"></i>
|
|
7009
|
+
}
|
|
7010
|
+
</button>
|
|
7011
|
+
|
|
7012
|
+
<div [class]="cn(
|
|
7013
|
+
'grid transition-[grid-template-rows] duration-300 ease-in-out',
|
|
7014
|
+
isParentExpanded(group, item, gIndex, i) && !collapsed ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'
|
|
7015
|
+
)">
|
|
7016
|
+
<div class="overflow-hidden">
|
|
7017
|
+
<div class="flex flex-col gap-1 mt-1 ml-4 border-l border-border/50 pl-2">
|
|
7018
|
+
|
|
7019
|
+
@for (subItem of item.items; track subItem.id || subItem.title || $index; let j = $index) {
|
|
7020
|
+
|
|
7021
|
+
@if (subItem.items && subItem.items.length) {
|
|
7022
|
+
<div class="relative">
|
|
7023
|
+
<button
|
|
7024
|
+
type="button"
|
|
7025
|
+
(click)="toggleChild(group, item, subItem, gIndex, i, j); $event.stopPropagation()"
|
|
7026
|
+
[class]="cn(
|
|
7027
|
+
'group w-full relative flex items-center rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
|
|
7028
|
+
'hover:bg-accent hover:text-accent-foreground text-muted-foreground',
|
|
7029
|
+
isChildExpanded(group, item, subItem, gIndex, i, j) ? 'text-foreground bg-accent/30' : ''
|
|
7030
|
+
)"
|
|
7031
|
+
>
|
|
7032
|
+
<span class="w-1.5 h-1.5 rounded-full bg-border shrink-0"></span>
|
|
7033
|
+
<span class="ml-2 truncate">{{ subItem.title }}</span>
|
|
7034
|
+
<i [class]="cn(
|
|
7035
|
+
'ri-arrow-right-s-line ml-auto transition-transform duration-300 text-xs',
|
|
7036
|
+
isChildExpanded(group, item, subItem, gIndex, i, j) ? 'rotate-90' : ''
|
|
7037
|
+
)"></i>
|
|
7038
|
+
</button>
|
|
7039
|
+
|
|
7040
|
+
<div [class]="cn(
|
|
7041
|
+
'grid transition-[grid-template-rows] duration-300 ease-in-out',
|
|
7042
|
+
isChildExpanded(group, item, subItem, gIndex, i, j) ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'
|
|
7043
|
+
)">
|
|
7044
|
+
<div class="overflow-hidden">
|
|
7045
|
+
<div class="flex flex-col gap-1 mt-1 ml-4 border-l border-border/30 pl-2">
|
|
7046
|
+
@for (grandChild of subItem.items; track grandChild.title) {
|
|
7047
|
+
<a
|
|
7048
|
+
[routerLink]="grandChild.url"
|
|
7049
|
+
routerLinkActive="bg-accent/50 text-accent-foreground"
|
|
7050
|
+
[routerLinkActiveOptions]="{ exact: true }"
|
|
7051
|
+
class="flex items-center gap-2 hover:no-underline rounded-md px-3 py-1.5 text-sm transition-colors hover:bg-accent hover:text-accent-foreground text-muted-foreground whitespace-nowrap"
|
|
7052
|
+
>
|
|
7053
|
+
<span class="w-1.5 h-1.5 rounded-full bg-border/70 shrink-0"></span>
|
|
7054
|
+
<span class="truncate">{{ grandChild.title }}</span>
|
|
7055
|
+
</a>
|
|
7056
|
+
}
|
|
7057
|
+
</div>
|
|
7058
|
+
</div>
|
|
7059
|
+
</div>
|
|
7060
|
+
</div>
|
|
7061
|
+
}
|
|
7062
|
+
@else {
|
|
7063
|
+
<a
|
|
7064
|
+
[routerLink]="subItem.url"
|
|
7065
|
+
routerLinkActive="bg-accent/50 text-accent-foreground"
|
|
7066
|
+
[routerLinkActiveOptions]="{ exact: true }"
|
|
7067
|
+
class="flex items-center gap-2 hover:no-underline rounded-md px-3 py-1.5 text-sm transition-colors hover:bg-accent hover:text-accent-foreground text-muted-foreground whitespace-nowrap"
|
|
7068
|
+
>
|
|
7069
|
+
<span class="w-1.5 h-1.5 rounded-full bg-border shrink-0"></span>
|
|
7070
|
+
<span class="truncate">{{ subItem.title }}</span>
|
|
7071
|
+
</a>
|
|
7072
|
+
}
|
|
7073
|
+
}
|
|
7074
|
+
</div>
|
|
7075
|
+
</div>
|
|
7076
|
+
</div>
|
|
7077
|
+
</div>
|
|
7078
|
+
}
|
|
7079
|
+
@else {
|
|
7080
|
+
<a
|
|
7081
|
+
[routerLink]="item.url"
|
|
7082
|
+
routerLinkActive="bg-primary/10 text-primary"
|
|
7083
|
+
[routerLinkActiveOptions]="{ exact: true }"
|
|
7084
|
+
[class]="cn(
|
|
7085
|
+
'group relative hover:no-underline flex items-center rounded-md px-3 py-2 text-sm font-medium transition-colors',
|
|
7086
|
+
'hover:bg-accent hover:text-accent-foreground text-muted-foreground',
|
|
7087
|
+
collapsed ? 'justify-center' : 'justify-start'
|
|
7088
|
+
)"
|
|
7089
|
+
>
|
|
7090
|
+
<i [class]="cn(
|
|
7091
|
+
item.icon || 'ri-circle-fill',
|
|
7092
|
+
'h-4 w-4 text-lg shrink-0 transition-transform',
|
|
7093
|
+
!collapsed && 'group-hover:scale-110'
|
|
7094
|
+
)"></i>
|
|
7095
|
+
<span [class]="cn(
|
|
7096
|
+
'truncate transition-all duration-300',
|
|
7097
|
+
collapsed ? 'opacity-0 w-0 ml-0' : 'opacity-100 w-auto ml-3'
|
|
7098
|
+
)">
|
|
7099
|
+
{{ item.title }}
|
|
7100
|
+
</span>
|
|
7101
|
+
</a>
|
|
7102
|
+
}
|
|
7103
|
+
}
|
|
7104
|
+
</div>
|
|
7105
|
+
</div>
|
|
7106
|
+
}
|
|
7107
|
+
</div>
|
|
7108
|
+
|
|
7109
|
+
<div class="border-t shrink-0 p-3 overflow-hidden whitespace-nowrap">
|
|
7110
|
+
<ng-content select="[footer]"></ng-content>
|
|
7111
|
+
</div>
|
|
7112
|
+
</aside>
|
|
7113
|
+
`, styles: [":host{display:block;height:100%}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:rgba(156,163,175,.3) transparent}.custom-scrollbar::-webkit-scrollbar{width:4px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background-color:#9ca3af4d;border-radius:20px}button:disabled{cursor:not-allowed;opacity:.6}*{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ml-4{margin-left:1rem}.border-l{border-left-width:1px}\n"] }]
|
|
7114
|
+
}], propDecorators: { items: [{
|
|
7115
|
+
type: Input
|
|
7116
|
+
}], collapsed: [{
|
|
7117
|
+
type: Input
|
|
7118
|
+
}], class: [{
|
|
7119
|
+
type: Input
|
|
7120
|
+
}] } });
|
|
7121
|
+
|
|
6450
7122
|
/*
|
|
6451
7123
|
* Public API Surface of tolle
|
|
6452
7124
|
*/
|
|
@@ -6455,5 +7127,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6455
7127
|
* Generated bundle index. Do not edit.
|
|
6456
7128
|
*/
|
|
6457
7129
|
|
|
6458
|
-
export { AccordionComponent, AccordionItemComponent, AlertComponent, AvatarComponent, AvatarFallbackComponent, BadgeComponent, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbLinkComponent, BreadcrumbSeparatorComponent, ButtonComponent, ButtonGroupComponent, CalendarComponent, CardComponent, CardContentComponent, CardFooterComponent, CardHeaderComponent, CardTitleComponent, CheckboxComponent, DataTableComponent, DatePickerComponent, DateRangePickerComponent, DropdownItemComponent, DropdownLabelComponent, DropdownMenuComponent, DropdownSeparatorComponent, DropdownTriggerDirective, EmptyStateComponent, InputComponent, MaskedInputComponent, Modal, ModalComponent, ModalRef, ModalService, ModalStackService, MultiSelectComponent, OtpComponent, OtpGroupComponent, OtpSlotComponent, PaginationComponent, PopoverComponent, PopoverContentComponent, RadioGroupComponent, RadioItemComponent, RangeCalendarComponent, SelectComponent, SelectGroupComponent, SelectItemComponent, SelectSeparatorComponent, SkeletonComponent, SwitchComponent, TOLLE_CONFIG, TextareaComponent, ThemeService, ToastContainerComponent, ToastService, TolleCellDirective, TooltipDirective, cn, provideTolleConfig };
|
|
7130
|
+
export { AccordionComponent, AccordionItemComponent, AlertComponent, AvatarComponent, AvatarFallbackComponent, BadgeComponent, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbLinkComponent, BreadcrumbSeparatorComponent, ButtonComponent, ButtonGroupComponent, CalendarComponent, CardComponent, CardContentComponent, CardFooterComponent, CardHeaderComponent, CardTitleComponent, CheckboxComponent, DataTableComponent, DatePickerComponent, DateRangePickerComponent, DropdownItemComponent, DropdownLabelComponent, DropdownMenuComponent, DropdownSeparatorComponent, DropdownTriggerDirective, EmptyStateComponent, InputComponent, MaskedInputComponent, Modal, ModalComponent, ModalRef, ModalService, ModalStackService, MultiSelectComponent, OtpComponent, OtpGroupComponent, OtpSlotComponent, PaginationComponent, PopoverComponent, PopoverContentComponent, RadioGroupComponent, RadioItemComponent, RangeCalendarComponent, SegmentedComponent, SelectComponent, SelectGroupComponent, SelectItemComponent, SelectSeparatorComponent, SidebarComponent, SkeletonComponent, SwitchComponent, TOLLE_CONFIG, TextareaComponent, ThemeService, ToastContainerComponent, ToastService, TolleCellDirective, TooltipDirective, cn, provideTolleConfig };
|
|
6459
7131
|
//# sourceMappingURL=tolle-ui.mjs.map
|