@akcelik/strct 0.3.0 → 0.4.0
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/akcelik-strct.mjs +475 -430
- package/fesm2022/akcelik-strct.mjs.map +1 -1
- package/package.json +1 -1
- package/types/akcelik-strct.d.ts +98 -79
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, DOCUMENT, signal, computed, Injectable, input, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, NgZone, afterNextRender, Directive, booleanAttribute, output, HostListener, model, contentChildren, effect,
|
|
2
|
+
import { inject, DOCUMENT, signal, computed, Injectable, input, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, NgZone, afterNextRender, Directive, booleanAttribute, output, HostListener, model, contentChildren, effect, ApplicationRef, EnvironmentInjector, createComponent, DestroyRef, forwardRef, TemplateRef, contentChild, Renderer2 } from '@angular/core';
|
|
3
3
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
4
4
|
import { DOCUMENT as DOCUMENT$1, NgTemplateOutlet } from '@angular/common';
|
|
5
5
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
@@ -1130,6 +1130,336 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
1130
1130
|
`, host: { class: 'strct-tabs' }, styles: [".strct-tabs{display:block}.strct-tabs__bar{display:flex;gap:2px;border-bottom:1px solid var(--b2)}.strct-tabs__btn{appearance:none;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t2);padding:9px 14px;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color .14s ease,border-color .14s ease}.strct-tabs__btn:hover{color:var(--t1)}.strct-tabs__btn--active{color:var(--acc);border-bottom-color:var(--acc)}.strct-tabs__btn:disabled{color:var(--t4);cursor:not-allowed}.strct-tabs__panels{padding-top:16px}\n"] }]
|
|
1131
1131
|
}], ctorParameters: () => [], propDecorators: { tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctTab), { isSignal: true }] }] } });
|
|
1132
1132
|
|
|
1133
|
+
/**
|
|
1134
|
+
* Floating menu panel — portaled into `<body>` (so it escapes overflow /
|
|
1135
|
+
* transform clipping), positioned by its real measured size, with full keyboard
|
|
1136
|
+
* navigation and recursive submenus. Usually created by `[strctContextMenu]`,
|
|
1137
|
+
* but can be embedded directly with `submenu`.
|
|
1138
|
+
*/
|
|
1139
|
+
class StrctMenuPanel {
|
|
1140
|
+
host = inject(ElementRef);
|
|
1141
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
1142
|
+
data = input(undefined, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
1143
|
+
x = input(0, ...(ngDevMode ? [{ debugName: "x" }] : /* istanbul ignore next */ []));
|
|
1144
|
+
y = input(0, ...(ngDevMode ? [{ debugName: "y" }] : /* istanbul ignore next */ []));
|
|
1145
|
+
submenu = input(false, { ...(ngDevMode ? { debugName: "submenu" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1146
|
+
select = output();
|
|
1147
|
+
close = output();
|
|
1148
|
+
/** ArrowLeft inside a submenu — asks the parent to close it. */
|
|
1149
|
+
back = output();
|
|
1150
|
+
posX = signal(0, ...(ngDevMode ? [{ debugName: "posX" }] : /* istanbul ignore next */ []));
|
|
1151
|
+
posY = signal(0, ...(ngDevMode ? [{ debugName: "posY" }] : /* istanbul ignore next */ []));
|
|
1152
|
+
flipLeft = signal(false, ...(ngDevMode ? [{ debugName: "flipLeft" }] : /* istanbul ignore next */ []));
|
|
1153
|
+
activeIndex = signal(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
1154
|
+
openSubIndex = signal(null, ...(ngDevMode ? [{ debugName: "openSubIndex" }] : /* istanbul ignore next */ []));
|
|
1155
|
+
navIndices = computed(() => this.items()
|
|
1156
|
+
.map((it, i) => (it.divider ? -1 : i))
|
|
1157
|
+
.filter((i) => i >= 0), ...(ngDevMode ? [{ debugName: "navIndices" }] : /* istanbul ignore next */ []));
|
|
1158
|
+
constructor() {
|
|
1159
|
+
this.posX.set(this.x());
|
|
1160
|
+
this.posY.set(this.y());
|
|
1161
|
+
afterNextRender(() => {
|
|
1162
|
+
this.activeIndex.set(this.navIndices()[0] ?? 0);
|
|
1163
|
+
if (!this.submenu())
|
|
1164
|
+
this.clampToViewport();
|
|
1165
|
+
this.focusItem(this.activeIndex());
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
clampToViewport() {
|
|
1169
|
+
const host = this.host.nativeElement;
|
|
1170
|
+
const w = host.offsetWidth;
|
|
1171
|
+
const h = host.offsetHeight;
|
|
1172
|
+
const vw = window.innerWidth;
|
|
1173
|
+
const vh = window.innerHeight;
|
|
1174
|
+
const m = 6;
|
|
1175
|
+
let nx = this.x();
|
|
1176
|
+
let ny = this.y();
|
|
1177
|
+
if (nx + w > vw - m)
|
|
1178
|
+
nx = Math.max(m, Math.min(this.x() - w, vw - w - m));
|
|
1179
|
+
if (ny + h > vh - m)
|
|
1180
|
+
ny = Math.max(m, vh - h - m);
|
|
1181
|
+
this.posX.set(nx);
|
|
1182
|
+
this.posY.set(ny);
|
|
1183
|
+
// Submenus of a panel near the right edge open to the left.
|
|
1184
|
+
this.flipLeft.set(nx + w > vw - 220);
|
|
1185
|
+
}
|
|
1186
|
+
focusItem(i) {
|
|
1187
|
+
this.activeIndex.set(i);
|
|
1188
|
+
this.host.nativeElement
|
|
1189
|
+
.querySelector(`.strct-menu__item[data-idx="${i}"]`)
|
|
1190
|
+
?.focus();
|
|
1191
|
+
}
|
|
1192
|
+
move(dir) {
|
|
1193
|
+
const nav = this.navIndices();
|
|
1194
|
+
if (!nav.length)
|
|
1195
|
+
return;
|
|
1196
|
+
const pos = nav.indexOf(this.activeIndex());
|
|
1197
|
+
const next = nav[(pos + dir + nav.length) % nav.length];
|
|
1198
|
+
this.openSubIndex.set(null);
|
|
1199
|
+
this.focusItem(next);
|
|
1200
|
+
}
|
|
1201
|
+
onHover(i) {
|
|
1202
|
+
this.activeIndex.set(i);
|
|
1203
|
+
const it = this.items()[i];
|
|
1204
|
+
this.openSubIndex.set(it?.children?.length ? i : null);
|
|
1205
|
+
}
|
|
1206
|
+
onLeave(i) {
|
|
1207
|
+
if (this.openSubIndex() === i)
|
|
1208
|
+
this.openSubIndex.set(null);
|
|
1209
|
+
}
|
|
1210
|
+
onItemClick(item, i, event) {
|
|
1211
|
+
event.stopPropagation();
|
|
1212
|
+
if (item.disabled)
|
|
1213
|
+
return;
|
|
1214
|
+
if (item.children?.length) {
|
|
1215
|
+
this.openSubIndex.set(this.openSubIndex() === i ? null : i);
|
|
1216
|
+
this.focusItem(i);
|
|
1217
|
+
}
|
|
1218
|
+
else {
|
|
1219
|
+
this.select.emit(item);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
closeSub() {
|
|
1223
|
+
this.openSubIndex.set(null);
|
|
1224
|
+
}
|
|
1225
|
+
onKeydown(event) {
|
|
1226
|
+
const key = event.key;
|
|
1227
|
+
const item = this.items()[this.activeIndex()];
|
|
1228
|
+
switch (key) {
|
|
1229
|
+
case 'ArrowDown':
|
|
1230
|
+
event.preventDefault();
|
|
1231
|
+
event.stopPropagation();
|
|
1232
|
+
this.move(1);
|
|
1233
|
+
break;
|
|
1234
|
+
case 'ArrowUp':
|
|
1235
|
+
event.preventDefault();
|
|
1236
|
+
event.stopPropagation();
|
|
1237
|
+
this.move(-1);
|
|
1238
|
+
break;
|
|
1239
|
+
case 'Home':
|
|
1240
|
+
event.preventDefault();
|
|
1241
|
+
event.stopPropagation();
|
|
1242
|
+
this.focusItem(this.navIndices()[0] ?? 0);
|
|
1243
|
+
break;
|
|
1244
|
+
case 'End':
|
|
1245
|
+
event.preventDefault();
|
|
1246
|
+
event.stopPropagation();
|
|
1247
|
+
this.focusItem(this.navIndices().at(-1) ?? 0);
|
|
1248
|
+
break;
|
|
1249
|
+
case 'ArrowRight':
|
|
1250
|
+
if (item?.children?.length) {
|
|
1251
|
+
event.preventDefault();
|
|
1252
|
+
event.stopPropagation();
|
|
1253
|
+
this.openSubIndex.set(this.activeIndex());
|
|
1254
|
+
}
|
|
1255
|
+
break;
|
|
1256
|
+
case 'ArrowLeft':
|
|
1257
|
+
event.preventDefault();
|
|
1258
|
+
event.stopPropagation();
|
|
1259
|
+
if (this.openSubIndex() != null)
|
|
1260
|
+
this.closeSub();
|
|
1261
|
+
else if (this.submenu())
|
|
1262
|
+
this.back.emit();
|
|
1263
|
+
break;
|
|
1264
|
+
case 'Enter':
|
|
1265
|
+
case ' ':
|
|
1266
|
+
event.preventDefault();
|
|
1267
|
+
event.stopPropagation();
|
|
1268
|
+
if (item && !item.disabled) {
|
|
1269
|
+
if (item.children?.length)
|
|
1270
|
+
this.openSubIndex.set(this.activeIndex());
|
|
1271
|
+
else
|
|
1272
|
+
this.select.emit(item);
|
|
1273
|
+
}
|
|
1274
|
+
break;
|
|
1275
|
+
case 'Escape':
|
|
1276
|
+
event.preventDefault();
|
|
1277
|
+
event.stopPropagation();
|
|
1278
|
+
this.close.emit();
|
|
1279
|
+
break;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctMenuPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1283
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctMenuPanel, isStandalone: true, selector: "strct-menu-panel", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: false, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: false, transformFunction: null }, submenu: { classPropertyName: "submenu", publicName: "submenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select", close: "close", back: "back" }, host: { properties: { "style.position": "submenu() ? null : 'fixed'", "style.left.px": "submenu() ? null : posX()", "style.top.px": "submenu() ? null : posY()", "style.zIndex": "submenu() ? null : 1100" }, classAttribute: "strct-menu-host" }, ngImport: i0, template: `
|
|
1284
|
+
<div class="strct-menu" role="menu" tabindex="-1" (keydown)="onKeydown($event)">
|
|
1285
|
+
@for (item of items(); track $index; let i = $index) {
|
|
1286
|
+
@if (item.divider) {
|
|
1287
|
+
<div class="strct-menu__sep" role="separator"></div>
|
|
1288
|
+
} @else {
|
|
1289
|
+
<div class="strct-menu__wrap" (mouseenter)="onHover(i)" (mouseleave)="onLeave(i)">
|
|
1290
|
+
<button
|
|
1291
|
+
type="button"
|
|
1292
|
+
class="strct-menu__item"
|
|
1293
|
+
[attr.data-idx]="i"
|
|
1294
|
+
[class.strct-menu__item--danger]="item.danger"
|
|
1295
|
+
[class.strct-menu__item--active]="i === activeIndex()"
|
|
1296
|
+
[disabled]="item.disabled"
|
|
1297
|
+
role="menuitem"
|
|
1298
|
+
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
1299
|
+
[attr.aria-expanded]="item.children?.length ? openSubIndex() === i : null"
|
|
1300
|
+
[attr.tabindex]="i === activeIndex() ? 0 : -1"
|
|
1301
|
+
(click)="onItemClick(item, i, $event)"
|
|
1302
|
+
>
|
|
1303
|
+
@if (item.icon) {
|
|
1304
|
+
<strct-icon class="strct-menu__icon" [name]="item.icon" [size]="14" [strokeWidth]="1.3" />
|
|
1305
|
+
} @else {
|
|
1306
|
+
<span class="strct-menu__icon-spacer" aria-hidden="true"></span>
|
|
1307
|
+
}
|
|
1308
|
+
<span class="strct-menu__label">{{ item.label }}</span>
|
|
1309
|
+
@if (item.children?.length) {
|
|
1310
|
+
<strct-icon class="strct-menu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
1311
|
+
}
|
|
1312
|
+
</button>
|
|
1313
|
+
@if (openSubIndex() === i && item.children?.length) {
|
|
1314
|
+
<strct-menu-panel
|
|
1315
|
+
submenu
|
|
1316
|
+
class="strct-menu__subpanel"
|
|
1317
|
+
[class.strct-menu__subpanel--flip]="flipLeft()"
|
|
1318
|
+
[items]="item.children!"
|
|
1319
|
+
[data]="data()"
|
|
1320
|
+
(select)="select.emit($event)"
|
|
1321
|
+
(close)="close.emit()"
|
|
1322
|
+
(back)="closeSub(); focusItem(i)"
|
|
1323
|
+
/>
|
|
1324
|
+
}
|
|
1325
|
+
</div>
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
</div>
|
|
1329
|
+
`, isInline: true, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:left}.strct-menu__item:hover:not(:disabled),.strct-menu__item--active:not(:disabled){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--danger{color:var(--crt)}.strct-menu__item--danger:hover:not(:disabled),.strct-menu__item--danger.strct-menu__item--active:not(:disabled){background:var(--crt-bg)}.strct-menu__item:disabled{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--danger .strct-menu__icon{color:var(--crt)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;left:100%;margin-left:2px;z-index:1}.strct-menu__subpanel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"], dependencies: [{ kind: "component", type: StrctMenuPanel, selector: "strct-menu-panel", inputs: ["items", "data", "x", "y", "submenu"], outputs: ["select", "close", "back"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1330
|
+
}
|
|
1331
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctMenuPanel, decorators: [{
|
|
1332
|
+
type: Component,
|
|
1333
|
+
args: [{ selector: 'strct-menu-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon], template: `
|
|
1334
|
+
<div class="strct-menu" role="menu" tabindex="-1" (keydown)="onKeydown($event)">
|
|
1335
|
+
@for (item of items(); track $index; let i = $index) {
|
|
1336
|
+
@if (item.divider) {
|
|
1337
|
+
<div class="strct-menu__sep" role="separator"></div>
|
|
1338
|
+
} @else {
|
|
1339
|
+
<div class="strct-menu__wrap" (mouseenter)="onHover(i)" (mouseleave)="onLeave(i)">
|
|
1340
|
+
<button
|
|
1341
|
+
type="button"
|
|
1342
|
+
class="strct-menu__item"
|
|
1343
|
+
[attr.data-idx]="i"
|
|
1344
|
+
[class.strct-menu__item--danger]="item.danger"
|
|
1345
|
+
[class.strct-menu__item--active]="i === activeIndex()"
|
|
1346
|
+
[disabled]="item.disabled"
|
|
1347
|
+
role="menuitem"
|
|
1348
|
+
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
1349
|
+
[attr.aria-expanded]="item.children?.length ? openSubIndex() === i : null"
|
|
1350
|
+
[attr.tabindex]="i === activeIndex() ? 0 : -1"
|
|
1351
|
+
(click)="onItemClick(item, i, $event)"
|
|
1352
|
+
>
|
|
1353
|
+
@if (item.icon) {
|
|
1354
|
+
<strct-icon class="strct-menu__icon" [name]="item.icon" [size]="14" [strokeWidth]="1.3" />
|
|
1355
|
+
} @else {
|
|
1356
|
+
<span class="strct-menu__icon-spacer" aria-hidden="true"></span>
|
|
1357
|
+
}
|
|
1358
|
+
<span class="strct-menu__label">{{ item.label }}</span>
|
|
1359
|
+
@if (item.children?.length) {
|
|
1360
|
+
<strct-icon class="strct-menu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
1361
|
+
}
|
|
1362
|
+
</button>
|
|
1363
|
+
@if (openSubIndex() === i && item.children?.length) {
|
|
1364
|
+
<strct-menu-panel
|
|
1365
|
+
submenu
|
|
1366
|
+
class="strct-menu__subpanel"
|
|
1367
|
+
[class.strct-menu__subpanel--flip]="flipLeft()"
|
|
1368
|
+
[items]="item.children!"
|
|
1369
|
+
[data]="data()"
|
|
1370
|
+
(select)="select.emit($event)"
|
|
1371
|
+
(close)="close.emit()"
|
|
1372
|
+
(back)="closeSub(); focusItem(i)"
|
|
1373
|
+
/>
|
|
1374
|
+
}
|
|
1375
|
+
</div>
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
</div>
|
|
1379
|
+
`, host: {
|
|
1380
|
+
class: 'strct-menu-host',
|
|
1381
|
+
'[style.position]': "submenu() ? null : 'fixed'",
|
|
1382
|
+
'[style.left.px]': 'submenu() ? null : posX()',
|
|
1383
|
+
'[style.top.px]': 'submenu() ? null : posY()',
|
|
1384
|
+
'[style.zIndex]': 'submenu() ? null : 1100',
|
|
1385
|
+
}, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:left}.strct-menu__item:hover:not(:disabled),.strct-menu__item--active:not(:disabled){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--danger{color:var(--crt)}.strct-menu__item--danger:hover:not(:disabled),.strct-menu__item--danger.strct-menu__item--active:not(:disabled){background:var(--crt-bg)}.strct-menu__item:disabled{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--danger .strct-menu__icon{color:var(--crt)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;left:100%;margin-left:2px;z-index:1}.strct-menu__subpanel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"] }]
|
|
1386
|
+
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], x: [{ type: i0.Input, args: [{ isSignal: true, alias: "x", required: false }] }], y: [{ type: i0.Input, args: [{ isSignal: true, alias: "y", required: false }] }], submenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "submenu", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], close: [{ type: i0.Output, args: ["close"] }], back: [{ type: i0.Output, args: ["back"] }] } });
|
|
1387
|
+
/**
|
|
1388
|
+
* Right-click (context) menu driven by a data array. Attach to any trigger; the
|
|
1389
|
+
* menu portals into `<body>` and runs each item's `action` on selection.
|
|
1390
|
+
* <div [strctContextMenu]="menuFor(host)" [strctContextMenuData]="host"
|
|
1391
|
+
* (menuSelect)="onPick($event)">…</div>
|
|
1392
|
+
*/
|
|
1393
|
+
class StrctContextMenuTrigger {
|
|
1394
|
+
appRef = inject(ApplicationRef);
|
|
1395
|
+
envInjector = inject(EnvironmentInjector);
|
|
1396
|
+
zone = inject(NgZone);
|
|
1397
|
+
doc = inject(DOCUMENT$1);
|
|
1398
|
+
items = input.required({ ...(ngDevMode ? { debugName: "items" } : /* istanbul ignore next */ {}), alias: 'strctContextMenu' });
|
|
1399
|
+
data = input(undefined, { ...(ngDevMode ? { debugName: "data" } : /* istanbul ignore next */ {}), alias: 'strctContextMenuData' });
|
|
1400
|
+
menuSelect = output();
|
|
1401
|
+
ref = null;
|
|
1402
|
+
onClose = () => this.zone.run(() => this.closeMenu());
|
|
1403
|
+
onContextMenu(event) {
|
|
1404
|
+
if (!this.items()?.length)
|
|
1405
|
+
return;
|
|
1406
|
+
event.preventDefault();
|
|
1407
|
+
this.openAt(event.clientX, event.clientY);
|
|
1408
|
+
}
|
|
1409
|
+
openAt(x, y) {
|
|
1410
|
+
this.closeMenu();
|
|
1411
|
+
const ref = createComponent(StrctMenuPanel, { environmentInjector: this.envInjector });
|
|
1412
|
+
ref.setInput('items', this.items());
|
|
1413
|
+
ref.setInput('data', this.data());
|
|
1414
|
+
ref.setInput('x', x);
|
|
1415
|
+
ref.setInput('y', y);
|
|
1416
|
+
ref.instance.select.subscribe((item) => {
|
|
1417
|
+
item.action?.(this.data());
|
|
1418
|
+
this.menuSelect.emit(item);
|
|
1419
|
+
this.closeMenu();
|
|
1420
|
+
});
|
|
1421
|
+
ref.instance.close.subscribe(() => this.closeMenu());
|
|
1422
|
+
this.appRef.attachView(ref.hostView);
|
|
1423
|
+
this.doc.body.appendChild(ref.location.nativeElement);
|
|
1424
|
+
this.ref = ref;
|
|
1425
|
+
// Defer global listeners so the opening right-click doesn't immediately close.
|
|
1426
|
+
setTimeout(() => {
|
|
1427
|
+
this.zone.runOutsideAngular(() => {
|
|
1428
|
+
this.doc.addEventListener('mousedown', this.onOutside, true);
|
|
1429
|
+
window.addEventListener('scroll', this.onClose, true);
|
|
1430
|
+
window.addEventListener('resize', this.onClose);
|
|
1431
|
+
});
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
onOutside = (event) => {
|
|
1435
|
+
if (this.ref && !this.ref.location.nativeElement.contains(event.target)) {
|
|
1436
|
+
this.onClose();
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
closeMenu() {
|
|
1440
|
+
if (!this.ref)
|
|
1441
|
+
return;
|
|
1442
|
+
this.doc.removeEventListener('mousedown', this.onOutside, true);
|
|
1443
|
+
window.removeEventListener('scroll', this.onClose, true);
|
|
1444
|
+
window.removeEventListener('resize', this.onClose);
|
|
1445
|
+
this.appRef.detachView(this.ref.hostView);
|
|
1446
|
+
this.ref.destroy();
|
|
1447
|
+
this.ref = null;
|
|
1448
|
+
}
|
|
1449
|
+
ngOnDestroy() {
|
|
1450
|
+
this.closeMenu();
|
|
1451
|
+
}
|
|
1452
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctContextMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1453
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.16", type: StrctContextMenuTrigger, isStandalone: true, selector: "[strctContextMenu]", inputs: { items: { classPropertyName: "items", publicName: "strctContextMenu", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "strctContextMenuData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { menuSelect: "menuSelect" }, host: { listeners: { "contextmenu": "onContextMenu($event)" } }, ngImport: i0 });
|
|
1454
|
+
}
|
|
1455
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctContextMenuTrigger, decorators: [{
|
|
1456
|
+
type: Directive,
|
|
1457
|
+
args: [{ selector: '[strctContextMenu]' }]
|
|
1458
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "strctContextMenu", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "strctContextMenuData", required: false }] }], menuSelect: [{ type: i0.Output, args: ["menuSelect"] }], onContextMenu: [{
|
|
1459
|
+
type: HostListener,
|
|
1460
|
+
args: ['contextmenu', ['$event']]
|
|
1461
|
+
}] } });
|
|
1462
|
+
|
|
1133
1463
|
/**
|
|
1134
1464
|
* Tree node. Two modes:
|
|
1135
1465
|
* - **Content:** nest `<strct-tree-node>` children manually.
|
|
@@ -1148,10 +1478,20 @@ class StrctTreeNode {
|
|
|
1148
1478
|
badge = input('none', ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
|
|
1149
1479
|
active = input(false, ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
|
|
1150
1480
|
expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
1481
|
+
/** Per-node menu resolver (data mode); bubbles down the recursion. */
|
|
1482
|
+
nodeMenu = input(null, ...(ngDevMode ? [{ debugName: "nodeMenu" }] : /* istanbul ignore next */ []));
|
|
1151
1483
|
/** Content-mode click. */
|
|
1152
1484
|
activated = output();
|
|
1153
1485
|
/** Data-mode click — carries the activated node (bubbles to the tree). */
|
|
1154
1486
|
nodeActivated = output();
|
|
1487
|
+
/** Data-mode right-click menu selection (bubbles to the tree). */
|
|
1488
|
+
nodeMenuSelect = output();
|
|
1489
|
+
/** Right-click menu items for this node ([] when no resolver / not data mode). */
|
|
1490
|
+
menuItems = computed(() => {
|
|
1491
|
+
const fn = this.nodeMenu();
|
|
1492
|
+
const n = this.node();
|
|
1493
|
+
return fn && n ? fn(n) : [];
|
|
1494
|
+
}, ...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
1155
1495
|
childNodes = contentChildren(StrctTreeNode, ...(ngDevMode ? [{ debugName: "childNodes" }] : /* istanbul ignore next */ []));
|
|
1156
1496
|
/** Data-mode expansion (seeded from node.expanded on first toggle). */
|
|
1157
1497
|
dataExpanded = signal(null, ...(ngDevMode ? [{ debugName: "dataExpanded" }] : /* istanbul ignore next */ []));
|
|
@@ -1183,13 +1523,21 @@ class StrctTreeNode {
|
|
|
1183
1523
|
else
|
|
1184
1524
|
this.activated.emit();
|
|
1185
1525
|
}
|
|
1526
|
+
onMenuSelect(item) {
|
|
1527
|
+
const n = this.node();
|
|
1528
|
+
if (n)
|
|
1529
|
+
this.nodeMenuSelect.emit({ node: n, item });
|
|
1530
|
+
}
|
|
1186
1531
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTreeNode, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1187
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTreeNode, isStandalone: true, selector: "strct-tree-node", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange", activated: "activated", nodeActivated: "nodeActivated" }, host: { classAttribute: "strct-tnode" }, queries: [{ propertyName: "childNodes", predicate: StrctTreeNode, isSignal: true }], ngImport: i0, template: `
|
|
1532
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTreeNode, isStandalone: true, selector: "strct-tree-node", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, nodeMenu: { classPropertyName: "nodeMenu", publicName: "nodeMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange", activated: "activated", nodeActivated: "nodeActivated", nodeMenuSelect: "nodeMenuSelect" }, host: { classAttribute: "strct-tnode" }, queries: [{ propertyName: "childNodes", predicate: StrctTreeNode, isSignal: true }], ngImport: i0, template: `
|
|
1188
1533
|
<div
|
|
1189
1534
|
class="strct-tnode__row"
|
|
1190
1535
|
[class.strct-tnode__row--active]="displayActive()"
|
|
1191
1536
|
role="treeitem"
|
|
1192
1537
|
[attr.aria-expanded]="hasChildren() ? isOpen() : null"
|
|
1538
|
+
[strctContextMenu]="menuItems()"
|
|
1539
|
+
[strctContextMenuData]="node()"
|
|
1540
|
+
(menuSelect)="onMenuSelect($event)"
|
|
1193
1541
|
(click)="onActivate()"
|
|
1194
1542
|
>
|
|
1195
1543
|
@if (hasChildren()) {
|
|
@@ -1219,23 +1567,31 @@ class StrctTreeNode {
|
|
|
1219
1567
|
<div class="strct-tnode__children" role="group">
|
|
1220
1568
|
@if (node()) {
|
|
1221
1569
|
@for (child of node()!.children ?? []; track $index) {
|
|
1222
|
-
<strct-tree-node
|
|
1570
|
+
<strct-tree-node
|
|
1571
|
+
[node]="child"
|
|
1572
|
+
[nodeMenu]="nodeMenu()"
|
|
1573
|
+
(nodeActivated)="nodeActivated.emit($event)"
|
|
1574
|
+
(nodeMenuSelect)="nodeMenuSelect.emit($event)"
|
|
1575
|
+
/>
|
|
1223
1576
|
}
|
|
1224
1577
|
} @else {
|
|
1225
1578
|
<ng-content />
|
|
1226
1579
|
}
|
|
1227
1580
|
</div>
|
|
1228
1581
|
}
|
|
1229
|
-
`, isInline: true, styles: [".strct-tnode{display:block}.strct-tnode__row{display:flex;align-items:center;gap:7px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1);-webkit-user-select:none;user-select:none}.strct-tnode__row:hover{background:var(--bg-3)}.strct-tnode__row--active{background:var(--acc-m);color:var(--acc);font-weight:500}.strct-tnode__row--active .strct-tnode__icon,.strct-tnode__row--active .strct-tnode__chevron{color:var(--acc)}.strct-tnode__chevron{display:inline-flex;color:var(--t3);transition:transform .15s ease;width:14px;justify-content:center}.strct-tnode__chevron--open{transform:rotate(90deg)}.strct-tnode__spacer{width:14px;flex-shrink:0}.strct-tnode__icon{color:var(--t2);flex-shrink:0}.strct-tnode__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-tnode__children{margin-left:16px}\n"], dependencies: [{ kind: "component", type: StrctTreeNode, selector: "strct-tree-node", inputs: ["node", "label", "icon", "badge", "active", "expanded"], outputs: ["expandedChange", "activated", "nodeActivated"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1582
|
+
`, isInline: true, styles: [".strct-tnode{display:block}.strct-tnode__row{display:flex;align-items:center;gap:7px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1);-webkit-user-select:none;user-select:none}.strct-tnode__row:hover{background:var(--bg-3)}.strct-tnode__row--active{background:var(--acc-m);color:var(--acc);font-weight:500}.strct-tnode__row--active .strct-tnode__icon,.strct-tnode__row--active .strct-tnode__chevron{color:var(--acc)}.strct-tnode__chevron{display:inline-flex;color:var(--t3);transition:transform .15s ease;width:14px;justify-content:center}.strct-tnode__chevron--open{transform:rotate(90deg)}.strct-tnode__spacer{width:14px;flex-shrink:0}.strct-tnode__icon{color:var(--t2);flex-shrink:0}.strct-tnode__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-tnode__children{margin-left:16px}\n"], dependencies: [{ kind: "component", type: StrctTreeNode, selector: "strct-tree-node", inputs: ["node", "label", "icon", "badge", "active", "expanded", "nodeMenu"], outputs: ["expandedChange", "activated", "nodeActivated", "nodeMenuSelect"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }, { kind: "directive", type: StrctContextMenuTrigger, selector: "[strctContextMenu]", inputs: ["strctContextMenu", "strctContextMenuData"], outputs: ["menuSelect"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1230
1583
|
}
|
|
1231
1584
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTreeNode, decorators: [{
|
|
1232
1585
|
type: Component,
|
|
1233
|
-
args: [{ selector: 'strct-tree-node', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon], template: `
|
|
1586
|
+
args: [{ selector: 'strct-tree-node', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon, StrctContextMenuTrigger], template: `
|
|
1234
1587
|
<div
|
|
1235
1588
|
class="strct-tnode__row"
|
|
1236
1589
|
[class.strct-tnode__row--active]="displayActive()"
|
|
1237
1590
|
role="treeitem"
|
|
1238
1591
|
[attr.aria-expanded]="hasChildren() ? isOpen() : null"
|
|
1592
|
+
[strctContextMenu]="menuItems()"
|
|
1593
|
+
[strctContextMenuData]="node()"
|
|
1594
|
+
(menuSelect)="onMenuSelect($event)"
|
|
1239
1595
|
(click)="onActivate()"
|
|
1240
1596
|
>
|
|
1241
1597
|
@if (hasChildren()) {
|
|
@@ -1265,7 +1621,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
1265
1621
|
<div class="strct-tnode__children" role="group">
|
|
1266
1622
|
@if (node()) {
|
|
1267
1623
|
@for (child of node()!.children ?? []; track $index) {
|
|
1268
|
-
<strct-tree-node
|
|
1624
|
+
<strct-tree-node
|
|
1625
|
+
[node]="child"
|
|
1626
|
+
[nodeMenu]="nodeMenu()"
|
|
1627
|
+
(nodeActivated)="nodeActivated.emit($event)"
|
|
1628
|
+
(nodeMenuSelect)="nodeMenuSelect.emit($event)"
|
|
1629
|
+
/>
|
|
1269
1630
|
}
|
|
1270
1631
|
} @else {
|
|
1271
1632
|
<ng-content />
|
|
@@ -1273,7 +1634,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
1273
1634
|
</div>
|
|
1274
1635
|
}
|
|
1275
1636
|
`, host: { class: 'strct-tnode' }, styles: [".strct-tnode{display:block}.strct-tnode__row{display:flex;align-items:center;gap:7px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1);-webkit-user-select:none;user-select:none}.strct-tnode__row:hover{background:var(--bg-3)}.strct-tnode__row--active{background:var(--acc-m);color:var(--acc);font-weight:500}.strct-tnode__row--active .strct-tnode__icon,.strct-tnode__row--active .strct-tnode__chevron{color:var(--acc)}.strct-tnode__chevron{display:inline-flex;color:var(--t3);transition:transform .15s ease;width:14px;justify-content:center}.strct-tnode__chevron--open{transform:rotate(90deg)}.strct-tnode__spacer{width:14px;flex-shrink:0}.strct-tnode__icon{color:var(--t2);flex-shrink:0}.strct-tnode__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-tnode__children{margin-left:16px}\n"] }]
|
|
1276
|
-
}], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], activated: [{ type: i0.Output, args: ["activated"] }], nodeActivated: [{ type: i0.Output, args: ["nodeActivated"] }], childNodes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctTreeNode), { isSignal: true }] }] } });
|
|
1637
|
+
}], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], nodeMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeMenu", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }], nodeActivated: [{ type: i0.Output, args: ["nodeActivated"] }], nodeMenuSelect: [{ type: i0.Output, args: ["nodeMenuSelect"] }], childNodes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctTreeNode), { isSignal: true }] }] } });
|
|
1277
1638
|
/**
|
|
1278
1639
|
* Root container for a tree. Either project `<strct-tree-node>` children, or
|
|
1279
1640
|
* pass `[nodes]` for a fully data-driven, self-recursing tree:
|
|
@@ -1282,31 +1643,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
1282
1643
|
class StrctTree {
|
|
1283
1644
|
/** Data-driven node list; when set, projected content is ignored. */
|
|
1284
1645
|
nodes = input(null, ...(ngDevMode ? [{ debugName: "nodes" }] : /* istanbul ignore next */ []));
|
|
1646
|
+
/** Per-node right-click menu resolver. */
|
|
1647
|
+
nodeMenu = input(null, ...(ngDevMode ? [{ debugName: "nodeMenu" }] : /* istanbul ignore next */ []));
|
|
1285
1648
|
/** Emitted when any data-driven node is clicked. */
|
|
1286
1649
|
nodeActivated = output();
|
|
1650
|
+
/** Emitted when a data-driven node's right-click menu item is chosen. */
|
|
1651
|
+
nodeMenuSelect = output();
|
|
1287
1652
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTree, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1288
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTree, isStandalone: true, selector: "strct-tree", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeActivated: "nodeActivated" }, host: { attributes: { "role": "tree" }, classAttribute: "strct-tree" }, ngImport: i0, template: `
|
|
1653
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTree, isStandalone: true, selector: "strct-tree", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null }, nodeMenu: { classPropertyName: "nodeMenu", publicName: "nodeMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeActivated: "nodeActivated", nodeMenuSelect: "nodeMenuSelect" }, host: { attributes: { "role": "tree" }, classAttribute: "strct-tree" }, ngImport: i0, template: `
|
|
1289
1654
|
@if (nodes(); as ns) {
|
|
1290
1655
|
@for (n of ns; track $index) {
|
|
1291
|
-
<strct-tree-node
|
|
1656
|
+
<strct-tree-node
|
|
1657
|
+
[node]="n"
|
|
1658
|
+
[nodeMenu]="nodeMenu()"
|
|
1659
|
+
(nodeActivated)="nodeActivated.emit($event)"
|
|
1660
|
+
(nodeMenuSelect)="nodeMenuSelect.emit($event)"
|
|
1661
|
+
/>
|
|
1292
1662
|
}
|
|
1293
1663
|
} @else {
|
|
1294
1664
|
<ng-content />
|
|
1295
1665
|
}
|
|
1296
|
-
`, isInline: true, styles: [".strct-tree{display:block}\n"], dependencies: [{ kind: "component", type: StrctTreeNode, selector: "strct-tree-node", inputs: ["node", "label", "icon", "badge", "active", "expanded"], outputs: ["expandedChange", "activated", "nodeActivated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1666
|
+
`, isInline: true, styles: [".strct-tree{display:block}\n"], dependencies: [{ kind: "component", type: StrctTreeNode, selector: "strct-tree-node", inputs: ["node", "label", "icon", "badge", "active", "expanded", "nodeMenu"], outputs: ["expandedChange", "activated", "nodeActivated", "nodeMenuSelect"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1297
1667
|
}
|
|
1298
1668
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTree, decorators: [{
|
|
1299
1669
|
type: Component,
|
|
1300
1670
|
args: [{ selector: 'strct-tree', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctTreeNode], template: `
|
|
1301
1671
|
@if (nodes(); as ns) {
|
|
1302
1672
|
@for (n of ns; track $index) {
|
|
1303
|
-
<strct-tree-node
|
|
1673
|
+
<strct-tree-node
|
|
1674
|
+
[node]="n"
|
|
1675
|
+
[nodeMenu]="nodeMenu()"
|
|
1676
|
+
(nodeActivated)="nodeActivated.emit($event)"
|
|
1677
|
+
(nodeMenuSelect)="nodeMenuSelect.emit($event)"
|
|
1678
|
+
/>
|
|
1304
1679
|
}
|
|
1305
1680
|
} @else {
|
|
1306
1681
|
<ng-content />
|
|
1307
1682
|
}
|
|
1308
1683
|
`, host: { class: 'strct-tree', role: 'tree' }, styles: [".strct-tree{display:block}\n"] }]
|
|
1309
|
-
}], propDecorators: { nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }], nodeActivated: [{ type: i0.Output, args: ["nodeActivated"] }] } });
|
|
1684
|
+
}], propDecorators: { nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }], nodeMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeMenu", required: false }] }], nodeActivated: [{ type: i0.Output, args: ["nodeActivated"] }], nodeMenuSelect: [{ type: i0.Output, args: ["nodeMenuSelect"] }] } });
|
|
1310
1685
|
|
|
1311
1686
|
let modalCounter = 0;
|
|
1312
1687
|
// Body scroll-lock shared across any number of simultaneously open modals.
|
|
@@ -1663,434 +2038,104 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
1663
2038
|
}], propDecorators: { onDocClick: [{
|
|
1664
2039
|
type: HostListener,
|
|
1665
2040
|
args: ['document:click']
|
|
1666
|
-
}], onEscape: [{
|
|
1667
|
-
type: HostListener,
|
|
1668
|
-
args: ['document:keydown.escape']
|
|
1669
|
-
}], onResize: [{
|
|
1670
|
-
type: HostListener,
|
|
1671
|
-
args: ['window:resize']
|
|
1672
|
-
}] } });
|
|
1673
|
-
|
|
1674
|
-
/**
|
|
1675
|
-
* A nested fly-out inside a `strct-context-menu` or `strct-dropdown`. Opens on
|
|
1676
|
-
* hover, click/tap, or the keyboard (Enter / Space / →), and flips to the left
|
|
1677
|
-
* near the right edge of the viewport. Reuse `strct-dropdown-item` for entries.
|
|
1678
|
-
* <strct-submenu label="Power">
|
|
1679
|
-
* <strct-dropdown-item>Power on</strct-dropdown-item>
|
|
1680
|
-
* <strct-dropdown-item>Power off</strct-dropdown-item>
|
|
1681
|
-
* </strct-submenu>
|
|
1682
|
-
*/
|
|
1683
|
-
class StrctSubmenu {
|
|
1684
|
-
host = inject(ElementRef);
|
|
1685
|
-
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1686
|
-
/** Optional leading icon; when omitted the icon column is still reserved so
|
|
1687
|
-
* the label stays aligned with sibling items that do have icons. */
|
|
1688
|
-
icon = input('', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
1689
|
-
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
1690
|
-
/** Open to the left when the fly-out would overflow the right edge. */
|
|
1691
|
-
flip = signal(false, ...(ngDevMode ? [{ debugName: "flip" }] : /* istanbul ignore next */ []));
|
|
1692
|
-
setOpen(value) {
|
|
1693
|
-
if (value) {
|
|
1694
|
-
const rect = this.host.nativeElement.getBoundingClientRect();
|
|
1695
|
-
this.flip.set(rect.right + 190 > window.innerWidth);
|
|
1696
|
-
}
|
|
1697
|
-
this.open.set(value);
|
|
1698
|
-
}
|
|
1699
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSubmenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1700
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctSubmenu, isStandalone: true, selector: "strct-submenu", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-submenu-host" }, ngImport: i0, template: `
|
|
1701
|
-
<div class="strct-submenu" (mouseenter)="setOpen(true)" (mouseleave)="open.set(false)">
|
|
1702
|
-
<div
|
|
1703
|
-
class="strct-submenu__trigger"
|
|
1704
|
-
role="menuitem"
|
|
1705
|
-
tabindex="0"
|
|
1706
|
-
aria-haspopup="menu"
|
|
1707
|
-
[attr.aria-expanded]="open()"
|
|
1708
|
-
(click)="$event.stopPropagation(); setOpen(!open())"
|
|
1709
|
-
(keydown.enter)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
1710
|
-
(keydown.space)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
1711
|
-
(keydown.arrowright)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
1712
|
-
(keydown.arrowleft)="$event.stopPropagation(); open.set(false)"
|
|
1713
|
-
(keydown.escape)="$event.stopPropagation(); open.set(false)"
|
|
1714
|
-
>
|
|
1715
|
-
@if (icon()) {
|
|
1716
|
-
<strct-icon class="strct-submenu__icon" [name]="icon()" [size]="14" [strokeWidth]="1.3" />
|
|
1717
|
-
} @else {
|
|
1718
|
-
<span class="strct-submenu__icon-spacer" aria-hidden="true"></span>
|
|
1719
|
-
}
|
|
1720
|
-
<span class="strct-submenu__label">{{ label() }}<ng-content select="[strctSubmenuLabel]" /></span>
|
|
1721
|
-
<strct-icon class="strct-submenu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
1722
|
-
</div>
|
|
1723
|
-
@if (open()) {
|
|
1724
|
-
<div class="strct-submenu__panel" [class.strct-submenu__panel--flip]="flip()" role="menu">
|
|
1725
|
-
<ng-content />
|
|
1726
|
-
</div>
|
|
1727
|
-
}
|
|
1728
|
-
</div>
|
|
1729
|
-
`, isInline: true, styles: [".strct-submenu{position:relative}.strct-submenu__trigger{display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:default;font-size:13px;color:var(--t1)}.strct-submenu__trigger:hover{background:var(--bg-3)}.strct-submenu__trigger:focus-visible{outline:none;background:var(--bg-3)}.strct-submenu__icon{color:var(--t2);flex-shrink:0}.strct-submenu__icon-spacer{width:14px;flex-shrink:0}.strct-submenu__label{flex:1;display:inline-flex;align-items:center;gap:8px}.strct-submenu__arrow{color:var(--t3)}.strct-submenu__panel{position:absolute;top:-5px;left:100%;z-index:1;min-width:170px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-submenu-in .1s ease}.strct-submenu__panel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-submenu-in{0%{opacity:0;transform:translate(-4px)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1730
|
-
}
|
|
1731
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSubmenu, decorators: [{
|
|
1732
|
-
type: Component,
|
|
1733
|
-
args: [{ selector: 'strct-submenu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon], template: `
|
|
1734
|
-
<div class="strct-submenu" (mouseenter)="setOpen(true)" (mouseleave)="open.set(false)">
|
|
1735
|
-
<div
|
|
1736
|
-
class="strct-submenu__trigger"
|
|
1737
|
-
role="menuitem"
|
|
1738
|
-
tabindex="0"
|
|
1739
|
-
aria-haspopup="menu"
|
|
1740
|
-
[attr.aria-expanded]="open()"
|
|
1741
|
-
(click)="$event.stopPropagation(); setOpen(!open())"
|
|
1742
|
-
(keydown.enter)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
1743
|
-
(keydown.space)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
1744
|
-
(keydown.arrowright)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
1745
|
-
(keydown.arrowleft)="$event.stopPropagation(); open.set(false)"
|
|
1746
|
-
(keydown.escape)="$event.stopPropagation(); open.set(false)"
|
|
1747
|
-
>
|
|
1748
|
-
@if (icon()) {
|
|
1749
|
-
<strct-icon class="strct-submenu__icon" [name]="icon()" [size]="14" [strokeWidth]="1.3" />
|
|
1750
|
-
} @else {
|
|
1751
|
-
<span class="strct-submenu__icon-spacer" aria-hidden="true"></span>
|
|
1752
|
-
}
|
|
1753
|
-
<span class="strct-submenu__label">{{ label() }}<ng-content select="[strctSubmenuLabel]" /></span>
|
|
1754
|
-
<strct-icon class="strct-submenu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
1755
|
-
</div>
|
|
1756
|
-
@if (open()) {
|
|
1757
|
-
<div class="strct-submenu__panel" [class.strct-submenu__panel--flip]="flip()" role="menu">
|
|
1758
|
-
<ng-content />
|
|
1759
|
-
</div>
|
|
1760
|
-
}
|
|
1761
|
-
</div>
|
|
1762
|
-
`, host: { class: 'strct-submenu-host' }, styles: [".strct-submenu{position:relative}.strct-submenu__trigger{display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:default;font-size:13px;color:var(--t1)}.strct-submenu__trigger:hover{background:var(--bg-3)}.strct-submenu__trigger:focus-visible{outline:none;background:var(--bg-3)}.strct-submenu__icon{color:var(--t2);flex-shrink:0}.strct-submenu__icon-spacer{width:14px;flex-shrink:0}.strct-submenu__label{flex:1;display:inline-flex;align-items:center;gap:8px}.strct-submenu__arrow{color:var(--t3)}.strct-submenu__panel{position:absolute;top:-5px;left:100%;z-index:1;min-width:170px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-submenu-in .1s ease}.strct-submenu__panel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-submenu-in{0%{opacity:0;transform:translate(-4px)}}\n"] }]
|
|
1763
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
|
|
1764
|
-
|
|
1765
|
-
/**
|
|
1766
|
-
* Floating menu panel — portaled into `<body>` (so it escapes overflow /
|
|
1767
|
-
* transform clipping), positioned by its real measured size, with full keyboard
|
|
1768
|
-
* navigation and recursive submenus. Usually created by `[strctContextMenu]`,
|
|
1769
|
-
* but can be embedded directly with `submenu`.
|
|
1770
|
-
*/
|
|
1771
|
-
class StrctMenuPanel {
|
|
1772
|
-
host = inject(ElementRef);
|
|
1773
|
-
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
1774
|
-
data = input(undefined, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
1775
|
-
x = input(0, ...(ngDevMode ? [{ debugName: "x" }] : /* istanbul ignore next */ []));
|
|
1776
|
-
y = input(0, ...(ngDevMode ? [{ debugName: "y" }] : /* istanbul ignore next */ []));
|
|
1777
|
-
submenu = input(false, { ...(ngDevMode ? { debugName: "submenu" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1778
|
-
select = output();
|
|
1779
|
-
close = output();
|
|
1780
|
-
/** ArrowLeft inside a submenu — asks the parent to close it. */
|
|
1781
|
-
back = output();
|
|
1782
|
-
posX = signal(0, ...(ngDevMode ? [{ debugName: "posX" }] : /* istanbul ignore next */ []));
|
|
1783
|
-
posY = signal(0, ...(ngDevMode ? [{ debugName: "posY" }] : /* istanbul ignore next */ []));
|
|
1784
|
-
flipLeft = signal(false, ...(ngDevMode ? [{ debugName: "flipLeft" }] : /* istanbul ignore next */ []));
|
|
1785
|
-
activeIndex = signal(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
1786
|
-
openSubIndex = signal(null, ...(ngDevMode ? [{ debugName: "openSubIndex" }] : /* istanbul ignore next */ []));
|
|
1787
|
-
navIndices = computed(() => this.items()
|
|
1788
|
-
.map((it, i) => (it.divider ? -1 : i))
|
|
1789
|
-
.filter((i) => i >= 0), ...(ngDevMode ? [{ debugName: "navIndices" }] : /* istanbul ignore next */ []));
|
|
1790
|
-
constructor() {
|
|
1791
|
-
this.posX.set(this.x());
|
|
1792
|
-
this.posY.set(this.y());
|
|
1793
|
-
afterNextRender(() => {
|
|
1794
|
-
this.activeIndex.set(this.navIndices()[0] ?? 0);
|
|
1795
|
-
if (!this.submenu())
|
|
1796
|
-
this.clampToViewport();
|
|
1797
|
-
this.focusItem(this.activeIndex());
|
|
1798
|
-
});
|
|
1799
|
-
}
|
|
1800
|
-
clampToViewport() {
|
|
1801
|
-
const host = this.host.nativeElement;
|
|
1802
|
-
const w = host.offsetWidth;
|
|
1803
|
-
const h = host.offsetHeight;
|
|
1804
|
-
const vw = window.innerWidth;
|
|
1805
|
-
const vh = window.innerHeight;
|
|
1806
|
-
const m = 6;
|
|
1807
|
-
let nx = this.x();
|
|
1808
|
-
let ny = this.y();
|
|
1809
|
-
if (nx + w > vw - m)
|
|
1810
|
-
nx = Math.max(m, Math.min(this.x() - w, vw - w - m));
|
|
1811
|
-
if (ny + h > vh - m)
|
|
1812
|
-
ny = Math.max(m, vh - h - m);
|
|
1813
|
-
this.posX.set(nx);
|
|
1814
|
-
this.posY.set(ny);
|
|
1815
|
-
// Submenus of a panel near the right edge open to the left.
|
|
1816
|
-
this.flipLeft.set(nx + w > vw - 220);
|
|
1817
|
-
}
|
|
1818
|
-
focusItem(i) {
|
|
1819
|
-
this.activeIndex.set(i);
|
|
1820
|
-
this.host.nativeElement
|
|
1821
|
-
.querySelector(`.strct-menu__item[data-idx="${i}"]`)
|
|
1822
|
-
?.focus();
|
|
1823
|
-
}
|
|
1824
|
-
move(dir) {
|
|
1825
|
-
const nav = this.navIndices();
|
|
1826
|
-
if (!nav.length)
|
|
1827
|
-
return;
|
|
1828
|
-
const pos = nav.indexOf(this.activeIndex());
|
|
1829
|
-
const next = nav[(pos + dir + nav.length) % nav.length];
|
|
1830
|
-
this.openSubIndex.set(null);
|
|
1831
|
-
this.focusItem(next);
|
|
1832
|
-
}
|
|
1833
|
-
onHover(i) {
|
|
1834
|
-
this.activeIndex.set(i);
|
|
1835
|
-
const it = this.items()[i];
|
|
1836
|
-
this.openSubIndex.set(it?.children?.length ? i : null);
|
|
1837
|
-
}
|
|
1838
|
-
onLeave(i) {
|
|
1839
|
-
if (this.openSubIndex() === i)
|
|
1840
|
-
this.openSubIndex.set(null);
|
|
1841
|
-
}
|
|
1842
|
-
onItemClick(item, i, event) {
|
|
1843
|
-
event.stopPropagation();
|
|
1844
|
-
if (item.disabled)
|
|
1845
|
-
return;
|
|
1846
|
-
if (item.children?.length) {
|
|
1847
|
-
this.openSubIndex.set(this.openSubIndex() === i ? null : i);
|
|
1848
|
-
this.focusItem(i);
|
|
1849
|
-
}
|
|
1850
|
-
else {
|
|
1851
|
-
this.select.emit(item);
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
closeSub() {
|
|
1855
|
-
this.openSubIndex.set(null);
|
|
1856
|
-
}
|
|
1857
|
-
onKeydown(event) {
|
|
1858
|
-
const key = event.key;
|
|
1859
|
-
const item = this.items()[this.activeIndex()];
|
|
1860
|
-
switch (key) {
|
|
1861
|
-
case 'ArrowDown':
|
|
1862
|
-
event.preventDefault();
|
|
1863
|
-
event.stopPropagation();
|
|
1864
|
-
this.move(1);
|
|
1865
|
-
break;
|
|
1866
|
-
case 'ArrowUp':
|
|
1867
|
-
event.preventDefault();
|
|
1868
|
-
event.stopPropagation();
|
|
1869
|
-
this.move(-1);
|
|
1870
|
-
break;
|
|
1871
|
-
case 'Home':
|
|
1872
|
-
event.preventDefault();
|
|
1873
|
-
event.stopPropagation();
|
|
1874
|
-
this.focusItem(this.navIndices()[0] ?? 0);
|
|
1875
|
-
break;
|
|
1876
|
-
case 'End':
|
|
1877
|
-
event.preventDefault();
|
|
1878
|
-
event.stopPropagation();
|
|
1879
|
-
this.focusItem(this.navIndices().at(-1) ?? 0);
|
|
1880
|
-
break;
|
|
1881
|
-
case 'ArrowRight':
|
|
1882
|
-
if (item?.children?.length) {
|
|
1883
|
-
event.preventDefault();
|
|
1884
|
-
event.stopPropagation();
|
|
1885
|
-
this.openSubIndex.set(this.activeIndex());
|
|
1886
|
-
}
|
|
1887
|
-
break;
|
|
1888
|
-
case 'ArrowLeft':
|
|
1889
|
-
event.preventDefault();
|
|
1890
|
-
event.stopPropagation();
|
|
1891
|
-
if (this.openSubIndex() != null)
|
|
1892
|
-
this.closeSub();
|
|
1893
|
-
else if (this.submenu())
|
|
1894
|
-
this.back.emit();
|
|
1895
|
-
break;
|
|
1896
|
-
case 'Enter':
|
|
1897
|
-
case ' ':
|
|
1898
|
-
event.preventDefault();
|
|
1899
|
-
event.stopPropagation();
|
|
1900
|
-
if (item && !item.disabled) {
|
|
1901
|
-
if (item.children?.length)
|
|
1902
|
-
this.openSubIndex.set(this.activeIndex());
|
|
1903
|
-
else
|
|
1904
|
-
this.select.emit(item);
|
|
1905
|
-
}
|
|
1906
|
-
break;
|
|
1907
|
-
case 'Escape':
|
|
1908
|
-
event.preventDefault();
|
|
1909
|
-
event.stopPropagation();
|
|
1910
|
-
this.close.emit();
|
|
1911
|
-
break;
|
|
2041
|
+
}], onEscape: [{
|
|
2042
|
+
type: HostListener,
|
|
2043
|
+
args: ['document:keydown.escape']
|
|
2044
|
+
}], onResize: [{
|
|
2045
|
+
type: HostListener,
|
|
2046
|
+
args: ['window:resize']
|
|
2047
|
+
}] } });
|
|
2048
|
+
|
|
2049
|
+
/**
|
|
2050
|
+
* A nested fly-out inside a `strct-context-menu` or `strct-dropdown`. Opens on
|
|
2051
|
+
* hover, click/tap, or the keyboard (Enter / Space / →), and flips to the left
|
|
2052
|
+
* near the right edge of the viewport. Reuse `strct-dropdown-item` for entries.
|
|
2053
|
+
* <strct-submenu label="Power">
|
|
2054
|
+
* <strct-dropdown-item>Power on</strct-dropdown-item>
|
|
2055
|
+
* <strct-dropdown-item>Power off</strct-dropdown-item>
|
|
2056
|
+
* </strct-submenu>
|
|
2057
|
+
*/
|
|
2058
|
+
class StrctSubmenu {
|
|
2059
|
+
host = inject(ElementRef);
|
|
2060
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2061
|
+
/** Optional leading icon; when omitted the icon column is still reserved so
|
|
2062
|
+
* the label stays aligned with sibling items that do have icons. */
|
|
2063
|
+
icon = input('', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
2064
|
+
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
2065
|
+
/** Open to the left when the fly-out would overflow the right edge. */
|
|
2066
|
+
flip = signal(false, ...(ngDevMode ? [{ debugName: "flip" }] : /* istanbul ignore next */ []));
|
|
2067
|
+
setOpen(value) {
|
|
2068
|
+
if (value) {
|
|
2069
|
+
const rect = this.host.nativeElement.getBoundingClientRect();
|
|
2070
|
+
this.flip.set(rect.right + 190 > window.innerWidth);
|
|
1912
2071
|
}
|
|
2072
|
+
this.open.set(value);
|
|
1913
2073
|
}
|
|
1914
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
1915
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type:
|
|
1916
|
-
<div class="strct-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
2074
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSubmenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2075
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctSubmenu, isStandalone: true, selector: "strct-submenu", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-submenu-host" }, ngImport: i0, template: `
|
|
2076
|
+
<div class="strct-submenu" (mouseenter)="setOpen(true)" (mouseleave)="open.set(false)">
|
|
2077
|
+
<div
|
|
2078
|
+
class="strct-submenu__trigger"
|
|
2079
|
+
role="menuitem"
|
|
2080
|
+
tabindex="0"
|
|
2081
|
+
aria-haspopup="menu"
|
|
2082
|
+
[attr.aria-expanded]="open()"
|
|
2083
|
+
(click)="$event.stopPropagation(); setOpen(!open())"
|
|
2084
|
+
(keydown.enter)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
2085
|
+
(keydown.space)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
2086
|
+
(keydown.arrowright)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
2087
|
+
(keydown.arrowleft)="$event.stopPropagation(); open.set(false)"
|
|
2088
|
+
(keydown.escape)="$event.stopPropagation(); open.set(false)"
|
|
2089
|
+
>
|
|
2090
|
+
@if (icon()) {
|
|
2091
|
+
<strct-icon class="strct-submenu__icon" [name]="icon()" [size]="14" [strokeWidth]="1.3" />
|
|
1920
2092
|
} @else {
|
|
1921
|
-
<
|
|
1922
|
-
<button
|
|
1923
|
-
type="button"
|
|
1924
|
-
class="strct-menu__item"
|
|
1925
|
-
[attr.data-idx]="i"
|
|
1926
|
-
[class.strct-menu__item--danger]="item.danger"
|
|
1927
|
-
[class.strct-menu__item--active]="i === activeIndex()"
|
|
1928
|
-
[disabled]="item.disabled"
|
|
1929
|
-
role="menuitem"
|
|
1930
|
-
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
1931
|
-
[attr.aria-expanded]="item.children?.length ? openSubIndex() === i : null"
|
|
1932
|
-
[attr.tabindex]="i === activeIndex() ? 0 : -1"
|
|
1933
|
-
(click)="onItemClick(item, i, $event)"
|
|
1934
|
-
>
|
|
1935
|
-
@if (item.icon) {
|
|
1936
|
-
<strct-icon class="strct-menu__icon" [name]="item.icon" [size]="14" [strokeWidth]="1.3" />
|
|
1937
|
-
} @else {
|
|
1938
|
-
<span class="strct-menu__icon-spacer" aria-hidden="true"></span>
|
|
1939
|
-
}
|
|
1940
|
-
<span class="strct-menu__label">{{ item.label }}</span>
|
|
1941
|
-
@if (item.children?.length) {
|
|
1942
|
-
<strct-icon class="strct-menu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
1943
|
-
}
|
|
1944
|
-
</button>
|
|
1945
|
-
@if (openSubIndex() === i && item.children?.length) {
|
|
1946
|
-
<strct-menu-panel
|
|
1947
|
-
submenu
|
|
1948
|
-
class="strct-menu__subpanel"
|
|
1949
|
-
[class.strct-menu__subpanel--flip]="flipLeft()"
|
|
1950
|
-
[items]="item.children!"
|
|
1951
|
-
[data]="data()"
|
|
1952
|
-
(select)="select.emit($event)"
|
|
1953
|
-
(close)="close.emit()"
|
|
1954
|
-
(back)="closeSub(); focusItem(i)"
|
|
1955
|
-
/>
|
|
1956
|
-
}
|
|
1957
|
-
</div>
|
|
2093
|
+
<span class="strct-submenu__icon-spacer" aria-hidden="true"></span>
|
|
1958
2094
|
}
|
|
2095
|
+
<span class="strct-submenu__label">{{ label() }}<ng-content select="[strctSubmenuLabel]" /></span>
|
|
2096
|
+
<strct-icon class="strct-submenu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
2097
|
+
</div>
|
|
2098
|
+
@if (open()) {
|
|
2099
|
+
<div class="strct-submenu__panel" [class.strct-submenu__panel--flip]="flip()" role="menu">
|
|
2100
|
+
<ng-content />
|
|
2101
|
+
</div>
|
|
1959
2102
|
}
|
|
1960
2103
|
</div>
|
|
1961
|
-
`, isInline: true, styles: [".strct-
|
|
2104
|
+
`, isInline: true, styles: [".strct-submenu{position:relative}.strct-submenu__trigger{display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:default;font-size:13px;color:var(--t1)}.strct-submenu__trigger:hover{background:var(--bg-3)}.strct-submenu__trigger:focus-visible{outline:none;background:var(--bg-3)}.strct-submenu__icon{color:var(--t2);flex-shrink:0}.strct-submenu__icon-spacer{width:14px;flex-shrink:0}.strct-submenu__label{flex:1;display:inline-flex;align-items:center;gap:8px}.strct-submenu__arrow{color:var(--t3)}.strct-submenu__panel{position:absolute;top:-5px;left:100%;z-index:1;min-width:170px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-submenu-in .1s ease}.strct-submenu__panel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-submenu-in{0%{opacity:0;transform:translate(-4px)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1962
2105
|
}
|
|
1963
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
2106
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSubmenu, decorators: [{
|
|
1964
2107
|
type: Component,
|
|
1965
|
-
args: [{ selector: 'strct-
|
|
1966
|
-
<div class="strct-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2108
|
+
args: [{ selector: 'strct-submenu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon], template: `
|
|
2109
|
+
<div class="strct-submenu" (mouseenter)="setOpen(true)" (mouseleave)="open.set(false)">
|
|
2110
|
+
<div
|
|
2111
|
+
class="strct-submenu__trigger"
|
|
2112
|
+
role="menuitem"
|
|
2113
|
+
tabindex="0"
|
|
2114
|
+
aria-haspopup="menu"
|
|
2115
|
+
[attr.aria-expanded]="open()"
|
|
2116
|
+
(click)="$event.stopPropagation(); setOpen(!open())"
|
|
2117
|
+
(keydown.enter)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
2118
|
+
(keydown.space)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
2119
|
+
(keydown.arrowright)="$event.preventDefault(); $event.stopPropagation(); setOpen(true)"
|
|
2120
|
+
(keydown.arrowleft)="$event.stopPropagation(); open.set(false)"
|
|
2121
|
+
(keydown.escape)="$event.stopPropagation(); open.set(false)"
|
|
2122
|
+
>
|
|
2123
|
+
@if (icon()) {
|
|
2124
|
+
<strct-icon class="strct-submenu__icon" [name]="icon()" [size]="14" [strokeWidth]="1.3" />
|
|
1970
2125
|
} @else {
|
|
1971
|
-
<
|
|
1972
|
-
<button
|
|
1973
|
-
type="button"
|
|
1974
|
-
class="strct-menu__item"
|
|
1975
|
-
[attr.data-idx]="i"
|
|
1976
|
-
[class.strct-menu__item--danger]="item.danger"
|
|
1977
|
-
[class.strct-menu__item--active]="i === activeIndex()"
|
|
1978
|
-
[disabled]="item.disabled"
|
|
1979
|
-
role="menuitem"
|
|
1980
|
-
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
1981
|
-
[attr.aria-expanded]="item.children?.length ? openSubIndex() === i : null"
|
|
1982
|
-
[attr.tabindex]="i === activeIndex() ? 0 : -1"
|
|
1983
|
-
(click)="onItemClick(item, i, $event)"
|
|
1984
|
-
>
|
|
1985
|
-
@if (item.icon) {
|
|
1986
|
-
<strct-icon class="strct-menu__icon" [name]="item.icon" [size]="14" [strokeWidth]="1.3" />
|
|
1987
|
-
} @else {
|
|
1988
|
-
<span class="strct-menu__icon-spacer" aria-hidden="true"></span>
|
|
1989
|
-
}
|
|
1990
|
-
<span class="strct-menu__label">{{ item.label }}</span>
|
|
1991
|
-
@if (item.children?.length) {
|
|
1992
|
-
<strct-icon class="strct-menu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
1993
|
-
}
|
|
1994
|
-
</button>
|
|
1995
|
-
@if (openSubIndex() === i && item.children?.length) {
|
|
1996
|
-
<strct-menu-panel
|
|
1997
|
-
submenu
|
|
1998
|
-
class="strct-menu__subpanel"
|
|
1999
|
-
[class.strct-menu__subpanel--flip]="flipLeft()"
|
|
2000
|
-
[items]="item.children!"
|
|
2001
|
-
[data]="data()"
|
|
2002
|
-
(select)="select.emit($event)"
|
|
2003
|
-
(close)="close.emit()"
|
|
2004
|
-
(back)="closeSub(); focusItem(i)"
|
|
2005
|
-
/>
|
|
2006
|
-
}
|
|
2007
|
-
</div>
|
|
2126
|
+
<span class="strct-submenu__icon-spacer" aria-hidden="true"></span>
|
|
2008
2127
|
}
|
|
2128
|
+
<span class="strct-submenu__label">{{ label() }}<ng-content select="[strctSubmenuLabel]" /></span>
|
|
2129
|
+
<strct-icon class="strct-submenu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
|
|
2130
|
+
</div>
|
|
2131
|
+
@if (open()) {
|
|
2132
|
+
<div class="strct-submenu__panel" [class.strct-submenu__panel--flip]="flip()" role="menu">
|
|
2133
|
+
<ng-content />
|
|
2134
|
+
</div>
|
|
2009
2135
|
}
|
|
2010
2136
|
</div>
|
|
2011
|
-
`, host: {
|
|
2012
|
-
|
|
2013
|
-
'[style.position]': "submenu() ? null : 'fixed'",
|
|
2014
|
-
'[style.left.px]': 'submenu() ? null : posX()',
|
|
2015
|
-
'[style.top.px]': 'submenu() ? null : posY()',
|
|
2016
|
-
'[style.zIndex]': 'submenu() ? null : 1100',
|
|
2017
|
-
}, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:left}.strct-menu__item:hover:not(:disabled),.strct-menu__item--active:not(:disabled){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--danger{color:var(--crt)}.strct-menu__item--danger:hover:not(:disabled),.strct-menu__item--danger.strct-menu__item--active:not(:disabled){background:var(--crt-bg)}.strct-menu__item:disabled{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--danger .strct-menu__icon{color:var(--crt)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;left:100%;margin-left:2px;z-index:1}.strct-menu__subpanel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"] }]
|
|
2018
|
-
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], x: [{ type: i0.Input, args: [{ isSignal: true, alias: "x", required: false }] }], y: [{ type: i0.Input, args: [{ isSignal: true, alias: "y", required: false }] }], submenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "submenu", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], close: [{ type: i0.Output, args: ["close"] }], back: [{ type: i0.Output, args: ["back"] }] } });
|
|
2019
|
-
/**
|
|
2020
|
-
* Right-click (context) menu driven by a data array. Attach to any trigger; the
|
|
2021
|
-
* menu portals into `<body>` and runs each item's `action` on selection.
|
|
2022
|
-
* <div [strctContextMenu]="menuFor(host)" [strctContextMenuData]="host"
|
|
2023
|
-
* (menuSelect)="onPick($event)">…</div>
|
|
2024
|
-
*/
|
|
2025
|
-
class StrctContextMenuTrigger {
|
|
2026
|
-
appRef = inject(ApplicationRef);
|
|
2027
|
-
envInjector = inject(EnvironmentInjector);
|
|
2028
|
-
zone = inject(NgZone);
|
|
2029
|
-
doc = inject(DOCUMENT$1);
|
|
2030
|
-
items = input.required({ ...(ngDevMode ? { debugName: "items" } : /* istanbul ignore next */ {}), alias: 'strctContextMenu' });
|
|
2031
|
-
data = input(undefined, { ...(ngDevMode ? { debugName: "data" } : /* istanbul ignore next */ {}), alias: 'strctContextMenuData' });
|
|
2032
|
-
menuSelect = output();
|
|
2033
|
-
ref = null;
|
|
2034
|
-
onClose = () => this.zone.run(() => this.closeMenu());
|
|
2035
|
-
onContextMenu(event) {
|
|
2036
|
-
if (!this.items()?.length)
|
|
2037
|
-
return;
|
|
2038
|
-
event.preventDefault();
|
|
2039
|
-
this.openAt(event.clientX, event.clientY);
|
|
2040
|
-
}
|
|
2041
|
-
openAt(x, y) {
|
|
2042
|
-
this.closeMenu();
|
|
2043
|
-
const ref = createComponent(StrctMenuPanel, { environmentInjector: this.envInjector });
|
|
2044
|
-
ref.setInput('items', this.items());
|
|
2045
|
-
ref.setInput('data', this.data());
|
|
2046
|
-
ref.setInput('x', x);
|
|
2047
|
-
ref.setInput('y', y);
|
|
2048
|
-
ref.instance.select.subscribe((item) => {
|
|
2049
|
-
item.action?.(this.data());
|
|
2050
|
-
this.menuSelect.emit(item);
|
|
2051
|
-
this.closeMenu();
|
|
2052
|
-
});
|
|
2053
|
-
ref.instance.close.subscribe(() => this.closeMenu());
|
|
2054
|
-
this.appRef.attachView(ref.hostView);
|
|
2055
|
-
this.doc.body.appendChild(ref.location.nativeElement);
|
|
2056
|
-
this.ref = ref;
|
|
2057
|
-
// Defer global listeners so the opening right-click doesn't immediately close.
|
|
2058
|
-
setTimeout(() => {
|
|
2059
|
-
this.zone.runOutsideAngular(() => {
|
|
2060
|
-
this.doc.addEventListener('mousedown', this.onOutside, true);
|
|
2061
|
-
window.addEventListener('scroll', this.onClose, true);
|
|
2062
|
-
window.addEventListener('resize', this.onClose);
|
|
2063
|
-
});
|
|
2064
|
-
});
|
|
2065
|
-
}
|
|
2066
|
-
onOutside = (event) => {
|
|
2067
|
-
if (this.ref && !this.ref.location.nativeElement.contains(event.target)) {
|
|
2068
|
-
this.onClose();
|
|
2069
|
-
}
|
|
2070
|
-
};
|
|
2071
|
-
closeMenu() {
|
|
2072
|
-
if (!this.ref)
|
|
2073
|
-
return;
|
|
2074
|
-
this.doc.removeEventListener('mousedown', this.onOutside, true);
|
|
2075
|
-
window.removeEventListener('scroll', this.onClose, true);
|
|
2076
|
-
window.removeEventListener('resize', this.onClose);
|
|
2077
|
-
this.appRef.detachView(this.ref.hostView);
|
|
2078
|
-
this.ref.destroy();
|
|
2079
|
-
this.ref = null;
|
|
2080
|
-
}
|
|
2081
|
-
ngOnDestroy() {
|
|
2082
|
-
this.closeMenu();
|
|
2083
|
-
}
|
|
2084
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctContextMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2085
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.16", type: StrctContextMenuTrigger, isStandalone: true, selector: "[strctContextMenu]", inputs: { items: { classPropertyName: "items", publicName: "strctContextMenu", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "strctContextMenuData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { menuSelect: "menuSelect" }, host: { listeners: { "contextmenu": "onContextMenu($event)" } }, ngImport: i0 });
|
|
2086
|
-
}
|
|
2087
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctContextMenuTrigger, decorators: [{
|
|
2088
|
-
type: Directive,
|
|
2089
|
-
args: [{ selector: '[strctContextMenu]' }]
|
|
2090
|
-
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "strctContextMenu", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "strctContextMenuData", required: false }] }], menuSelect: [{ type: i0.Output, args: ["menuSelect"] }], onContextMenu: [{
|
|
2091
|
-
type: HostListener,
|
|
2092
|
-
args: ['contextmenu', ['$event']]
|
|
2093
|
-
}] } });
|
|
2137
|
+
`, host: { class: 'strct-submenu-host' }, styles: [".strct-submenu{position:relative}.strct-submenu__trigger{display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:default;font-size:13px;color:var(--t1)}.strct-submenu__trigger:hover{background:var(--bg-3)}.strct-submenu__trigger:focus-visible{outline:none;background:var(--bg-3)}.strct-submenu__icon{color:var(--t2);flex-shrink:0}.strct-submenu__icon-spacer{width:14px;flex-shrink:0}.strct-submenu__label{flex:1;display:inline-flex;align-items:center;gap:8px}.strct-submenu__arrow{color:var(--t3)}.strct-submenu__panel{position:absolute;top:-5px;left:100%;z-index:1;min-width:170px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-submenu-in .1s ease}.strct-submenu__panel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-submenu-in{0%{opacity:0;transform:translate(-4px)}}\n"] }]
|
|
2138
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
|
|
2094
2139
|
|
|
2095
2140
|
/** A single wizard step. `label` names it in the step header. */
|
|
2096
2141
|
class StrctStep {
|
|
@@ -3945,7 +3990,7 @@ class StrctCombobox {
|
|
|
3945
3990
|
}
|
|
3946
3991
|
</div>
|
|
3947
3992
|
}
|
|
3948
|
-
`, isInline: true, styles: [".strct-cbx{position:relative;display:
|
|
3993
|
+
`, isInline: true, styles: [".strct-cbx{position:relative;display:block;width:100%}.strct-cbx__field{position:relative}.strct-cbx__input{padding-right:30px}.strct-cbx__caret{position:absolute;right:9px;top:50%;transform:translateY(-50%);color:var(--t3);pointer-events:none}.strct-cbx__menu{z-index:200;max-height:220px;overflow-y:auto;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}.strct-cbx__opt{padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-cbx__opt--highlight{background:var(--bg-3)}.strct-cbx__opt--active{color:var(--acc)}.strct-cbx__opt--active.strct-cbx__opt--highlight{background:var(--acc-m)}.strct-cbx__empty{padding:9px 10px;font-size:13px;color:var(--t3)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3949
3994
|
}
|
|
3950
3995
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCombobox, decorators: [{
|
|
3951
3996
|
type: Component,
|
|
@@ -3999,7 +4044,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
3999
4044
|
}
|
|
4000
4045
|
</div>
|
|
4001
4046
|
}
|
|
4002
|
-
`, host: { class: 'strct-cbx' }, styles: [".strct-cbx{position:relative;display:
|
|
4047
|
+
`, host: { class: 'strct-cbx' }, styles: [".strct-cbx{position:relative;display:block;width:100%}.strct-cbx__field{position:relative}.strct-cbx__input{padding-right:30px}.strct-cbx__caret{position:absolute;right:9px;top:50%;transform:translateY(-50%);color:var(--t3);pointer-events:none}.strct-cbx__menu{z-index:200;max-height:220px;overflow-y:auto;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}.strct-cbx__opt{padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-cbx__opt--highlight{background:var(--bg-3)}.strct-cbx__opt--active{color:var(--acc)}.strct-cbx__opt--active.strct-cbx__opt--highlight{background:var(--acc-m)}.strct-cbx__empty{padding:9px 10px;font-size:13px;color:var(--t3)}\n"] }]
|
|
4003
4048
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], onDocClick: [{
|
|
4004
4049
|
type: HostListener,
|
|
4005
4050
|
args: ['document:click', ['$event']]
|