@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 +182 -7
- package/fesm2022/ojiepermana-angular-component.mjs +1 -1
- package/fesm2022/ojiepermana-angular-component.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-etos.mjs +541 -6
- package/fesm2022/ojiepermana-angular-etos.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ojiepermana-angular-component.d.ts +2 -2
- package/types/ojiepermana-angular-etos.d.ts +110 -7
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 {
|
|
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: {
|
|
27
|
-
|
|
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: [
|
|
38
|
-
template:
|
|
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 `
|
|
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',
|