@ojiepermana/angular 21.1.2 → 21.1.5
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/etos/README.md +243 -0
- package/etos/styles/layout.css +11 -0
- package/fesm2022/ojiepermana-angular-component.mjs +1 -1
- package/fesm2022/ojiepermana-angular-component.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-etos.mjs +808 -2
- package/fesm2022/ojiepermana-angular-etos.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-layout.mjs +2 -2
- package/fesm2022/ojiepermana-angular-layout.mjs.map +1 -1
- package/package.json +1 -7
- package/theme/styles/etos.css +1 -1
- package/types/ojiepermana-angular-component.d.ts +2 -2
- package/types/ojiepermana-angular-etos.d.ts +176 -1
- package/brand/etos/README.md +0 -68
- package/brand/etos/package.json +0 -4
- package/brand/etos/styles/color.css +0 -21
- package/brand/etos/styles/index.css +0 -15
- package/brand/etos/styles/layout.css +0 -175
- package/brand/etos/styles/style.css +0 -51
- package/fesm2022/ojiepermana-angular-brand-etos.mjs +0 -285
- package/fesm2022/ojiepermana-angular-brand-etos.mjs.map +0 -1
- package/types/ojiepermana-angular-brand-etos.d.ts +0 -73
|
@@ -1,12 +1,818 @@
|
|
|
1
|
-
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { provideEnvironmentInitializer, inject, makeEnvironmentProviders, viewChild, input, output, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { provideMaterialLayout, LayoutService } from '@ojiepermana/angular/layout';
|
|
4
|
+
import { NavigationService, DEFAULT_NAVIGATION_ID, UiNavIconComponent, TopbarComponent, SidebarComponent } from '@ojiepermana/angular/navigation';
|
|
5
|
+
import { provideMaterialTheme, withMaterialDefaults, ThemeService } from '@ojiepermana/angular/theme';
|
|
6
|
+
import { cn, AvatarComponent, AvatarFallbackComponent, AvatarImageComponent, ButtonComponent, PopoverContentDirective, PopoverTriggerDirective } from '@ojiepermana/angular/component';
|
|
7
|
+
import { RouterOutlet } from '@angular/router';
|
|
8
|
+
|
|
9
|
+
const ETOS_BRAND_NAME = 'etos';
|
|
10
|
+
const ETOS_THEME_CONFIG = {
|
|
11
|
+
mode: 'light',
|
|
12
|
+
brand: ETOS_BRAND_NAME,
|
|
13
|
+
};
|
|
14
|
+
const ETOS_LAYOUT_CONFIG = {
|
|
15
|
+
mode: 'vertical',
|
|
16
|
+
width: 'fixed',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function provideEtosTheme(config = {}, ...features) {
|
|
20
|
+
return provideMaterialTheme({
|
|
21
|
+
...ETOS_THEME_CONFIG,
|
|
22
|
+
...config,
|
|
23
|
+
brand: ETOS_BRAND_NAME,
|
|
24
|
+
'theme-brand': ETOS_BRAND_NAME,
|
|
25
|
+
}, ...features);
|
|
26
|
+
}
|
|
27
|
+
function provideEtosLayout(config = {}) {
|
|
28
|
+
return provideMaterialLayout({
|
|
29
|
+
...ETOS_LAYOUT_CONFIG,
|
|
30
|
+
...config,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function provideEtosBrand(options = {}) {
|
|
34
|
+
const providers = [
|
|
35
|
+
provideEtosTheme(options.theme, ...(options.materialDefaults === false ? [] : [withMaterialDefaults()])),
|
|
36
|
+
provideEtosLayout(options.layout),
|
|
37
|
+
];
|
|
38
|
+
const navigation = options.navigation;
|
|
39
|
+
if (navigation) {
|
|
40
|
+
providers.push(provideEnvironmentInitializer(() => {
|
|
41
|
+
inject(NavigationService).registerItems(options.navigationId ?? DEFAULT_NAVIGATION_ID, navigation);
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
return makeEnvironmentProviders(providers);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const THEME_SCHEME_OPTIONS = [
|
|
48
|
+
{ value: 'light', label: 'Light', icon: 'light_mode' },
|
|
49
|
+
{ value: 'dark', label: 'Dark', icon: 'dark_mode' },
|
|
50
|
+
{ value: 'system', label: 'System', icon: 'computer' },
|
|
51
|
+
];
|
|
52
|
+
const LAYOUT_MODE_OPTIONS = [
|
|
53
|
+
{ value: 'horizontal', label: 'Horizontal', icon: 'view_column' },
|
|
54
|
+
{ value: 'vertical', label: 'Vertical', icon: 'view_sidebar' },
|
|
55
|
+
];
|
|
56
|
+
const LAYOUT_WIDTH_OPTIONS = [
|
|
57
|
+
{ value: 'full', label: 'Full', icon: 'fit_screen' },
|
|
58
|
+
{ value: 'fixed', label: 'Fixed', icon: 'center_focus_strong' },
|
|
59
|
+
];
|
|
60
|
+
class EtosThemeSwitcherComponent {
|
|
61
|
+
theme = inject(ThemeService);
|
|
62
|
+
layout = inject(LayoutService);
|
|
63
|
+
popoverTrigger = viewChild.required('trigger');
|
|
64
|
+
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
65
|
+
userInfo = input(null, ...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
|
|
66
|
+
userName = input('User', ...(ngDevMode ? [{ debugName: "userName" }] : /* istanbul ignore next */ []));
|
|
67
|
+
userSubtitle = input('Theme and layout preferences', ...(ngDevMode ? [{ debugName: "userSubtitle" }] : /* istanbul ignore next */ []));
|
|
68
|
+
avatarSrc = input(null, ...(ngDevMode ? [{ debugName: "avatarSrc" }] : /* istanbul ignore next */ []));
|
|
69
|
+
avatarAlt = input('', ...(ngDevMode ? [{ debugName: "avatarAlt" }] : /* istanbul ignore next */ []));
|
|
70
|
+
quickActions = input.required(...(ngDevMode ? [{ debugName: "quickActions" }] : /* istanbul ignore next */ []));
|
|
71
|
+
notificationShortcut = input(null, ...(ngDevMode ? [{ debugName: "notificationShortcut" }] : /* istanbul ignore next */ []));
|
|
72
|
+
showNotificationShortcut = input(false, ...(ngDevMode ? [{ debugName: "showNotificationShortcut" }] : /* istanbul ignore next */ []));
|
|
73
|
+
popoverSide = input('bottom', ...(ngDevMode ? [{ debugName: "popoverSide" }] : /* istanbul ignore next */ []));
|
|
74
|
+
popoverAlign = input('end', ...(ngDevMode ? [{ debugName: "popoverAlign" }] : /* istanbul ignore next */ []));
|
|
75
|
+
actionSelected = output();
|
|
76
|
+
themeMode = this.theme.mode;
|
|
77
|
+
themeScheme = this.theme.scheme;
|
|
78
|
+
layoutMode = this.layout.mode;
|
|
79
|
+
layoutWidth = this.layout.width;
|
|
80
|
+
themeSchemeOptions = THEME_SCHEME_OPTIONS;
|
|
81
|
+
layoutModeOptions = LAYOUT_MODE_OPTIONS;
|
|
82
|
+
layoutWidthOptions = LAYOUT_WIDTH_OPTIONS;
|
|
83
|
+
notificationShortcutConfig = computed(() => {
|
|
84
|
+
const shortcut = this.notificationShortcut();
|
|
85
|
+
if (shortcut) {
|
|
86
|
+
return {
|
|
87
|
+
value: shortcut.value ?? 'notifications',
|
|
88
|
+
icon: shortcut.icon ?? 'notifications',
|
|
89
|
+
ariaLabel: shortcut.ariaLabel ?? `Open notifications for ${this.resolvedUserName()}`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (!this.showNotificationShortcut()) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
value: 'notifications',
|
|
97
|
+
icon: 'notifications',
|
|
98
|
+
ariaLabel: `Open notifications for ${this.resolvedUserName()}`,
|
|
99
|
+
};
|
|
100
|
+
}, ...(ngDevMode ? [{ debugName: "notificationShortcutConfig" }] : /* istanbul ignore next */ []));
|
|
101
|
+
actionOptions = computed(() => {
|
|
102
|
+
const shortcutValue = this.notificationShortcutConfig()?.value;
|
|
103
|
+
if (!shortcutValue) {
|
|
104
|
+
return this.quickActions();
|
|
105
|
+
}
|
|
106
|
+
return this.quickActions().filter((action) => action.value !== shortcutValue);
|
|
107
|
+
}, ...(ngDevMode ? [{ debugName: "actionOptions" }] : /* istanbul ignore next */ []));
|
|
108
|
+
hostClasses = computed(() => cn('inline-flex shrink-0 items-center gap-2', this.class()), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
109
|
+
resolvedUserName = computed(() => this.userInfo()?.name?.trim() || this.userName(), ...(ngDevMode ? [{ debugName: "resolvedUserName" }] : /* istanbul ignore next */ []));
|
|
110
|
+
resolvedUserSubtitle = computed(() => this.userInfo()?.subtitle ?? this.userSubtitle(), ...(ngDevMode ? [{ debugName: "resolvedUserSubtitle" }] : /* istanbul ignore next */ []));
|
|
111
|
+
resolvedAvatarSrc = computed(() => this.userInfo()?.avatarSrc ?? this.avatarSrc(), ...(ngDevMode ? [{ debugName: "resolvedAvatarSrc" }] : /* istanbul ignore next */ []));
|
|
112
|
+
resolvedAvatarAlt = computed(() => this.userInfo()?.avatarAlt ?? this.avatarAlt(), ...(ngDevMode ? [{ debugName: "resolvedAvatarAlt" }] : /* istanbul ignore next */ []));
|
|
113
|
+
hasAvatar = computed(() => !!this.resolvedAvatarSrc(), ...(ngDevMode ? [{ debugName: "hasAvatar" }] : /* istanbul ignore next */ []));
|
|
114
|
+
avatarImageSrc = computed(() => this.resolvedAvatarSrc() ?? '', ...(ngDevMode ? [{ debugName: "avatarImageSrc" }] : /* istanbul ignore next */ []));
|
|
115
|
+
avatarAltText = computed(() => this.resolvedAvatarAlt() || `${this.resolvedUserName()} avatar`, ...(ngDevMode ? [{ debugName: "avatarAltText" }] : /* istanbul ignore next */ []));
|
|
116
|
+
initials = computed(() => this.toInitials(this.resolvedUserName()), ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
|
|
117
|
+
triggerLabel = computed(() => `Open user info for ${this.resolvedUserName()}`, ...(ngDevMode ? [{ debugName: "triggerLabel" }] : /* istanbul ignore next */ []));
|
|
118
|
+
triggerButtonClasses(open) {
|
|
119
|
+
return cn('relative h-8 w-8 rounded-full p-0 transition-colors duration-150 hover:bg-muted/40 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background', open && 'bg-muted/50');
|
|
120
|
+
}
|
|
121
|
+
notificationButtonClasses() {
|
|
122
|
+
return cn('h-8 w-8 rounded-[var(--etos-layout-frame-radius)] p-0 text-muted-foreground transition-colors duration-150 hover:bg-muted/50 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background');
|
|
123
|
+
}
|
|
124
|
+
segmentedOptionClasses(active) {
|
|
125
|
+
return cn('h-10 rounded-[var(--etos-layout-frame-radius)] border border-transparent px-[0.3125rem] py-[0.1875rem] text-foreground transition-colors', active ? 'bg-background shadow-sm' : 'text-muted-foreground hover:bg-background/70');
|
|
126
|
+
}
|
|
127
|
+
themeOptionClasses(active) {
|
|
128
|
+
return this.segmentedOptionClasses(active);
|
|
129
|
+
}
|
|
130
|
+
themeIconClasses(active) {
|
|
131
|
+
return active ? 'text-foreground' : 'text-muted-foreground';
|
|
132
|
+
}
|
|
133
|
+
actionButtonClasses(tone = 'default') {
|
|
134
|
+
return cn('h-12 w-full justify-start gap-2.5 rounded-[var(--etos-layout-frame-radius)] border border-transparent px-2 py-1.5 text-left transition-colors hover:bg-muted/50', tone === 'destructive' && 'hover:bg-destructive/8 focus-visible:ring-destructive/30');
|
|
135
|
+
}
|
|
136
|
+
actionIconClasses(tone = 'default') {
|
|
137
|
+
return tone === 'destructive' ? 'text-destructive' : 'text-foreground';
|
|
138
|
+
}
|
|
139
|
+
actionLabelClasses(tone = 'default') {
|
|
140
|
+
return tone === 'destructive' ? 'text-sm font-medium text-destructive' : 'text-sm font-medium text-foreground';
|
|
141
|
+
}
|
|
142
|
+
setThemeScheme(mode) {
|
|
143
|
+
this.theme.setScheme(mode);
|
|
144
|
+
}
|
|
145
|
+
setLayoutMode(mode) {
|
|
146
|
+
this.layout.setMode(mode);
|
|
147
|
+
}
|
|
148
|
+
setLayoutWidth(width) {
|
|
149
|
+
this.layout.setWidth(width);
|
|
150
|
+
}
|
|
151
|
+
triggerAction(action) {
|
|
152
|
+
this.actionSelected.emit(action);
|
|
153
|
+
this.popoverTrigger().close();
|
|
154
|
+
}
|
|
155
|
+
triggerNotificationAction(event) {
|
|
156
|
+
event.stopPropagation();
|
|
157
|
+
const shortcut = this.notificationShortcutConfig();
|
|
158
|
+
if (!shortcut) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this.actionSelected.emit(shortcut.value);
|
|
162
|
+
}
|
|
163
|
+
labelForLayoutMode(mode) {
|
|
164
|
+
return mode === 'horizontal' ? 'Horizontal' : 'Vertical';
|
|
165
|
+
}
|
|
166
|
+
labelForLayoutWidth(width) {
|
|
167
|
+
return width === 'full' ? 'Full' : 'Fixed';
|
|
168
|
+
}
|
|
169
|
+
toInitials(name) {
|
|
170
|
+
const segments = name.trim().split(/\s+/).filter(Boolean);
|
|
171
|
+
if (segments.length === 0) {
|
|
172
|
+
return 'UI';
|
|
173
|
+
}
|
|
174
|
+
if (segments.length === 1) {
|
|
175
|
+
return segments[0].slice(0, 2).toUpperCase();
|
|
176
|
+
}
|
|
177
|
+
return `${segments[0][0] ?? ''}${segments[1][0] ?? ''}`.toUpperCase();
|
|
178
|
+
}
|
|
179
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosThemeSwitcherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
180
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: EtosThemeSwitcherComponent, isStandalone: true, selector: "etos-theme-switcher", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: false, transformFunction: null }, userName: { classPropertyName: "userName", publicName: "userName", isSignal: true, isRequired: false, transformFunction: null }, userSubtitle: { classPropertyName: "userSubtitle", publicName: "userSubtitle", isSignal: true, isRequired: false, transformFunction: null }, avatarSrc: { classPropertyName: "avatarSrc", publicName: "avatarSrc", isSignal: true, isRequired: false, transformFunction: null }, avatarAlt: { classPropertyName: "avatarAlt", publicName: "avatarAlt", isSignal: true, isRequired: false, transformFunction: null }, quickActions: { classPropertyName: "quickActions", publicName: "quickActions", isSignal: true, isRequired: true, transformFunction: null }, notificationShortcut: { classPropertyName: "notificationShortcut", publicName: "notificationShortcut", isSignal: true, isRequired: false, transformFunction: null }, showNotificationShortcut: { classPropertyName: "showNotificationShortcut", publicName: "showNotificationShortcut", isSignal: true, isRequired: false, transformFunction: null }, popoverSide: { classPropertyName: "popoverSide", publicName: "popoverSide", isSignal: true, isRequired: false, transformFunction: null }, popoverAlign: { classPropertyName: "popoverAlign", publicName: "popoverAlign", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionSelected: "actionSelected" }, host: { properties: { "class": "hostClasses()" } }, viewQueries: [{ propertyName: "popoverTrigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
181
|
+
@if (notificationShortcutConfig(); as shortcut) {
|
|
182
|
+
<button
|
|
183
|
+
type="button"
|
|
184
|
+
ui-button
|
|
185
|
+
variant="ghost"
|
|
186
|
+
size="icon"
|
|
187
|
+
data-trigger-action="notifications"
|
|
188
|
+
[attr.data-value]="shortcut.value"
|
|
189
|
+
[attr.aria-label]="shortcut.ariaLabel"
|
|
190
|
+
[class]="notificationButtonClasses()"
|
|
191
|
+
(click)="triggerNotificationAction($event)">
|
|
192
|
+
<ui-nav-icon [name]="shortcut.icon" [size]="18" class="text-current" />
|
|
193
|
+
</button>
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
<button
|
|
197
|
+
#trigger="uiPopoverTrigger"
|
|
198
|
+
type="button"
|
|
199
|
+
ui-button
|
|
200
|
+
variant="ghost"
|
|
201
|
+
size="icon"
|
|
202
|
+
[uiPopoverTrigger]="preferencesPanel"
|
|
203
|
+
[side]="popoverSide()"
|
|
204
|
+
[align]="popoverAlign()"
|
|
205
|
+
[attr.aria-label]="triggerLabel()"
|
|
206
|
+
[class]="triggerButtonClasses(trigger.isOpen())">
|
|
207
|
+
<ui-avatar class="h-8 w-8 border border-border/60 shadow-[inset_0_1px_0_rgba(255,255,255,0.18)]">
|
|
208
|
+
@if (hasAvatar()) {
|
|
209
|
+
<ui-avatar-image [src]="avatarImageSrc()" [alt]="avatarAltText()" />
|
|
210
|
+
}
|
|
211
|
+
<ui-avatar-fallback class="bg-primary text-xs font-semibold tracking-[0.24em] text-primary-foreground">
|
|
212
|
+
{{ initials() }}
|
|
213
|
+
</ui-avatar-fallback>
|
|
214
|
+
</ui-avatar>
|
|
215
|
+
</button>
|
|
216
|
+
|
|
217
|
+
<ng-template uiPopoverContent #preferencesPanel="uiPopoverContent">
|
|
218
|
+
<section
|
|
219
|
+
data-etos-theme-switcher-panel
|
|
220
|
+
role="dialog"
|
|
221
|
+
aria-label="User Info"
|
|
222
|
+
class="w-[min(21rem,calc(100vw-1.5rem))] overflow-hidden rounded-[var(--etos-layout-frame-radius)] border border-border/70 bg-background text-foreground shadow-[0_18px_48px_rgba(15,23,42,0.12)]">
|
|
223
|
+
<header class="p-5 pb-4">
|
|
224
|
+
<div class="flex items-center gap-4">
|
|
225
|
+
<ui-avatar class="h-14 w-14 border border-border/60 shadow-sm">
|
|
226
|
+
@if (hasAvatar()) {
|
|
227
|
+
<ui-avatar-image [src]="avatarImageSrc()" [alt]="avatarAltText()" />
|
|
228
|
+
}
|
|
229
|
+
<ui-avatar-fallback class="bg-primary text-sm font-semibold tracking-[0.24em] text-primary-foreground">
|
|
230
|
+
{{ initials() }}
|
|
231
|
+
</ui-avatar-fallback>
|
|
232
|
+
</ui-avatar>
|
|
233
|
+
|
|
234
|
+
<div class="min-w-0 flex min-h-14 flex-1 flex-col justify-center self-center">
|
|
235
|
+
<div class="space-y-px">
|
|
236
|
+
<h2 class="truncate text-[1.1rem] font-semibold leading-none tracking-tight text-foreground">
|
|
237
|
+
{{ resolvedUserName() }}
|
|
238
|
+
</h2>
|
|
239
|
+
<p class="text-sm leading-[0.95rem] text-muted-foreground">
|
|
240
|
+
{{ resolvedUserSubtitle() }}
|
|
241
|
+
</p>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</header>
|
|
246
|
+
|
|
247
|
+
<div class="space-y-4 px-5 pb-5">
|
|
248
|
+
<section
|
|
249
|
+
data-setting="theme-scheme"
|
|
250
|
+
[attr.data-current]="themeScheme()"
|
|
251
|
+
class="rounded-[var(--etos-layout-frame-radius)] bg-muted/65 p-0.5">
|
|
252
|
+
<div class="grid grid-cols-3 gap-1">
|
|
253
|
+
@for (option of themeSchemeOptions; track option.value) {
|
|
254
|
+
<button
|
|
255
|
+
type="button"
|
|
256
|
+
ui-button
|
|
257
|
+
size="sm"
|
|
258
|
+
variant="ghost"
|
|
259
|
+
[class]="themeOptionClasses(themeScheme() === option.value)"
|
|
260
|
+
data-setting-option="theme-scheme"
|
|
261
|
+
[attr.data-value]="option.value"
|
|
262
|
+
(click)="setThemeScheme(option.value)">
|
|
263
|
+
<span class="inline-flex items-center gap-2.5">
|
|
264
|
+
<ui-nav-icon
|
|
265
|
+
[name]="option.icon"
|
|
266
|
+
[size]="18"
|
|
267
|
+
[class]="themeIconClasses(themeScheme() === option.value)" />
|
|
268
|
+
<span class="text-sm font-semibold leading-none">{{ option.label }}</span>
|
|
269
|
+
</span>
|
|
270
|
+
</button>
|
|
271
|
+
}
|
|
272
|
+
</div>
|
|
273
|
+
</section>
|
|
274
|
+
|
|
275
|
+
<section data-setting="layout-mode" [attr.data-current]="layoutMode()" class="space-y-2">
|
|
276
|
+
<div class="px-1">
|
|
277
|
+
<p class="text-[0.72rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground">Layout</p>
|
|
278
|
+
</div>
|
|
279
|
+
<div class="rounded-[var(--etos-layout-frame-radius)] bg-muted/65 p-0.5">
|
|
280
|
+
<div class="grid grid-cols-2 gap-1">
|
|
281
|
+
@for (option of layoutModeOptions; track option.value) {
|
|
282
|
+
<button
|
|
283
|
+
type="button"
|
|
284
|
+
ui-button
|
|
285
|
+
size="sm"
|
|
286
|
+
variant="ghost"
|
|
287
|
+
[class]="segmentedOptionClasses(layoutMode() === option.value)"
|
|
288
|
+
data-setting-option="layout-mode"
|
|
289
|
+
[attr.data-value]="option.value"
|
|
290
|
+
(click)="setLayoutMode(option.value)">
|
|
291
|
+
<span class="inline-flex items-center gap-2.5">
|
|
292
|
+
<ui-nav-icon
|
|
293
|
+
[name]="option.icon"
|
|
294
|
+
[size]="18"
|
|
295
|
+
[class]="themeIconClasses(layoutMode() === option.value)" />
|
|
296
|
+
<span class="text-sm font-semibold leading-none">{{ option.label }}</span>
|
|
297
|
+
</span>
|
|
298
|
+
</button>
|
|
299
|
+
}
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
</section>
|
|
303
|
+
|
|
304
|
+
<section data-setting="layout-width" [attr.data-current]="layoutWidth()" class="space-y-2">
|
|
305
|
+
<div class="px-1">
|
|
306
|
+
<p class="text-[0.72rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground">Width</p>
|
|
307
|
+
</div>
|
|
308
|
+
<div class="rounded-[var(--etos-layout-frame-radius)] bg-muted/65 p-0.5">
|
|
309
|
+
<div class="grid grid-cols-2 gap-1">
|
|
310
|
+
@for (option of layoutWidthOptions; track option.value) {
|
|
311
|
+
<button
|
|
312
|
+
type="button"
|
|
313
|
+
ui-button
|
|
314
|
+
size="sm"
|
|
315
|
+
variant="ghost"
|
|
316
|
+
[class]="segmentedOptionClasses(layoutWidth() === option.value)"
|
|
317
|
+
data-setting-option="layout-width"
|
|
318
|
+
[attr.data-value]="option.value"
|
|
319
|
+
(click)="setLayoutWidth(option.value)">
|
|
320
|
+
<span class="inline-flex items-center gap-2.5">
|
|
321
|
+
<ui-nav-icon
|
|
322
|
+
[name]="option.icon"
|
|
323
|
+
[size]="18"
|
|
324
|
+
[class]="themeIconClasses(layoutWidth() === option.value)" />
|
|
325
|
+
<span class="text-sm font-semibold leading-none">{{ option.label }}</span>
|
|
326
|
+
</span>
|
|
327
|
+
</button>
|
|
328
|
+
}
|
|
329
|
+
</div>
|
|
330
|
+
</div>
|
|
331
|
+
</section>
|
|
332
|
+
|
|
333
|
+
<section class="space-y-1 border-t border-border/70 pt-2">
|
|
334
|
+
<h3 class="sr-only">Quick Actions</h3>
|
|
335
|
+
<div class="grid gap-1">
|
|
336
|
+
@for (action of actionOptions(); track action.value) {
|
|
337
|
+
<button
|
|
338
|
+
type="button"
|
|
339
|
+
ui-button
|
|
340
|
+
variant="ghost"
|
|
341
|
+
[class]="actionButtonClasses(action.tone ?? 'default')"
|
|
342
|
+
data-action-option
|
|
343
|
+
[attr.data-value]="action.value"
|
|
344
|
+
(click)="triggerAction(action.value)">
|
|
345
|
+
<span class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-muted/65">
|
|
346
|
+
<ui-nav-icon
|
|
347
|
+
[name]="action.icon"
|
|
348
|
+
[size]="19"
|
|
349
|
+
[class]="actionIconClasses(action.tone ?? 'default')" />
|
|
350
|
+
</span>
|
|
351
|
+
<span [class]="actionLabelClasses(action.tone ?? 'default')">
|
|
352
|
+
{{ action.label }}
|
|
353
|
+
</span>
|
|
354
|
+
</button>
|
|
355
|
+
}
|
|
356
|
+
</div>
|
|
357
|
+
</section>
|
|
358
|
+
</div>
|
|
359
|
+
</section>
|
|
360
|
+
</ng-template>
|
|
361
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AvatarComponent, selector: "ui-avatar", inputs: ["class"] }, { kind: "component", type: AvatarFallbackComponent, selector: "ui-avatar-fallback", inputs: ["class"] }, { kind: "component", type: AvatarImageComponent, selector: "ui-avatar-image", inputs: ["src", "alt", "class"] }, { kind: "component", type: ButtonComponent, selector: "button[ui-button], a[ui-button]", inputs: ["variant", "size", "class"] }, { kind: "directive", type: PopoverContentDirective, selector: "ng-template[uiPopoverContent]", exportAs: ["uiPopoverContent"] }, { kind: "directive", type: PopoverTriggerDirective, selector: "[uiPopoverTrigger]", inputs: ["uiPopoverTrigger", "side", "align", "disabled"], outputs: ["openedChange"], exportAs: ["uiPopoverTrigger"] }, { kind: "component", type: UiNavIconComponent, selector: "ui-nav-icon", inputs: ["name", "class", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
362
|
+
}
|
|
363
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosThemeSwitcherComponent, decorators: [{
|
|
364
|
+
type: Component,
|
|
365
|
+
args: [{
|
|
366
|
+
selector: 'etos-theme-switcher',
|
|
367
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
368
|
+
imports: [
|
|
369
|
+
AvatarComponent,
|
|
370
|
+
AvatarFallbackComponent,
|
|
371
|
+
AvatarImageComponent,
|
|
372
|
+
ButtonComponent,
|
|
373
|
+
PopoverContentDirective,
|
|
374
|
+
PopoverTriggerDirective,
|
|
375
|
+
UiNavIconComponent,
|
|
376
|
+
],
|
|
377
|
+
host: {
|
|
378
|
+
'[class]': 'hostClasses()',
|
|
379
|
+
},
|
|
380
|
+
template: `
|
|
381
|
+
@if (notificationShortcutConfig(); as shortcut) {
|
|
382
|
+
<button
|
|
383
|
+
type="button"
|
|
384
|
+
ui-button
|
|
385
|
+
variant="ghost"
|
|
386
|
+
size="icon"
|
|
387
|
+
data-trigger-action="notifications"
|
|
388
|
+
[attr.data-value]="shortcut.value"
|
|
389
|
+
[attr.aria-label]="shortcut.ariaLabel"
|
|
390
|
+
[class]="notificationButtonClasses()"
|
|
391
|
+
(click)="triggerNotificationAction($event)">
|
|
392
|
+
<ui-nav-icon [name]="shortcut.icon" [size]="18" class="text-current" />
|
|
393
|
+
</button>
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
<button
|
|
397
|
+
#trigger="uiPopoverTrigger"
|
|
398
|
+
type="button"
|
|
399
|
+
ui-button
|
|
400
|
+
variant="ghost"
|
|
401
|
+
size="icon"
|
|
402
|
+
[uiPopoverTrigger]="preferencesPanel"
|
|
403
|
+
[side]="popoverSide()"
|
|
404
|
+
[align]="popoverAlign()"
|
|
405
|
+
[attr.aria-label]="triggerLabel()"
|
|
406
|
+
[class]="triggerButtonClasses(trigger.isOpen())">
|
|
407
|
+
<ui-avatar class="h-8 w-8 border border-border/60 shadow-[inset_0_1px_0_rgba(255,255,255,0.18)]">
|
|
408
|
+
@if (hasAvatar()) {
|
|
409
|
+
<ui-avatar-image [src]="avatarImageSrc()" [alt]="avatarAltText()" />
|
|
410
|
+
}
|
|
411
|
+
<ui-avatar-fallback class="bg-primary text-xs font-semibold tracking-[0.24em] text-primary-foreground">
|
|
412
|
+
{{ initials() }}
|
|
413
|
+
</ui-avatar-fallback>
|
|
414
|
+
</ui-avatar>
|
|
415
|
+
</button>
|
|
416
|
+
|
|
417
|
+
<ng-template uiPopoverContent #preferencesPanel="uiPopoverContent">
|
|
418
|
+
<section
|
|
419
|
+
data-etos-theme-switcher-panel
|
|
420
|
+
role="dialog"
|
|
421
|
+
aria-label="User Info"
|
|
422
|
+
class="w-[min(21rem,calc(100vw-1.5rem))] overflow-hidden rounded-[var(--etos-layout-frame-radius)] border border-border/70 bg-background text-foreground shadow-[0_18px_48px_rgba(15,23,42,0.12)]">
|
|
423
|
+
<header class="p-5 pb-4">
|
|
424
|
+
<div class="flex items-center gap-4">
|
|
425
|
+
<ui-avatar class="h-14 w-14 border border-border/60 shadow-sm">
|
|
426
|
+
@if (hasAvatar()) {
|
|
427
|
+
<ui-avatar-image [src]="avatarImageSrc()" [alt]="avatarAltText()" />
|
|
428
|
+
}
|
|
429
|
+
<ui-avatar-fallback class="bg-primary text-sm font-semibold tracking-[0.24em] text-primary-foreground">
|
|
430
|
+
{{ initials() }}
|
|
431
|
+
</ui-avatar-fallback>
|
|
432
|
+
</ui-avatar>
|
|
433
|
+
|
|
434
|
+
<div class="min-w-0 flex min-h-14 flex-1 flex-col justify-center self-center">
|
|
435
|
+
<div class="space-y-px">
|
|
436
|
+
<h2 class="truncate text-[1.1rem] font-semibold leading-none tracking-tight text-foreground">
|
|
437
|
+
{{ resolvedUserName() }}
|
|
438
|
+
</h2>
|
|
439
|
+
<p class="text-sm leading-[0.95rem] text-muted-foreground">
|
|
440
|
+
{{ resolvedUserSubtitle() }}
|
|
441
|
+
</p>
|
|
442
|
+
</div>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</header>
|
|
446
|
+
|
|
447
|
+
<div class="space-y-4 px-5 pb-5">
|
|
448
|
+
<section
|
|
449
|
+
data-setting="theme-scheme"
|
|
450
|
+
[attr.data-current]="themeScheme()"
|
|
451
|
+
class="rounded-[var(--etos-layout-frame-radius)] bg-muted/65 p-0.5">
|
|
452
|
+
<div class="grid grid-cols-3 gap-1">
|
|
453
|
+
@for (option of themeSchemeOptions; track option.value) {
|
|
454
|
+
<button
|
|
455
|
+
type="button"
|
|
456
|
+
ui-button
|
|
457
|
+
size="sm"
|
|
458
|
+
variant="ghost"
|
|
459
|
+
[class]="themeOptionClasses(themeScheme() === option.value)"
|
|
460
|
+
data-setting-option="theme-scheme"
|
|
461
|
+
[attr.data-value]="option.value"
|
|
462
|
+
(click)="setThemeScheme(option.value)">
|
|
463
|
+
<span class="inline-flex items-center gap-2.5">
|
|
464
|
+
<ui-nav-icon
|
|
465
|
+
[name]="option.icon"
|
|
466
|
+
[size]="18"
|
|
467
|
+
[class]="themeIconClasses(themeScheme() === option.value)" />
|
|
468
|
+
<span class="text-sm font-semibold leading-none">{{ option.label }}</span>
|
|
469
|
+
</span>
|
|
470
|
+
</button>
|
|
471
|
+
}
|
|
472
|
+
</div>
|
|
473
|
+
</section>
|
|
474
|
+
|
|
475
|
+
<section data-setting="layout-mode" [attr.data-current]="layoutMode()" class="space-y-2">
|
|
476
|
+
<div class="px-1">
|
|
477
|
+
<p class="text-[0.72rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground">Layout</p>
|
|
478
|
+
</div>
|
|
479
|
+
<div class="rounded-[var(--etos-layout-frame-radius)] bg-muted/65 p-0.5">
|
|
480
|
+
<div class="grid grid-cols-2 gap-1">
|
|
481
|
+
@for (option of layoutModeOptions; track option.value) {
|
|
482
|
+
<button
|
|
483
|
+
type="button"
|
|
484
|
+
ui-button
|
|
485
|
+
size="sm"
|
|
486
|
+
variant="ghost"
|
|
487
|
+
[class]="segmentedOptionClasses(layoutMode() === option.value)"
|
|
488
|
+
data-setting-option="layout-mode"
|
|
489
|
+
[attr.data-value]="option.value"
|
|
490
|
+
(click)="setLayoutMode(option.value)">
|
|
491
|
+
<span class="inline-flex items-center gap-2.5">
|
|
492
|
+
<ui-nav-icon
|
|
493
|
+
[name]="option.icon"
|
|
494
|
+
[size]="18"
|
|
495
|
+
[class]="themeIconClasses(layoutMode() === option.value)" />
|
|
496
|
+
<span class="text-sm font-semibold leading-none">{{ option.label }}</span>
|
|
497
|
+
</span>
|
|
498
|
+
</button>
|
|
499
|
+
}
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
</section>
|
|
503
|
+
|
|
504
|
+
<section data-setting="layout-width" [attr.data-current]="layoutWidth()" class="space-y-2">
|
|
505
|
+
<div class="px-1">
|
|
506
|
+
<p class="text-[0.72rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground">Width</p>
|
|
507
|
+
</div>
|
|
508
|
+
<div class="rounded-[var(--etos-layout-frame-radius)] bg-muted/65 p-0.5">
|
|
509
|
+
<div class="grid grid-cols-2 gap-1">
|
|
510
|
+
@for (option of layoutWidthOptions; track option.value) {
|
|
511
|
+
<button
|
|
512
|
+
type="button"
|
|
513
|
+
ui-button
|
|
514
|
+
size="sm"
|
|
515
|
+
variant="ghost"
|
|
516
|
+
[class]="segmentedOptionClasses(layoutWidth() === option.value)"
|
|
517
|
+
data-setting-option="layout-width"
|
|
518
|
+
[attr.data-value]="option.value"
|
|
519
|
+
(click)="setLayoutWidth(option.value)">
|
|
520
|
+
<span class="inline-flex items-center gap-2.5">
|
|
521
|
+
<ui-nav-icon
|
|
522
|
+
[name]="option.icon"
|
|
523
|
+
[size]="18"
|
|
524
|
+
[class]="themeIconClasses(layoutWidth() === option.value)" />
|
|
525
|
+
<span class="text-sm font-semibold leading-none">{{ option.label }}</span>
|
|
526
|
+
</span>
|
|
527
|
+
</button>
|
|
528
|
+
}
|
|
529
|
+
</div>
|
|
530
|
+
</div>
|
|
531
|
+
</section>
|
|
532
|
+
|
|
533
|
+
<section class="space-y-1 border-t border-border/70 pt-2">
|
|
534
|
+
<h3 class="sr-only">Quick Actions</h3>
|
|
535
|
+
<div class="grid gap-1">
|
|
536
|
+
@for (action of actionOptions(); track action.value) {
|
|
537
|
+
<button
|
|
538
|
+
type="button"
|
|
539
|
+
ui-button
|
|
540
|
+
variant="ghost"
|
|
541
|
+
[class]="actionButtonClasses(action.tone ?? 'default')"
|
|
542
|
+
data-action-option
|
|
543
|
+
[attr.data-value]="action.value"
|
|
544
|
+
(click)="triggerAction(action.value)">
|
|
545
|
+
<span class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-muted/65">
|
|
546
|
+
<ui-nav-icon
|
|
547
|
+
[name]="action.icon"
|
|
548
|
+
[size]="19"
|
|
549
|
+
[class]="actionIconClasses(action.tone ?? 'default')" />
|
|
550
|
+
</span>
|
|
551
|
+
<span [class]="actionLabelClasses(action.tone ?? 'default')">
|
|
552
|
+
{{ action.label }}
|
|
553
|
+
</span>
|
|
554
|
+
</button>
|
|
555
|
+
}
|
|
556
|
+
</div>
|
|
557
|
+
</section>
|
|
558
|
+
</div>
|
|
559
|
+
</section>
|
|
560
|
+
</ng-template>
|
|
561
|
+
`,
|
|
562
|
+
}]
|
|
563
|
+
}], propDecorators: { popoverTrigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], userInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "userInfo", required: false }] }], userName: [{ type: i0.Input, args: [{ isSignal: true, alias: "userName", required: false }] }], userSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "userSubtitle", required: false }] }], avatarSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarSrc", required: false }] }], avatarAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarAlt", required: false }] }], quickActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActions", required: true }] }], notificationShortcut: [{ type: i0.Input, args: [{ isSignal: true, alias: "notificationShortcut", required: false }] }], showNotificationShortcut: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNotificationShortcut", required: false }] }], popoverSide: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverSide", required: false }] }], popoverAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverAlign", required: false }] }], actionSelected: [{ type: i0.Output, args: ["actionSelected"] }] } });
|
|
564
|
+
|
|
565
|
+
class EtosEmptyLayoutComponent {
|
|
566
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosEmptyLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
567
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: EtosEmptyLayoutComponent, isStandalone: true, selector: "etos-empty-layout", host: { attributes: { "data-brand-layout": "etos-empty" }, classAttribute: "etos-layout-empty-host" }, ngImport: i0, template: `
|
|
568
|
+
<main class="etos-layout-empty-main">
|
|
569
|
+
<router-outlet />
|
|
570
|
+
</main>
|
|
571
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
572
|
+
}
|
|
573
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosEmptyLayoutComponent, decorators: [{
|
|
574
|
+
type: Component,
|
|
575
|
+
args: [{
|
|
576
|
+
selector: 'etos-empty-layout',
|
|
577
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
578
|
+
imports: [RouterOutlet],
|
|
579
|
+
host: {
|
|
580
|
+
class: 'etos-layout-empty-host',
|
|
581
|
+
'data-brand-layout': 'etos-empty',
|
|
582
|
+
},
|
|
583
|
+
template: `
|
|
584
|
+
<main class="etos-layout-empty-main">
|
|
585
|
+
<router-outlet />
|
|
586
|
+
</main>
|
|
587
|
+
`,
|
|
588
|
+
}]
|
|
589
|
+
}] });
|
|
590
|
+
|
|
591
|
+
class EtosHorizontalLayoutComponent {
|
|
592
|
+
layout = inject(LayoutService);
|
|
593
|
+
topbarAppearance = input('default', ...(ngDevMode ? [{ debugName: "topbarAppearance" }] : /* istanbul ignore next */ []));
|
|
594
|
+
ariaLabel = input('Primary', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
595
|
+
brandLayout = 'etos-horizontal';
|
|
596
|
+
layoutWidth = this.layout.width;
|
|
597
|
+
dividerBorderWidth = computed(() => 'var(--border-width)', ...(ngDevMode ? [{ debugName: "dividerBorderWidth" }] : /* istanbul ignore next */ []));
|
|
598
|
+
hostClasses = computed(() => {
|
|
599
|
+
const classes = ['etos-layout-host', 'etos-layout-host--horizontal'];
|
|
600
|
+
if (this.layoutWidth() === 'fixed') {
|
|
601
|
+
classes.push('etos-layout-host--fixed');
|
|
602
|
+
}
|
|
603
|
+
return classes.join(' ');
|
|
604
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
605
|
+
frameClasses = computed(() => {
|
|
606
|
+
const classes = ['etos-layout-frame', 'etos-layout-frame--horizontal'];
|
|
607
|
+
if (this.layoutWidth() === 'fixed') {
|
|
608
|
+
classes.push('etos-layout-frame--fixed');
|
|
609
|
+
}
|
|
610
|
+
return classes.join(' ');
|
|
611
|
+
}, ...(ngDevMode ? [{ debugName: "frameClasses" }] : /* istanbul ignore next */ []));
|
|
612
|
+
mainClasses = computed(() => {
|
|
613
|
+
const classes = ['etos-layout-main'];
|
|
614
|
+
if (this.layoutWidth() === 'fixed') {
|
|
615
|
+
classes.push('etos-layout-main--fixed');
|
|
616
|
+
}
|
|
617
|
+
return classes.join(' ');
|
|
618
|
+
}, ...(ngDevMode ? [{ debugName: "mainClasses" }] : /* istanbul ignore next */ []));
|
|
619
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosHorizontalLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
620
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: EtosHorizontalLayoutComponent, isStandalone: true, selector: "etos-horizontal-layout", inputs: { topbarAppearance: { classPropertyName: "topbarAppearance", publicName: "topbarAppearance", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.data-brand-layout": "brandLayout", "attr.data-layout-width": "layoutWidth()" } }, ngImport: i0, template: `
|
|
621
|
+
<div [class]="frameClasses()">
|
|
622
|
+
<ui-topbar
|
|
623
|
+
class="etos-layout-topbar"
|
|
624
|
+
[appearance]="topbarAppearance()"
|
|
625
|
+
[ariaLabel]="ariaLabel()"
|
|
626
|
+
[style.border-bottom-width]="dividerBorderWidth()">
|
|
627
|
+
<div ui-topbar-start class="etos-layout-topbar-slot etos-layout-topbar-slot--start">
|
|
628
|
+
<ng-content select="[ui-layout-brand],[ui-topbar-start]" />
|
|
629
|
+
</div>
|
|
630
|
+
<div ui-topbar-end class="etos-layout-topbar-slot etos-layout-topbar-slot--end">
|
|
631
|
+
<ng-content select="[ui-layout-profile],[ui-topbar-end]" />
|
|
632
|
+
</div>
|
|
633
|
+
</ui-topbar>
|
|
634
|
+
<main [class]="mainClasses()">
|
|
635
|
+
<router-outlet />
|
|
636
|
+
</main>
|
|
637
|
+
</div>
|
|
638
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: TopbarComponent, selector: "ui-topbar", inputs: ["items", "navigationId", "appearance", "ariaLabel", "class", "autoRegister", "showHamburger", "hamburgerLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
639
|
+
}
|
|
640
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosHorizontalLayoutComponent, decorators: [{
|
|
641
|
+
type: Component,
|
|
642
|
+
args: [{
|
|
643
|
+
selector: 'etos-horizontal-layout',
|
|
644
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
645
|
+
imports: [RouterOutlet, TopbarComponent],
|
|
646
|
+
host: {
|
|
647
|
+
'[class]': 'hostClasses()',
|
|
648
|
+
'[attr.data-brand-layout]': 'brandLayout',
|
|
649
|
+
'[attr.data-layout-width]': 'layoutWidth()',
|
|
650
|
+
},
|
|
651
|
+
template: `
|
|
652
|
+
<div [class]="frameClasses()">
|
|
653
|
+
<ui-topbar
|
|
654
|
+
class="etos-layout-topbar"
|
|
655
|
+
[appearance]="topbarAppearance()"
|
|
656
|
+
[ariaLabel]="ariaLabel()"
|
|
657
|
+
[style.border-bottom-width]="dividerBorderWidth()">
|
|
658
|
+
<div ui-topbar-start class="etos-layout-topbar-slot etos-layout-topbar-slot--start">
|
|
659
|
+
<ng-content select="[ui-layout-brand],[ui-topbar-start]" />
|
|
660
|
+
</div>
|
|
661
|
+
<div ui-topbar-end class="etos-layout-topbar-slot etos-layout-topbar-slot--end">
|
|
662
|
+
<ng-content select="[ui-layout-profile],[ui-topbar-end]" />
|
|
663
|
+
</div>
|
|
664
|
+
</ui-topbar>
|
|
665
|
+
<main [class]="mainClasses()">
|
|
666
|
+
<router-outlet />
|
|
667
|
+
</main>
|
|
668
|
+
</div>
|
|
669
|
+
`,
|
|
670
|
+
}]
|
|
671
|
+
}], propDecorators: { topbarAppearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarAppearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
672
|
+
|
|
673
|
+
class EtosVerticalLayoutComponent {
|
|
674
|
+
layout = inject(LayoutService);
|
|
675
|
+
sidebarAppearance = input('default', ...(ngDevMode ? [{ debugName: "sidebarAppearance" }] : /* istanbul ignore next */ []));
|
|
676
|
+
sidebarPosition = input('left', ...(ngDevMode ? [{ debugName: "sidebarPosition" }] : /* istanbul ignore next */ []));
|
|
677
|
+
ariaLabel = input('Primary', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
678
|
+
brandLayout = 'etos-vertical';
|
|
679
|
+
layoutWidth = this.layout.width;
|
|
680
|
+
dividerBorderWidth = computed(() => 'var(--border-width)', ...(ngDevMode ? [{ debugName: "dividerBorderWidth" }] : /* istanbul ignore next */ []));
|
|
681
|
+
hostClasses = computed(() => {
|
|
682
|
+
const classes = ['etos-layout-host', 'etos-layout-host--vertical'];
|
|
683
|
+
if (this.layoutWidth() === 'fixed') {
|
|
684
|
+
classes.push('etos-layout-host--fixed');
|
|
685
|
+
}
|
|
686
|
+
return classes.join(' ');
|
|
687
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
688
|
+
frameClasses = computed(() => {
|
|
689
|
+
const classes = ['etos-layout-frame', 'etos-layout-frame--vertical'];
|
|
690
|
+
if (this.layoutWidth() === 'fixed') {
|
|
691
|
+
classes.push('etos-layout-frame--fixed', 'etos-layout-frame--vertical-fixed');
|
|
692
|
+
}
|
|
693
|
+
return classes.join(' ');
|
|
694
|
+
}, ...(ngDevMode ? [{ debugName: "frameClasses" }] : /* istanbul ignore next */ []));
|
|
695
|
+
mainClasses = computed(() => {
|
|
696
|
+
const classes = ['etos-layout-main'];
|
|
697
|
+
if (this.layoutWidth() === 'fixed') {
|
|
698
|
+
classes.push('etos-layout-main--fixed', 'etos-layout-main--vertical-fixed');
|
|
699
|
+
}
|
|
700
|
+
return classes.join(' ');
|
|
701
|
+
}, ...(ngDevMode ? [{ debugName: "mainClasses" }] : /* istanbul ignore next */ []));
|
|
702
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosVerticalLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
703
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: EtosVerticalLayoutComponent, isStandalone: true, selector: "etos-vertical-layout", inputs: { sidebarAppearance: { classPropertyName: "sidebarAppearance", publicName: "sidebarAppearance", isSignal: true, isRequired: false, transformFunction: null }, sidebarPosition: { classPropertyName: "sidebarPosition", publicName: "sidebarPosition", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.data-brand-layout": "brandLayout", "attr.data-layout-width": "layoutWidth()" } }, ngImport: i0, template: `
|
|
704
|
+
<div [class]="frameClasses()">
|
|
705
|
+
<ui-sidebar
|
|
706
|
+
class="etos-layout-sidebar"
|
|
707
|
+
[appearance]="sidebarAppearance()"
|
|
708
|
+
[position]="sidebarPosition()"
|
|
709
|
+
[ariaLabel]="ariaLabel()"
|
|
710
|
+
[style.border-left-width]="dividerBorderWidth()"
|
|
711
|
+
[style.border-right-width]="dividerBorderWidth()">
|
|
712
|
+
<div ui-sidebar-header class="flex h-full w-full min-w-0 items-center">
|
|
713
|
+
<ng-content select="[ui-layout-brand],[ui-topbar-start],[ui-sidebar-header]" />
|
|
714
|
+
</div>
|
|
715
|
+
|
|
716
|
+
<div ui-sidebar-footer class="flex h-full w-full min-w-0 items-center justify-between gap-3 px-3">
|
|
717
|
+
<ng-content select="[ui-layout-profile],[ui-topbar-end],[ui-sidebar-footer]" />
|
|
718
|
+
</div>
|
|
719
|
+
</ui-sidebar>
|
|
720
|
+
<main [class]="mainClasses()">
|
|
721
|
+
<router-outlet />
|
|
722
|
+
</main>
|
|
723
|
+
</div>
|
|
724
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: SidebarComponent, selector: "ui-sidebar", inputs: ["items", "navigationId", "appearance", "position", "ariaLabel", "header", "class", "autoMobile", "autoRegister"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
725
|
+
}
|
|
726
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosVerticalLayoutComponent, decorators: [{
|
|
727
|
+
type: Component,
|
|
728
|
+
args: [{
|
|
729
|
+
selector: 'etos-vertical-layout',
|
|
730
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
731
|
+
imports: [RouterOutlet, SidebarComponent],
|
|
732
|
+
host: {
|
|
733
|
+
'[class]': 'hostClasses()',
|
|
734
|
+
'[attr.data-brand-layout]': 'brandLayout',
|
|
735
|
+
'[attr.data-layout-width]': 'layoutWidth()',
|
|
736
|
+
},
|
|
737
|
+
template: `
|
|
738
|
+
<div [class]="frameClasses()">
|
|
739
|
+
<ui-sidebar
|
|
740
|
+
class="etos-layout-sidebar"
|
|
741
|
+
[appearance]="sidebarAppearance()"
|
|
742
|
+
[position]="sidebarPosition()"
|
|
743
|
+
[ariaLabel]="ariaLabel()"
|
|
744
|
+
[style.border-left-width]="dividerBorderWidth()"
|
|
745
|
+
[style.border-right-width]="dividerBorderWidth()">
|
|
746
|
+
<div ui-sidebar-header class="flex h-full w-full min-w-0 items-center">
|
|
747
|
+
<ng-content select="[ui-layout-brand],[ui-topbar-start],[ui-sidebar-header]" />
|
|
748
|
+
</div>
|
|
749
|
+
|
|
750
|
+
<div ui-sidebar-footer class="flex h-full w-full min-w-0 items-center justify-between gap-3 px-3">
|
|
751
|
+
<ng-content select="[ui-layout-profile],[ui-topbar-end],[ui-sidebar-footer]" />
|
|
752
|
+
</div>
|
|
753
|
+
</ui-sidebar>
|
|
754
|
+
<main [class]="mainClasses()">
|
|
755
|
+
<router-outlet />
|
|
756
|
+
</main>
|
|
757
|
+
</div>
|
|
758
|
+
`,
|
|
759
|
+
}]
|
|
760
|
+
}], propDecorators: { sidebarAppearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarAppearance", required: false }] }], sidebarPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarPosition", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
761
|
+
|
|
762
|
+
class EtosLayoutComponent {
|
|
763
|
+
layout = inject(LayoutService);
|
|
764
|
+
ariaLabel = input('Primary', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
765
|
+
layoutMode = this.layout.mode;
|
|
766
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
767
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: EtosLayoutComponent, isStandalone: true, selector: "etos-layout", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
768
|
+
@switch (layoutMode()) {
|
|
769
|
+
@case ('horizontal') {
|
|
770
|
+
<etos-horizontal-layout [ariaLabel]="ariaLabel()">
|
|
771
|
+
<ng-content select="[ui-layout-brand],[ui-topbar-start]" />
|
|
772
|
+
<ng-content select="[ui-layout-profile],[ui-topbar-end]" />
|
|
773
|
+
</etos-horizontal-layout>
|
|
774
|
+
}
|
|
775
|
+
@default {
|
|
776
|
+
<etos-vertical-layout [ariaLabel]="ariaLabel()" />
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
`, isInline: true, dependencies: [{ kind: "component", type: EtosHorizontalLayoutComponent, selector: "etos-horizontal-layout", inputs: ["topbarAppearance", "ariaLabel"] }, { kind: "component", type: EtosVerticalLayoutComponent, selector: "etos-vertical-layout", inputs: ["sidebarAppearance", "sidebarPosition", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
780
|
+
}
|
|
781
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EtosLayoutComponent, decorators: [{
|
|
782
|
+
type: Component,
|
|
783
|
+
args: [{
|
|
784
|
+
selector: 'etos-layout',
|
|
785
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
786
|
+
imports: [EtosHorizontalLayoutComponent, EtosVerticalLayoutComponent],
|
|
787
|
+
host: {
|
|
788
|
+
class: 'contents',
|
|
789
|
+
},
|
|
790
|
+
template: `
|
|
791
|
+
@switch (layoutMode()) {
|
|
792
|
+
@case ('horizontal') {
|
|
793
|
+
<etos-horizontal-layout [ariaLabel]="ariaLabel()">
|
|
794
|
+
<ng-content select="[ui-layout-brand],[ui-topbar-start]" />
|
|
795
|
+
<ng-content select="[ui-layout-profile],[ui-topbar-end]" />
|
|
796
|
+
</etos-horizontal-layout>
|
|
797
|
+
}
|
|
798
|
+
@default {
|
|
799
|
+
<etos-vertical-layout [ariaLabel]="ariaLabel()" />
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
`,
|
|
803
|
+
}]
|
|
804
|
+
}], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
2
805
|
|
|
3
806
|
/*
|
|
4
807
|
* Public API Surface of @ojiepermana/angular/etos
|
|
5
808
|
*
|
|
6
|
-
* Etos-specific implementation
|
|
809
|
+
* Etos-specific implementation lives directly under projects/angular/etos.
|
|
7
810
|
*/
|
|
811
|
+
const ETOS_BRAND_VERSION = '0.0.1';
|
|
8
812
|
|
|
9
813
|
/**
|
|
10
814
|
* Generated bundle index. Do not edit.
|
|
11
815
|
*/
|
|
816
|
+
|
|
817
|
+
export { ETOS_BRAND_NAME, ETOS_BRAND_VERSION, ETOS_LAYOUT_CONFIG, ETOS_THEME_CONFIG, EtosEmptyLayoutComponent, EtosHorizontalLayoutComponent, EtosLayoutComponent, EtosThemeSwitcherComponent, EtosVerticalLayoutComponent, provideEtosBrand, provideEtosLayout, provideEtosTheme };
|
|
12
818
|
//# sourceMappingURL=ojiepermana-angular-etos.mjs.map
|