mn-angular-lib 1.0.171 → 1.0.172
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.
|
@@ -14206,6 +14206,376 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
14206
14206
|
type: Output
|
|
14207
14207
|
}] } });
|
|
14208
14208
|
|
|
14209
|
+
/**
|
|
14210
|
+
* Styling for {@link MnIconChip}: one 10% wash of the colour behind an icon drawn in
|
|
14211
|
+
* the consumer's `--color-<colour>-text` token when it defines one (the shade it uses
|
|
14212
|
+
* for readable coloured text on a tinted ground) and in the base colour otherwise, the
|
|
14213
|
+
* same device `mnBadge` uses. The radius grows with the box so the corner reads the
|
|
14214
|
+
* same at every size.
|
|
14215
|
+
*/
|
|
14216
|
+
const mnIconChipVariants = tv({
|
|
14217
|
+
base: 'inline-flex shrink-0 items-center justify-center',
|
|
14218
|
+
variants: {
|
|
14219
|
+
/** `sm` for list rows, `md` for section-card headers and stat tiles, `lg` for page headers. */
|
|
14220
|
+
size: {
|
|
14221
|
+
sm: 'h-9 w-9 rounded-lg',
|
|
14222
|
+
md: 'h-10 w-10 rounded-xl',
|
|
14223
|
+
lg: 'h-12 w-12 rounded-2xl',
|
|
14224
|
+
},
|
|
14225
|
+
color: {
|
|
14226
|
+
primary: 'bg-primary/10 text-(--color-primary-text,var(--color-primary))',
|
|
14227
|
+
secondary: 'bg-secondary/10 text-(--color-secondary-text,var(--color-secondary))',
|
|
14228
|
+
accent: 'bg-accent/10 text-(--color-accent-text,var(--color-accent))',
|
|
14229
|
+
success: 'bg-success/10 text-(--color-success-text,var(--color-success))',
|
|
14230
|
+
warning: 'bg-warning/10 text-(--color-warning-text,var(--color-warning))',
|
|
14231
|
+
danger: 'bg-error/10 text-(--color-error-text,var(--color-error))',
|
|
14232
|
+
gray: 'bg-base-content/10 text-base-content/70',
|
|
14233
|
+
},
|
|
14234
|
+
},
|
|
14235
|
+
defaultVariants: {
|
|
14236
|
+
size: 'md',
|
|
14237
|
+
color: 'primary',
|
|
14238
|
+
},
|
|
14239
|
+
});
|
|
14240
|
+
|
|
14241
|
+
/**
|
|
14242
|
+
* The tinted square that carries an icon in front of a card title, a stat or a list
|
|
14243
|
+
* row: the one place a colour says "what kind of thing this is". Project the icon as
|
|
14244
|
+
* content; the chip sizes and tints itself and never grows with the row.
|
|
14245
|
+
*
|
|
14246
|
+
* Decorative for assistive technology: the title or label beside it carries the
|
|
14247
|
+
* meaning, so the chip is `aria-hidden` and a screen reader never meets a bare icon.
|
|
14248
|
+
*
|
|
14249
|
+
* ```html
|
|
14250
|
+
* <mn-icon-chip [data]="{ color: 'success', size: 'md' }">
|
|
14251
|
+
* <svg lucideCheck [size]="20"></svg>
|
|
14252
|
+
* </mn-icon-chip>
|
|
14253
|
+
* ```
|
|
14254
|
+
*/
|
|
14255
|
+
class MnIconChip {
|
|
14256
|
+
/** Size and colour; see {@link MnIconChipTypes}. */
|
|
14257
|
+
data = {};
|
|
14258
|
+
/** The chip's own classes; the consumer's static classes merge with them. */
|
|
14259
|
+
get hostClasses() {
|
|
14260
|
+
return mnIconChipVariants({
|
|
14261
|
+
size: this.data.size,
|
|
14262
|
+
color: this.data.color,
|
|
14263
|
+
});
|
|
14264
|
+
}
|
|
14265
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnIconChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14266
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: MnIconChip, isStandalone: true, selector: "mn-icon-chip", inputs: { data: "data" }, host: { attributes: { "aria-hidden": "true" }, properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<ng-content></ng-content>\n" });
|
|
14267
|
+
}
|
|
14268
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnIconChip, decorators: [{
|
|
14269
|
+
type: Component,
|
|
14270
|
+
args: [{ selector: 'mn-icon-chip', standalone: true, host: { 'aria-hidden': 'true' }, template: "<ng-content></ng-content>\n" }]
|
|
14271
|
+
}], propDecorators: { data: [{
|
|
14272
|
+
type: Input
|
|
14273
|
+
}], hostClasses: [{
|
|
14274
|
+
type: HostBinding,
|
|
14275
|
+
args: ['class']
|
|
14276
|
+
}] } });
|
|
14277
|
+
|
|
14278
|
+
/**
|
|
14279
|
+
* Styling for {@link MnCard}, as tailwind-variants slots: `root` is the card element
|
|
14280
|
+
* itself, `accent` the optional bar along its top edge, `header` the heading row and
|
|
14281
|
+
* `title` the `h2` inside it.
|
|
14282
|
+
*
|
|
14283
|
+
* Theme tokens only, so the card holds up in light and dark. The surface reads the
|
|
14284
|
+
* consumer's `--color-base-card` when it defines one (a card ground a step off the
|
|
14285
|
+
* page background) and falls back to `base-100` otherwise, the same fallback device
|
|
14286
|
+
* `mnBadge` uses for its `-text` tokens.
|
|
14287
|
+
*/
|
|
14288
|
+
const mnCardVariants = tv({
|
|
14289
|
+
slots: {
|
|
14290
|
+
root: 'relative flex overflow-hidden border border-base-300 ' +
|
|
14291
|
+
'bg-(--color-base-card,var(--color-base-100)) transition-all duration-200 motion-reduce:transition-none',
|
|
14292
|
+
accent: 'absolute inset-x-0 top-0 h-1',
|
|
14293
|
+
header: 'flex flex-wrap items-center gap-3',
|
|
14294
|
+
title: 'text-lg font-semibold text-base-content',
|
|
14295
|
+
},
|
|
14296
|
+
variants: {
|
|
14297
|
+
/**
|
|
14298
|
+
* Inner padding, and with it the gap between the card's children: a tile needs
|
|
14299
|
+
* less air than a section card, and a section card that had to say `gap-4` on
|
|
14300
|
+
* every use would drift.
|
|
14301
|
+
*/
|
|
14302
|
+
padding: {
|
|
14303
|
+
sm: { root: 'p-4 gap-3' },
|
|
14304
|
+
md: { root: 'p-5 gap-4' },
|
|
14305
|
+
lg: { root: 'p-6 gap-5' },
|
|
14306
|
+
},
|
|
14307
|
+
/** How the children flow: stacked (the default) or on one line, centred. */
|
|
14308
|
+
layout: {
|
|
14309
|
+
column: { root: 'flex-col' },
|
|
14310
|
+
row: { root: 'flex-row items-center' },
|
|
14311
|
+
},
|
|
14312
|
+
/**
|
|
14313
|
+
* Hover response. `shadow` is a little depth for a card that only sits there;
|
|
14314
|
+
* `lift` promises a destination and belongs on a card that is a link.
|
|
14315
|
+
*/
|
|
14316
|
+
hover: {
|
|
14317
|
+
none: {},
|
|
14318
|
+
shadow: { root: 'hover:shadow-md' },
|
|
14319
|
+
lift: { root: 'hover:-translate-y-1 hover:shadow-lg' },
|
|
14320
|
+
},
|
|
14321
|
+
/**
|
|
14322
|
+
* Entrance. `rise` plays the consumer's `--animate-rise` keyframes when its theme
|
|
14323
|
+
* defines them (a short rise-in, delayed per card through
|
|
14324
|
+
* {@link MnCard.enterDelayMs}) and is a no-op otherwise; reduced-motion users
|
|
14325
|
+
* never see it.
|
|
14326
|
+
*/
|
|
14327
|
+
enter: {
|
|
14328
|
+
none: {},
|
|
14329
|
+
rise: { root: 'animate-rise motion-reduce:animate-none' },
|
|
14330
|
+
},
|
|
14331
|
+
/** Corner rounding, in mn-button's radius tokens. */
|
|
14332
|
+
borderRadius: {
|
|
14333
|
+
none: { root: 'rounded-none' },
|
|
14334
|
+
xs: { root: 'rounded-xs' },
|
|
14335
|
+
sm: { root: 'rounded-sm' },
|
|
14336
|
+
md: { root: 'rounded-md' },
|
|
14337
|
+
lg: { root: 'rounded-lg' },
|
|
14338
|
+
xl: { root: 'rounded-xl' },
|
|
14339
|
+
two_xl: { root: 'rounded-2xl' },
|
|
14340
|
+
three_xl: { root: 'rounded-3xl' },
|
|
14341
|
+
four_xl: { root: 'rounded-4xl' },
|
|
14342
|
+
},
|
|
14343
|
+
/**
|
|
14344
|
+
* Colour of the accent bar and of the heading's icon chip: the same palette as
|
|
14345
|
+
* mn-button and the icon chip. What the colour *means* (a kind, a status, a
|
|
14346
|
+
* module) is the consumer's choice; the card only renders it.
|
|
14347
|
+
*/
|
|
14348
|
+
color: {
|
|
14349
|
+
primary: { accent: 'bg-primary' },
|
|
14350
|
+
secondary: { accent: 'bg-secondary' },
|
|
14351
|
+
accent: { accent: 'bg-accent' },
|
|
14352
|
+
success: { accent: 'bg-success' },
|
|
14353
|
+
warning: { accent: 'bg-warning' },
|
|
14354
|
+
danger: { accent: 'bg-error' },
|
|
14355
|
+
gray: { accent: 'bg-base-content/30' },
|
|
14356
|
+
},
|
|
14357
|
+
},
|
|
14358
|
+
defaultVariants: {
|
|
14359
|
+
padding: 'sm',
|
|
14360
|
+
layout: 'column',
|
|
14361
|
+
hover: 'shadow',
|
|
14362
|
+
enter: 'rise',
|
|
14363
|
+
borderRadius: 'two_xl',
|
|
14364
|
+
color: 'primary',
|
|
14365
|
+
},
|
|
14366
|
+
});
|
|
14367
|
+
|
|
14368
|
+
/**
|
|
14369
|
+
* The card: a rounded surface with a hairline border, a hover response and an
|
|
14370
|
+
* optional accent bar along its top edge. The body is whatever the consumer projects,
|
|
14371
|
+
* so a booking, a competition and a pending-action tile share one look without
|
|
14372
|
+
* sharing a view model.
|
|
14373
|
+
*
|
|
14374
|
+
* It is an attribute as well as an element, like `mnButton` and `mnBadge`: `<mn-card>`
|
|
14375
|
+
* for a plain surface, `<a mnCard [routerLink]>` for a card that is a link,
|
|
14376
|
+
* `<section mnCard>` when the landmark matters. Extra classes on the host merge with
|
|
14377
|
+
* the card's own, so sizing it (`min-w-0 flex-1`, `lg:w-80`) is ordinary CSS on the
|
|
14378
|
+
* element, not an input.
|
|
14379
|
+
*
|
|
14380
|
+
* A **section card** passes a {@link heading}: the card then renders the shared header
|
|
14381
|
+
* row, an {@link MnIconChip} beside an `h2`, then whatever trails the title (a badge, a
|
|
14382
|
+
* button). Project the icon with the `cardIcon` attribute and group the trailing content
|
|
14383
|
+
* in one `cardHeaderEnd` container, so the template reads icon, header end, body:
|
|
14384
|
+
*
|
|
14385
|
+
* ```html
|
|
14386
|
+
* <mn-card [data]="{ padding: 'md', color: 'primary' }" heading="meetings.agenda.title">
|
|
14387
|
+
* <svg cardIcon lucideListOrdered [size]="20"></svg>
|
|
14388
|
+
* <ng-container cardHeaderEnd>
|
|
14389
|
+
* <span mnBadge [data]="{ size: 'sm', color: 'warning' }">Draft</span>
|
|
14390
|
+
* </ng-container>
|
|
14391
|
+
* ...body...
|
|
14392
|
+
* </mn-card>
|
|
14393
|
+
* ```
|
|
14394
|
+
*
|
|
14395
|
+
* The other members of the family build on this shell: {@link MnStatTile} for one
|
|
14396
|
+
* figure at a glance, and {@link MnProportionBar} for the bar inside a card.
|
|
14397
|
+
*/
|
|
14398
|
+
class MnCard {
|
|
14399
|
+
/** Padding, layout, hover, entrance, radius, colour and accent; see {@link MnCardTypes}. */
|
|
14400
|
+
data = {};
|
|
14401
|
+
/**
|
|
14402
|
+
* Section title, as a translation key or a literal. When set, the header row with
|
|
14403
|
+
* the icon chip and `h2` renders above the body. Deliberately not called `title`: a
|
|
14404
|
+
* static `title="..."` on the host would also become a browser tooltip.
|
|
14405
|
+
*/
|
|
14406
|
+
heading;
|
|
14407
|
+
/**
|
|
14408
|
+
* Delay before the entrance animation starts, in milliseconds, so a row of cards
|
|
14409
|
+
* can rise one after another. Ignored when {@link MnCardTypes.enter} is `none`.
|
|
14410
|
+
*/
|
|
14411
|
+
enterDelayMs = 0;
|
|
14412
|
+
/** Resolved slot classes for the current configuration. */
|
|
14413
|
+
get styles() {
|
|
14414
|
+
return mnCardVariants({
|
|
14415
|
+
padding: this.data.padding,
|
|
14416
|
+
layout: this.data.layout,
|
|
14417
|
+
hover: this.data.hover,
|
|
14418
|
+
enter: this.data.enter,
|
|
14419
|
+
borderRadius: this.data.borderRadius,
|
|
14420
|
+
color: this.data.color,
|
|
14421
|
+
});
|
|
14422
|
+
}
|
|
14423
|
+
/** The card element's own classes; the consumer's static classes merge with them. */
|
|
14424
|
+
get hostClasses() {
|
|
14425
|
+
return this.styles.root();
|
|
14426
|
+
}
|
|
14427
|
+
/** Staggers the entrance per card. */
|
|
14428
|
+
get animationDelay() {
|
|
14429
|
+
return `${this.enterDelayMs}ms`;
|
|
14430
|
+
}
|
|
14431
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14432
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnCard, isStandalone: true, selector: "mn-card, [mnCard]", inputs: { data: "data", heading: "heading", enterDelayMs: "enterDelayMs" }, host: { properties: { "class": "this.hostClasses", "style.animation-delay": "this.animationDelay" } }, ngImport: i0, template: "<!-- The accent bar sits on the card's top edge, clipped by the host's overflow-hidden\n into the corner radius. Decorative: the colour's meaning is in the content. -->\n@if (data.accent) {\n <span [class]=\"styles.accent()\" aria-hidden=\"true\"></span>\n}\n<!-- The section header: chip, title, then whatever the consumer marks cardHeaderEnd.\n Wraps on narrow screens so a full-width button drops under the title. -->\n@if (heading; as text) {\n <div [class]=\"styles.header()\">\n <mn-icon-chip [data]=\"{ color: data.color }\">\n <ng-content select=\"[cardIcon]\"></ng-content>\n </mn-icon-chip>\n <h2 [class]=\"styles.title()\">{{ text | mnTranslate }}</h2>\n <ng-content select=\"[cardHeaderEnd]\"></ng-content>\n </div>\n}\n<ng-content></ng-content>\n", dependencies: [{ kind: "component", type: MnIconChip, selector: "mn-icon-chip", inputs: ["data"] }, { kind: "pipe", type: MnTranslatePipe, name: "mnTranslate" }] });
|
|
14433
|
+
}
|
|
14434
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnCard, decorators: [{
|
|
14435
|
+
type: Component,
|
|
14436
|
+
args: [{ selector: 'mn-card, [mnCard]', standalone: true, imports: [MnIconChip, MnTranslatePipe], template: "<!-- The accent bar sits on the card's top edge, clipped by the host's overflow-hidden\n into the corner radius. Decorative: the colour's meaning is in the content. -->\n@if (data.accent) {\n <span [class]=\"styles.accent()\" aria-hidden=\"true\"></span>\n}\n<!-- The section header: chip, title, then whatever the consumer marks cardHeaderEnd.\n Wraps on narrow screens so a full-width button drops under the title. -->\n@if (heading; as text) {\n <div [class]=\"styles.header()\">\n <mn-icon-chip [data]=\"{ color: data.color }\">\n <ng-content select=\"[cardIcon]\"></ng-content>\n </mn-icon-chip>\n <h2 [class]=\"styles.title()\">{{ text | mnTranslate }}</h2>\n <ng-content select=\"[cardHeaderEnd]\"></ng-content>\n </div>\n}\n<ng-content></ng-content>\n" }]
|
|
14437
|
+
}], propDecorators: { data: [{
|
|
14438
|
+
type: Input
|
|
14439
|
+
}], heading: [{
|
|
14440
|
+
type: Input
|
|
14441
|
+
}], enterDelayMs: [{
|
|
14442
|
+
type: Input
|
|
14443
|
+
}], hostClasses: [{
|
|
14444
|
+
type: HostBinding,
|
|
14445
|
+
args: ['class']
|
|
14446
|
+
}], animationDelay: [{
|
|
14447
|
+
type: HostBinding,
|
|
14448
|
+
args: ['style.animation-delay']
|
|
14449
|
+
}] } });
|
|
14450
|
+
|
|
14451
|
+
/**
|
|
14452
|
+
* One fact at a glance: a tinted icon chip, a muted label and a large tabular number,
|
|
14453
|
+
* on the {@link MnCard} shell, in a tile that shares a row with its siblings as
|
|
14454
|
+
* `flex-1`. Project the icon as content; project a badge or a short note into the
|
|
14455
|
+
* `trailing` slot when the number needs a qualifier.
|
|
14456
|
+
*
|
|
14457
|
+
* ```html
|
|
14458
|
+
* <div class="flex flex-wrap gap-4">
|
|
14459
|
+
* <mn-stat-tile label="meetings.attending" [value]="yesCount" [data]="{ color: 'success' }">
|
|
14460
|
+
* <svg lucideCheck [size]="20"></svg>
|
|
14461
|
+
* </mn-stat-tile>
|
|
14462
|
+
* </div>
|
|
14463
|
+
* ```
|
|
14464
|
+
*/
|
|
14465
|
+
class MnStatTile {
|
|
14466
|
+
/** Caption under the number, as a translation key or a literal. */
|
|
14467
|
+
label;
|
|
14468
|
+
/** The figure, already formatted for display. */
|
|
14469
|
+
value;
|
|
14470
|
+
/** Colour of the chip; see {@link MnStatTileTypes}. */
|
|
14471
|
+
data = {};
|
|
14472
|
+
/** Grows to share its row and never forces the row wider than its siblings. */
|
|
14473
|
+
hostClasses = 'flex flex-1 basis-40 min-w-0';
|
|
14474
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnStatTile, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14475
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: MnStatTile, isStandalone: true, selector: "mn-stat-tile", inputs: { label: "label", value: "value", data: "data" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<!-- The card is a row: chip, then label over number. The muted label reads the\n consumer's muted-text token when it has one and plain base text otherwise. -->\n<div mnCard class=\"w-full\" [data]=\"{ layout: 'row' }\">\n <mn-icon-chip [data]=\"{ color: data.color }\">\n <ng-content></ng-content>\n </mn-icon-chip>\n <div class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span class=\"text-sm text-(--color-base-content-muted,var(--color-base-content))\">{{ label | mnTranslate }}</span>\n <div class=\"flex flex-wrap items-baseline gap-2\">\n <span class=\"text-2xl font-bold leading-none tabular-nums text-base-content\">{{ value }}</span>\n <ng-content select=\"[trailing]\"></ng-content>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: MnCard, selector: "mn-card, [mnCard]", inputs: ["data", "heading", "enterDelayMs"] }, { kind: "component", type: MnIconChip, selector: "mn-icon-chip", inputs: ["data"] }, { kind: "pipe", type: MnTranslatePipe, name: "mnTranslate" }] });
|
|
14476
|
+
}
|
|
14477
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnStatTile, decorators: [{
|
|
14478
|
+
type: Component,
|
|
14479
|
+
args: [{ selector: 'mn-stat-tile', standalone: true, imports: [MnCard, MnIconChip, MnTranslatePipe], template: "<!-- The card is a row: chip, then label over number. The muted label reads the\n consumer's muted-text token when it has one and plain base text otherwise. -->\n<div mnCard class=\"w-full\" [data]=\"{ layout: 'row' }\">\n <mn-icon-chip [data]=\"{ color: data.color }\">\n <ng-content></ng-content>\n </mn-icon-chip>\n <div class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span class=\"text-sm text-(--color-base-content-muted,var(--color-base-content))\">{{ label | mnTranslate }}</span>\n <div class=\"flex flex-wrap items-baseline gap-2\">\n <span class=\"text-2xl font-bold leading-none tabular-nums text-base-content\">{{ value }}</span>\n <ng-content select=\"[trailing]\"></ng-content>\n </div>\n </div>\n</div>\n" }]
|
|
14480
|
+
}], propDecorators: { label: [{
|
|
14481
|
+
type: Input,
|
|
14482
|
+
args: [{ required: true }]
|
|
14483
|
+
}], value: [{
|
|
14484
|
+
type: Input,
|
|
14485
|
+
args: [{ required: true }]
|
|
14486
|
+
}], data: [{
|
|
14487
|
+
type: Input
|
|
14488
|
+
}], hostClasses: [{
|
|
14489
|
+
type: HostBinding,
|
|
14490
|
+
args: ['class']
|
|
14491
|
+
}] } });
|
|
14492
|
+
|
|
14493
|
+
/** Fill class per colour, spelled out so Tailwind's scanner finds every one. */
|
|
14494
|
+
const SEGMENT_CLASS = {
|
|
14495
|
+
primary: 'bg-primary',
|
|
14496
|
+
secondary: 'bg-secondary',
|
|
14497
|
+
accent: 'bg-accent',
|
|
14498
|
+
success: 'bg-success',
|
|
14499
|
+
warning: 'bg-warning',
|
|
14500
|
+
danger: 'bg-error',
|
|
14501
|
+
gray: 'bg-base-content/25',
|
|
14502
|
+
};
|
|
14503
|
+
/** Track height per size. */
|
|
14504
|
+
const HEIGHT_CLASS = {
|
|
14505
|
+
sm: 'h-2',
|
|
14506
|
+
md: 'h-2.5',
|
|
14507
|
+
};
|
|
14508
|
+
/**
|
|
14509
|
+
* The proportional bar every turnout, budget, capacity and collection figure draws:
|
|
14510
|
+
* a rounded track with one coloured run per segment, widths from the values. Empty
|
|
14511
|
+
* segments are skipped so a zero never leaves a hairline. Announced as one image with
|
|
14512
|
+
* the caller's label, because the numbers it visualises are always written out next
|
|
14513
|
+
* to it.
|
|
14514
|
+
*
|
|
14515
|
+
* ```html
|
|
14516
|
+
* <mn-proportion-bar
|
|
14517
|
+
* [segments]="[{ value: yes, color: 'success' }, { value: maybe, color: 'warning' }]"
|
|
14518
|
+
* [total]="invited"
|
|
14519
|
+
* ariaLabel="meetings.responses.title">
|
|
14520
|
+
* </mn-proportion-bar>
|
|
14521
|
+
* ```
|
|
14522
|
+
*/
|
|
14523
|
+
class MnProportionBar {
|
|
14524
|
+
/** The coloured runs, in draw order from the left. */
|
|
14525
|
+
segments;
|
|
14526
|
+
/** The whole the segments are measured against; defaults to their sum. */
|
|
14527
|
+
total;
|
|
14528
|
+
/** Accessible name for the bar as a whole, as a translation key or a literal. */
|
|
14529
|
+
ariaLabel;
|
|
14530
|
+
/** Track thickness; see {@link MnProportionBarTypes}. */
|
|
14531
|
+
data = {};
|
|
14532
|
+
/** Resolves the accessible name against the app's bundle. */
|
|
14533
|
+
lang = inject(MnLanguageService);
|
|
14534
|
+
/** The translated accessible name. */
|
|
14535
|
+
get label() {
|
|
14536
|
+
return this.lang.translate(this.ariaLabel);
|
|
14537
|
+
}
|
|
14538
|
+
/** Every class on the track element. */
|
|
14539
|
+
get trackClass() {
|
|
14540
|
+
return `flex w-full overflow-hidden rounded-full bg-base-content/10 ${HEIGHT_CLASS[this.data.height ?? 'md']}`;
|
|
14541
|
+
}
|
|
14542
|
+
/** The denominator actually used: the explicit total when positive, else the segment sum. */
|
|
14543
|
+
get denominator() {
|
|
14544
|
+
const explicit = this.total;
|
|
14545
|
+
if (explicit !== null && explicit !== undefined && explicit > 0)
|
|
14546
|
+
return explicit;
|
|
14547
|
+
return this.segments.reduce((sum, segment) => sum + Math.max(0, segment.value), 0);
|
|
14548
|
+
}
|
|
14549
|
+
/** Segments with a width, empty ones dropped. */
|
|
14550
|
+
get rendered() {
|
|
14551
|
+
const denominator = this.denominator;
|
|
14552
|
+
if (denominator <= 0)
|
|
14553
|
+
return [];
|
|
14554
|
+
return this.segments
|
|
14555
|
+
.filter((segment) => segment.value > 0)
|
|
14556
|
+
.map((segment) => ({
|
|
14557
|
+
widthPct: Math.min(100, (segment.value / denominator) * 100),
|
|
14558
|
+
fillClass: SEGMENT_CLASS[segment.color],
|
|
14559
|
+
}));
|
|
14560
|
+
}
|
|
14561
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnProportionBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14562
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnProportionBar, isStandalone: true, selector: "mn-proportion-bar", inputs: { segments: "segments", total: "total", ariaLabel: "ariaLabel", data: "data" }, ngImport: i0, template: "<!-- One labelled image: the runs are decoration, the numbers live in the caller's text. -->\n<div role=\"img\" [attr.aria-label]=\"label\" [class]=\"trackClass\">\n @for (segment of rendered; track $index) {\n <span\n class=\"h-full transition-[width] duration-300 ease-out motion-reduce:transition-none\"\n [class]=\"segment.fillClass\"\n [style.width.%]=\"segment.widthPct\"\n ></span>\n }\n</div>\n" });
|
|
14563
|
+
}
|
|
14564
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnProportionBar, decorators: [{
|
|
14565
|
+
type: Component,
|
|
14566
|
+
args: [{ selector: 'mn-proportion-bar', standalone: true, template: "<!-- One labelled image: the runs are decoration, the numbers live in the caller's text. -->\n<div role=\"img\" [attr.aria-label]=\"label\" [class]=\"trackClass\">\n @for (segment of rendered; track $index) {\n <span\n class=\"h-full transition-[width] duration-300 ease-out motion-reduce:transition-none\"\n [class]=\"segment.fillClass\"\n [style.width.%]=\"segment.widthPct\"\n ></span>\n }\n</div>\n" }]
|
|
14567
|
+
}], propDecorators: { segments: [{
|
|
14568
|
+
type: Input,
|
|
14569
|
+
args: [{ required: true }]
|
|
14570
|
+
}], total: [{
|
|
14571
|
+
type: Input
|
|
14572
|
+
}], ariaLabel: [{
|
|
14573
|
+
type: Input,
|
|
14574
|
+
args: [{ required: true }]
|
|
14575
|
+
}], data: [{
|
|
14576
|
+
type: Input
|
|
14577
|
+
}] } });
|
|
14578
|
+
|
|
14209
14579
|
/**
|
|
14210
14580
|
* Injection token for the base URL used by all CRUD service requests.
|
|
14211
14581
|
*
|
|
@@ -14707,5 +15077,5 @@ function enableMnPreviewMode(configService, langService, allowedOrigins) {
|
|
|
14707
15077
|
* Generated bundle index. Do not edit.
|
|
14708
15078
|
*/
|
|
14709
15079
|
|
|
14710
|
-
export { API_BASE_URL, ActionStyle, BackdropMode, BaseModalBuilder, CALENDAR_CONFIG, CALENDAR_DATE_FORMATTER, CalendarDayComponent, CalendarEventComponent, CalendarEventDefaultComponent, CalendarEventLayoutService, CalendarMonthComponent, CalendarUtility, CalendarView, CalendarViewComponent, CalendarWeekComponent, CloseMode, ColumnSortType, ConfirmationModalBuilder, ConfirmationTone, CrudService, CustomModalBuilder, DEFAULT_CALENDAR_CONFIG, DEFAULT_MN_ALERT_CONFIG, DefaultCalendarDateFormatter, FieldAppearance, FieldKind, FormLayoutMode, FormModalBuilder, KeyboardMode, MN_ALERT_CONFIG, MN_CALENDAR_COMPONENT_NAME, MN_CALENDAR_CONFIG, MN_CHECKBOX_CONFIG, MN_DATETIME_CONFIG, MN_DROPDOWN_CONFIG, MN_HAPTICS, MN_ICON_MAP, MN_INPUT_FIELD_CONFIG, MN_INSTANCE_ID, MN_LIB_DUAL_HORIZONTAL_IMAGE, MN_MODAL_ACTION_ICONS, MN_MULTI_SELECT_CONFIG, MN_SECTION_PATH, MN_SELECT_CONFIG, MN_TEXTAREA_CONFIG, MODAL_ACTION_ICON_SIZE, MODAL_ACTION_ICON_SIZE_SM, MnAlertOutletComponent, MnAlertService, MnAlertStore, MnBadge, MnBottomSheet, MnBreadcrumbs, MnButton, MnCheckbox, MnCollectionBase, MnCollectionPagination, MnCollectionState, MnConfigService, MnConfirmationBodyComponent, MnCustomBodyHostComponent, MnDateSelectorBar, MnDatetime, MnDropdown, MnDualHorizontalImage, MnFileInput, MnFormBodyComponent, MnGrid, MnHiddenBelowDirective, MnHttpService, MnIcon, MnIconAttributes, MnInformationCard, MnInputField, MnInstanceDirective, MnKeyboard, MnLanguageService, MnList, MnModalRef, MnModalService, MnModalShellComponent, MnMultiSelect, MnRichTextEditor, MnSectionDirective, MnSegmented, MnSelect, MnSelectableCollectionBase, MnShowAboveDirective, MnShowBelowDirective, MnSkeleton, MnTabComponent, MnTable, MnTextarea, MnTranslatePipe, MnWizardBodyComponent, ModalBuilder, ModalCloseReason, ModalIntent, ModalKind, ModalSize, NavigationDirection, OptionState, SelectionMode, StepBuilder, StepState, SubmitMode, UpcomingEventRowComponent, UpcomingEventsComponent, ValidationCode, ValidationStatus, WizardFlowMode, WizardModalBuilder, dateTimeAdapter, defaultFilterPredicate, defaultIconForStyle, defaultTextAdapter, emptyFilterValue, enableMnPreviewMode, isFilterValueActive, isTranslatable, matchesColumnFilter, mnAlertVariants, mnBadgeVariants, mnBreadcrumbsVariants, mnButtonVariants, mnCheckboxVariants, mnCheckboxWrapperVariants, mnDatetimeVariants, mnDropdownTriggerVariants, mnFileInputVariants, mnIconVariants, mnInformationCardVariants, mnInputFieldVariants, mnMultiSelectVariants, mnSegmentedVariants, mnSelectVariants, mnSkeletonVariants, mnTextareaVariants, numberAdapter, pickAdapter, provideMnAlerts, provideMnCalendarConfig, provideMnComponentConfig, provideMnConfig, provideMnLanguage, resolveCalendarConfig, resolveFilterableValue };
|
|
15080
|
+
export { API_BASE_URL, ActionStyle, BackdropMode, BaseModalBuilder, CALENDAR_CONFIG, CALENDAR_DATE_FORMATTER, CalendarDayComponent, CalendarEventComponent, CalendarEventDefaultComponent, CalendarEventLayoutService, CalendarMonthComponent, CalendarUtility, CalendarView, CalendarViewComponent, CalendarWeekComponent, CloseMode, ColumnSortType, ConfirmationModalBuilder, ConfirmationTone, CrudService, CustomModalBuilder, DEFAULT_CALENDAR_CONFIG, DEFAULT_MN_ALERT_CONFIG, DefaultCalendarDateFormatter, FieldAppearance, FieldKind, FormLayoutMode, FormModalBuilder, KeyboardMode, MN_ALERT_CONFIG, MN_CALENDAR_COMPONENT_NAME, MN_CALENDAR_CONFIG, MN_CHECKBOX_CONFIG, MN_DATETIME_CONFIG, MN_DROPDOWN_CONFIG, MN_HAPTICS, MN_ICON_MAP, MN_INPUT_FIELD_CONFIG, MN_INSTANCE_ID, MN_LIB_DUAL_HORIZONTAL_IMAGE, MN_MODAL_ACTION_ICONS, MN_MULTI_SELECT_CONFIG, MN_SECTION_PATH, MN_SELECT_CONFIG, MN_TEXTAREA_CONFIG, MODAL_ACTION_ICON_SIZE, MODAL_ACTION_ICON_SIZE_SM, MnAlertOutletComponent, MnAlertService, MnAlertStore, MnBadge, MnBottomSheet, MnBreadcrumbs, MnButton, MnCard, MnCheckbox, MnCollectionBase, MnCollectionPagination, MnCollectionState, MnConfigService, MnConfirmationBodyComponent, MnCustomBodyHostComponent, MnDateSelectorBar, MnDatetime, MnDropdown, MnDualHorizontalImage, MnFileInput, MnFormBodyComponent, MnGrid, MnHiddenBelowDirective, MnHttpService, MnIcon, MnIconAttributes, MnIconChip, MnInformationCard, MnInputField, MnInstanceDirective, MnKeyboard, MnLanguageService, MnList, MnModalRef, MnModalService, MnModalShellComponent, MnMultiSelect, MnProportionBar, MnRichTextEditor, MnSectionDirective, MnSegmented, MnSelect, MnSelectableCollectionBase, MnShowAboveDirective, MnShowBelowDirective, MnSkeleton, MnStatTile, MnTabComponent, MnTable, MnTextarea, MnTranslatePipe, MnWizardBodyComponent, ModalBuilder, ModalCloseReason, ModalIntent, ModalKind, ModalSize, NavigationDirection, OptionState, SelectionMode, StepBuilder, StepState, SubmitMode, UpcomingEventRowComponent, UpcomingEventsComponent, ValidationCode, ValidationStatus, WizardFlowMode, WizardModalBuilder, dateTimeAdapter, defaultFilterPredicate, defaultIconForStyle, defaultTextAdapter, emptyFilterValue, enableMnPreviewMode, isFilterValueActive, isTranslatable, matchesColumnFilter, mnAlertVariants, mnBadgeVariants, mnBreadcrumbsVariants, mnButtonVariants, mnCardVariants, mnCheckboxVariants, mnCheckboxWrapperVariants, mnDatetimeVariants, mnDropdownTriggerVariants, mnFileInputVariants, mnIconChipVariants, mnIconVariants, mnInformationCardVariants, mnInputFieldVariants, mnMultiSelectVariants, mnSegmentedVariants, mnSelectVariants, mnSkeletonVariants, mnTextareaVariants, numberAdapter, pickAdapter, provideMnAlerts, provideMnCalendarConfig, provideMnComponentConfig, provideMnConfig, provideMnLanguage, resolveCalendarConfig, resolveFilterableValue };
|
|
14711
15081
|
//# sourceMappingURL=mn-angular-lib.mjs.map
|