@ojiepermana/angular-theme 22.0.32 → 22.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { isPlatformBrowser } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
3
  import { inject, PLATFORM_ID, signal, Service, computed, DestroyRef } from '@angular/core';
4
- import { LAYOUT_SURFACE_STORAGE_KEY, isUiLayoutSurface, LAYOUT_TYPE_STORAGE_KEY, isUiLayoutType, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutWidth, LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_STYLE_STORAGE_KEY, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_STYLE, LAYOUT_DEFAULT_WIDTH, isUiLayoutStyle } from '@ojiepermana/angular-theme/layout/types';
4
+ import { LAYOUT_SURFACE_STORAGE_KEY, isUiLayoutSurface, LAYOUT_TYPE_STORAGE_KEY, isUiLayoutType, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutWidth, LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_APPEARANCE, LAYOUT_DEFAULT_WIDTH, isUiLayoutAppearance } from '@ojiepermana/angular-theme/layout/types';
5
5
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
6
  import { Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError, NavigationSkipped } from '@angular/router';
7
7
  import { HttpContextToken } from '@angular/common/http';
@@ -13,13 +13,13 @@ class LayoutService {
13
13
  ...(ngDevMode ? [{ debugName: "surfaceState" }] : /* istanbul ignore next */ []));
14
14
  typeState = signal(this.getStoredType(), /* @ts-ignore */
15
15
  ...(ngDevMode ? [{ debugName: "typeState" }] : /* istanbul ignore next */ []));
16
- styleState = signal(this.getStoredStyle(), /* @ts-ignore */
17
- ...(ngDevMode ? [{ debugName: "styleState" }] : /* istanbul ignore next */ []));
16
+ appearanceState = signal(this.getStoredAppearance(), /* @ts-ignore */
17
+ ...(ngDevMode ? [{ debugName: "appearanceState" }] : /* istanbul ignore next */ []));
18
18
  widthState = signal(this.getStoredWidth(), /* @ts-ignore */
19
19
  ...(ngDevMode ? [{ debugName: "widthState" }] : /* istanbul ignore next */ []));
20
20
  surface = this.surfaceState.asReadonly();
21
21
  type = this.typeState.asReadonly();
22
- appearance = this.styleState.asReadonly();
22
+ appearance = this.appearanceState.asReadonly();
23
23
  width = this.widthState.asReadonly();
