@ojiepermana/angular 21.1.4 → 21.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/etos/README.md CHANGED
@@ -20,11 +20,24 @@ Shared services, types, and primitives stay in the generic libraries:
20
20
  Published consumers should import Etos through the short public entrypoint:
21
21
 
22
22
  ```ts
23
- import { type EtosBrandOptions, EtosLayoutComponent, provideEtosBrand } from '@ojiepermana/angular/etos';
23
+ import {
24
+ type EtosBrandOptions,
25
+ EtosHorizontalLayoutComponent,
26
+ EtosThemeSwitcherComponent,
27
+ EtosVerticalLayoutComponent,
28
+ provideEtosBrand,
29
+ } from '@ojiepermana/angular/etos';
30
+ import { LayoutService } from '@ojiepermana/angular/layout';
24
31
 
25
32
  export const etosBrandConfig = {
26
- theme: { mode: 'light' },
27
- layout: { mode: 'vertical' },
33
+ theme: {
34
+ mode: 'light',
35
+ style: 'default',
36
+ },
37
+ layout: {
38
+ mode: 'vertical',
39
+ width: 'fixed',
40
+ },
28
41
  } satisfies EtosBrandOptions;
29
42
 
30
43
  export const appConfig = {
@@ -32,14 +45,68 @@ export const appConfig = {
32
45
  };
33
46
  ```
34
47
 
48
+ `provideEtosBrand()` applies the Etos brand tokens and wires the shared `ThemeService` and `LayoutService` defaults for the app.
49
+
35
50
  ```ts
36
51
  @Component({
37
- imports: [EtosLayoutComponent],
38
- template: `<etos-layout />`,
52
+ imports: [EtosHorizontalLayoutComponent, EtosThemeSwitcherComponent, EtosVerticalLayoutComponent],
53
+ template: `
54
+ @switch (layoutMode()) {
55
+ @case ('horizontal') {
56
+ <etos-horizontal-layout>
57
+ <div ui-layout-profile>
58
+ <etos-theme-switcher
59
+ [userInfo]="profileInfo"
60
+ [quickActions]="horizontalQuickActions"
61
+ [notificationShortcut]="horizontalNotificationShortcut" />
62
+ </div>
63
+ </etos-horizontal-layout>
64
+ }
65
+ @default {
66
+ <etos-vertical-layout>
67
+ <div ui-sidebar-footer class="flex items-center gap-3">
68
+ <etos-theme-switcher [userInfo]="profileInfo" [quickActions]="verticalQuickActions" popoverAlign="start" />
69
+
70
+ <div class="flex flex-col gap-px">
71
+ <span>Ojie Permana</span>
72
+ <span>Etos design system navigator</span>
73
+ </div>
74
+ </div>
75
+ </etos-vertical-layout>
76
+ }
77
+ }
78
+ `,
39
79
  })
40
- export class Pages {}
80
+ export class Pages {
81
+ protected readonly layoutMode = inject(LayoutService).mode;
82
+ protected readonly profileInfo = {
83
+ name: 'Ojie Permana',
84
+ subtitle: 'Etos design system navigator',
85
+ avatarSrc: '/avatar-ojie.svg',
86
+ avatarAlt: 'Portrait of Ojie Permana',
87
+ };
88
+ protected readonly horizontalQuickActions = [
89
+ { value: 'sign-out', label: 'Logout', icon: 'logout', tone: 'destructive' },
90
+ ];
91
+ protected readonly verticalQuickActions = [
92
+ { value: 'notifications', label: 'Notifications', icon: 'notifications' },
93
+ { value: 'sign-out', label: 'Logout', icon: 'logout', tone: 'destructive' },
94
+ ];
95
+ protected readonly horizontalNotificationShortcut = {
96
+ value: 'notifications',
97
+ icon: 'notifications',
98
+ ariaLabel: 'Open notifications for Ojie Permana',
99
+ };
100
+ }
41
101
  ```
42
102
 
103
+ ## Using the brand theme
104
+
105
+ The Etos brand theme has two parts:
106
+
107
+ - TypeScript setup through `provideEtosBrand()` for theme and layout defaults.
108
+ - CSS setup through the Etos stylesheet so the `theme-brand="etos"` tokens are available at runtime.
109
+
43
110
  App CSS should import the Etos package stylesheet before Tailwind:
44
111
 
45
112
  ```css
@@ -48,12 +115,120 @@ App CSS should import the Etos package stylesheet before Tailwind:
48
115
  @import '@ojiepermana/angular/theme/tailwind/theme.css';
49
116
  ```
50
117
 
