@ojiepermana/angular-theme 22.0.36 → 22.0.43

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.
Files changed (46) hide show
  1. package/README.md +25 -12
  2. package/fesm2022/ojiepermana-angular-theme-layout-types.mjs +10 -1
  3. package/fesm2022/ojiepermana-angular-theme-layout-wrapper.mjs +72 -22
  4. package/fesm2022/ojiepermana-angular-theme-layout.mjs +117 -45
  5. package/fesm2022/ojiepermana-angular-theme-page.mjs +251 -101
  6. package/fesm2022/ojiepermana-angular-theme-styles.mjs +19 -0
  7. package/layout/README.md +41 -36
  8. package/package.json +3 -3
  9. package/page/README.md +53 -15
  10. package/styles/README.md +11 -3
  11. package/styles/css/base/components.css +212 -0
  12. package/styles/css/base/theme.css +117 -49
  13. package/styles/css/base/tokens.css +98 -48
  14. package/styles/css/color/amber.css +2 -0
  15. package/styles/css/color/blue.css +2 -0
  16. package/styles/css/color/cyan.css +2 -0
  17. package/styles/css/color/emerald.css +2 -0
  18. package/styles/css/color/fuchsia.css +2 -0
  19. package/styles/css/color/green.css +2 -0
  20. package/styles/css/color/indigo.css +2 -0
  21. package/styles/css/color/lime.css +2 -0
  22. package/styles/css/color/orange.css +2 -0
  23. package/styles/css/color/pink.css +2 -0
  24. package/styles/css/color/purple.css +2 -0
  25. package/styles/css/color/red.css +2 -0
  26. package/styles/css/color/rose.css +2 -0
  27. package/styles/css/color/sky.css +2 -0
  28. package/styles/css/color/teal.css +2 -0
  29. package/styles/css/color/violet.css +2 -0
  30. package/styles/css/color/yellow.css +2 -0
  31. package/styles/css/neutral/gray.css +2 -0
  32. package/styles/css/neutral/mauve.css +2 -0
  33. package/styles/css/neutral/mist.css +2 -0
  34. package/styles/css/neutral/neutral.css +2 -0
  35. package/styles/css/neutral/olive.css +2 -0
  36. package/styles/css/neutral/slate.css +2 -0
  37. package/styles/css/neutral/stone.css +2 -0
  38. package/styles/css/neutral/taupe.css +2 -0
  39. package/styles/css/neutral/zinc.css +2 -0
  40. package/styles/css/space/index.css +6 -3
  41. package/types/ojiepermana-angular-theme-layout-services.d.ts +1 -1
  42. package/types/ojiepermana-angular-theme-layout-types.d.ts +1 -1
  43. package/types/ojiepermana-angular-theme-layout-wrapper.d.ts +40 -7
  44. package/types/ojiepermana-angular-theme-layout.d.ts +4 -2
  45. package/types/ojiepermana-angular-theme-page.d.ts +88 -36
  46. package/types/ojiepermana-angular-theme-styles.d.ts +1 -0
@@ -1,6 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, Injectable, inject, input, effect, untracked, ChangeDetectionStrategy, Component, contentChild, output } from '@angular/core';
2
+ import { signal, computed, Injectable, inject, input, ChangeDetectionStrategy, Component, effect, untracked, contentChild, output, booleanAttribute } from '@angular/core';
3
3
  import { cn } from '@ojiepermana/angular-component/utils';
4
+ import { NavigationContainerComponent, NavigationFlyoutComponent, NavigationHeaderComponent, NavigationFooterComponent } from '@ojiepermana/angular-navigation';
5
+ import { NavigationService } from '@ojiepermana/angular-navigation/service';
6
+ import { LayoutService } from '@ojiepermana/angular-theme/layout';
7
+ import { LayoutIdentityService, LayoutBrand, LayoutUser } from '@ojiepermana/angular-theme/layout/wrapper';
4
8
  import { DOCUMENT } from '@angular/common';
5
9
 
6
10
  const PAGE_VARIANTS = ['stacked', 'side'];
@@ -8,11 +12,14 @@ const PAGE_SIDE_POSITIONS = ['left', 'right'];
8
12
  const PAGE_SIDE_MODES = ['sticky', 'drawer', 'overlay'];
9
13
  const PAGE_SCROLL_VALUES = ['content', 'page'];
10
14
  const PAGE_HEIGHT_VALUES = ['auto', 'fix'];
15
+ /** Visual appearance shared with the layout/navigation axes — unifies borders. */
16
+ const PAGE_APPEARANCES = ['flat', 'border-rail'];
11
17
  const PAGE_DEFAULT_VARIANT = 'stacked';
12
18
  const PAGE_DEFAULT_SIDE_POSITION = 'left';
13
19
  const PAGE_DEFAULT_SIDE_MODE = 'sticky';
14
20
  const PAGE_DEFAULT_SCROLL = 'content';
15
21
  const PAGE_DEFAULT_HEIGHT = 'auto';
22
+ const PAGE_DEFAULT_APPEARANCE = 'flat';
16
23
  const PAGE_DEFAULT_SIDE_WIDTH = '16rem';