24
24
  registerDefaults(defaults) {
25
25
  if (defaults.surface !== undefined) {
@@ -78,12 +78,11 @@ class LayoutService {
78
78
  this.writeStorage(LAYOUT_TYPE_STORAGE_KEY, type);
79
79
  }
80
80
  setAppearance(appearance, options = {}) {
81
- this.styleState.set(appearance);
81
+ this.appearanceState.set(appearance);
82
82
  if (options.persist === false) {
83
83
  return;
84
84
  }
85
85
  this.writeStorage(LAYOUT_APPEARANCE_STORAGE_KEY, appearance);
86
- this.removeStorage(LAYOUT_STYLE_STORAGE_KEY);
87
86
  }
88
87
  setWidth(width, options = {}) {
89
88
  this.widthState.set(width);
@@ -102,10 +101,7 @@ class LayoutService {
102
101
  }
103
102
  getStoredAppearance() {
104
103
  const value = this.readStoredAppearance();
105
- return value ?? LAYOUT_DEFAULT_STYLE;
106
- }
107
- getStoredStyle() {
108
- return this.getStoredAppearance();
104
+ return value ?? LAYOUT_DEFAULT_APPEARANCE;
109
105
  }
110
106
  getStoredWidth() {
111
107
  const value = this.readStorage(LAYOUT_WIDTH_STORAGE_KEY);
@@ -123,18 +119,6 @@ class LayoutService {
123
119
  return null;
124
120
  }
125
121
  }
126
- removeStorage(key) {
127
- const storage = this.getStorage();
128
- if (!storage) {
129
- return;
130
- }
131
- try {
132
- storage.removeItem(key);
133
- }
134
- catch {
135
- return;
136
- }
137
- }
138
122
  writeStorage(key, value) {
139
123
  const storage = this.getStorage();
140
124
  if (!storage) {
@@ -160,11 +144,7 @@ class LayoutService {
160
144
  }
161
145
  readStoredAppearance() {
162
146
  const appearance = this.readStorage(LAYOUT_APPEARANCE_STORAGE_KEY);
163
- if (isUiLayoutStyle(appearance)) {
164
- return appearance;
165
- }
166
- const legacyStyle = this.readStorage(LAYOUT_STYLE_STORAGE_KEY);
167
- return isUiLayoutStyle(legacyStyle) ? legacyStyle : null;
147
+ return isUiLayoutAppearance(appearance) ? appearance : null;
168
148
  }
169
149
  getStoredAppearanceOrDefault(fallback) {
170
150
  return this.readStoredAppearance() ?? fallback;
@@ -1,15 +1,14 @@
1
1
  const LAYOUT_TYPES = ['vertical', 'horizontal', 'empty', 'fluid'];
2
2
  const LAYOUT_SURFACES = ['flat', 'grid', 'honeycome', 'line-vertical', 'line-horizontal'];
3
- const LAYOUT_STYLES = ['flat', 'border-rail'];
3
+ const LAYOUT_APPEARANCES = ['flat', 'border-rail'];
4
4
  const LAYOUT_WIDTHS = ['full', 'wide', 'container', 'fluid'];
5
5
  const LAYOUT_DEFAULT_SURFACE = 'flat';
6
6
  const LAYOUT_DEFAULT_TYPE = 'vertical';
7
- const LAYOUT_DEFAULT_STYLE = 'flat';
7
+ const LAYOUT_DEFAULT_APPEARANCE = 'flat';
8
8
  const LAYOUT_DEFAULT_WIDTH = 'full';
9
9
  const LAYOUT_SURFACE_STORAGE_KEY = 'layout-surface';
10
10
  const LAYOUT_APPEARANCE_STORAGE_KEY = 'layout-appearance';
11
11
  const LAYOUT_TYPE_STORAGE_KEY = 'layout-type';
12
- const LAYOUT_STYLE_STORAGE_KEY = 'layout-style';
13
12
  const LAYOUT_WIDTH_STORAGE_KEY = 'layout-width';
14
13
  function isUiLayoutSurface(value) {
15
14
  return value !== null && LAYOUT_SURFACES.includes(value);
@@ -17,8 +16,8 @@ function isUiLayoutSurface(value) {
17
16
  function isUiLayoutType(value) {
18
17
  return value !== null && LAYOUT_TYPES.includes(value);
19
18
  }
20
- function isUiLayoutStyle(value) {
21
- return value !== null && LAYOUT_STYLES.includes(value);
19
+ function isUiLayoutAppearance(value) {
20
+ return value !== null && LAYOUT_APPEARANCES.includes(value);
22
21
  }
23
22
  function isUiLayoutWidth(value) {
24
23
  return value !== null && LAYOUT_WIDTHS.includes(value);
@@ -28,4 +27,4 @@ function isUiLayoutWidth(value) {
28
27
  * Generated bundle index. Do not edit.
29
28
  */
30
29
 
31
- export { LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_STYLE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_STYLES, LAYOUT_STYLE_STORAGE_KEY, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutStyle, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth };
30
+ export { LAYOUT_APPEARANCES, LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_APPEARANCE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutAppearance, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth };
@@ -3,8 +3,8 @@ import { inject, input, computed, DestroyRef, Component, effect, ChangeDetection
3
3
  import { cn } from '@ojiepermana/angular-component/utils';
4
4
  import { LayoutLoadingService, LayoutService } from '@ojiepermana/angular-theme/layout/services';
5
5
  export { LAYOUT_LOADING_HIDE_DELAY_MS, LAYOUT_LOADING_INITIAL_PROGRESS, LAYOUT_LOADING_SKIP, LAYOUT_LOADING_TRICKLE_CEILING, LAYOUT_LOADING_TRICKLE_INTERVAL_MS, LayoutLoadingService, LayoutService, layoutLoadingInterceptor } from '@ojiepermana/angular-theme/layout/services';
6
- import { LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_STYLE, LAYOUT_DEFAULT_WIDTH } from '@ojiepermana/angular-theme/layout/types';
7
- export { LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_STYLE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_STYLES, LAYOUT_STYLE_STORAGE_KEY, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutStyle, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth } from '@ojiepermana/angular-theme/layout/types';
6
+ import { LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_APPEARANCE, LAYOUT_DEFAULT_WIDTH } from '@ojiepermana/angular-theme/layout/types';
7
+ export { LAYOUT_APPEARANCES, LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_APPEARANCE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutAppearance, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth } from '@ojiepermana/angular-theme/layout/types';
8
8
  import { NavigationContainerComponent } from '@ojiepermana/angular-navigation';
9
9
 
10
10
  /**
@@ -92,27 +92,32 @@ class LayoutComponent {
92
92
  ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
93
93
  appearance = input(null, /* @ts-ignore */
94
94
  ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
95
- layoutStyleAttribute = input(null, { ...(ngDevMode ? { debugName: "layoutStyleAttribute" } : /* istanbul ignore next */ {}), alias: 'layout-style' });
95
+ layoutAppearanceAttribute = input(null, { ...(ngDevMode ? { debugName: "layoutAppearanceAttribute" } : /* istanbul ignore next */ {}), alias: 'layout-appearance' });
96
96
  width = input(null, /* @ts-ignore */
97
97
  ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
98
+ /**
99
+ * Tipe layout (`vertical` | `horizontal` | `empty` | `fluid`). Bila di-set, menjadi sumber
100
+ * kebenaran tipe (override variant `Layout*`); bila `null`, variant yang menetapkan.
101
+ */
102
+ type = input(null, { ...(ngDevMode ? { debugName: "type" } : /* istanbul ignore next */ {}), alias: 'layout-type' });
98
103
  class = input('', /* @ts-ignore */
99
104
  ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
100
- appearanceInput = computed(() => this.appearance() ?? this.layoutStyleAttribute(), /* @ts-ignore */
105
+ appearanceInput = computed(() => this.appearance() ?? this.layoutAppearanceAttribute(), /* @ts-ignore */
101
106
  ...(ngDevMode ? [{ debugName: "appearanceInput" }] : /* istanbul ignore next */ []));
102
107
  resolvedSurface = computed(() => this.surface() ?? this.layout.surface(), /* @ts-ignore */
103
108
  ...(ngDevMode ? [{ debugName: "resolvedSurface" }] : /* istanbul ignore next */ []));
104
109
  resolvedAppearance = computed(() => this.appearanceInput() ?? this.layout.appearance(), /* @ts-ignore */
105
110
  ...(ngDevMode ? [{ debugName: "resolvedAppearance" }] : /* istanbul ignore next */ []));
106
- resolvedStyle = computed(() => this.layout.appearance(), /* @ts-ignore */
107
- ...(ngDevMode ? [{ debugName: "resolvedStyle" }] : /* istanbul ignore next */ []));
108
111
  resolvedWidth = computed(() => this.width() ?? this.layout.width(), /* @ts-ignore */
109
112
  ...(ngDevMode ? [{ debugName: "resolvedWidth" }] : /* istanbul ignore next */ []));
113
+ resolvedType = computed(() => this.type() ?? this.layout.type(), /* @ts-ignore */
114
+ ...(ngDevMode ? [{ debugName: "resolvedType" }] : /* istanbul ignore next */ []));
110
115
  isBorderRail = computed(() => this.resolvedAppearance() === 'border-rail', /* @ts-ignore */
111
116
  ...(ngDevMode ? [{ debugName: "isBorderRail" }] : /* istanbul ignore next */ []));
112
- isFluidFrame = computed(() => this.resolvedWidth() === 'fluid' && this.layout.type() === 'fluid', /* @ts-ignore */
117
+ isFluidFrame = computed(() => this.resolvedWidth() === 'fluid' && this.resolvedType() === 'fluid', /* @ts-ignore */
113
118
  ...(ngDevMode ? [{ debugName: "isFluidFrame" }] : /* istanbul ignore next */ []));
114
119
  showsInsetRails = computed(() => {
115
- const layoutType = this.layout.type();
120
+ const layoutType = this.resolvedType();
116
121
  return this.isBorderRail() && (layoutType === 'horizontal' || layoutType === 'vertical');
117
122
  }, /* @ts-ignore */
118
123
  ...(ngDevMode ? [{ debugName: "showsInsetRails" }] : /* istanbul ignore next */ []));
@@ -142,7 +147,7 @@ class LayoutComponent {
142
147
  this.layout.setAppearance(appearance, { persist: false });
143
148
  }
144
149
  else {
145
- this.layout.registerAppearance(LAYOUT_DEFAULT_STYLE);
150
+ this.layout.registerAppearance(LAYOUT_DEFAULT_APPEARANCE);
146
151
  }
147
152
  const width = this.width();
148
153
  if (width !== null) {
@@ -151,6 +156,13 @@ class LayoutComponent {
151
156
  else {
152
157
  this.layout.registerWidth(LAYOUT_DEFAULT_WIDTH);
153
158
  }
159
+ // Type: bila consumer mendaftarkan `layout-type`, itu jadi sumber kebenaran (override
160
+ // variant). Bila null, dibiarkan — variant `Layout*` yang menetapkan (registerType default
161
+ // sengaja TIDAK dipanggil agar tidak menimpa type yang sudah di-set variant).
162
+ const type = this.type();
163
+ if (type !== null) {
164
+ this.layout.setType(type, { persist: false });
165
+ }
154
166
  });
155
167
  }
156
168
  surfaceClasses() {
@@ -183,10 +195,12 @@ class LayoutComponent {
183
195
  if (this.isFluidFrame()) {
184
196
  return 'h-auto w-auto max-h-full max-w-full';
185
197
  }
186
- return this.resolvedWidth() === 'container' ? 'h-full w-full lg:container lg:mx-auto' : 'h-full w-full';
198
+ return this.resolvedWidth() === 'container'
199
+ ? 'h-full w-full lg:container lg:mx-auto'
200
+ : 'h-full w-full';
187
201
  }
188
202
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
189
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: LayoutComponent, isStandalone: true, selector: "Layout", inputs: { surface: { classPropertyName: "surface", publicName: "surface", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, layoutStyleAttribute: { classPropertyName: "layoutStyleAttribute", publicName: "layout-style", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.data-surface": "resolvedSurface()", "attr.data-layout-appearance": "resolvedAppearance()", "attr.data-layout-style": "resolvedStyle()", "attr.data-layout-width": "resolvedWidth()", "attr.data-layout-type": "layout.type()" } }, ngImport: i0, template: `
203
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: LayoutComponent, isStandalone: true, selector: "Layout", inputs: { surface: { classPropertyName: "surface", publicName: "surface", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, layoutAppearanceAttribute: { classPropertyName: "layoutAppearanceAttribute", publicName: "layout-appearance", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "layout-type", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.data-surface": "resolvedSurface()", "attr.data-layout-appearance": "resolvedAppearance()", "attr.data-layout-width": "resolvedWidth()", "attr.data-layout-type": "resolvedType()" } }, ngImport: i0, template: `
190
204
  <LayoutLoading />
191
205
 
192
206
  <div data-layout-stage [class]="frameStageClasses()">
@@ -194,63 +208,92 @@ class LayoutComponent {
194
208
  <div
195
209
  aria-hidden="true"
196
210
  data-layout-rail
197
- class="pointer-events-none col-start-1 row-start-1 z-0 overflow-visible">
211
+ class="pointer-events-none col-start-1 row-start-1 z-0 overflow-visible"
212
+ >
198
213
  <div data-layout-rail-anchor [class]="railAnchorClasses()">
199
214
  <div
200
215
  data-layout-rail-top-left-horizontal
201
- class="absolute top-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
216
+ class="absolute top-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
217
+ ></div>
202
218
  <div
203
219
  data-layout-rail-top-left-vertical
204
- class="absolute bottom-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
220
+ class="absolute bottom-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
221
+ ></div>
205
222
  <div
206
223
  data-layout-rail-top-right-horizontal
207
- class="absolute top-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
224
+ class="absolute top-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
225
+ ></div>
208
226
  <div
209
227
  data-layout-rail-top-right-vertical
210
- class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
228
+ class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
229
+ ></div>
211
230
  <div
212
231
  data-layout-rail-bottom-left-horizontal
213
- class="absolute bottom-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
232
+ class="absolute bottom-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
233
+ ></div>
214
234
  <div
215
235
  data-layout-rail-bottom-left-vertical
216
- class="absolute top-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
236
+ class="absolute top-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
237
+ ></div>
217
238
  <div
218
239
  data-layout-rail-bottom-right-horizontal
219
- class="absolute bottom-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
240
+ class="absolute bottom-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
241
+ ></div>
220
242
  <div
221
243
  data-layout-rail-bottom-right-vertical
222
- class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
244
+ class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
245
+ ></div>
223
246
 
224
247
  @if (showsInsetRails()) {
225
- <div data-layout-horizontal-top-rail class="absolute inset-x-0 top-12 h-[1.5px] bg-border"></div>
248
+ <div
249
+ data-layout-horizontal-top-rail
250
+ class="absolute inset-x-0 top-12 h-[1.5px] bg-border"
251
+ ></div>
226
252
  <div
227
253
  data-layout-horizontal-top-left-extension
228
- class="absolute top-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
254
+ class="absolute top-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
255
+ ></div>
229
256
  <div
230
257
  data-layout-horizontal-top-right-extension
231
- class="absolute top-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
232
- <div data-layout-horizontal-bottom-rail class="absolute inset-x-0 bottom-12 h-[1.5px] bg-border"></div>
258
+ class="absolute top-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
259
+ ></div>
260
+ <div
261
+ data-layout-horizontal-bottom-rail
262
+ class="absolute inset-x-0 bottom-12 h-[1.5px] bg-border"
263
+ ></div>
233
264
  <div
234
265
  data-layout-horizontal-bottom-left-extension
235
- class="absolute bottom-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
266
+ class="absolute bottom-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
267
+ ></div>
236
268
  <div
237
269
  data-layout-horizontal-bottom-right-extension
238
- class="absolute bottom-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
270
+ class="absolute bottom-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
271
+ ></div>
239
272
 
240
- <div data-layout-vertical-left-rail class="absolute inset-y-0 -left-4 w-[1.5px] bg-border"></div>
273
+ <div
274
+ data-layout-vertical-left-rail
275
+ class="absolute inset-y-0 -left-4 w-[1.5px] bg-border"
276
+ ></div>
241
277
  <div
242
278
  data-layout-vertical-left-top-extension
243
- class="absolute bottom-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
279
+ class="absolute bottom-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
280
+ ></div>
244
281
  <div
245
282
  data-layout-vertical-left-bottom-extension
246
- class="absolute top-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
247
- <div data-layout-vertical-right-rail class="absolute inset-y-0 -right-4 w-[1.5px] bg-border"></div>
283
+ class="absolute top-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
284
+ ></div>
285
+ <div
286
+ data-layout-vertical-right-rail
287
+ class="absolute inset-y-0 -right-4 w-[1.5px] bg-border"
288
+ ></div>
248
289
  <div
249
290
  data-layout-vertical-right-top-extension
250
- class="absolute bottom-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
291
+ class="absolute bottom-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
292
+ ></div>
251
293
  <div
252
294
  data-layout-vertical-right-bottom-extension
253
- class="absolute top-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
295
+ class="absolute top-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
296
+ ></div>
254
297
  }
255
298
  </div>
256
299
  </div>
@@ -274,9 +317,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
274
317
  '[class]': 'hostClasses()',
275
318
  '[attr.data-surface]': 'resolvedSurface()',
276
319
  '[attr.data-layout-appearance]': 'resolvedAppearance()',
277
- '[attr.data-layout-style]': 'resolvedStyle()',
278
320
  '[attr.data-layout-width]': 'resolvedWidth()',
279
- '[attr.data-layout-type]': 'layout.type()',
321
+ '[attr.data-layout-type]': 'resolvedType()',
280
322
  },
281
323
  template: `
282
324
  <LayoutLoading />
@@ -286,63 +328,92 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
286
328
  <div
287
329
  aria-hidden="true"
288
330
  data-layout-rail
289
- class="pointer-events-none col-start-1 row-start-1 z-0 overflow-visible">
331
+ class="pointer-events-none col-start-1 row-start-1 z-0 overflow-visible"
332
+ >
290
333
  <div data-layout-rail-anchor [class]="railAnchorClasses()">
291
334
  <div
292
335
  data-layout-rail-top-left-horizontal
293
- class="absolute top-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
336
+ class="absolute top-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
337
+ ></div>
294
338
  <div
295
339
  data-layout-rail-top-left-vertical
296
- class="absolute bottom-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
340
+ class="absolute bottom-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
341
+ ></div>
297
342
  <div
298
343
  data-layout-rail-top-right-horizontal
299
- class="absolute top-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
344
+ class="absolute top-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
345
+ ></div>
300
346
  <div
301
347
  data-layout-rail-top-right-vertical
302
- class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
348
+ class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
349
+ ></div>
303
350
  <div
304
351
  data-layout-rail-bottom-left-horizontal
305
- class="absolute bottom-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
352
+ class="absolute bottom-0 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
353
+ ></div>
306
354
  <div
307
355
  data-layout-rail-bottom-left-vertical
308
- class="absolute top-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
356
+ class="absolute top-full left-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
357
+ ></div>
309
358
  <div
310
359
  data-layout-rail-bottom-right-horizontal
311
- class="absolute bottom-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
360
+ class="absolute bottom-0 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
361
+ ></div>
312
362
  <div
313
363
  data-layout-rail-bottom-right-vertical
314
- class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
364
+ class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
365
+ ></div>
315
366
 
316
367
  @if (showsInsetRails()) {
317
- <div data-layout-horizontal-top-rail class="absolute inset-x-0 top-12 h-[1.5px] bg-border"></div>
368
+ <div
369
+ data-layout-horizontal-top-rail
370
+ class="absolute inset-x-0 top-12 h-[1.5px] bg-border"
371
+ ></div>
318
372
  <div
319
373
  data-layout-horizontal-top-left-extension
320
- class="absolute top-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
374
+ class="absolute top-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
375
+ ></div>
321
376
  <div
322
377
  data-layout-horizontal-top-right-extension
323
- class="absolute top-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
324
- <div data-layout-horizontal-bottom-rail class="absolute inset-x-0 bottom-12 h-[1.5px] bg-border"></div>
378
+ class="absolute top-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
379
+ ></div>
380
+ <div
381
+ data-layout-horizontal-bottom-rail
382
+ class="absolute inset-x-0 bottom-12 h-[1.5px] bg-border"
383
+ ></div>
325
384
  <div
326
385
  data-layout-horizontal-bottom-left-extension
327
- class="absolute bottom-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
386
+ class="absolute bottom-12 right-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
387
+ ></div>
328
388
  <div
329
389
  data-layout-horizontal-bottom-right-extension
330
- class="absolute bottom-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"></div>
390
+ class="absolute bottom-12 left-full h-[1.5px] w-[calc((100vw-100%)/2)] bg-border"
391
+ ></div>
331
392
 
332
- <div data-layout-vertical-left-rail class="absolute inset-y-0 -left-4 w-[1.5px] bg-border"></div>
393
+ <div
394
+ data-layout-vertical-left-rail
395
+ class="absolute inset-y-0 -left-4 w-[1.5px] bg-border"
396
+ ></div>
333
397
  <div
334
398
  data-layout-vertical-left-top-extension
335
- class="absolute bottom-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
399
+ class="absolute bottom-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
400
+ ></div>
336
401
  <div
337
402
  data-layout-vertical-left-bottom-extension
338
- class="absolute top-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
339
- <div data-layout-vertical-right-rail class="absolute inset-y-0 -right-4 w-[1.5px] bg-border"></div>
403
+ class="absolute top-full -left-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
404
+ ></div>
405
+ <div
406
+ data-layout-vertical-right-rail
407
+ class="absolute inset-y-0 -right-4 w-[1.5px] bg-border"
408
+ ></div>
340
409
  <div
341
410
  data-layout-vertical-right-top-extension
342
- class="absolute bottom-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
411
+ class="absolute bottom-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
412
+ ></div>
343
413
  <div
344
414
  data-layout-vertical-right-bottom-extension
345
- class="absolute top-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
415
+ class="absolute top-full -right-4 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
416
+ ></div>
346
417
  }
347
418
  </div>
348
419
  </div>
@@ -356,7 +427,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
356
427
  </div>
357
428
  `,
358
429
  }]
359
- }], ctorParameters: () => [], propDecorators: { surface: [{ type: i0.Input, args: [{ isSignal: true, alias: "surface", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], layoutStyleAttribute: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout-style", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
430
+ }], ctorParameters: () => [], propDecorators: { surface: [{ type: i0.Input, args: [{ isSignal: true, alias: "surface", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], layoutAppearanceAttribute: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout-appearance", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout-type", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
360
431
 
361
432
  class LayoutVerticalComponent {
362
433
  layout = inject(LayoutService);
@@ -480,24 +551,30 @@ class LayoutNavigationComponent {
480
551
  // overflow-visible: clipping diatur host <Navigation>; overlay nav (aside
481
552
  // drawer dockbar, preview rail) keluar dari kolom w-16 dan overflow-hidden
482
553
  // di sini ikut ter-scroll oleh focus scroll-into-view sehingga rail hilang.
483
- layoutType === 'vertical' && 'h-full w-max max-w-full shrink-0 overflow-visible', layoutType === 'empty' && 'hidden', this.class());
554
+ layoutType === 'vertical' && 'h-full w-max max-w-full shrink-0 overflow-visible',
555
+ // empty & fluid = layout fokus-konten: slot nav boleh tetap diproyeksikan agar struktur
556
+ // konsumen seragam (`LayoutNavigation` + `LayoutContent`), tapi nav-nya disembunyikan.
557
+ (layoutType === 'empty' || layoutType === 'fluid') && 'hidden', this.class());
484
558
  }, /* @ts-ignore */
485
559
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
486
560
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: LayoutNavigationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
487
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: LayoutNavigationComponent, isStandalone: true, selector: "LayoutNavigation", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, railOffset: { classPropertyName: "railOffset", publicName: "railOffset", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, properties: { "class": "classes()", "attr.aria-label": "ariaLabel() || null", "attr.data-layout-type": "layout.type()", "attr.data-layout-appearance": "layout.appearance()", "attr.data-layout-style": "layout.appearance()", "attr.data-layout-nav-rail-offset": "resolvedRailOffset()" } }, queries: [{ propertyName: "projectedNav", first: true, predicate: NavigationContainerComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
561
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: LayoutNavigationComponent, isStandalone: true, selector: "LayoutNavigation", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, railOffset: { classPropertyName: "railOffset", publicName: "railOffset", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, properties: { "class": "classes()", "attr.aria-label": "ariaLabel() || null", "attr.data-layout-type": "layout.type()", "attr.data-layout-appearance": "layout.appearance()", "attr.data-layout-nav-rail-offset": "resolvedRailOffset()" } }, queries: [{ propertyName: "projectedNav", first: true, predicate: NavigationContainerComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
488
562
  @if (showsVerticalRail()) {
489
563
  <div
490
564
  aria-hidden="true"
491
565
  data-layout-nav-rail
492
566
  class="pointer-events-none absolute inset-y-0 right-0 z-20 w-[1.5px] transition-transform duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:transition-none"
493
- [style.transform]="railTransform()">
567
+ [style.transform]="railTransform()"
568
+ >
494
569
  <div data-layout-nav-rail-line class="absolute inset-y-0 right-0 w-[1.5px] bg-border"></div>
495
570
  <div
496
571
  data-layout-nav-rail-top
497
- class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
572
+ class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
573
+ ></div>
498
574
  <div
499
575
  data-layout-nav-rail-bottom
500
- class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
576
+ class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
577
+ ></div>
501
578
  </div>
502
579
  }
503
580
 
@@ -515,7 +592,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
515
592
  '[attr.aria-label]': 'ariaLabel() || null',
516
593
  '[attr.data-layout-type]': 'layout.type()',
517
594
  '[attr.data-layout-appearance]': 'layout.appearance()',
518
- '[attr.data-layout-style]': 'layout.appearance()',
519
595
  '[attr.data-layout-nav-rail-offset]': 'resolvedRailOffset()',
520
596
  },
521
597
  template: `
@@ -524,14 +600,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
524
600
  aria-hidden="true"
525
601
  data-layout-nav-rail
526
602
  class="pointer-events-none absolute inset-y-0 right-0 z-20 w-[1.5px] transition-transform duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:transition-none"
527
- [style.transform]="railTransform()">
603
+ [style.transform]="railTransform()"
604
+ >
528
605
  <div data-layout-nav-rail-line class="absolute inset-y-0 right-0 w-[1.5px] bg-border"></div>
529
606
  <div
530
607
  data-layout-nav-rail-top
531
- class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
608
+ class="absolute bottom-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
609
+ ></div>
532
610
  <div
533
611
  data-layout-nav-rail-bottom
534
- class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"></div>
612
+ class="absolute top-full right-0 h-[calc((100dvh-100%)/2)] w-[1.5px] bg-border"
613
+ ></div>
535
614
  </div>
536
615
  }
537
616
 
@@ -546,7 +625,9 @@ class LayoutContentComponent {
546
625
  ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
547
626
  classes = computed(() => {
548
627
  const layoutType = this.layout.type();
549
- return cn('block min-h-0 min-w-0 overflow-auto', layoutType === 'horizontal' && 'flex-1', layoutType === 'vertical' && 'h-full', layoutType === 'empty' && 'h-full w-full', this.layout.width() === 'container' && 'w-full lg:container lg:mx-auto', this.class());
628
+ return cn('block min-h-0 min-w-0 overflow-auto', layoutType === 'horizontal' && 'flex-1', layoutType === 'vertical' && 'h-full', layoutType === 'empty' && 'h-full w-full',
629
+ // fluid: konten dipusatkan oleh LayoutFluid; batasi ke ukuran frame agar tetap scrollable.
630
+ layoutType === 'fluid' && 'max-h-full max-w-full', this.layout.width() === 'container' && 'w-full lg:container lg:mx-auto', this.class());
550
631
  }, /* @ts-ignore */
551
632
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
552
633
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: LayoutContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
package/layout/README.md CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  LayoutHorizontalComponent,
19
19
  LayoutNavigationComponent,
20
20
  LayoutVerticalComponent,
21
- type LayoutStyle,
21
+ type LayoutAppearance,
22
22
  type LayoutSurface,
23
23
  type LayoutType,
24
24
  type LayoutWidth,
@@ -30,25 +30,24 @@ Secondary entry point tetap tersedia bila consumer ingin import yang lebih ekspl
30
30
  ```ts
31
31
  import { LayoutService } from '@ojiepermana/angular-theme/layout/services';
32
32
  import {
33
- LAYOUT_DEFAULT_STYLE,
33
+ LAYOUT_DEFAULT_APPEARANCE,
34
34
  LAYOUT_DEFAULT_SURFACE,
35
35
  LAYOUT_DEFAULT_TYPE,
36
36
  LAYOUT_DEFAULT_WIDTH,
37
37
  LAYOUT_APPEARANCE_STORAGE_KEY,
38
- LAYOUT_STYLES,
38
+ LAYOUT_APPEARANCES,
39
39
  LAYOUT_SURFACE_STORAGE_KEY,
40
- LAYOUT_STYLE_STORAGE_KEY,
41
40
  LAYOUT_SURFACES,
42
41
  LAYOUT_TYPES,
43
42
  LAYOUT_TYPE_STORAGE_KEY,
44
43
  LAYOUT_WIDTHS,
45
44
  LAYOUT_WIDTH_STORAGE_KEY,
46
45
  isUiLayoutSurface,
47
- isUiLayoutStyle,
46
+ isUiLayoutAppearance,
48
47
  isUiLayoutType,
49
48
  isUiLayoutWidth,
50
49
  type LayoutContextValue,
51
- type LayoutStyle,
50
+ type LayoutAppearance,
52
51
  type LayoutSurface,
53
52
  type LayoutType,
54
53
  type LayoutWidth,
@@ -149,9 +148,18 @@ import {
149
148
  @Component({
150
149
  selector: 'demo-board',
151
150
  changeDetection: ChangeDetectionStrategy.OnPush,
152
- imports: [LayoutComponent, LayoutHorizontalComponent, LayoutNavigationComponent, LayoutContentComponent],
151
+ imports: [
152
+ LayoutComponent,
153
+ LayoutHorizontalComponent,
154
+ LayoutNavigationComponent,
155
+ LayoutContentComponent,
156
+ ],
153
157
  template: `
154
- <Layout [surface]="layout.surface()" [appearance]="layout.appearance()" [width]="layout.width()">
158
+ <Layout
159
+ [surface]="layout.surface()"
160
+ [appearance]="layout.appearance()"
161
+ [width]="layout.width()"
162
+ >
155
163
  <LayoutHorizontal>
156
164
  <LayoutNavigation ariaLabel="Board navigation">...</LayoutNavigation>
157
165
  <LayoutContent>...</LayoutContent>
@@ -186,20 +194,20 @@ Selector: `Layout`
186
194
 
187
195
  Inputs:
188
196
 
189
- | Input | Type | Default | Deskripsi |
190
- | -------------- | --------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
191
- | `surface` | `LayoutSurface` | `'flat'` | Menentukan fallback background root layout. Jika local storage `layout-surface` berisi nilai valid, nilai storage yang dipakai. |
192
- | `appearance` | `LayoutStyle or null` | `null` | API template utama untuk menentukan fallback appearance frame. Jika input ini kosong, primitive mencoba alias `layout-style`, lalu fallback efektif akhirnya `flat`. |
193
- | `layout-style` | `LayoutStyle or null` | `null` | Alias kompatibilitas untuk template lama. Tetap dibaca sebagai fallback, tetapi API yang direkomendasikan adalah `appearance`. |
194
- | `width` | `LayoutWidth` | `'full'` | Menentukan fallback padding outer dan perilaku container frame. Jika local storage `layout-width` berisi nilai valid, nilai storage yang dipakai. |
195
- | `class` | `string` | `''` | Menambahkan class pada host `Layout`. |
197
+ | Input | Type | Default | Deskripsi |
198
+ | ------------------- | -------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
199
+ | `surface` | `LayoutSurface` | `'flat'` | Menentukan fallback background root layout. Jika local storage `layout-surface` berisi nilai valid, nilai storage yang dipakai. |
200
+ | `appearance` | `LayoutAppearance or null` | `null` | API template untuk menentukan fallback appearance frame. Jika input ini kosong, primitive mencoba alias `layout-appearance`, lalu fallback efektif akhirnya `flat`. |
201
+ | `layout-appearance` | `LayoutAppearance or null` | `null` | Alias simetris dengan `nav-appearance` pada navigation (kosakata sama `flat \| border-rail`). Memberi `appearance` yang sama ke shell & nav membuat keduanya seragam. |
202
+ | `width` | `LayoutWidth` | `'full'` | Menentukan fallback padding outer dan perilaku container frame. Jika local storage `layout-width` berisi nilai valid, nilai storage yang dipakai. |
203
+ | `class` | `string` | `''` | Menambahkan class pada host `Layout`. |
196
204
 
197
205
  Behavior:
198
206
 
199
207
  - Jika consumer memberi input manual `surface`, `appearance`, atau `width`, nilai itu dipakai sebagai override in-memory untuk instance aktif tanpa menulis `localStorage`.
200
208
  - Jika input manual kosong, primitive mendaftarkan default `surface`, `appearance`, dan `width` ke `LayoutService` hanya saat local storage belum memiliki nilai valid.
201
209
  - Nilai visual final selalu dibaca kembali dari `LayoutService`, sehingga child primitive tetap membaca state yang sama selama instance aktif.
202
- - Menambahkan atribut host `data-surface`, `data-layout-appearance`, `data-layout-style`, `data-layout-width`, dan `data-layout-type`.
210
+ - Menambahkan atribut host `data-surface`, `data-layout-appearance`, `data-layout-width`, dan `data-layout-type`.
203
211
  - Root tidak menyediakan input `type`. Type aktif dikendalikan oleh variant layout yang dirender sebagai override in-memory, atau oleh consumer melalui `LayoutService.registerDefaults({ type })` sebelum template mengevaluasi `layout.type()`.
204
212
  - Selalu merender frame border.
205
213
  - Jika `appearance="border-rail"`, root menambah rail dekoratif di empat sudut frame, rail inset horizontal, dan rail vertikal sekunder di luar sisi kiri-kanan frame sehingga frame terlihat seperti memiliki double rail.
@@ -276,7 +284,7 @@ Inputs:
276
284
  Behavior:
277
285
 
278
286
  - Host selalu memiliki `role="navigation"`.
279
- - Menambahkan atribut host `data-layout-type`, `data-layout-appearance`, dan `data-layout-style`.
287
+ - Menambahkan atribut host `data-layout-type` dan `data-layout-appearance`.
280
288
  - Pada layout `horizontal`, nav menggunakan tinggi tetap `h-12`.
281
289
  - Pada layout `vertical`, nav menggunakan `w-max max-w-full`, sehingga lebar nav mengikuti isi child.
282
290
  - Pada layout `vertical` dengan `appearance="border-rail"`, komponen ini merender rail vertikal di sisi kanan nav, termasuk ekstensinya ke atas dan bawah viewport.
@@ -321,14 +329,14 @@ Nilai `surface` yang tersedia berasal dari `LAYOUT_SURFACES`.
321
329
 
322
330
  ## Appearance API
323
331
 
324
- Nilai `appearance` yang tersedia berasal dari `LAYOUT_STYLES`.
332
+ Nilai `appearance` yang tersedia berasal dari `LAYOUT_APPEARANCES`.
325
333
 
326
334
  | Nilai | Efek visual |
327
335
  | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
328
336
  | `'flat'` | Frame tetap memiliki border 1px tanpa rail luar. |
329
337
  | `'border-rail'` | Frame memiliki border lebih tebal, rail dekoratif pada sudut frame, rail inset horizontal, serta rail vertikal sekunder di luar sisi kiri-kanan untuk efek double rail; untuk layout vertical, nav juga mendapat rail kanan yang mengekstensi ke atas dan bawah viewport. |
330
338
 
331
- Gunakan `appearance` di template Angular. Alias `layout-style` tetap tersedia untuk kompatibilitas template lama. Nilai persisted untuk appearance disimpan dengan key local storage `layout-appearance`.
339
+ Gunakan `appearance` atau alias `layout-appearance` (simetris dengan `nav-appearance` di navigation; kosakata sama `flat | border-rail`) di template Angular. Nilai persisted untuk appearance disimpan dengan key local storage `layout-appearance`.
332
340
 
333
341
  ## Width API
334
342
 
@@ -359,34 +367,30 @@ import { LayoutService } from '@ojiepermana/angular-theme/layout/services';
359
367
 
360
368
  Readonly signals:
361
369
 
362
- | Properti | Type | Deskripsi |
363
- | ------------ | ----------------------- | --------------------------------------------------- |
364
- | `surface` | `Signal<LayoutSurface>` | Surface layout aktif. |
365
- | `type` | `Signal<LayoutType>` | Type layout aktif. |
366
- | `appearance` | `Signal<LayoutStyle>` | Appearance layout aktif. |
367
- | `style` | `Signal<LayoutStyle>` | Alias kompatibilitas untuk appearance layout aktif. |
368
- | `width` | `Signal<LayoutWidth>` | Width mode aktif. |
370
+ | Properti | Type | Deskripsi |
371
+ | ------------ | -------------------------- | ------------------------ |
372
+ | `surface` | `Signal<LayoutSurface>` | Surface layout aktif. |
373
+ | `type` | `Signal<LayoutType>` | Type layout aktif. |
374
+ | `appearance` | `Signal<LayoutAppearance>` | Appearance layout aktif. |
375
+ | `width` | `Signal<LayoutWidth>` | Width mode aktif. |
369
376
 
370
377
  Methods:
371
378
 
372
- | Method | Signature | Deskripsi |
373
- | --------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
374
- | `registerSurface` | `(surface: LayoutSurface) => void` | Mendaftarkan fallback `layout-surface` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
375
- | `registerType` | `(type: LayoutType) => void` | Mendaftarkan fallback `layout-type` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
376
- | `registerAppearance` | `(appearance: LayoutStyle) => void` | Mendaftarkan fallback `layout-appearance` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
377
- | `registerStyle` | `(style: LayoutStyle) => void` | Alias kompatibilitas untuk `registerAppearance(...)`. |
378
- | `registerWidth` | `(width: LayoutWidth) => void` | Mendaftarkan fallback `layout-width` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
379
- | `registerDefaults` | `(defaults: { surface?, appearance?, type?, width? }) => this` | Mendaftarkan beberapa fallback sekaligus. Ini adalah API yang direkomendasikan untuk page-level default karena consumer cukup memanggil satu method dan tetap menghormati nilai storage yang sudah valid. |
380
- | `setSurface` | `(surface: LayoutSurface, options?: { persist?: boolean }) => void` | Menulis surface ke signal. Secara default juga menulis `localStorage`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
381
- | `setType` | `(type: LayoutType, options?: { persist?: boolean }) => void` | Menulis type ke signal. Secara default juga menulis `localStorage`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
382
- | `setAppearance` | `(appearance: LayoutStyle, options?: { persist?: boolean }) => void` | Menulis appearance ke signal. Secara default juga menulis `layout-appearance`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
383
- | `setStyle` | `(style: LayoutStyle, options?: { persist?: boolean }) => void` | Alias kompatibilitas untuk `setAppearance(...)`, termasuk opsi `persist`. |
384
- | `setWidth` | `(width: LayoutWidth, options?: { persist?: boolean }) => void` | Menulis width ke signal. Secara default juga menulis `localStorage`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
385
- | `getStoredSurface` | `() => LayoutSurface` | Membaca surface yang valid dari storage atau default. |
386
- | `getStoredType` | `() => LayoutType` | Membaca type yang valid dari storage atau default. |
387
- | `getStoredAppearance` | `() => LayoutStyle` | Membaca appearance yang valid dari storage atau default. |
388
- | `getStoredStyle` | `() => LayoutStyle` | Alias kompatibilitas untuk `getStoredAppearance()`. |
389
- | `getStoredWidth` | `() => LayoutWidth` | Membaca width yang valid dari storage atau default. |
379
+ | Method | Signature | Deskripsi |
380
+ | --------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
381
+ | `registerSurface` | `(surface: LayoutSurface) => void` | Mendaftarkan fallback `layout-surface` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
382
+ | `registerType` | `(type: LayoutType) => void` | Mendaftarkan fallback `layout-type` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
383
+ | `registerAppearance` | `(appearance: LayoutAppearance) => void` | Mendaftarkan fallback `layout-appearance` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
384
+ | `registerWidth` | `(width: LayoutWidth) => void` | Mendaftarkan fallback `layout-width` ke local storage hanya jika storage belum memiliki nilai valid. Jika sudah ada nilai valid, service tetap memakai nilai yang tersimpan. |
385
+ | `registerDefaults` | `(defaults: { surface?, appearance?, type?, width? }) => this` | Mendaftarkan beberapa fallback sekaligus. Ini adalah API yang direkomendasikan untuk page-level default karena consumer cukup memanggil satu method dan tetap menghormati nilai storage yang sudah valid. |
386
+ | `setSurface` | `(surface: LayoutSurface, options?: { persist?: boolean }) => void` | Menulis surface ke signal. Secara default juga menulis `localStorage`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
387
+ | `setType` | `(type: LayoutType, options?: { persist?: boolean }) => void` | Menulis type ke signal. Secara default juga menulis `localStorage`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
388
+ | `setAppearance` | `(appearance: LayoutAppearance, options?: { persist?: boolean }) => void` | Menulis appearance ke signal. Secara default juga menulis `layout-appearance`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
389
+ | `setWidth` | `(width: LayoutWidth, options?: { persist?: boolean }) => void` | Menulis width ke signal. Secara default juga menulis `localStorage`, tetapi consumer dapat memakai `persist: false` untuk override sementara. |
390
+ | `getStoredSurface` | `() => LayoutSurface` | Membaca surface yang valid dari storage atau default. |
391
+ | `getStoredType` | `() => LayoutType` | Membaca type yang valid dari storage atau default. |
392
+ | `getStoredAppearance` | `() => LayoutAppearance` | Membaca appearance yang valid dari storage atau default. |
393
+ | `getStoredWidth` | `() => LayoutWidth` | Membaca width yang valid dari storage atau default. |
390
394
 
391
395
  Persistence behavior:
392
396
 
@@ -395,7 +399,6 @@ Persistence behavior:
395
399
  - `registerDefaults(...)` adalah API yang direkomendasikan untuk menetapkan default per halaman tanpa menimpa nilai valid yang sudah tersimpan sebelumnya.
396
400
  - Manual template input pada `Layout` dan variant layout yang dirender consumer hanya mengubah state aktif; keduanya tidak lagi menulis `localStorage`.
397
401
  - Method `registerSurface(...)`, `registerType(...)`, `registerAppearance(...)`, dan `registerWidth(...)` tetap tersedia bila consumer memang perlu registrasi yang lebih granular.
398
- - Legacy storage key `layout-style` masih dibaca untuk kompatibilitas dan akan dibersihkan ketika appearance ditulis ulang ke `layout-appearance`.
399
402
  - Aman untuk SSR karena hanya mengakses `localStorage` saat runtime browser tersedia.
400
403
 
401
404
  Contoh penggunaan:
@@ -423,13 +426,13 @@ Seluruh symbol berikut diekspor dari `@ojiepermana/angular-theme/layout/types`.
423
426
 
424
427
  ### Types
425
428
 
426
- | Symbol | Nilai |
427
- | -------------------- | --------------------------------------------------------------------------------------------------------- |
428
- | `LayoutType` | `vertical`, `horizontal`, `empty`, `fluid` |
429
- | `LayoutSurface` | `flat`, `grid`, `honeycome`, `line-vertical`, `line-horizontal` |
430
- | `LayoutStyle` | `flat`, `border-rail` |
431
- | `LayoutWidth` | `full`, `wide`, `container`, `fluid` |
432
- | `LayoutContextValue` | Objekt berbentuk `{ surface, type, appearance, style, width }` yang masing-masing berupa readonly signal. |
429
+ | Symbol | Nilai |
430
+ | -------------------- | -------------------------------------------------------------------------------------------------- |
431
+ | `LayoutType` | `vertical`, `horizontal`, `empty`, `fluid` |
432
+ | `LayoutSurface` | `flat`, `grid`, `honeycome`, `line-vertical`, `line-horizontal` |
433
+ | `LayoutAppearance` | `flat`, `border-rail` |
434
+ | `LayoutWidth` | `full`, `wide`, `container`, `fluid` |
435
+ | `LayoutContextValue` | Objekt berbentuk `{ surface, type, appearance, width }` yang masing-masing berupa readonly signal. |
433
436
 
434
437
  ### Constants
435
438
 
@@ -437,16 +440,15 @@ Seluruh symbol berikut diekspor dari `@ojiepermana/angular-theme/layout/types`.
437
440
  | ------------------------------- | ------------------------------------------------------------------- |
438
441
  | `LAYOUT_TYPES` | `['vertical', 'horizontal', 'empty', 'fluid']` |
439
442
  | `LAYOUT_SURFACES` | `['flat', 'grid', 'honeycome', 'line-vertical', 'line-horizontal']` |
440
- | `LAYOUT_STYLES` | `['flat', 'border-rail']` |
443
+ | `LAYOUT_APPEARANCES` | `['flat', 'border-rail']` |
441
444
  | `LAYOUT_WIDTHS` | `['full', 'wide', 'container', 'fluid']` |
442
445
  | `LAYOUT_DEFAULT_SURFACE` | `'flat'` |
443
446
  | `LAYOUT_DEFAULT_TYPE` | `'vertical'` |
444
- | `LAYOUT_DEFAULT_STYLE` | `'flat'` |
447
+ | `LAYOUT_DEFAULT_APPEARANCE` | `'flat'` |
445
448
  | `LAYOUT_DEFAULT_WIDTH` | `'full'` |
446
449
  | `LAYOUT_SURFACE_STORAGE_KEY` | `'layout-surface'` |
447
450
  | `LAYOUT_APPEARANCE_STORAGE_KEY` | `'layout-appearance'` |
448
451
  | `LAYOUT_TYPE_STORAGE_KEY` | `'layout-type'` |
449
- | `LAYOUT_STYLE_STORAGE_KEY` | `'layout-style'` `(legacy compatibility key)` |
450
452
  | `LAYOUT_WIDTH_STORAGE_KEY` | `'layout-width'` |
451
453
 
452
454
  ### Guards
@@ -455,14 +457,14 @@ Seluruh symbol berikut diekspor dari `@ojiepermana/angular-theme/layout/types`.
455
457
  Memvalidasi string terhadap daftar surface yang didukung.
456
458
  - `isUiLayoutType(value: string | null): value is LayoutType`
457
459
  Memvalidasi string terhadap daftar type yang didukung.
458
- - `isUiLayoutStyle(value: string | null): value is LayoutStyle`
460
+ - `isUiLayoutAppearance(value: string | null): value is LayoutAppearance`
459
461
  Memvalidasi string terhadap daftar style yang didukung.
460
462
  - `isUiLayoutWidth(value: string | null): value is LayoutWidth`
461
463
  Memvalidasi string terhadap daftar width yang didukung.
462
464
 
463
465
  ## Consumer guidance
464
466
 
465
- - Gunakan `appearance` di template. `layout-style` dipertahankan hanya untuk kompatibilitas.
467
+ - Gunakan `appearance` atau alias `layout-appearance` di template (kosakata sama dengan `nav-appearance` pada navigation).
466
468
  - Untuk halaman yang punya default layout sendiri, utamakan `inject(LayoutService).registerDefaults({...})` sekali di level page daripada memanggil empat method `register...` terpisah.
467
469
  - Jika halaman harus merender variant berdasarkan preferensi yang tersimpan, pakai `layout.type()` sebagai sumber branching dan bind root `Layout` ke `layout.surface()`, `layout.appearance()`, dan `layout.width()`.
468
470
  - Tempatkan scroll page utama di `LayoutContent`, bukan di root `Layout`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ojiepermana/angular-theme",
3
- "version": "22.0.32",
3
+ "version": "22.0.33",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/edsis/angular.git"
@@ -13,8 +13,8 @@
13
13
  "@angular/common": ">=22.0.0",
14
14
  "@angular/core": ">=22.0.0",
15
15
  "@angular/router": ">=22.0.0",
16
- "@ojiepermana/angular-navigation": "^22.0.32",
17
- "@ojiepermana/angular-component": "^22.0.32",
16
+ "@ojiepermana/angular-navigation": "^22.0.33",
17
+ "@ojiepermana/angular-component": "^22.0.33",
18
18
  "rxjs": ">=7.8.0"
19
19
  },
20
20
  "dependencies": {
@@ -1,5 +1,5 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { LayoutSurface, LayoutStyle, LayoutType, LayoutWidth } from '@ojiepermana/angular-theme/layout/types';
2
+ import { LayoutSurface, LayoutAppearance, LayoutType, LayoutWidth } from '@ojiepermana/angular-theme/layout/types';
3
3
  import { HttpContextToken, HttpInterceptorFn } from '@angular/common/http';
4
4
 
5
5
  interface LayoutMutationOptions {
@@ -9,7 +9,7 @@ declare class LayoutService {
9
9
  private readonly platformId;
10
10
  private readonly surfaceState;
11
11
  private readonly typeState;
12
- private readonly styleState;
12
+ private readonly appearanceState;
13
13
  private readonly widthState;
14
14
  readonly surface: _angular_core.Signal<"flat" | "grid" | "honeycome" | "line-vertical" | "line-horizontal">;
15
15
  readonly type: _angular_core.Signal<"vertical" | "horizontal" | "empty" | "fluid">;
@@ -17,25 +17,23 @@ declare class LayoutService {
17
17
  readonly width: _angular_core.Signal<"fluid" | "full" | "wide" | "container">;
18
18
  registerDefaults(defaults: {
19
19
  surface?: LayoutSurface;
20
- appearance?: LayoutStyle;
20
+ appearance?: LayoutAppearance;
21
21
  type?: LayoutType;
22
22
  width?: LayoutWidth;
23
23
  }): this;
24
24
  registerSurface(surface: LayoutSurface): void;
25
25
  registerType(type: LayoutType): void;
26
- registerAppearance(appearance: LayoutStyle): void;
26
+ registerAppearance(appearance: LayoutAppearance): void;
27
27
  registerWidth(width: LayoutWidth): void;
28
28
  setSurface(surface: LayoutSurface, options?: LayoutMutationOptions): void;
29
29
  setType(type: LayoutType, options?: LayoutMutationOptions): void;
30
- setAppearance(appearance: LayoutStyle, options?: LayoutMutationOptions): void;
30
+ setAppearance(appearance: LayoutAppearance, options?: LayoutMutationOptions): void;
31
31
  setWidth(width: LayoutWidth, options?: LayoutMutationOptions): void;
32
32
  getStoredSurface(): LayoutSurface;
33
33
  getStoredType(): LayoutType;
34
- getStoredAppearance(): LayoutStyle;
35
- getStoredStyle(): LayoutStyle;
34
+ getStoredAppearance(): LayoutAppearance;
36
35
  getStoredWidth(): LayoutWidth;
37
36
  private readStorage;
38
- private removeStorage;
39
37
  private writeStorage;
40
38
  private getStorage;
41
39
  private readStoredAppearance;
@@ -2,32 +2,30 @@ import { Signal } from '@angular/core';
2
2
 
3
3
  declare const LAYOUT_TYPES: readonly ["vertical", "horizontal", "empty", "fluid"];
4
4
  declare const LAYOUT_SURFACES: readonly ["flat", "grid", "honeycome", "line-vertical", "line-horizontal"];
5
- declare const LAYOUT_STYLES: readonly ["flat", "border-rail"];
5
+ declare const LAYOUT_APPEARANCES: readonly ["flat", "border-rail"];
6
6
  declare const LAYOUT_WIDTHS: readonly ["full", "wide", "container", "fluid"];
7
7
  type LayoutType = (typeof LAYOUT_TYPES)[number];
8
8
  type LayoutSurface = (typeof LAYOUT_SURFACES)[number];
9
- type LayoutStyle = (typeof LAYOUT_STYLES)[number];
9
+ type LayoutAppearance = (typeof LAYOUT_APPEARANCES)[number];
10
10
  type LayoutWidth = (typeof LAYOUT_WIDTHS)[number];
11
11
  declare const LAYOUT_DEFAULT_SURFACE: LayoutSurface;
12
12
  declare const LAYOUT_DEFAULT_TYPE: LayoutType;
13
- declare const LAYOUT_DEFAULT_STYLE: LayoutStyle;
13
+ declare const LAYOUT_DEFAULT_APPEARANCE: LayoutAppearance;
14
14
  declare const LAYOUT_DEFAULT_WIDTH: LayoutWidth;
15
15
  declare const LAYOUT_SURFACE_STORAGE_KEY = "layout-surface";
16
16
  declare const LAYOUT_APPEARANCE_STORAGE_KEY = "layout-appearance";
17
17
  declare const LAYOUT_TYPE_STORAGE_KEY = "layout-type";
18
- declare const LAYOUT_STYLE_STORAGE_KEY = "layout-style";
19
18
  declare const LAYOUT_WIDTH_STORAGE_KEY = "layout-width";
20
19
  interface LayoutContextValue {
21
20
  surface: Signal<LayoutSurface>;
22
21
  type: Signal<LayoutType>;
23
- appearance: Signal<LayoutStyle>;
24
- style: Signal<LayoutStyle>;
22
+ appearance: Signal<LayoutAppearance>;
25
23
  width: Signal<LayoutWidth>;
26
24
  }
27
25
  declare function isUiLayoutSurface(value: string | null): value is LayoutSurface;
28
26
  declare function isUiLayoutType(value: string | null): value is LayoutType;
29
- declare function isUiLayoutStyle(value: string | null): value is LayoutStyle;
27
+ declare function isUiLayoutAppearance(value: string | null): value is LayoutAppearance;
30
28
  declare function isUiLayoutWidth(value: string | null): value is LayoutWidth;
31
29
 
32
- export { LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_STYLE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_STYLES, LAYOUT_STYLE_STORAGE_KEY, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutStyle, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth };
33
- export type { LayoutContextValue, LayoutStyle, LayoutSurface, LayoutType, LayoutWidth };
30
+ export { LAYOUT_APPEARANCES, LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_APPEARANCE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, isUiLayoutAppearance, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth };
31
+ export type { LayoutAppearance, LayoutContextValue, LayoutSurface, LayoutType, LayoutWidth };
@@ -2,20 +2,25 @@ import * as _angular_core from '@angular/core';
2
2
  import { LayoutService, LayoutLoadingService } from '@ojiepermana/angular-theme/layout/services';
3
3
  export { LAYOUT_LOADING_HIDE_DELAY_MS, LAYOUT_LOADING_INITIAL_PROGRESS, LAYOUT_LOADING_SKIP, LAYOUT_LOADING_TRICKLE_CEILING, LAYOUT_LOADING_TRICKLE_INTERVAL_MS, LayoutLoadingService, LayoutService, layoutLoadingInterceptor } from '@ojiepermana/angular-theme/layout/services';
4
4
  import { NavigationContainerComponent } from '@ojiepermana/angular-navigation';
5
- export { LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_STYLE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_STYLES, LAYOUT_STYLE_STORAGE_KEY, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, LayoutContextValue, LayoutStyle, LayoutSurface, LayoutType, LayoutWidth, isUiLayoutStyle, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth } from '@ojiepermana/angular-theme/layout/types';
5
+ export { LAYOUT_APPEARANCES, LAYOUT_APPEARANCE_STORAGE_KEY, LAYOUT_DEFAULT_APPEARANCE, LAYOUT_DEFAULT_SURFACE, LAYOUT_DEFAULT_TYPE, LAYOUT_DEFAULT_WIDTH, LAYOUT_SURFACES, LAYOUT_SURFACE_STORAGE_KEY, LAYOUT_TYPES, LAYOUT_TYPE_STORAGE_KEY, LAYOUT_WIDTHS, LAYOUT_WIDTH_STORAGE_KEY, LayoutAppearance, LayoutContextValue, LayoutSurface, LayoutType, LayoutWidth, isUiLayoutAppearance, isUiLayoutSurface, isUiLayoutType, isUiLayoutWidth } from '@ojiepermana/angular-theme/layout/types';
6
6
 
7
7
  declare class LayoutComponent {
8
8
  protected readonly layout: LayoutService;
9
9
  readonly surface: _angular_core.InputSignal<"flat" | "grid" | "honeycome" | "line-vertical" | "line-horizontal" | null>;
10
10
  readonly appearance: _angular_core.InputSignal<"flat" | "border-rail" | null>;
11
- readonly layoutStyleAttribute: _angular_core.InputSignal<"flat" | "border-rail" | null>;
11
+ readonly layoutAppearanceAttribute: _angular_core.InputSignal<"flat" | "border-rail" | null>;
12
12
  readonly width: _angular_core.InputSignal<"full" | "wide" | "container" | "fluid" | null>;
13
+ /**
14
+ * Tipe layout (`vertical` | `horizontal` | `empty` | `fluid`). Bila di-set, menjadi sumber
15
+ * kebenaran tipe (override variant `Layout*`); bila `null`, variant yang menetapkan.
16
+ */
17
+ readonly type: _angular_core.InputSignal<"fluid" | "vertical" | "horizontal" | "empty" | null>;
13
18
  readonly class: _angular_core.InputSignal<string>;
14
19
  protected readonly appearanceInput: _angular_core.Signal<"flat" | "border-rail" | null>;
15
20
  protected readonly resolvedSurface: _angular_core.Signal<"flat" | "grid" | "honeycome" | "line-vertical" | "line-horizontal">;
16
21
  protected readonly resolvedAppearance: _angular_core.Signal<"flat" | "border-rail">;
17
- protected readonly resolvedStyle: _angular_core.Signal<"flat" | "border-rail">;
18
22
  protected readonly resolvedWidth: _angular_core.Signal<"full" | "wide" | "container" | "fluid">;
23
+ protected readonly resolvedType: _angular_core.Signal<"fluid" | "vertical" | "horizontal" | "empty">;
19
24
  protected readonly isBorderRail: _angular_core.Signal<boolean>;
20
25
  protected readonly isFluidFrame: _angular_core.Signal<boolean>;
21
26
  protected readonly showsInsetRails: _angular_core.Signal<boolean>;
@@ -30,7 +35,7 @@ declare class LayoutComponent {
30
35
  private widthPaddingClasses;
31
36
  private frameSizeClasses;
32
37
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LayoutComponent, never>;
33
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<LayoutComponent, "Layout", never, { "surface": { "alias": "surface"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "layoutStyleAttribute": { "alias": "layout-style"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "class": { "alias": "class"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
38
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LayoutComponent, "Layout", never, { "surface": { "alias": "surface"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "layoutAppearanceAttribute": { "alias": "layout-appearance"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "type": { "alias": "layout-type"; "required": false; "isSignal": true; }; "class": { "alias": "class"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
34
39
  }
35
40
 
36
41
  declare class LayoutVerticalComponent {