cerxos-ui 0.0.6 → 0.0.7
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/fesm2022/cerxos-ui.mjs +189 -2
- package/fesm2022/cerxos-ui.mjs.map +1 -1
- package/index.d.ts +44 -3
- package/package.json +1 -1
package/fesm2022/cerxos-ui.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Component, EventEmitter,
|
|
2
|
+
import { Component, EventEmitter, ElementRef, HostListener, ViewChildren, ViewChild, Output, Input, ChangeDetectionStrategy, Attribute, forwardRef, Directive, ContentChildren, ContentChild } from '@angular/core';
|
|
3
3
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
4
|
import * as i1 from '@angular/common';
|
|
5
5
|
import { NgTemplateOutlet, CommonModule, NgIf } from '@angular/common';
|
|
@@ -21,6 +21,193 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
21
21
|
` }]
|
|
22
22
|
}] });
|
|
23
23
|
|
|
24
|
+
const TRIGGER_BASE_CLASSES = 'inline-flex items-center justify-center rounded-[var(--cxs-radius-md)] p-1.5 ' +
|
|
25
|
+
'text-[var(--cxs-color-on-surface-muted)] transition-colors ' +
|
|
26
|
+
'hover:bg-[var(--cxs-color-surface-hover)] hover:text-[var(--cxs-color-on-surface)] ' +
|
|
27
|
+
'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
|
|
28
|
+
'focus-visible:outline-[var(--cxs-color-focus)]';
|
|
29
|
+
const TRIGGER_DISABLED_CLASSES = 'pointer-events-none opacity-60';
|
|
30
|
+
const MENU_BASE_CLASSES = 'absolute z-40 mt-2 min-w-[10rem] rounded-[var(--cxs-radius-md)] ' +
|
|
31
|
+
'border border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] py-1 ' +
|
|
32
|
+
'shadow-[var(--cxs-shadow-sm)]';
|
|
33
|
+
const MENU_ALIGN_CLASSES = {
|
|
34
|
+
start: 'left-0 origin-top-left',
|
|
35
|
+
end: 'right-0 origin-top-right'
|
|
36
|
+
};
|
|
37
|
+
const ITEM_BASE_CLASSES$1 = 'flex w-full items-center gap-2 rounded-[var(--cxs-radius-sm)] px-3 py-2 text-left text-sm ' +
|
|
38
|
+
'transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
|
|
39
|
+
'focus-visible:outline-[var(--cxs-color-focus)]';
|
|
40
|
+
const ITEM_DEFAULT_CLASSES = 'text-[var(--cxs-color-on-surface)] hover:bg-[var(--cxs-color-surface-hover)]';
|
|
41
|
+
const ITEM_DANGER_CLASSES = 'text-[var(--cxs-color-danger)] hover:bg-[var(--cxs-color-surface-hover)]';
|
|
42
|
+
const ITEM_DISABLED_CLASSES$1 = 'pointer-events-none opacity-60';
|
|
43
|
+
const EMPTY_STATE_CLASSES$1 = 'block px-3 py-2 text-sm text-[var(--cxs-color-on-surface-muted)]';
|
|
44
|
+
class CxsActionMenuComponent {
|
|
45
|
+
elementRef;
|
|
46
|
+
static nextId = 0;
|
|
47
|
+
items = [];
|
|
48
|
+
align = 'end';
|
|
49
|
+
ariaLabel = 'Open actions menu';
|
|
50
|
+
menuLabel = 'Actions';
|
|
51
|
+
disabled = false;
|
|
52
|
+
itemSelected = new EventEmitter();
|
|
53
|
+
trigger;
|
|
54
|
+
menuItems;
|
|
55
|
+
menuId = `cxs-action-menu-${CxsActionMenuComponent.nextId++}`;
|
|
56
|
+
isOpen = false;
|
|
57
|
+
constructor(elementRef) {
|
|
58
|
+
this.elementRef = elementRef;
|
|
59
|
+
}
|
|
60
|
+
get triggerClass() {
|
|
61
|
+
return [TRIGGER_BASE_CLASSES, this.disabled ? TRIGGER_DISABLED_CLASSES : ''].filter(Boolean).join(' ');
|
|
62
|
+
}
|
|
63
|
+
get menuClass() {
|
|
64
|
+
return [MENU_BASE_CLASSES, MENU_ALIGN_CLASSES[this.align]].join(' ');
|
|
65
|
+
}
|
|
66
|
+
get emptyStateClass() {
|
|
67
|
+
return EMPTY_STATE_CLASSES$1;
|
|
68
|
+
}
|
|
69
|
+
isItemDisabled(item) {
|
|
70
|
+
return this.disabled || !!item.disabled;
|
|
71
|
+
}
|
|
72
|
+
getItemClass(item) {
|
|
73
|
+
return [
|
|
74
|
+
ITEM_BASE_CLASSES$1,
|
|
75
|
+
item.tone === 'danger' ? ITEM_DANGER_CLASSES : ITEM_DEFAULT_CLASSES,
|
|
76
|
+
this.isItemDisabled(item) ? ITEM_DISABLED_CLASSES$1 : ''
|
|
77
|
+
]
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.join(' ');
|
|
80
|
+
}
|
|
81
|
+
toggle() {
|
|
82
|
+
if (this.isOpen) {
|
|
83
|
+
this.close();
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
this.open();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
open() {
|
|
90
|
+
if (this.disabled) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.isOpen = true;
|
|
94
|
+
this.focusFirstItem();
|
|
95
|
+
}
|
|
96
|
+
close() {
|
|
97
|
+
this.isOpen = false;
|
|
98
|
+
}
|
|
99
|
+
onTriggerKeydown(event) {
|
|
100
|
+
if (this.disabled) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
this.toggle();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (event.key === 'ArrowDown') {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
this.open();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
onMenuKeydown(event) {
|
|
114
|
+
if (typeof document === 'undefined') {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (event.key === 'Escape') {
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
this.close();
|
|
120
|
+
this.focusTrigger();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const items = this.getFocusableItems();
|
|
124
|
+
if (!items.length) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const currentIndex = items.findIndex((item) => item === document.activeElement);
|
|
128
|
+
let nextIndex = currentIndex;
|
|
129
|
+
switch (event.key) {
|
|
130
|
+
case 'ArrowDown':
|
|
131
|
+
nextIndex = currentIndex >= 0 ? (currentIndex + 1) % items.length : 0;
|
|
132
|
+
break;
|
|
133
|
+
case 'ArrowUp':
|
|
134
|
+
nextIndex = currentIndex >= 0 ? (currentIndex - 1 + items.length) % items.length : items.length - 1;
|
|
135
|
+
break;
|
|
136
|
+
case 'Home':
|
|
137
|
+
nextIndex = 0;
|
|
138
|
+
break;
|
|
139
|
+
case 'End':
|
|
140
|
+
nextIndex = items.length - 1;
|
|
141
|
+
break;
|
|
142
|
+
default:
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
items[nextIndex]?.focus();
|
|
147
|
+
}
|
|
148
|
+
onItemClick(item) {
|
|
149
|
+
if (this.isItemDisabled(item)) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
this.itemSelected.emit(item);
|
|
153
|
+
this.close();
|
|
154
|
+
this.focusTrigger();
|
|
155
|
+
}
|
|
156
|
+
onDocumentClick(event) {
|
|
157
|
+
if (!this.isOpen) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const target = event.target;
|
|
161
|
+
if (target && !this.elementRef.nativeElement.contains(target)) {
|
|
162
|
+
this.close();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
focusFirstItem() {
|
|
166
|
+
if (typeof document === 'undefined') {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
const items = this.getFocusableItems();
|
|
171
|
+
items[0]?.focus();
|
|
172
|
+
}, 0);
|
|
173
|
+
}
|
|
174
|
+
focusTrigger() {
|
|
175
|
+
this.trigger?.nativeElement.focus();
|
|
176
|
+
}
|
|
177
|
+
getFocusableItems() {
|
|
178
|
+
return (this.menuItems?.toArray() ?? [])
|
|
179
|
+
.map((item) => item.nativeElement)
|
|
180
|
+
.filter((item) => !item.hasAttribute('disabled') && !item.hasAttribute('data-disabled'));
|
|
181
|
+
}
|
|
182
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsActionMenuComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
183
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsActionMenuComponent, isStandalone: true, selector: "cxs-action-menu", inputs: { items: "items", align: "align", ariaLabel: "ariaLabel", menuLabel: "menuLabel", disabled: "disabled" }, outputs: { itemSelected: "itemSelected" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, read: ElementRef }, { propertyName: "menuItems", predicate: ["menuItem"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"relative inline-flex\">\n <button\n #trigger\n type=\"button\"\n [class]=\"triggerClass\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-controls]=\"menuId\"\n [attr.aria-label]=\"ariaLabel\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n <svg class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <circle cx=\"4\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"10\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"16\" cy=\"10\" r=\"1.5\"></circle>\n </svg>\n </button>\n\n @if (isOpen) {\n <div\n [class]=\"menuClass\"\n [attr.id]=\"menuId\"\n role=\"menu\"\n [attr.aria-label]=\"menuLabel\"\n (keydown)=\"onMenuKeydown($event)\"\n >\n @if (items.length) {\n @for (item of items; track item.value) {\n <button\n #menuItem\n type=\"button\"\n role=\"menuitem\"\n [class]=\"getItemClass(item)\"\n [attr.data-disabled]=\"isItemDisabled(item) ? '' : null\"\n [attr.aria-disabled]=\"isItemDisabled(item) ? 'true' : null\"\n [disabled]=\"isItemDisabled(item)\"\n (click)=\"onItemClick(item)\"\n >\n {{ item.label }}\n </button>\n }\n } @else {\n <span [class]=\"emptyStateClass\">No actions</span>\n }\n </div>\n }\n</div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
184
|
+
}
|
|
185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsActionMenuComponent, decorators: [{
|
|
186
|
+
type: Component,
|
|
187
|
+
args: [{ selector: 'cxs-action-menu', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative inline-flex\">\n <button\n #trigger\n type=\"button\"\n [class]=\"triggerClass\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-controls]=\"menuId\"\n [attr.aria-label]=\"ariaLabel\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n <svg class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <circle cx=\"4\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"10\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"16\" cy=\"10\" r=\"1.5\"></circle>\n </svg>\n </button>\n\n @if (isOpen) {\n <div\n [class]=\"menuClass\"\n [attr.id]=\"menuId\"\n role=\"menu\"\n [attr.aria-label]=\"menuLabel\"\n (keydown)=\"onMenuKeydown($event)\"\n >\n @if (items.length) {\n @for (item of items; track item.value) {\n <button\n #menuItem\n type=\"button\"\n role=\"menuitem\"\n [class]=\"getItemClass(item)\"\n [attr.data-disabled]=\"isItemDisabled(item) ? '' : null\"\n [attr.aria-disabled]=\"isItemDisabled(item) ? 'true' : null\"\n [disabled]=\"isItemDisabled(item)\"\n (click)=\"onItemClick(item)\"\n >\n {{ item.label }}\n </button>\n }\n } @else {\n <span [class]=\"emptyStateClass\">No actions</span>\n }\n </div>\n }\n</div>\n" }]
|
|
188
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { items: [{
|
|
189
|
+
type: Input
|
|
190
|
+
}], align: [{
|
|
191
|
+
type: Input
|
|
192
|
+
}], ariaLabel: [{
|
|
193
|
+
type: Input
|
|
194
|
+
}], menuLabel: [{
|
|
195
|
+
type: Input
|
|
196
|
+
}], disabled: [{
|
|
197
|
+
type: Input
|
|
198
|
+
}], itemSelected: [{
|
|
199
|
+
type: Output
|
|
200
|
+
}], trigger: [{
|
|
201
|
+
type: ViewChild,
|
|
202
|
+
args: ['trigger', { read: ElementRef }]
|
|
203
|
+
}], menuItems: [{
|
|
204
|
+
type: ViewChildren,
|
|
205
|
+
args: ['menuItem', { read: ElementRef }]
|
|
206
|
+
}], onDocumentClick: [{
|
|
207
|
+
type: HostListener,
|
|
208
|
+
args: ['document:click', ['$event']]
|
|
209
|
+
}] } });
|
|
210
|
+
|
|
24
211
|
const BASE_CLASSES$a = 'relative flex w-full gap-3 rounded-[var(--cxs-radius-md)] border border-l-4 px-4 py-3 text-sm ' +
|
|
25
212
|
'text-[var(--cxs-color-on-surface)]';
|
|
26
213
|
const VARIANT_CLASSES$8 = {
|
|
@@ -3562,5 +3749,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3562
3749
|
* Generated bundle index. Do not edit.
|
|
3563
3750
|
*/
|
|
3564
3751
|
|
|
3565
|
-
export { CerxosUi, CxsAccordionComponent, CxsAccordionItemComponent, CxsAlertComponent, CxsAvatarComponent, CxsBadgeComponent, CxsBreadcrumbComponent, CxsButtonComponent, CxsCardComponent, CxsCarouselComponent, CxsCheckboxComponent, CxsDataTableCellDirective, CxsDataTableComponent, CxsDatepickerComponent, CxsDialogComponent, CxsInputComponent, CxsMenubarComponent, CxsMultiSelectComponent, CxsRadioComponent, CxsSelectComponent, CxsTabLabelDirective, CxsTabPanelComponent, CxsTableComponent, CxsTabsComponent, CxsThemeDirective, CxsToastComponent, CxsToggleComponent, CxsTooltipComponent };
|
|
3752
|
+
export { CerxosUi, CxsAccordionComponent, CxsAccordionItemComponent, CxsActionMenuComponent, CxsAlertComponent, CxsAvatarComponent, CxsBadgeComponent, CxsBreadcrumbComponent, CxsButtonComponent, CxsCardComponent, CxsCarouselComponent, CxsCheckboxComponent, CxsDataTableCellDirective, CxsDataTableComponent, CxsDatepickerComponent, CxsDialogComponent, CxsInputComponent, CxsMenubarComponent, CxsMultiSelectComponent, CxsRadioComponent, CxsSelectComponent, CxsTabLabelDirective, CxsTabPanelComponent, CxsTableComponent, CxsTabsComponent, CxsThemeDirective, CxsToastComponent, CxsToggleComponent, CxsTooltipComponent };
|
|
3566
3753
|
//# sourceMappingURL=cerxos-ui.mjs.map
|