17
24
  function isUiPageVariant(value) {
18
25
  return value !== null && PAGE_VARIANTS.includes(value);
@@ -29,6 +36,9 @@ function isUiPageScroll(value) {
29
36
  function isUiPageHeight(value) {
30
37
  return value !== null && PAGE_HEIGHT_VALUES.includes(value);
31
38
  }
39
+ function isUiPageAppearance(value) {
40
+ return value !== null && PAGE_APPEARANCES.includes(value);
41
+ }
32
42
 
33
43
  class PageStateService {
34
44
  variantState = signal(PAGE_DEFAULT_VARIANT, /* @ts-ignore */
@@ -37,6 +47,8 @@ class PageStateService {
37
47
  ...(ngDevMode ? [{ debugName: "heightState" }] : /* istanbul ignore next */ []));
38
48
  scrollState = signal(PAGE_DEFAULT_SCROLL, /* @ts-ignore */
39
49
  ...(ngDevMode ? [{ debugName: "scrollState" }] : /* istanbul ignore next */ []));
50
+ appearanceState = signal(PAGE_DEFAULT_APPEARANCE, /* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "appearanceState" }] : /* istanbul ignore next */ []));
40
52
  positionState = signal(PAGE_DEFAULT_SIDE_POSITION, /* @ts-ignore */
41
53
  ...(ngDevMode ? [{ debugName: "positionState" }] : /* istanbul ignore next */ []));
42
54
  sideModeState = signal(PAGE_DEFAULT_SIDE_MODE, /* @ts-ignore */
@@ -53,15 +65,20 @@ class PageStateService {
53
65
  ...(ngDevMode ? [{ debugName: "sideOpenRequestState" }] : /* istanbul ignore next */ []));
54
66
  sideOpenRequestVersionState = signal(0, /* @ts-ignore */
55
67
  ...(ngDevMode ? [{ debugName: "sideOpenRequestVersionState" }] : /* istanbul ignore next */ []));
68
+ /** Aktif saat apps-launcher mengambang di atas `PageHeader`; header memesan ruang kanan agar isinya tidak tertimpa. */
69
+ appsLauncherReserveState = signal(false, /* @ts-ignore */
70
+ ...(ngDevMode ? [{ debugName: "appsLauncherReserveState" }] : /* istanbul ignore next */ []));
56
71
  variant = this.variantState.asReadonly();
57
72
  height = this.heightState.asReadonly();
58
73
  scroll = this.scrollState.asReadonly();
74
+ appearance = this.appearanceState.asReadonly();
59
75
  position = this.positionState.asReadonly();
60
76
  sideMode = this.sideModeState.asReadonly();
61
77
  sideWidth = this.sideWidthState.asReadonly();
62
78
  sideId = this.sideIdState.asReadonly();
63
79
  sideOpenRequest = this.sideOpenRequestState.asReadonly();
64
80
  sideOpenRequestVersion = this.sideOpenRequestVersionState.asReadonly();
81
+ appsLauncherReserve = this.appsLauncherReserveState.asReadonly();
65
82
  sideOpen = computed(() => this.controlledSideOpenState() ?? this.internalSideOpenState(), /* @ts-ignore */
66
83
  ...(ngDevMode ? [{ debugName: "sideOpen" }] : /* istanbul ignore next */ []));
67
84
  isSideInteractive = computed(() => this.sideMode() === 'drawer' || this.sideMode() === 'overlay', /* @ts-ignore */
@@ -72,6 +89,7 @@ class PageStateService {
72
89
  this.variantState.set(config.variant);
73
90
  this.heightState.set(config.height);
74
91
  this.scrollState.set(config.scroll);
92
+ this.appearanceState.set(config.appearance);
75
93
  this.positionState.set(config.position);
76
94
  this.sideModeState.set(config.sideMode);
77
95
  this.sideWidthState.set(config.sideWidth);
@@ -82,6 +100,9 @@ class PageStateService {
82
100
  this.sideWidthState.set(config.width);
83
101
  this.sideIdState.set(config.id);
84
102
  }
103
+ setAppsLauncherReserve(reserve) {
104
+ this.appsLauncherReserveState.set(reserve);
105
+ }
85
106
  setControlledSideOpen(open) {
86
107
  this.controlledSideOpenState.set(open);
87
108
  if (open !== null) {
@@ -115,6 +136,119 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImpor
115
136
  type: Injectable
116
137
  }] });
117
138
 
139
+ function buildPageBodyClasses(scroll, customClass) {
140
+ return cn('block min-w-0', scroll === 'content' && 'h-full min-h-0 overflow-auto', scroll === 'page' && 'overflow-visible', customClass);
141
+ }
142
+ class PageHeaderComponent {
143
+ page = inject(PageStateService, { optional: true });
144
+ class = input('', /* @ts-ignore */
145
+ ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
146
+ resolvedHeight = computed(() => this.page?.height() ?? PAGE_DEFAULT_HEIGHT, /* @ts-ignore */
147
+ ...(ngDevMode ? [{ debugName: "resolvedHeight" }] : /* istanbul ignore next */ []));
148
+ isBorderRail = computed(() => (this.page?.appearance() ?? PAGE_DEFAULT_APPEARANCE) === 'border-rail', /* @ts-ignore */
149
+ ...(ngDevMode ? [{ debugName: "isBorderRail" }] : /* istanbul ignore next */ []));
150
+ /** Saat tombol apps mengambang di atas header, sisakan ruang kanan agar isi header tidak tertimpa. */
151
+ reservesAppsLauncher = computed(() => this.page?.appsLauncherReserve() ?? false, /* @ts-ignore */
152
+ ...(ngDevMode ? [{ debugName: "reservesAppsLauncher" }] : /* istanbul ignore next */ []));
153
+ /** Lebar tombol apps (h-9 w-9 = 36px) + offset kanan (right-2 = 8px) + jarak aman; `null` = tak memesan. */
154
+ appsLauncherReservePadding = computed(() => this.reservesAppsLauncher() ? '3.5rem' : null, /* @ts-ignore */
155
+ ...(ngDevMode ? [{ debugName: "appsLauncherReservePadding" }] : /* istanbul ignore next */ []));
156
+ classes = computed(() => cn('block shrink-0 border-border bg-background',
157
+ // appearance unifies the border with the layout/nav: border-rail = 1.5px.
158
+ this.isBorderRail() ? 'border-b-[1.5px]' : 'border-b', this.class(), this.resolvedHeight() === 'fix' && 'h-12 overflow-hidden'), /* @ts-ignore */
159
+ ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
160
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
161
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageHeaderComponent, isStandalone: true, selector: "PageHeader", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "header" }, properties: { "class": "classes()", "style.padding-right": "appsLauncherReservePadding()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
162
+ }
163
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageHeaderComponent, decorators: [{
164
+ type: Component,
165
+ args: [{
166
+ selector: 'PageHeader',
167
+ changeDetection: ChangeDetectionStrategy.OnPush,
168
+ host: {
169
+ '[class]': 'classes()',
170
+ // Inline style menang atas utility responsif konsumen (mis. `md:px-6`), jadi ruang
171
+ // untuk tombol apps yang mengambang tetap terjamin di semua breakpoint.
172
+ '[style.padding-right]': 'appsLauncherReservePadding()',
173
+ 'data-page-slot': 'header',
174
+ },
175
+ template: `<ng-content />`,
176
+ }]
177
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
178
+ class PageContentComponent {
179
+ page = inject(PageStateService, { optional: true });
180
+ class = input('', /* @ts-ignore */
181
+ ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
182
+ resolvedScroll = computed(() => this.page?.scroll() ?? PAGE_DEFAULT_SCROLL, /* @ts-ignore */
183
+ ...(ngDevMode ? [{ debugName: "resolvedScroll" }] : /* istanbul ignore next */ []));
184
+ classes = computed(() => buildPageBodyClasses(this.resolvedScroll(), this.class()), /* @ts-ignore */
185
+ ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
186
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
187
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageContentComponent, isStandalone: true, selector: "PageContent", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "content" }, properties: { "class": "classes()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
188
+ }
189
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageContentComponent, decorators: [{
190
+ type: Component,
191
+ args: [{
192
+ selector: 'PageContent',
193
+ changeDetection: ChangeDetectionStrategy.OnPush,
194
+ host: {
195
+ '[class]': 'classes()',
196
+ 'data-page-slot': 'content',
197
+ },
198
+ template: `<ng-content />`,
199
+ }]
200
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
201
+ class PageDashboardComponent {
202
+ page = inject(PageStateService, { optional: true });
203
+ class = input('', /* @ts-ignore */
204
+ ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
205
+ resolvedScroll = computed(() => this.page?.scroll() ?? PAGE_DEFAULT_SCROLL, /* @ts-ignore */
206
+ ...(ngDevMode ? [{ debugName: "resolvedScroll" }] : /* istanbul ignore next */ []));
207
+ classes = computed(() => buildPageBodyClasses(this.resolvedScroll(), this.class()), /* @ts-ignore */
208
+ ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
209
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageDashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
210
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageDashboardComponent, isStandalone: true, selector: "PageDashboard", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "dashboard" }, properties: { "class": "classes()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
211
+ }
212
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageDashboardComponent, decorators: [{
213
+ type: Component,
214
+ args: [{
215
+ selector: 'PageDashboard',
216
+ changeDetection: ChangeDetectionStrategy.OnPush,
217
+ host: {
218
+ '[class]': 'classes()',
219
+ 'data-page-slot': 'dashboard',
220
+ },
221
+ template: `<ng-content />`,
222
+ }]
223
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
224
+ class PageFooterComponent {
225
+ page = inject(PageStateService, { optional: true });
226
+ class = input('', /* @ts-ignore */
227
+ ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
228
+ resolvedHeight = computed(() => this.page?.height() ?? PAGE_DEFAULT_HEIGHT, /* @ts-ignore */
229
+ ...(ngDevMode ? [{ debugName: "resolvedHeight" }] : /* istanbul ignore next */ []));
230
+ isBorderRail = computed(() => (this.page?.appearance() ?? PAGE_DEFAULT_APPEARANCE) === 'border-rail', /* @ts-ignore */
231
+ ...(ngDevMode ? [{ debugName: "isBorderRail" }] : /* istanbul ignore next */ []));
232
+ classes = computed(() => cn('block shrink-0 border-border bg-background',
233
+ // appearance unifies the border with the layout/nav: border-rail = 1.5px.
234
+ this.isBorderRail() ? 'border-t-[1.5px]' : 'border-t', this.class(), this.resolvedHeight() === 'fix' && 'h-12 overflow-hidden'), /* @ts-ignore */
235
+ ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
236
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
237
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageFooterComponent, isStandalone: true, selector: "PageFooter", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "footer" }, properties: { "class": "classes()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
238
+ }
239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageFooterComponent, decorators: [{
240
+ type: Component,
241
+ args: [{
242
+ selector: 'PageFooter',
243
+ changeDetection: ChangeDetectionStrategy.OnPush,
244
+ host: {
245
+ '[class]': 'classes()',
246
+ 'data-page-slot': 'footer',
247
+ },
248
+ template: `<ng-content />`,
249
+ }]
250
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
251
+
118
252
  let nextPageSideId = 0;
119
253
  class PageSideComponent {
120
254
  document = inject(DOCUMENT, { optional: true });
@@ -208,16 +342,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImpor
208
342
  }]
209
343
  }], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], closeOnEsc: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEsc", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
210
344
 
345
+ /** Penghitung instance untuk id unik tiap apps-launcher (hindari bentrok `claimId` saat beberapa `Page` hidup). */
346
+ let pageAppsLauncherInstanceId = 0;
211
347
  class PageComponent {
212
348
  page = inject(PageStateService);
349
+ layout = inject(LayoutService, { optional: true });
350
+ navigation = inject(NavigationService, { optional: true });
351
+ identity = inject(LayoutIdentityService, { optional: true });
213
352
  projectedSide = contentChild(PageSideComponent, /* @ts-ignore */
214
353
  ...(ngDevMode ? [{ debugName: "projectedSide" }] : /* istanbul ignore next */ []));
354
+ projectedHeader = contentChild(PageHeaderComponent, /* @ts-ignore */
355
+ ...(ngDevMode ? [{ debugName: "projectedHeader" }] : /* istanbul ignore next */ []));
215
356
  variant = input(PAGE_DEFAULT_VARIANT, /* @ts-ignore */
216
357
  ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
217
358
  height = input(PAGE_DEFAULT_HEIGHT, /* @ts-ignore */
218
359
  ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
219
360
  scroll = input(PAGE_DEFAULT_SCROLL, /* @ts-ignore */
220
361
  ...(ngDevMode ? [{ debugName: "scroll" }] : /* istanbul ignore next */ []));
362
+ /** Visual appearance shared with the layout (`flat | border-rail`); unifies header/footer borders. */
363
+ appearance = input(PAGE_DEFAULT_APPEARANCE, /* @ts-ignore */
364
+ ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
221
365
  position = input(PAGE_DEFAULT_SIDE_POSITION, /* @ts-ignore */
222
366
  ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
223
367
  sideMode = input(PAGE_DEFAULT_SIDE_MODE, /* @ts-ignore */
@@ -229,6 +373,19 @@ class PageComponent {
229
373
  class = input('', /* @ts-ignore */
230
374
  ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
231
375
  sideOpenChange = output();
376
+ /** Saat layout `empty`, munculkan tombol apps (flyout main navigation) di pojok kanan-atas. Set `false` untuk menonaktifkan. */
377
+ appsLauncher = input(true, { ...(ngDevMode ? { debugName: "appsLauncher" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
378
+ /** Id navigasi yang disurface oleh apps-launcher (default `main`). */
379
+ appsNavId = input('main', /* @ts-ignore */
380
+ ...(ngDevMode ? [{ debugName: "appsNavId" }] : /* istanbul ignore next */ []));
381
+ /** Ikon Material untuk tombol apps-launcher. */
382
+ appsIcon = input('apps', /* @ts-ignore */
383
+ ...(ngDevMode ? [{ debugName: "appsIcon" }] : /* istanbul ignore next */ []));
384
+ /** Label/aria-label tombol apps-launcher (tombol icon-only). */
385
+ appsLabel = input('Open navigation', /* @ts-ignore */
386
+ ...(ngDevMode ? [{ debugName: "appsLabel" }] : /* istanbul ignore next */ []));
387
+ /** Id unik untuk instance `<Navigation>` apps-launcher; tak boleh memakai id `main` (akan bentrok `claimId`). */
388
+ launcherNavId = `__page-apps-${(pageAppsLauncherInstanceId += 1)}`;
232
389
  resolvedPosition = computed(() => this.projectedSide()?.position() ?? this.position(), /* @ts-ignore */
233
390
  ...(ngDevMode ? [{ debugName: "resolvedPosition" }] : /* istanbul ignore next */ []));
234
391
  resolvedSideMode = computed(() => this.projectedSide()?.mode() ?? this.sideMode(), /* @ts-ignore */
@@ -239,6 +396,29 @@ class PageComponent {
239
396
  ...(ngDevMode ? [{ debugName: "isRightSide" }] : /* istanbul ignore next */ []));
240
397
  showsOverlayBackdrop = computed(() => this.variant() === 'side' && this.resolvedSideMode() === 'overlay' && this.page.sideOpen(), /* @ts-ignore */
241
398
  ...(ngDevMode ? [{ debugName: "showsOverlayBackdrop" }] : /* istanbul ignore next */ []));
399
+ /** Signal data untuk id yang dipilih; di-recompute hanya saat `appsNavId` berubah. */
400
+ appsNavSource = computed(() => this.navigation?.data(this.appsNavId()) ?? null, /* @ts-ignore */
401
+ ...(ngDevMode ? [{ debugName: "appsNavSource" }] : /* istanbul ignore next */ []));
402
+ appsNavData = computed(() => this.appsNavSource()?.() ?? [], /* @ts-ignore */
403
+ ...(ngDevMode ? [{ debugName: "appsNavData" }] : /* istanbul ignore next */ []));
404
+ /** Apps-launcher hanya muncul di layout `empty`, saat diaktifkan, dan saat nav target punya data. */
405
+ showsAppsLauncher = computed(() => this.appsLauncher() && this.layout?.type() === 'empty' && this.appsNavData().length > 0, /* @ts-ignore */
406
+ ...(ngDevMode ? [{ debugName: "showsAppsLauncher" }] : /* istanbul ignore next */ []));
407
+ /**
408
+ * Host `<Navigation>` launcher di-absolute ke pojok kanan-atas (hanya membungkus tombol trigger;
409
+ * panel flyout tetap membentang selebar `Page` lewat pengukuran container). Saat ada `PageHeader`,
410
+ * tombol menyatu di dalam pita header (offset rapat); tanpa header, mengambang di atas konten.
411
+ */
412
+ appsLauncherHostClass = computed(() => cn('absolute z-30 h-auto w-auto', this.projectedHeader() ? 'right-2 top-1.5' : 'right-3 top-3'), /* @ts-ignore */
413
+ ...(ngDevMode ? [{ debugName: "appsLauncherHostClass" }] : /* istanbul ignore next */ []));
414
+ /** Appearance flyout mengikuti layout (seperti shell flyout); fallback ke appearance `Page`. */
415
+ appsLauncherAppearance = computed(() => this.layout?.appearance() ?? this.appearance(), /* @ts-ignore */
416
+ ...(ngDevMode ? [{ debugName: "appsLauncherAppearance" }] : /* istanbul ignore next */ []));
417
+ /** Brand/user untuk header & footer flyout — sama seperti shell flyout; `null` saat tak ada shell. */
418
+ appsBrand = computed(() => this.identity?.brand() ?? null, /* @ts-ignore */
419
+ ...(ngDevMode ? [{ debugName: "appsBrand" }] : /* istanbul ignore next */ []));
420
+ appsUser = computed(() => this.identity?.user() ?? null, /* @ts-ignore */
421
+ ...(ngDevMode ? [{ debugName: "appsUser" }] : /* istanbul ignore next */ []));
242
422
  hostClasses = computed(() => cn('relative block h-full min-h-0 w-full min-w-0 overflow-hidden text-foreground', this.class()), /* @ts-ignore */
243
423
  ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
244
424
  shellClasses = computed(() => cn('relative z-10 h-full min-h-0 w-full min-w-0', this.scroll() === 'content' && 'grid grid-rows-[auto_minmax(0,1fr)_auto]', this.scroll() === 'page' && 'overflow-auto'), /* @ts-ignore */
@@ -263,6 +443,7 @@ class PageComponent {
263
443
  variant: this.variant(),
264
444
  height: this.height(),
265
445
  scroll: this.scroll(),
446
+ appearance: this.appearance(),
266
447
  position: this.position(),
267
448
  sideMode: this.sideMode(),
268
449
  sideWidth: this.sideWidth(),
@@ -271,6 +452,10 @@ class PageComponent {
271
452
  effect(() => {
272
453
  this.page.setControlledSideOpen(this.sideOpen());
273
454
  });
455
+ // Header memesan ruang kanan hanya saat tombol apps benar-benar mengambang di atas header.
456
+ effect(() => {
457
+ this.page.setAppsLauncherReserve(this.showsAppsLauncher() && this.projectedHeader() !== undefined);
458
+ });
274
459
  effect(() => {
275
460
  const requestVersion = this.page.sideOpenRequestVersion();
276
461
  if (requestVersion === 0) {
@@ -283,7 +468,7 @@ class PageComponent {
283
468
  this.page.closeSide();
284
469
  }
285
470
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
286
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.3", type: PageComponent, isStandalone: true, selector: "Page", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, scroll: { classPropertyName: "scroll", publicName: "scroll", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, sideMode: { classPropertyName: "sideMode", publicName: "sideMode", isSignal: true, isRequired: false, transformFunction: null }, sideOpen: { classPropertyName: "sideOpen", publicName: "sideOpen", isSignal: true, isRequired: false, transformFunction: null }, sideWidth: { classPropertyName: "sideWidth", publicName: "sideWidth", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sideOpenChange: "sideOpenChange" }, host: { properties: { "class": "hostClasses()", "attr.data-page-variant": "variant()", "attr.data-page-height": "height()", "attr.data-page-scroll": "scroll()", "attr.data-page-position": "resolvedPosition()", "attr.data-page-side-mode": "resolvedSideMode()", "attr.data-page-side-open": "page.sideOpen()", "style.--page-side-width": "sideWidth()" } }, providers: [PageStateService], queries: [{ propertyName: "projectedSide", first: true, predicate: PageSideComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
471
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.3", type: PageComponent, isStandalone: true, selector: "Page", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, scroll: { classPropertyName: "scroll", publicName: "scroll", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, sideMode: { classPropertyName: "sideMode", publicName: "sideMode", isSignal: true, isRequired: false, transformFunction: null }, sideOpen: { classPropertyName: "sideOpen", publicName: "sideOpen", isSignal: true, isRequired: false, transformFunction: null }, sideWidth: { classPropertyName: "sideWidth", publicName: "sideWidth", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, appsLauncher: { classPropertyName: "appsLauncher", publicName: "appsLauncher", isSignal: true, isRequired: false, transformFunction: null }, appsNavId: { classPropertyName: "appsNavId", publicName: "appsNavId", isSignal: true, isRequired: false, transformFunction: null }, appsIcon: { classPropertyName: "appsIcon", publicName: "appsIcon", isSignal: true, isRequired: false, transformFunction: null }, appsLabel: { classPropertyName: "appsLabel", publicName: "appsLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sideOpenChange: "sideOpenChange" }, host: { properties: { "class": "hostClasses()", "attr.data-page-variant": "variant()", "attr.data-page-height": "height()", "attr.data-page-scroll": "scroll()", "attr.data-page-appearance": "appearance()", "attr.data-page-position": "resolvedPosition()", "attr.data-page-side-mode": "resolvedSideMode()", "attr.data-page-side-open": "page.sideOpen()", "style.--page-side-width": "sideWidth()" } }, providers: [PageStateService], queries: [{ propertyName: "projectedSide", first: true, predicate: PageSideComponent, descendants: true, isSignal: true }, { propertyName: "projectedHeader", first: true, predicate: PageHeaderComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
287
472
  @if (showsOverlayBackdrop()) {
288
473
  <button
289
474
  type="button"
@@ -307,7 +492,33 @@ class PageComponent {
307
492
 
308
493
  <ng-content select="PageFooter" />
309
494
  </div>
310
- `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
495
+
496
+ @if (showsAppsLauncher()) {
497
+ <Navigation
498
+ [id]="launcherNavId"
499
+ [data]="appsNavData()"
500
+ ariaLabel="Application navigation"
501
+ [class]="appsLauncherHostClass()">
502
+ <NavigationFlyout
503
+ [icon]="appsIcon()"
504
+ icon-only
505
+ trigger-variant="plain"
506
+ [nav-appearance]="appsLauncherAppearance()"
507
+ [label]="appsLabel()">
508
+ @if (appsBrand(); as brand) {
509
+ <NavigationHeader>
510
+ <LayoutBrand [brand]="brand" />
511
+ </NavigationHeader>
512
+ }
513
+ @if (appsUser(); as user) {
514
+ <NavigationFooter class="px-3">
515
+ <LayoutUser [user]="user" />
516
+ </NavigationFooter>
517
+ }
518
+ </NavigationFlyout>
519
+ </Navigation>
520
+ }
521
+ `, isInline: true, dependencies: [{ kind: "component", type: NavigationContainerComponent, selector: "Navigation", inputs: ["id", "data", "ariaLabel", "compact", "collapse-tree", "class", "itemClass", "nav-group-class", "activeIds", "activeUrl", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }, { kind: "component", type: NavigationFlyoutComponent, selector: "NavigationFlyout", inputs: ["label", "icon", "icon-only", "icon-position", "trigger-variant", "trigger-floating", "trigger-class", "nav-position", "nav-appearance", "class"] }, { kind: "component", type: NavigationHeaderComponent, selector: "NavigationHeader", inputs: ["toggle", "class"] }, { kind: "component", type: NavigationFooterComponent, selector: "NavigationFooter", inputs: ["class"] }, { kind: "component", type: LayoutBrand, selector: "LayoutBrand", inputs: ["brand", "compact"] }, { kind: "component", type: LayoutUser, selector: "LayoutUser", inputs: ["user", "detailed", "logoutLabel", "logoutIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
311
522
  }
312
523
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageComponent, decorators: [{
313
524
  type: Component,
@@ -315,11 +526,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImpor
315
526
  selector: 'Page',
316
527
  changeDetection: ChangeDetectionStrategy.OnPush,
317
528
  providers: [PageStateService],
529
+ imports: [
530
+ NavigationContainerComponent,
531
+ NavigationFlyoutComponent,
532
+ NavigationHeaderComponent,
533
+ NavigationFooterComponent,
534
+ LayoutBrand,
535
+ LayoutUser,
536
+ ],
318
537
  host: {
319
538
  '[class]': 'hostClasses()',
320
539
  '[attr.data-page-variant]': 'variant()',
321
540
  '[attr.data-page-height]': 'height()',
322
541
  '[attr.data-page-scroll]': 'scroll()',
542
+ '[attr.data-page-appearance]': 'appearance()',
323
543
  '[attr.data-page-position]': 'resolvedPosition()',
324
544
  '[attr.data-page-side-mode]': 'resolvedSideMode()',
325
545
  '[attr.data-page-side-open]': 'page.sideOpen()',
@@ -349,9 +569,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImpor
349
569
 
350
570
  <ng-content select="PageFooter" />
351
571
  </div>
572
+
573
+ @if (showsAppsLauncher()) {
574
+ <Navigation
575
+ [id]="launcherNavId"
576
+ [data]="appsNavData()"
577
+ ariaLabel="Application navigation"
578
+ [class]="appsLauncherHostClass()">
579
+ <NavigationFlyout
580
+ [icon]="appsIcon()"
581
+ icon-only
582
+ trigger-variant="plain"
583
+ [nav-appearance]="appsLauncherAppearance()"
584
+ [label]="appsLabel()">
585
+ @if (appsBrand(); as brand) {
586
+ <NavigationHeader>
587
+ <LayoutBrand [brand]="brand" />
588
+ </NavigationHeader>
589
+ }
590
+ @if (appsUser(); as user) {
591
+ <NavigationFooter class="px-3">
592
+ <LayoutUser [user]="user" />
593
+ </NavigationFooter>
594
+ }
595
+ </NavigationFlyout>
596
+ </Navigation>
597
+ }
352
598
  `,
353
599
  }]
354
- }], ctorParameters: () => [], propDecorators: { projectedSide: [{ type: i0.ContentChild, args: [i0.forwardRef(() => PageSideComponent), { isSignal: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], scroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "scroll", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], sideMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideMode", required: false }] }], sideOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOpen", required: false }] }], sideWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideWidth", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], sideOpenChange: [{ type: i0.Output, args: ["sideOpenChange"] }] } });
600
+ }], ctorParameters: () => [], propDecorators: { projectedSide: [{ type: i0.ContentChild, args: [i0.forwardRef(() => PageSideComponent), { isSignal: true }] }], projectedHeader: [{ type: i0.ContentChild, args: [i0.forwardRef(() => PageHeaderComponent), { isSignal: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], scroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "scroll", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], sideMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideMode", required: false }] }], sideOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOpen", required: false }] }], sideWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideWidth", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], sideOpenChange: [{ type: i0.Output, args: ["sideOpenChange"] }], appsLauncher: [{ type: i0.Input, args: [{ isSignal: true, alias: "appsLauncher", required: false }] }], appsNavId: [{ type: i0.Input, args: [{ isSignal: true, alias: "appsNavId", required: false }] }], appsIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "appsIcon", required: false }] }], appsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "appsLabel", required: false }] }] } });
355
601
 
356
602
  class PageSideToggleComponent {
357
603
  page = inject(PageStateService);
@@ -406,104 +652,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImpor
406
652
  }]
407
653
  }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], toggled: [{ type: i0.Output, args: ["toggled"] }] } });
408
654
 
409
- function buildPageBodyClasses(scroll, customClass) {
410
- return cn('block min-w-0', scroll === 'content' && 'h-full min-h-0 overflow-auto', scroll === 'page' && 'overflow-visible', customClass);
411
- }
412
- class PageHeaderComponent {
413
- page = inject(PageStateService, { optional: true });
414
- class = input('', /* @ts-ignore */
415
- ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
416
- resolvedHeight = computed(() => this.page?.height() ?? PAGE_DEFAULT_HEIGHT, /* @ts-ignore */
417
- ...(ngDevMode ? [{ debugName: "resolvedHeight" }] : /* istanbul ignore next */ []));
418
- classes = computed(() => cn('block shrink-0 border-b border-border bg-background', this.class(), this.resolvedHeight() === 'fix' && 'h-12 overflow-hidden'), /* @ts-ignore */
419
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
420
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
421
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageHeaderComponent, isStandalone: true, selector: "PageHeader", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "header" }, properties: { "class": "classes()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
422
- }
423
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageHeaderComponent, decorators: [{
424
- type: Component,
425
- args: [{
426
- selector: 'PageHeader',
427
- changeDetection: ChangeDetectionStrategy.OnPush,
428
- host: {
429
- '[class]': 'classes()',
430
- 'data-page-slot': 'header',
431
- },
432
- template: `<ng-content />`,
433
- }]
434
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
435
- class PageContentComponent {
436
- page = inject(PageStateService, { optional: true });
437
- class = input('', /* @ts-ignore */
438
- ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
439
- resolvedScroll = computed(() => this.page?.scroll() ?? PAGE_DEFAULT_SCROLL, /* @ts-ignore */
440
- ...(ngDevMode ? [{ debugName: "resolvedScroll" }] : /* istanbul ignore next */ []));
441
- classes = computed(() => buildPageBodyClasses(this.resolvedScroll(), this.class()), /* @ts-ignore */
442
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
443
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
444
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageContentComponent, isStandalone: true, selector: "PageContent", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "content" }, properties: { "class": "classes()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
445
- }
446
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageContentComponent, decorators: [{
447
- type: Component,
448
- args: [{
449
- selector: 'PageContent',
450
- changeDetection: ChangeDetectionStrategy.OnPush,
451
- host: {
452
- '[class]': 'classes()',
453
- 'data-page-slot': 'content',
454
- },
455
- template: `<ng-content />`,
456
- }]
457
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
458
- class PageDashboardComponent {
459
- page = inject(PageStateService, { optional: true });
460
- class = input('', /* @ts-ignore */
461
- ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
462
- resolvedScroll = computed(() => this.page?.scroll() ?? PAGE_DEFAULT_SCROLL, /* @ts-ignore */
463
- ...(ngDevMode ? [{ debugName: "resolvedScroll" }] : /* istanbul ignore next */ []));
464
- classes = computed(() => buildPageBodyClasses(this.resolvedScroll(), this.class()), /* @ts-ignore */
465
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
466
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageDashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
467
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageDashboardComponent, isStandalone: true, selector: "PageDashboard", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "dashboard" }, properties: { "class": "classes()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
468
- }
469
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageDashboardComponent, decorators: [{
470
- type: Component,
471
- args: [{
472
- selector: 'PageDashboard',
473
- changeDetection: ChangeDetectionStrategy.OnPush,
474
- host: {
475
- '[class]': 'classes()',
476
- 'data-page-slot': 'dashboard',
477
- },
478
- template: `<ng-content />`,
479
- }]
480
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
481
- class PageFooterComponent {
482
- page = inject(PageStateService, { optional: true });
483
- class = input('', /* @ts-ignore */
484
- ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
485
- resolvedHeight = computed(() => this.page?.height() ?? PAGE_DEFAULT_HEIGHT, /* @ts-ignore */
486
- ...(ngDevMode ? [{ debugName: "resolvedHeight" }] : /* istanbul ignore next */ []));
487
- classes = computed(() => cn('block shrink-0 border-t border-border bg-background', this.class(), this.resolvedHeight() === 'fix' && 'h-12 overflow-hidden'), /* @ts-ignore */
488
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
489
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
490
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.3", type: PageFooterComponent, isStandalone: true, selector: "PageFooter", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-page-slot": "footer" }, properties: { "class": "classes()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
491
- }
492
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.3", ngImport: i0, type: PageFooterComponent, decorators: [{
493
- type: Component,
494
- args: [{
495
- selector: 'PageFooter',
496
- changeDetection: ChangeDetectionStrategy.OnPush,
497
- host: {
498
- '[class]': 'classes()',
499
- 'data-page-slot': 'footer',
500
- },
501
- template: `<ng-content />`,
502
- }]
503
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
504
-
505
655
  /**
506
656
  * Generated bundle index. Do not edit.
507
657
  */
508
658
 
509
- export { PAGE_DEFAULT_HEIGHT, PAGE_DEFAULT_SCROLL, PAGE_DEFAULT_SIDE_MODE, PAGE_DEFAULT_SIDE_POSITION, PAGE_DEFAULT_SIDE_WIDTH, PAGE_DEFAULT_VARIANT, PAGE_HEIGHT_VALUES, PAGE_SCROLL_VALUES, PAGE_SIDE_MODES, PAGE_SIDE_POSITIONS, PAGE_VARIANTS, PageComponent, PageContentComponent, PageDashboardComponent, PageFooterComponent, PageHeaderComponent, PageSideComponent, PageSideToggleComponent, isUiPageHeight, isUiPageScroll, isUiPageSideMode, isUiPageSidePosition, isUiPageVariant };
659
+ export { PAGE_APPEARANCES, PAGE_DEFAULT_APPEARANCE, PAGE_DEFAULT_HEIGHT, PAGE_DEFAULT_SCROLL, PAGE_DEFAULT_SIDE_MODE, PAGE_DEFAULT_SIDE_POSITION, PAGE_DEFAULT_SIDE_WIDTH, PAGE_DEFAULT_VARIANT, PAGE_HEIGHT_VALUES, PAGE_SCROLL_VALUES, PAGE_SIDE_MODES, PAGE_SIDE_POSITIONS, PAGE_VARIANTS, PageComponent, PageContentComponent, PageDashboardComponent, PageFooterComponent, PageHeaderComponent, PageSideComponent, PageSideToggleComponent, isUiPageAppearance, isUiPageHeight, isUiPageScroll, isUiPageSideMode, isUiPageSidePosition, isUiPageVariant };
@@ -413,6 +413,25 @@ class ThemeRadiusService {
413
413
  radiusState = signal(DEFAULT_THEME_RADIUS, /* @ts-ignore */
414
414
  ...(ngDevMode ? [{ debugName: "radiusState" }] : /* istanbul ignore next */ []));
415
415
  radius = this.radiusState.asReadonly();
416
+ radiusPx = computed(() => {
417
+ switch (this.radius()) {
418
+ case 'none':
419
+ return 0;
420
+ case 'sm':
421
+ return 6;
422
+ case 'md':
423
+ return 10;
424
+ case 'lg':
425
+ return 14;
426
+ case 'xl':
427
+ return 20;
428
+ case 'full':
429
+ return 9999;
430
+ default:
431
+ return 10;
432
+ }
433
+ }, /* @ts-ignore */
434
+ ...(ngDevMode ? [{ debugName: "radiusPx" }] : /* istanbul ignore next */ []));
416
435
  constructor() {
417
436
  this.ensureDefaults();
418
437
  effect(() => {