@besaitech/ng-design-system 0.0.68 → 0.0.69

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.
@@ -18321,7 +18321,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
18321
18321
  * - **Collapsible** (`[collapsible]`) — the label becomes a button that expands and collapses the
18322
18322
  * group. Set `[basePath]` and the group opens itself whenever the active route is inside it, so a
18323
18323
  * deep link or a browser Back lands with the right section already open instead of the person
18324
- * having to find and re-open it.
18324
+ * having to find and re-open it. A group whose pages live under several prefixes (a business area
18325
+ * grouping `/people`, `/customers`, `/drivers`) lists them all in `[basePaths]`.
18326
+ *
18327
+ * A collapsible group can carry a `[badge]` of its own — typically the sum of its children's. It is
18328
+ * drawn on the header only while the children are hidden, so a closed section still says that
18329
+ * something inside it is waiting, and an open one does not show the same count twice.
18325
18330
  *
18326
18331
  * Collapsible mode exists because a flat rail stops scaling somewhere around a dozen destinations,
18327
18332
  * and the alternative — showing every child of every section at once — buries the ones in use.
@@ -18343,6 +18348,22 @@ class SdsNavGroup {
18343
18348
  * group counts as active and opens itself — unless the person has explicitly toggled it since.
18344
18349
  */
18345
18350
  basePath = input(null, ...(ngDevMode ? [{ debugName: "basePath" }] : []));
18351
+ /**
18352
+ * More URL prefixes owned by this group, for an area whose pages don't share one root
18353
+ * (`['/people', '/customers', '/drivers']`). Matched exactly like {@link basePath}, alongside it.
18354
+ */
18355
+ basePaths = input(null, ...(ngDevMode ? [{ debugName: "basePaths" }] : []));
18356
+ /**
18357
+ * A count for the header, e.g. the items waiting across the group's children. Drawn only while the
18358
+ * children are hidden; null or 0 shows nothing.
18359
+ */
18360
+ badge = input(null, ...(ngDevMode ? [{ debugName: "badge" }] : []));
18361
+ /** Spoken text for the badge; `{count}` is replaced. Pass a translated string. */
18362
+ badgeLabel = input('{count} pending', ...(ngDevMode ? [{ debugName: "badgeLabel" }] : []));
18363
+ /** Counts above this read as "max+" (e.g. 99+). */
18364
+ badgeMax = input(99, ...(ngDevMode ? [{ debugName: "badgeMax" }] : []));
18365
+ /** Badge colour, as on {@link SdsNavItem}. */
18366
+ badgeTone = input('brand', ...(ngDevMode ? [{ debugName: "badgeTone" }] : []));
18346
18367
  /** Emits the new state on every manual toggle. Not emitted for route-driven auto-expansion. */
18347
18368
  expandedChange = output();
18348
18369
  /** Explicit user choice; null means "follow the route". */
@@ -18354,20 +18375,50 @@ class SdsNavGroup {
18354
18375
  * first).
18355
18376
  */
18356
18377
  routeActive = computed(() => {
18357
- const base = this.basePath();
18358
- if (!base)
18378
+ const bases = [this.basePath(), ...(this.basePaths() ?? [])].filter((b) => !!b);
18379
+ if (!bases.length)
18359
18380
  return false;
18360
18381
  const path = this.url().split(/[?#]/)[0];
18361
- return path === base || path.startsWith(base + '/');
18382
+ return bases.some((base) => path === base || path.startsWith(base + '/'));
18362
18383
  }, ...(ngDevMode ? [{ debugName: "routeActive" }] : []));
18363
18384
  expanded = computed(() => this.manual() ?? this.routeActive(), ...(ngDevMode ? [{ debugName: "expanded" }] : []));
18364
18385
  collapsed = this.store.collapsed;
18386
+ /** The header badge's spoken text — only while the children (which show their own) are hidden. */
18387
+ headerBadgeText = computed(() => {
18388
+ const n = this.badge();
18389
+ if (n === null || n === undefined || !Number.isFinite(n) || n <= 0)
18390
+ return null;
18391
+ if (this.collapsible() && this.childrenVisible())
18392
+ return null;
18393
+ return this.badgeLabel().replace('{count}', String(n));
18394
+ }, ...(ngDevMode ? [{ debugName: "headerBadgeText" }] : []));
18395
+ badgeDisplay = computed(() => {
18396
+ const n = this.badge() ?? 0;
18397
+ return n > this.badgeMax() ? `${this.badgeMax()}+` : String(n);
18398
+ }, ...(ngDevMode ? [{ debugName: "badgeDisplay" }] : []));
18399
+ /** The same pill as {@link SdsNavItem}'s, pinned to the icon's corner on the collapsed rail. */
18400
+ badgeClass = computed(() => {
18401
+ const tone = this.badgeTone() === 'danger'
18402
+ ? 'bg-danger text-white'
18403
+ : this.badgeTone() === 'neutral'
18404
+ ? 'bg-muted text-ink-soft border border-border'
18405
+ : this.store.appearance() === 'surface'
18406
+ ? `bg-brand-600 text-white ${DARK_PRIMARY_BG} ${DARK_ON_PRIMARY}`
18407
+ : 'bg-white text-brand-800';
18408
+ const base = 'inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 ' +
18409
+ 'text-[11px] font-bold tabular-nums leading-none';
18410
+ const collapsed = this.collapsed()
18411
+ ? ' lg:absolute lg:right-1.5 lg:top-0.5 lg:h-4 lg:min-w-4 lg:px-1 lg:text-[10px]' +
18412
+ (this.store.appearance() === 'surface' ? ' lg:ring-2 lg:ring-surface' : '')
18413
+ : '';
18414
+ return `${base} ${tone}${collapsed}`;
18415
+ }, ...(ngDevMode ? [{ debugName: "badgeClass" }] : []));
18365
18416
  /** Rail paint, shared via the store — see SidebarStore.appearance. Drives the header/caption tones. */
18366
18417
  surface = computed(() => this.store.appearance() === 'surface', ...(ngDevMode ? [{ debugName: "surface" }] : []));
18367
18418
  /** Collapsible header, painted for the active rail (ink+brand on `surface`, white on `brand`). */
18368
18419
  headerClass = computed(() => {
18369
18420
  const s = this.surface();
18370
- const base = 'mb-1 flex h-10 w-full items-center gap-3 rounded-control px-3 text-sm font-medium ' +
18421
+ const base = 'relative mb-1 flex h-10 w-full items-center gap-3 rounded-control px-3 text-sm font-medium ' +
18371
18422
  'transition-colors focus-visible:outline-none focus-visible:ring-2 ' +
18372
18423
  (this.collapsed() ? 'lg:justify-center ' : '') +
18373
18424
  (s
@@ -18416,7 +18467,7 @@ class SdsNavGroup {
18416
18467
  this.expandedChange.emit(next);
18417
18468
  }
18418
18469
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsNavGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
18419
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsNavGroup, isStandalone: true, selector: "sds-nav-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandedChange: "expandedChange" }, host: { classAttribute: "block" }, ngImport: i0, template: `
18470
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsNavGroup, isStandalone: true, selector: "sds-nav-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null }, basePaths: { classPropertyName: "basePaths", publicName: "basePaths", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, badgeLabel: { classPropertyName: "badgeLabel", publicName: "badgeLabel", isSignal: true, isRequired: false, transformFunction: null }, badgeMax: { classPropertyName: "badgeMax", publicName: "badgeMax", isSignal: true, isRequired: false, transformFunction: null }, badgeTone: { classPropertyName: "badgeTone", publicName: "badgeTone", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandedChange: "expandedChange" }, host: { classAttribute: "block" }, ngImport: i0, template: `
18420
18471
  <div class="mt-5 first:mt-3">
18421
18472
  @if (label()) {
18422
18473
  @if (collapsible()) {
@@ -18445,6 +18496,10 @@ class SdsNavGroup {
18445
18496
  <span class="flex-1 truncate text-left" [class.lg:hidden]="collapsed()">
18446
18497
  {{ label() }}
18447
18498
  </span>
18499
+ @if (headerBadgeText(); as text) {
18500
+ <span [class]="badgeClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
18501
+ <span class="sr-only">, {{ text }}</span>
18502
+ }
18448
18503
  <sds-icon
18449
18504
  name="chevron-down"
18450
18505
  [size]="16"
@@ -18504,6 +18559,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
18504
18559
  <span class="flex-1 truncate text-left" [class.lg:hidden]="collapsed()">
18505
18560
  {{ label() }}
18506
18561
  </span>
18562
+ @if (headerBadgeText(); as text) {
18563
+ <span [class]="badgeClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
18564
+ <span class="sr-only">, {{ text }}</span>
18565
+ }
18507
18566
  <sds-icon
18508
18567
  name="chevron-down"
18509
18568
  [size]="16"
@@ -18527,7 +18586,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
18527
18586
  </div>
18528
18587
  `,
18529
18588
  }]
18530
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], basePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "basePath", required: false }] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }] } });
18589
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], basePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "basePath", required: false }] }], basePaths: [{ type: i0.Input, args: [{ isSignal: true, alias: "basePaths", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], badgeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeLabel", required: false }] }], badgeMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeMax", required: false }] }], badgeTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeTone", required: false }] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }] } });
18531
18590
 
18532
18591
  /**
18533
18592
  * A single sidebar navigation entry. Renders an anchor when [link] is set