118
+ Recommended provider configuration:
119
+
120
+ ```ts
121
+ import { type EtosBrandOptions, provideEtosBrand } from '@ojiepermana/angular/etos';
122
+
123
+ export const etosBrandConfig = {
124
+ theme: {
125
+ mode: 'light',
126
+ style: 'default',
127
+ },
128
+ layout: {
129
+ mode: 'vertical',
130
+ width: 'fixed',
131
+ },
132
+ } satisfies EtosBrandOptions;
133
+
134
+ export const appConfig = {
135
+ providers: [provideEtosBrand(etosBrandConfig)],
136
+ };
137
+ ```
138
+
139
+ From there, switch between `EtosHorizontalLayoutComponent` and `EtosVerticalLayoutComponent` based on the current `LayoutService.mode()` value, as shown above.
140
+
141
+ ## Using the theme switcher
142
+
143
+ `EtosThemeSwitcherComponent` is exported from `@ojiepermana/angular/etos` and can be mounted in either the horizontal topbar or the vertical sidebar footer.
144
+
145
+ Common inputs:
146
+
147
+ - `userInfo`: object input for the user display data: `name`, `subtitle`, `avatarSrc`, and `avatarAlt`.
148
+ - `quickActions`: required array of action items rendered in the popup footer.
149
+ - `notificationShortcut`: object input for the standalone notification trigger shown beside the avatar in horizontal mode.
150
+ - `popoverAlign` and `popoverSide`: override the popover anchor position.
151
+ - `showNotificationShortcut`: legacy boolean shortcut for rendering the default notification button. Prefer `notificationShortcut` when the data should come from the parent.
152
+
153
+ Horizontal usage:
154
+
155
+ ```html
156
+ <div ui-layout-profile class="etos-profile-trigger gap-2 px-0 py-0">
157
+ <etos-theme-switcher
158
+ [userInfo]="profileInfo"
159
+ [quickActions]="horizontalQuickActions"
160
+ [notificationShortcut]="horizontalNotificationShortcut" />
161
+ </div>
162
+ ```
163
+
164
+ In this mode the trigger shows only the avatar or initials plus the standalone notification shortcut.
165
+
166
+ Vertical usage:
167
+
168
+ ```html
169
+ <div ui-sidebar-footer class="flex h-full w-full min-w-0 items-center justify-start gap-3 px-0 py-0">
170
+ <etos-theme-switcher [userInfo]="profileInfo" [quickActions]="verticalQuickActions" popoverAlign="start" />
171
+
172
+ <div class="min-w-0 flex flex-col gap-px">
173
+ <span class="truncate text-sm font-semibold leading-none text-foreground">Ojie Permana</span>
174
+ <span class="truncate text-xs leading-none text-muted-foreground">Etos design system navigator</span>
175
+ </div>
176
+ </div>
177
+ ```
178
+
179
+ Use `popoverAlign="start"` in the vertical sidebar so the popup opens toward the content area instead of clipping against the left viewport edge.
180
+
181
+ Input shape examples:
182
+
183
+ ```ts
184
+ profileInfo = {
185
+ name: 'Ojie Permana',
186
+ subtitle: 'Etos design system navigator',
187
+ avatarSrc: '/avatar-ojie.svg',
188
+ avatarAlt: 'Portrait of Ojie Permana',
189
+ };
190
+
191
+ horizontalNotificationShortcut = {
192
+ value: 'notifications',
193
+ icon: 'notifications',
194
+ ariaLabel: 'Open notifications for Ojie Permana',
195
+ };
196
+
197
+ verticalQuickActions = [
198
+ { value: 'notifications', label: 'Notifications', icon: 'notifications' },
199
+ { value: 'sign-out', label: 'Logout', icon: 'logout', tone: 'destructive' },
200
+ ];
201
+ ```
202
+
203
+ The popup always exposes theme scheme, layout mode, and layout width controls. The quick action area is fully consumer-driven:
204
+
205
+ - Provide the action values and labels you need in `quickActions`.
206
+ - Handle actions such as logout in the app consumer through `(actionSelected)`.
207
+ - When `notificationShortcut.value` matches one of the `quickActions` values, the matching popup item is removed to avoid duplication.
208
+
209
+ Example consumer-owned action handling:
210
+
211
+ ```html
212
+ <etos-theme-switcher
213
+ [userInfo]="profileInfo"
214
+ [quickActions]="verticalQuickActions"
215
+ (actionSelected)="onThemeSwitcherAction($event)" />
216
+ ```
217
+
218
+ ```ts
219
+ onThemeSwitcherAction(action: string): void {
220
+ if (action === 'sign-out') {
221
+ this.authService.logout();
222
+ }
223
+ }
224
+ ```
225
+
51
226
  ## Workspace usage in this repository
52
227
 
53
228
  The Etos demo under `projects/demo/etos` already uses the short TypeScript entrypoint:
54
229
 
55
230
  - `src/app/app.config.ts` imports `provideEtosBrand` from `@ojiepermana/angular/etos`.
56
- - `src/pages/pages.ts` imports `EtosLayoutComponent` from `@ojiepermana/angular/etos`.
231
+ - `src/pages/pages.ts` imports `EtosHorizontalLayoutComponent`, `EtosVerticalLayoutComponent`, and `EtosThemeSwitcherComponent` from `@ojiepermana/angular/etos`.
57
232
 
58
233
  For CSS, the workspace demo currently imports the Etos source stylesheet directly:
59
234
 
@@ -525,7 +525,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
525
525
  }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
526
526
 
527
527
  const buttonVariants = cva([
528
- 'inline-flex items-center justify-center gap-2 whitespace-nowrap',
528
+ 'inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap',
529
529
  'rounded-md text-sm font-medium',
530
530
  'transition-colors',
531
531
  'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',