@besaitech/ng-design-system 0.0.54 → 0.0.55
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/README.md +6 -3
- package/fesm2022/besaitech-ng-design-system.mjs +1230 -65
- package/fesm2022/besaitech-ng-design-system.mjs.map +1 -1
- package/index.d.ts +354 -29
- package/package.json +1 -1
- package/themes/belvigo-emerald.css +73 -0
|
@@ -119,6 +119,10 @@ const SDS_ICONS = {
|
|
|
119
119
|
'grip-vertical': '<circle cx="9" cy="12" r="1"/><circle cx="9" cy="5" r="1"/><circle cx="9" cy="19" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="5" r="1"/><circle cx="15" cy="19" r="1"/>',
|
|
120
120
|
'upload': '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" x2="12" y1="3" y2="15"/>',
|
|
121
121
|
'image': '<rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>',
|
|
122
|
+
// A photo that failed or is missing (sds-avatar fallbacks, photo trays).
|
|
123
|
+
'image-off': '<line x1="2" x2="22" y1="2" y2="22"/><path d="M10.41 10.41a2 2 0 1 1-2.83-2.83"/><line x1="13.5" x2="6" y1="13.5" y2="21"/><line x1="18" x2="21" y1="12" y2="15"/><path d="M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59"/><path d="M21 15V5a2 2 0 0 0-2-2H9"/>',
|
|
124
|
+
// Fork and knife: the placeholder of a menu item without a photo.
|
|
125
|
+
'utensils': '<path d="M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2"/><path d="M7 2v20"/><path d="M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7"/>',
|
|
122
126
|
'zoom-in': '<circle cx="11" cy="11" r="8"/><line x1="21" x2="16.65" y1="21" y2="16.65"/><line x1="11" x2="11" y1="8" y2="14"/><line x1="8" x2="14" y1="11" y2="11"/>',
|
|
123
127
|
'zoom-out': '<circle cx="11" cy="11" r="8"/><line x1="21" x2="16.65" y1="21" y2="16.65"/><line x1="8" x2="14" y1="11" y2="11"/>',
|
|
124
128
|
'trash-2': '<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/>',
|
|
@@ -218,7 +222,7 @@ const VARIANTS$2 = {
|
|
|
218
222
|
'dark:hover:bg-white/10 dark:active:bg-white/15',
|
|
219
223
|
danger: 'bg-danger text-white shadow-sm hover:brightness-95 active:brightness-90',
|
|
220
224
|
};
|
|
221
|
-
const SIZES$
|
|
225
|
+
const SIZES$c = {
|
|
222
226
|
sm: 'h-8 px-3 text-sm',
|
|
223
227
|
md: 'h-10 px-4 text-sm',
|
|
224
228
|
lg: 'h-12 px-5 text-base',
|
|
@@ -278,7 +282,7 @@ class SdsButton {
|
|
|
278
282
|
BASE,
|
|
279
283
|
this.shape() === 'pill' ? 'rounded-full' : 'rounded-control',
|
|
280
284
|
VARIANTS$2[this.variant()],
|
|
281
|
-
SIZES$
|
|
285
|
+
SIZES$c[size],
|
|
282
286
|
this.iconOnly() ? ICON_ONLY[size] : '',
|
|
283
287
|
this.block() ? 'w-full' : '',
|
|
284
288
|
]
|
|
@@ -330,8 +334,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
330
334
|
`, styles: [".sds-spinner{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:9999px;animation:sds-spin .6s linear infinite}@keyframes sds-spin{to{transform:rotate(360deg)}}\n"] }]
|
|
331
335
|
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
332
336
|
|
|
333
|
-
let nextId$
|
|
334
|
-
const SIZES$
|
|
337
|
+
let nextId$n = 0;
|
|
338
|
+
const SIZES$b = {
|
|
335
339
|
sm: 'h-9 text-sm',
|
|
336
340
|
md: 'h-10 text-sm',
|
|
337
341
|
lg: 'h-12 text-base',
|
|
@@ -343,7 +347,7 @@ const SIZES$a = {
|
|
|
343
347
|
* sidebar search field).
|
|
344
348
|
*/
|
|
345
349
|
class SdsInput {
|
|
346
|
-
inputId = `sds-input-${nextId$
|
|
350
|
+
inputId = `sds-input-${nextId$n++}`;
|
|
347
351
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
348
352
|
/** Accessible name used when no visible [label] is provided. */
|
|
349
353
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -427,7 +431,7 @@ class SdsInput {
|
|
|
427
431
|
return `${left} ${right}`;
|
|
428
432
|
}, ...(ngDevMode ? [{ debugName: "fieldPadding" }] : []));
|
|
429
433
|
wrapperClasses = computed(() => {
|
|
430
|
-
const parts = [SIZES$
|
|
434
|
+
const parts = [SIZES$b[this.size()], this.pill() ? 'rounded-full' : 'rounded-control'];
|
|
431
435
|
if (this.isDisabled())
|
|
432
436
|
parts.push('opacity-60 cursor-not-allowed');
|
|
433
437
|
if (this.filled()) {
|
|
@@ -675,7 +679,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
675
679
|
`, styles: ["input:-webkit-autofill,input:-webkit-autofill:hover,input:-webkit-autofill:focus,input:-webkit-autofill:active{transition:background-color 100000s ease-in-out 0s;-webkit-text-fill-color:currentColor;caret-color:currentColor}\n"] }]
|
|
676
680
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], leadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingIcon", required: false }] }], trailingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingIcon", required: false }] }], trailingAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingAction", required: false }] }], trailingActionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionLabel", required: false }] }], trailingActionPressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionPressed", required: false }] }], trailingActionClick: [{ type: i0.Output, args: ["trailingActionClick"] }] } });
|
|
677
681
|
|
|
678
|
-
let nextId$
|
|
682
|
+
let nextId$m = 0;
|
|
679
683
|
const HEIGHTS = {
|
|
680
684
|
sm: 'h-9',
|
|
681
685
|
md: 'h-10',
|
|
@@ -703,7 +707,7 @@ const TEXT = {
|
|
|
703
707
|
* with "." ("1.234" in nl-BE) stays a thousands separator.
|
|
704
708
|
*/
|
|
705
709
|
class SdsInputNumber {
|
|
706
|
-
inputId = `sds-input-number-${nextId$
|
|
710
|
+
inputId = `sds-input-number-${nextId$m++}`;
|
|
707
711
|
fieldRef = viewChild('field', ...(ngDevMode ? [{ debugName: "fieldRef" }] : []));
|
|
708
712
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
709
713
|
/** Accessible name used when no visible [label] is provided. */
|
|
@@ -1470,7 +1474,577 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
1470
1474
|
}]
|
|
1471
1475
|
}], ctorParameters: () => [], propDecorators: { fieldRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedby", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], currencyDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyDisplay", required: false }] }], useGrouping: [{ type: i0.Input, args: [{ isSignal: true, alias: "useGrouping", required: false }] }], minFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "minFractionDigits", required: false }] }], maxFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFractionDigits", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], buttonLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLayout", required: false }] }], incrementIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "incrementIcon", required: false }] }], decrementIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "decrementIcon", required: false }] }], allowEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowEmpty", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], incrementLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "incrementLabel", required: false }] }], decrementLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "decrementLabel", required: false }] }] } });
|
|
1472
1476
|
|
|
1473
|
-
let nextId$
|
|
1477
|
+
let nextId$l = 0;
|
|
1478
|
+
const SIZES$a = {
|
|
1479
|
+
sm: 'h-9 text-sm',
|
|
1480
|
+
md: 'h-10 text-sm',
|
|
1481
|
+
lg: 'h-12 text-base',
|
|
1482
|
+
};
|
|
1483
|
+
const pad2$1 = (n) => String(n).padStart(2, '0');
|
|
1484
|
+
/** Parse `HH:mm` or `HH:mm:ss` (the seconds are ignored). Anything else is null. */
|
|
1485
|
+
function parseTime(value) {
|
|
1486
|
+
if (typeof value !== 'string')
|
|
1487
|
+
return null;
|
|
1488
|
+
const match = /^(\d{1,2}):(\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(value.trim());
|
|
1489
|
+
if (!match)
|
|
1490
|
+
return null;
|
|
1491
|
+
const h = Number(match[1]);
|
|
1492
|
+
const m = Number(match[2]);
|
|
1493
|
+
if (h > 23 || m > 59)
|
|
1494
|
+
return null;
|
|
1495
|
+
return { h, m };
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Time-of-day field, 24-hour, whatever the browser's locale: two segments (hours : minutes) in one
|
|
1499
|
+
* framed field, the value being a `"HH:mm"` string (or null) — the shape of a backend `LocalTime`.
|
|
1500
|
+
* Implements ControlValueAccessor: use `formControlName` or `[(ngModel)]`.
|
|
1501
|
+
*
|
|
1502
|
+
* Unlike a native `<input type="time">` it never switches to a 12-hour clock with AM/PM, and it is themed
|
|
1503
|
+
* like every other field (label, hint, error, sizes, `filled`, dark mode).
|
|
1504
|
+
*
|
|
1505
|
+
* Keyboard: type digits (the hours move on to the minutes by themselves after two digits, or one digit
|
|
1506
|
+
* above 2); `:`/`.`/→ jump to the minutes, ← or Backspace on an empty minute go back; ↑/↓ step the hours
|
|
1507
|
+
* by 1 and the minutes by [minuteStep] (wrapping, never carrying into the hour). Each segment is a
|
|
1508
|
+
* `spinbutton` with its own accessible name. An hour typed without minutes gets `:00` when the field is
|
|
1509
|
+
* left; emptying both segments sets null.
|
|
1510
|
+
*
|
|
1511
|
+
* @example
|
|
1512
|
+
* <sds-time-input label="Opens at" formControlName="start" [minuteStep]="15" />
|
|
1513
|
+
*
|
|
1514
|
+
* @example
|
|
1515
|
+
* <sds-time-input [ariaLabel]="'Closes at'" [ngModel]="end()" (ngModelChange)="end.set($event)" clearable />
|
|
1516
|
+
*/
|
|
1517
|
+
class SdsTimeInput {
|
|
1518
|
+
fieldId = `sds-time-input-${nextId$l++}`;
|
|
1519
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
1520
|
+
/** Accessible name of the field when there is no visible [label]. */
|
|
1521
|
+
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
1522
|
+
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
1523
|
+
error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
1524
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
1525
|
+
/** `filled` is borderless on a muted ground, like sds-input's `filled`. */
|
|
1526
|
+
appearance = input('default', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
1527
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
1528
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
1529
|
+
/** Show a clear button (sets null) while there is a value. */
|
|
1530
|
+
clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
1531
|
+
/** Leading clock icon. */
|
|
1532
|
+
showIcon = input(true, ...(ngDevMode ? [{ debugName: "showIcon", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
1533
|
+
/** Minutes moved by ↑/↓ on the minutes segment (snaps to the step first). Default 1. */
|
|
1534
|
+
minuteStep = input(1, ...(ngDevMode ? [{ debugName: "minuteStep", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
1535
|
+
/** Emit `HH:mm:ss` (seconds always `00`) instead of `HH:mm`. */
|
|
1536
|
+
withSeconds = input(false, ...(ngDevMode ? [{ debugName: "withSeconds", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
1537
|
+
/** Placeholder of each empty segment. */
|
|
1538
|
+
placeholderText = input('--', ...(ngDevMode ? [{ debugName: "placeholderText" }] : []));
|
|
1539
|
+
/** Accessible name of the hours segment. English default — translate it. */
|
|
1540
|
+
hoursLabel = input('Hours', ...(ngDevMode ? [{ debugName: "hoursLabel" }] : []));
|
|
1541
|
+
/** Accessible name of the minutes segment. English default — translate it. */
|
|
1542
|
+
minutesLabel = input('Minutes', ...(ngDevMode ? [{ debugName: "minutesLabel" }] : []));
|
|
1543
|
+
/** Accessible name of the clear button. English default — translate it. */
|
|
1544
|
+
clearLabel = input('Clear time', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
1545
|
+
hoursEl = viewChild.required('hoursEl');
|
|
1546
|
+
minutesEl = viewChild.required('minutesEl');
|
|
1547
|
+
hours = signal(null, ...(ngDevMode ? [{ debugName: "hours" }] : []));
|
|
1548
|
+
minutes = signal(null, ...(ngDevMode ? [{ debugName: "minutes" }] : []));
|
|
1549
|
+
/** Raw text of a segment while it is being typed (null = show the committed value). */
|
|
1550
|
+
hoursDraft = signal(null, ...(ngDevMode ? [{ debugName: "hoursDraft" }] : []));
|
|
1551
|
+
minutesDraft = signal(null, ...(ngDevMode ? [{ debugName: "minutesDraft" }] : []));
|
|
1552
|
+
cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
|
|
1553
|
+
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
1554
|
+
hasValue = computed(() => this.hours() !== null || this.minutes() !== null, ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
|
|
1555
|
+
hoursText = computed(() => this.hoursDraft() ?? (this.hours() === null ? '' : pad2$1(this.hours())), ...(ngDevMode ? [{ debugName: "hoursText" }] : []));
|
|
1556
|
+
minutesText = computed(() => this.minutesDraft() ?? (this.minutes() === null ? '' : pad2$1(this.minutes())), ...(ngDevMode ? [{ debugName: "minutesText" }] : []));
|
|
1557
|
+
describedBy = computed(() => {
|
|
1558
|
+
if (this.error())
|
|
1559
|
+
return `${this.fieldId}-err`;
|
|
1560
|
+
if (this.hint())
|
|
1561
|
+
return `${this.fieldId}-hint`;
|
|
1562
|
+
return null;
|
|
1563
|
+
}, ...(ngDevMode ? [{ debugName: "describedBy" }] : []));
|
|
1564
|
+
wrapperClasses = computed(() => {
|
|
1565
|
+
const parts = [SIZES$a[this.size()], 'rounded-control'];
|
|
1566
|
+
if (this.isDisabled())
|
|
1567
|
+
parts.push('opacity-60 cursor-not-allowed');
|
|
1568
|
+
if (this.appearance() === 'filled') {
|
|
1569
|
+
parts.push('border-transparent bg-muted');
|
|
1570
|
+
parts.push(this.error()
|
|
1571
|
+
? 'border-danger focus-within:ring-2 focus-within:ring-danger/30'
|
|
1572
|
+
: 'focus-within:ring-2 focus-within:ring-brand-500/25');
|
|
1573
|
+
}
|
|
1574
|
+
else {
|
|
1575
|
+
parts.push('bg-surface');
|
|
1576
|
+
parts.push(this.error()
|
|
1577
|
+
? 'border-danger focus-within:border-danger focus-within:ring-2 focus-within:ring-danger/25'
|
|
1578
|
+
: 'border-border focus-within:border-brand-500 focus-within:ring-2 focus-within:ring-brand-500/25');
|
|
1579
|
+
}
|
|
1580
|
+
return parts.join(' ');
|
|
1581
|
+
}, ...(ngDevMode ? [{ debugName: "wrapperClasses" }] : []));
|
|
1582
|
+
pad(n) {
|
|
1583
|
+
return pad2$1(n);
|
|
1584
|
+
}
|
|
1585
|
+
// --- ControlValueAccessor -------------------------------------------------
|
|
1586
|
+
onChange = () => { };
|
|
1587
|
+
onTouched = () => { };
|
|
1588
|
+
writeValue(value) {
|
|
1589
|
+
const t = parseTime(value);
|
|
1590
|
+
this.hours.set(t ? t.h : null);
|
|
1591
|
+
this.minutes.set(t ? t.m : null);
|
|
1592
|
+
this.hoursDraft.set(null);
|
|
1593
|
+
this.minutesDraft.set(null);
|
|
1594
|
+
}
|
|
1595
|
+
registerOnChange(fn) {
|
|
1596
|
+
this.onChange = fn;
|
|
1597
|
+
}
|
|
1598
|
+
registerOnTouched(fn) {
|
|
1599
|
+
this.onTouched = fn;
|
|
1600
|
+
}
|
|
1601
|
+
setDisabledState(isDisabled) {
|
|
1602
|
+
this.cvaDisabled.set(isDisabled);
|
|
1603
|
+
}
|
|
1604
|
+
// --- typing ---------------------------------------------------------------
|
|
1605
|
+
selectAll(event) {
|
|
1606
|
+
const el = event.target;
|
|
1607
|
+
queueMicrotask(() => el.select());
|
|
1608
|
+
}
|
|
1609
|
+
/** Clicking the frame (icon, padding) focuses the hours, like clicking a native field. */
|
|
1610
|
+
onFrameClick(event) {
|
|
1611
|
+
if (this.isDisabled())
|
|
1612
|
+
return;
|
|
1613
|
+
const target = event.target;
|
|
1614
|
+
if (target.tagName !== 'INPUT' && !target.closest('button'))
|
|
1615
|
+
this.hoursEl().nativeElement.focus();
|
|
1616
|
+
}
|
|
1617
|
+
onHoursInput(event) {
|
|
1618
|
+
const el = event.target;
|
|
1619
|
+
const text = el.value;
|
|
1620
|
+
// A pasted/autofilled full time ("09:45", "9.45", "9h45") fills both segments.
|
|
1621
|
+
if (/[:.h]/i.test(text)) {
|
|
1622
|
+
const t = parseTime(text.replace(/[.h]/i, ':'));
|
|
1623
|
+
if (t) {
|
|
1624
|
+
this.commitHours(t.h);
|
|
1625
|
+
this.commitMinutes(t.m);
|
|
1626
|
+
this.syncSegments();
|
|
1627
|
+
this.focusMinutes();
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
const digits = text.replace(/\D/g, '');
|
|
1632
|
+
if (digits === '') {
|
|
1633
|
+
el.value = '';
|
|
1634
|
+
this.hoursDraft.set('');
|
|
1635
|
+
this.hours.set(null);
|
|
1636
|
+
this.emitIfComplete();
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
// How many leading digits make the hour: "9" is 09 (no hour starts with 3-9 and has a second digit);
|
|
1640
|
+
// "1"/"2" wait for a second digit; "25" is 2 then 5 minutes. Whatever follows spills into minutes, so
|
|
1641
|
+
// typing "945" in one go (or a fast/IME/autofill burst) still reads as 09:45.
|
|
1642
|
+
let hourLength;
|
|
1643
|
+
if (Number(digits[0]) > 2)
|
|
1644
|
+
hourLength = 1;
|
|
1645
|
+
else if (digits.length === 1)
|
|
1646
|
+
hourLength = 0;
|
|
1647
|
+
else
|
|
1648
|
+
hourLength = Number(digits.slice(0, 2)) <= 23 ? 2 : 1;
|
|
1649
|
+
if (hourLength === 0) {
|
|
1650
|
+
el.value = digits;
|
|
1651
|
+
this.hoursDraft.set(digits);
|
|
1652
|
+
return;
|
|
1653
|
+
}
|
|
1654
|
+
this.commitHours(Number(digits.slice(0, hourLength)));
|
|
1655
|
+
el.value = this.hoursText();
|
|
1656
|
+
const rest = digits.slice(hourLength, hourLength + 2);
|
|
1657
|
+
if (rest)
|
|
1658
|
+
this.takeMinuteDigits(rest);
|
|
1659
|
+
this.focusMinutes();
|
|
1660
|
+
}
|
|
1661
|
+
onMinutesInput(event) {
|
|
1662
|
+
const el = event.target;
|
|
1663
|
+
const digits = el.value.replace(/\D/g, '').slice(0, 2);
|
|
1664
|
+
if (digits === '') {
|
|
1665
|
+
el.value = '';
|
|
1666
|
+
this.minutesDraft.set('');
|
|
1667
|
+
this.minutes.set(null);
|
|
1668
|
+
this.emitIfComplete();
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
this.takeMinuteDigits(digits);
|
|
1672
|
+
el.value = this.minutesText();
|
|
1673
|
+
}
|
|
1674
|
+
/** "7" (no minute starts with 6-9 and has a second digit) and any 2 digits commit; "0"-"5" wait. */
|
|
1675
|
+
takeMinuteDigits(digits) {
|
|
1676
|
+
if (digits.length >= 2 || Number(digits) > 5) {
|
|
1677
|
+
this.commitMinutes(Math.min(59, Number(digits.slice(0, 2))));
|
|
1678
|
+
}
|
|
1679
|
+
else {
|
|
1680
|
+
this.minutesDraft.set(digits);
|
|
1681
|
+
}
|
|
1682
|
+
this.minutesEl().nativeElement.value = this.minutesText();
|
|
1683
|
+
}
|
|
1684
|
+
/** Force both inputs to show the committed values (a binding does not repaint an unchanged value). */
|
|
1685
|
+
syncSegments() {
|
|
1686
|
+
this.hoursEl().nativeElement.value = this.hoursText();
|
|
1687
|
+
this.minutesEl().nativeElement.value = this.minutesText();
|
|
1688
|
+
}
|
|
1689
|
+
onHoursKeydown(event) {
|
|
1690
|
+
if (this.readonly())
|
|
1691
|
+
return;
|
|
1692
|
+
const el = event.target;
|
|
1693
|
+
switch (event.key) {
|
|
1694
|
+
case 'ArrowUp':
|
|
1695
|
+
case 'ArrowDown': {
|
|
1696
|
+
event.preventDefault();
|
|
1697
|
+
const delta = event.key === 'ArrowUp' ? 1 : -1;
|
|
1698
|
+
const current = this.draftNumber(this.hoursDraft()) ?? this.hours();
|
|
1699
|
+
const next = current === null ? (delta > 0 ? 0 : 23) : (current + delta + 24) % 24;
|
|
1700
|
+
this.commitHours(next);
|
|
1701
|
+
this.syncSegments();
|
|
1702
|
+
break;
|
|
1703
|
+
}
|
|
1704
|
+
case ':':
|
|
1705
|
+
case '.':
|
|
1706
|
+
case 'h':
|
|
1707
|
+
event.preventDefault();
|
|
1708
|
+
this.flushHours();
|
|
1709
|
+
this.syncSegments();
|
|
1710
|
+
this.focusMinutes();
|
|
1711
|
+
break;
|
|
1712
|
+
case 'ArrowRight':
|
|
1713
|
+
if (el.selectionStart === el.value.length) {
|
|
1714
|
+
event.preventDefault();
|
|
1715
|
+
this.flushHours();
|
|
1716
|
+
this.focusMinutes();
|
|
1717
|
+
}
|
|
1718
|
+
break;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
onMinutesKeydown(event) {
|
|
1722
|
+
if (this.readonly())
|
|
1723
|
+
return;
|
|
1724
|
+
const el = event.target;
|
|
1725
|
+
switch (event.key) {
|
|
1726
|
+
case 'ArrowUp':
|
|
1727
|
+
case 'ArrowDown': {
|
|
1728
|
+
event.preventDefault();
|
|
1729
|
+
const step = Math.max(1, Math.min(60, this.minuteStep()));
|
|
1730
|
+
const current = this.draftNumber(this.minutesDraft()) ?? this.minutes();
|
|
1731
|
+
let next;
|
|
1732
|
+
if (current === null) {
|
|
1733
|
+
next = event.key === 'ArrowUp' ? 0 : 60 - step;
|
|
1734
|
+
}
|
|
1735
|
+
else if (event.key === 'ArrowUp') {
|
|
1736
|
+
next = (Math.floor(current / step) + 1) * step;
|
|
1737
|
+
}
|
|
1738
|
+
else {
|
|
1739
|
+
next = current % step === 0 ? current - step : Math.floor(current / step) * step;
|
|
1740
|
+
}
|
|
1741
|
+
this.commitMinutes(((next % 60) + 60) % 60);
|
|
1742
|
+
this.syncSegments();
|
|
1743
|
+
break;
|
|
1744
|
+
}
|
|
1745
|
+
case 'Backspace':
|
|
1746
|
+
if (el.value === '') {
|
|
1747
|
+
event.preventDefault();
|
|
1748
|
+
this.focusHours();
|
|
1749
|
+
}
|
|
1750
|
+
break;
|
|
1751
|
+
case 'ArrowLeft':
|
|
1752
|
+
if (el.selectionStart === 0 && el.selectionEnd === 0) {
|
|
1753
|
+
event.preventDefault();
|
|
1754
|
+
this.flushMinutes();
|
|
1755
|
+
this.focusHours();
|
|
1756
|
+
}
|
|
1757
|
+
break;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
/** Leaving the whole field completes a half-typed time and marks the control touched. */
|
|
1761
|
+
onFocusOut(event) {
|
|
1762
|
+
const next = event.relatedTarget;
|
|
1763
|
+
const group = event.currentTarget;
|
|
1764
|
+
if (next && group.contains(next))
|
|
1765
|
+
return;
|
|
1766
|
+
this.flushHours();
|
|
1767
|
+
this.flushMinutes();
|
|
1768
|
+
if (this.hours() !== null && this.minutes() === null)
|
|
1769
|
+
this.commitMinutes(0);
|
|
1770
|
+
else if (this.hours() === null && this.minutes() !== null)
|
|
1771
|
+
this.commitHours(0);
|
|
1772
|
+
this.syncSegments();
|
|
1773
|
+
this.onTouched();
|
|
1774
|
+
}
|
|
1775
|
+
clear() {
|
|
1776
|
+
this.hours.set(null);
|
|
1777
|
+
this.minutes.set(null);
|
|
1778
|
+
this.hoursDraft.set(null);
|
|
1779
|
+
this.minutesDraft.set(null);
|
|
1780
|
+
this.onChange(null);
|
|
1781
|
+
this.onTouched();
|
|
1782
|
+
}
|
|
1783
|
+
// --- internals ------------------------------------------------------------
|
|
1784
|
+
draftNumber(draft) {
|
|
1785
|
+
return draft === null || draft === '' ? null : Number(draft);
|
|
1786
|
+
}
|
|
1787
|
+
flushHours() {
|
|
1788
|
+
const d = this.hoursDraft();
|
|
1789
|
+
if (d !== null && d !== '')
|
|
1790
|
+
this.commitHours(Math.min(23, Number(d)));
|
|
1791
|
+
else
|
|
1792
|
+
this.hoursDraft.set(null);
|
|
1793
|
+
}
|
|
1794
|
+
flushMinutes() {
|
|
1795
|
+
const d = this.minutesDraft();
|
|
1796
|
+
if (d !== null && d !== '')
|
|
1797
|
+
this.commitMinutes(Math.min(59, Number(d)));
|
|
1798
|
+
else
|
|
1799
|
+
this.minutesDraft.set(null);
|
|
1800
|
+
}
|
|
1801
|
+
commitHours(h) {
|
|
1802
|
+
this.hours.set(h);
|
|
1803
|
+
this.hoursDraft.set(null);
|
|
1804
|
+
this.emitIfComplete();
|
|
1805
|
+
}
|
|
1806
|
+
commitMinutes(m) {
|
|
1807
|
+
this.minutes.set(m);
|
|
1808
|
+
this.minutesDraft.set(null);
|
|
1809
|
+
this.emitIfComplete();
|
|
1810
|
+
}
|
|
1811
|
+
/** Emits `HH:mm` once both segments hold a value, and null once both are empty. */
|
|
1812
|
+
emitIfComplete() {
|
|
1813
|
+
const h = this.hours();
|
|
1814
|
+
const m = this.minutes();
|
|
1815
|
+
if (h !== null && m !== null) {
|
|
1816
|
+
this.onChange(`${pad2$1(h)}:${pad2$1(m)}${this.withSeconds() ? ':00' : ''}`);
|
|
1817
|
+
}
|
|
1818
|
+
else if (h === null && m === null) {
|
|
1819
|
+
this.onChange(null);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
focusMinutes() {
|
|
1823
|
+
const el = this.minutesEl().nativeElement;
|
|
1824
|
+
el.focus();
|
|
1825
|
+
el.select();
|
|
1826
|
+
}
|
|
1827
|
+
focusHours() {
|
|
1828
|
+
const el = this.hoursEl().nativeElement;
|
|
1829
|
+
el.focus();
|
|
1830
|
+
el.select();
|
|
1831
|
+
}
|
|
1832
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTimeInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1833
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTimeInput, isStandalone: true, selector: "sds-time-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, withSeconds: { classPropertyName: "withSeconds", publicName: "withSeconds", isSignal: true, isRequired: false, transformFunction: null }, placeholderText: { classPropertyName: "placeholderText", publicName: "placeholderText", isSignal: true, isRequired: false, transformFunction: null }, hoursLabel: { classPropertyName: "hoursLabel", publicName: "hoursLabel", isSignal: true, isRequired: false, transformFunction: null }, minutesLabel: { classPropertyName: "minutesLabel", publicName: "minutesLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
|
|
1834
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsTimeInput), multi: true },
|
|
1835
|
+
], viewQueries: [{ propertyName: "hoursEl", first: true, predicate: ["hoursEl"], descendants: true, isSignal: true }, { propertyName: "minutesEl", first: true, predicate: ["minutesEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1836
|
+
@if (label()) {
|
|
1837
|
+
<label
|
|
1838
|
+
[id]="fieldId + '-label'"
|
|
1839
|
+
[for]="fieldId + '-h'"
|
|
1840
|
+
class="mb-1.5 block text-sm font-medium text-ink"
|
|
1841
|
+
>
|
|
1842
|
+
{{ label() }}
|
|
1843
|
+
</label>
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
<div
|
|
1847
|
+
role="group"
|
|
1848
|
+
[attr.aria-labelledby]="label() ? fieldId + '-label' : null"
|
|
1849
|
+
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
1850
|
+
[attr.aria-describedby]="describedBy()"
|
|
1851
|
+
class="relative flex items-center border transition-colors"
|
|
1852
|
+
[class]="wrapperClasses()"
|
|
1853
|
+
(focusout)="onFocusOut($event)"
|
|
1854
|
+
(click)="onFrameClick($event)"
|
|
1855
|
+
>
|
|
1856
|
+
@if (showIcon()) {
|
|
1857
|
+
<sds-icon
|
|
1858
|
+
name="clock"
|
|
1859
|
+
[size]="16"
|
|
1860
|
+
class="pointer-events-none ml-3 shrink-0 text-ink-faint"
|
|
1861
|
+
/>
|
|
1862
|
+
}
|
|
1863
|
+
<div class="flex items-center tabular-nums" [class]="showIcon() ? 'pl-2' : 'pl-3.5'">
|
|
1864
|
+
<input
|
|
1865
|
+
#hoursEl
|
|
1866
|
+
[id]="fieldId + '-h'"
|
|
1867
|
+
type="text"
|
|
1868
|
+
inputmode="numeric"
|
|
1869
|
+
autocomplete="off"
|
|
1870
|
+
maxlength="5"
|
|
1871
|
+
role="spinbutton"
|
|
1872
|
+
aria-valuemin="0"
|
|
1873
|
+
aria-valuemax="23"
|
|
1874
|
+
[attr.aria-valuenow]="hours()"
|
|
1875
|
+
[attr.aria-valuetext]="hours() === null ? null : pad(hours()!)"
|
|
1876
|
+
[attr.aria-label]="hoursLabel()"
|
|
1877
|
+
[attr.aria-invalid]="error() ? 'true' : null"
|
|
1878
|
+
[attr.aria-describedby]="describedBy()"
|
|
1879
|
+
[value]="hoursText()"
|
|
1880
|
+
[placeholder]="placeholderText()"
|
|
1881
|
+
[disabled]="isDisabled()"
|
|
1882
|
+
[readOnly]="readonly()"
|
|
1883
|
+
class="w-[2.6ch] bg-transparent text-center text-ink outline-none placeholder:text-ink-faint disabled:cursor-not-allowed"
|
|
1884
|
+
(focus)="selectAll($event)"
|
|
1885
|
+
(input)="onHoursInput($event)"
|
|
1886
|
+
(keydown)="onHoursKeydown($event)"
|
|
1887
|
+
/>
|
|
1888
|
+
<span class="px-px text-ink-soft" aria-hidden="true">:</span>
|
|
1889
|
+
<input
|
|
1890
|
+
#minutesEl
|
|
1891
|
+
[id]="fieldId + '-m'"
|
|
1892
|
+
type="text"
|
|
1893
|
+
inputmode="numeric"
|
|
1894
|
+
autocomplete="off"
|
|
1895
|
+
maxlength="2"
|
|
1896
|
+
role="spinbutton"
|
|
1897
|
+
aria-valuemin="0"
|
|
1898
|
+
aria-valuemax="59"
|
|
1899
|
+
[attr.aria-valuenow]="minutes()"
|
|
1900
|
+
[attr.aria-valuetext]="minutes() === null ? null : pad(minutes()!)"
|
|
1901
|
+
[attr.aria-label]="minutesLabel()"
|
|
1902
|
+
[attr.aria-invalid]="error() ? 'true' : null"
|
|
1903
|
+
[attr.aria-describedby]="describedBy()"
|
|
1904
|
+
[value]="minutesText()"
|
|
1905
|
+
[placeholder]="placeholderText()"
|
|
1906
|
+
[disabled]="isDisabled()"
|
|
1907
|
+
[readOnly]="readonly()"
|
|
1908
|
+
class="w-[2.6ch] bg-transparent text-center text-ink outline-none placeholder:text-ink-faint disabled:cursor-not-allowed"
|
|
1909
|
+
(focus)="selectAll($event)"
|
|
1910
|
+
(input)="onMinutesInput($event)"
|
|
1911
|
+
(keydown)="onMinutesKeydown($event)"
|
|
1912
|
+
/>
|
|
1913
|
+
</div>
|
|
1914
|
+
|
|
1915
|
+
@if (clearable() && hasValue() && !isDisabled() && !readonly()) {
|
|
1916
|
+
<button
|
|
1917
|
+
type="button"
|
|
1918
|
+
tabindex="-1"
|
|
1919
|
+
[attr.aria-label]="clearLabel()"
|
|
1920
|
+
class="ml-auto mr-2 inline-flex h-6 w-6 items-center justify-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft dark:hover:bg-white/10"
|
|
1921
|
+
(click)="clear()"
|
|
1922
|
+
>
|
|
1923
|
+
<sds-icon name="x" [size]="15" />
|
|
1924
|
+
</button>
|
|
1925
|
+
}
|
|
1926
|
+
</div>
|
|
1927
|
+
|
|
1928
|
+
@if (error()) {
|
|
1929
|
+
<p [id]="fieldId + '-err'" class="mt-1.5 text-xs font-medium text-danger">{{ error() }}</p>
|
|
1930
|
+
} @else if (hint()) {
|
|
1931
|
+
<p [id]="fieldId + '-hint'" class="mt-1.5 text-xs text-ink-faint">{{ hint() }}</p>
|
|
1932
|
+
}
|
|
1933
|
+
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1934
|
+
}
|
|
1935
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTimeInput, decorators: [{
|
|
1936
|
+
type: Component,
|
|
1937
|
+
args: [{
|
|
1938
|
+
selector: 'sds-time-input',
|
|
1939
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1940
|
+
imports: [SdsIcon],
|
|
1941
|
+
providers: [
|
|
1942
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsTimeInput), multi: true },
|
|
1943
|
+
],
|
|
1944
|
+
host: { class: 'block' },
|
|
1945
|
+
template: `
|
|
1946
|
+
@if (label()) {
|
|
1947
|
+
<label
|
|
1948
|
+
[id]="fieldId + '-label'"
|
|
1949
|
+
[for]="fieldId + '-h'"
|
|
1950
|
+
class="mb-1.5 block text-sm font-medium text-ink"
|
|
1951
|
+
>
|
|
1952
|
+
{{ label() }}
|
|
1953
|
+
</label>
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
<div
|
|
1957
|
+
role="group"
|
|
1958
|
+
[attr.aria-labelledby]="label() ? fieldId + '-label' : null"
|
|
1959
|
+
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
1960
|
+
[attr.aria-describedby]="describedBy()"
|
|
1961
|
+
class="relative flex items-center border transition-colors"
|
|
1962
|
+
[class]="wrapperClasses()"
|
|
1963
|
+
(focusout)="onFocusOut($event)"
|
|
1964
|
+
(click)="onFrameClick($event)"
|
|
1965
|
+
>
|
|
1966
|
+
@if (showIcon()) {
|
|
1967
|
+
<sds-icon
|
|
1968
|
+
name="clock"
|
|
1969
|
+
[size]="16"
|
|
1970
|
+
class="pointer-events-none ml-3 shrink-0 text-ink-faint"
|
|
1971
|
+
/>
|
|
1972
|
+
}
|
|
1973
|
+
<div class="flex items-center tabular-nums" [class]="showIcon() ? 'pl-2' : 'pl-3.5'">
|
|
1974
|
+
<input
|
|
1975
|
+
#hoursEl
|
|
1976
|
+
[id]="fieldId + '-h'"
|
|
1977
|
+
type="text"
|
|
1978
|
+
inputmode="numeric"
|
|
1979
|
+
autocomplete="off"
|
|
1980
|
+
maxlength="5"
|
|
1981
|
+
role="spinbutton"
|
|
1982
|
+
aria-valuemin="0"
|
|
1983
|
+
aria-valuemax="23"
|
|
1984
|
+
[attr.aria-valuenow]="hours()"
|
|
1985
|
+
[attr.aria-valuetext]="hours() === null ? null : pad(hours()!)"
|
|
1986
|
+
[attr.aria-label]="hoursLabel()"
|
|
1987
|
+
[attr.aria-invalid]="error() ? 'true' : null"
|
|
1988
|
+
[attr.aria-describedby]="describedBy()"
|
|
1989
|
+
[value]="hoursText()"
|
|
1990
|
+
[placeholder]="placeholderText()"
|
|
1991
|
+
[disabled]="isDisabled()"
|
|
1992
|
+
[readOnly]="readonly()"
|
|
1993
|
+
class="w-[2.6ch] bg-transparent text-center text-ink outline-none placeholder:text-ink-faint disabled:cursor-not-allowed"
|
|
1994
|
+
(focus)="selectAll($event)"
|
|
1995
|
+
(input)="onHoursInput($event)"
|
|
1996
|
+
(keydown)="onHoursKeydown($event)"
|
|
1997
|
+
/>
|
|
1998
|
+
<span class="px-px text-ink-soft" aria-hidden="true">:</span>
|
|
1999
|
+
<input
|
|
2000
|
+
#minutesEl
|
|
2001
|
+
[id]="fieldId + '-m'"
|
|
2002
|
+
type="text"
|
|
2003
|
+
inputmode="numeric"
|
|
2004
|
+
autocomplete="off"
|
|
2005
|
+
maxlength="2"
|
|
2006
|
+
role="spinbutton"
|
|
2007
|
+
aria-valuemin="0"
|
|
2008
|
+
aria-valuemax="59"
|
|
2009
|
+
[attr.aria-valuenow]="minutes()"
|
|
2010
|
+
[attr.aria-valuetext]="minutes() === null ? null : pad(minutes()!)"
|
|
2011
|
+
[attr.aria-label]="minutesLabel()"
|
|
2012
|
+
[attr.aria-invalid]="error() ? 'true' : null"
|
|
2013
|
+
[attr.aria-describedby]="describedBy()"
|
|
2014
|
+
[value]="minutesText()"
|
|
2015
|
+
[placeholder]="placeholderText()"
|
|
2016
|
+
[disabled]="isDisabled()"
|
|
2017
|
+
[readOnly]="readonly()"
|
|
2018
|
+
class="w-[2.6ch] bg-transparent text-center text-ink outline-none placeholder:text-ink-faint disabled:cursor-not-allowed"
|
|
2019
|
+
(focus)="selectAll($event)"
|
|
2020
|
+
(input)="onMinutesInput($event)"
|
|
2021
|
+
(keydown)="onMinutesKeydown($event)"
|
|
2022
|
+
/>
|
|
2023
|
+
</div>
|
|
2024
|
+
|
|
2025
|
+
@if (clearable() && hasValue() && !isDisabled() && !readonly()) {
|
|
2026
|
+
<button
|
|
2027
|
+
type="button"
|
|
2028
|
+
tabindex="-1"
|
|
2029
|
+
[attr.aria-label]="clearLabel()"
|
|
2030
|
+
class="ml-auto mr-2 inline-flex h-6 w-6 items-center justify-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft dark:hover:bg-white/10"
|
|
2031
|
+
(click)="clear()"
|
|
2032
|
+
>
|
|
2033
|
+
<sds-icon name="x" [size]="15" />
|
|
2034
|
+
</button>
|
|
2035
|
+
}
|
|
2036
|
+
</div>
|
|
2037
|
+
|
|
2038
|
+
@if (error()) {
|
|
2039
|
+
<p [id]="fieldId + '-err'" class="mt-1.5 text-xs font-medium text-danger">{{ error() }}</p>
|
|
2040
|
+
} @else if (hint()) {
|
|
2041
|
+
<p [id]="fieldId + '-hint'" class="mt-1.5 text-xs text-ink-faint">{{ hint() }}</p>
|
|
2042
|
+
}
|
|
2043
|
+
`,
|
|
2044
|
+
}]
|
|
2045
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], withSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "withSeconds", required: false }] }], placeholderText: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderText", required: false }] }], hoursLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoursLabel", required: false }] }], minutesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "minutesLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], hoursEl: [{ type: i0.ViewChild, args: ['hoursEl', { isSignal: true }] }], minutesEl: [{ type: i0.ViewChild, args: ['minutesEl', { isSignal: true }] }] } });
|
|
2046
|
+
|
|
2047
|
+
let nextId$k = 0;
|
|
1474
2048
|
const SIZES$9 = {
|
|
1475
2049
|
sm: 'min-h-9 text-sm',
|
|
1476
2050
|
md: 'min-h-10 text-sm',
|
|
@@ -1490,7 +2064,7 @@ const SIZES$9 = {
|
|
|
1490
2064
|
* `<sds-localized-input [languages]="['fr','nl','en']" [(ngModel)]="title" />`.
|
|
1491
2065
|
*/
|
|
1492
2066
|
class SdsLocalizedInput {
|
|
1493
|
-
inputId = `sds-localized-input-${nextId$
|
|
2067
|
+
inputId = `sds-localized-input-${nextId$k++}`;
|
|
1494
2068
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
1495
2069
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
1496
2070
|
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
@@ -1746,7 +2320,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
1746
2320
|
}]
|
|
1747
2321
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], languages: [{ type: i0.Input, args: [{ isSignal: true, alias: "languages", required: false }] }], currentLanguage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentLanguage", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], languageSwitcherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "languageSwitcherLabel", required: false }] }], untranslatedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "untranslatedLabel", required: false }] }] } });
|
|
1748
2322
|
|
|
1749
|
-
let nextId$
|
|
2323
|
+
let nextId$j = 0;
|
|
1750
2324
|
const SIZES$8 = {
|
|
1751
2325
|
md: 'h-12 w-11 text-lg',
|
|
1752
2326
|
lg: 'h-14 w-12 text-xl',
|
|
@@ -1763,7 +2337,7 @@ const SIZES$8 = {
|
|
|
1763
2337
|
* first box and have it land correctly.
|
|
1764
2338
|
*/
|
|
1765
2339
|
class SdsOtpInput {
|
|
1766
|
-
groupId = `sds-otp-${nextId$
|
|
2340
|
+
groupId = `sds-otp-${nextId$j++}`;
|
|
1767
2341
|
/** How many boxes / characters the code has. */
|
|
1768
2342
|
length = input(6, ...(ngDevMode ? [{ debugName: "length", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
1769
2343
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
@@ -2063,7 +2637,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2063
2637
|
}]
|
|
2064
2638
|
}], ctorParameters: () => [], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], inputMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputMode", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], autoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFocus", required: false }] }], cellLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellLabel", required: false }] }], completed: [{ type: i0.Output, args: ["completed"] }], cells: [{ type: i0.ViewChildren, args: ['cell', { isSignal: true }] }] } });
|
|
2065
2639
|
|
|
2066
|
-
let nextId$
|
|
2640
|
+
let nextId$i = 0;
|
|
2067
2641
|
const SIZES$7 = {
|
|
2068
2642
|
sm: 'text-sm px-3 py-2',
|
|
2069
2643
|
md: 'text-sm px-3.5 py-2.5',
|
|
@@ -2075,7 +2649,7 @@ const SIZES$7 = {
|
|
|
2075
2649
|
* [(ngModel)].
|
|
2076
2650
|
*/
|
|
2077
2651
|
class SdsTextarea {
|
|
2078
|
-
fieldId = `sds-textarea-${nextId$
|
|
2652
|
+
fieldId = `sds-textarea-${nextId$i++}`;
|
|
2079
2653
|
field = viewChild('field', ...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
2080
2654
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2081
2655
|
/** Accessible name used when no visible [label] is provided. */
|
|
@@ -2335,7 +2909,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2335
2909
|
}]
|
|
2336
2910
|
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], autoResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoResize", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", required: false }] }], countLimitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countLimitLabel", required: false }] }], countLabelTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "countLabelTemplate", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }] } });
|
|
2337
2911
|
|
|
2338
|
-
let nextId$
|
|
2912
|
+
let nextId$h = 0;
|
|
2339
2913
|
const SIZES$6 = {
|
|
2340
2914
|
sm: { track: 'h-5 w-9', knob: 'h-4 w-4', on: 'translate-x-4', icon: 11 },
|
|
2341
2915
|
md: { track: 'h-6 w-11', knob: 'h-5 w-5', on: 'translate-x-5', icon: 13 },
|
|
@@ -2348,7 +2922,7 @@ const SIZES$6 = {
|
|
|
2348
2922
|
* states.
|
|
2349
2923
|
*/
|
|
2350
2924
|
class SdsToggleSwitch {
|
|
2351
|
-
fieldId = `sds-toggle-switch-${nextId$
|
|
2925
|
+
fieldId = `sds-toggle-switch-${nextId$h++}`;
|
|
2352
2926
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2353
2927
|
/** Accessible name used when no visible [label] is provided. */
|
|
2354
2928
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -2592,7 +3166,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2592
3166
|
}]
|
|
2593
3167
|
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], trueValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "trueValue", required: false }] }], falseValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "falseValue", required: false }] }], onIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "onIcon", required: false }] }], offIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "offIcon", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }] } });
|
|
2594
3168
|
|
|
2595
|
-
let nextId$
|
|
3169
|
+
let nextId$g = 0;
|
|
2596
3170
|
/**
|
|
2597
3171
|
* Boolean checkbox. Implements ControlValueAccessor — use with reactive forms
|
|
2598
3172
|
* or `[(ngModel)]`. Renders a styled box (brand-filled with a check when on)
|
|
@@ -2607,7 +3181,7 @@ let nextId$f = 0;
|
|
|
2607
3181
|
* <sds-checkbox label="Auto-merge" [(ngModel)]="autoMerge" />
|
|
2608
3182
|
*/
|
|
2609
3183
|
class SdsCheckbox {
|
|
2610
|
-
id = `sds-checkbox-${nextId$
|
|
3184
|
+
id = `sds-checkbox-${nextId$g++}`;
|
|
2611
3185
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2612
3186
|
/** Accessible name used when no visible [label] is provided. */
|
|
2613
3187
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -2755,7 +3329,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2755
3329
|
}]
|
|
2756
3330
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }] } });
|
|
2757
3331
|
|
|
2758
|
-
let nextId$
|
|
3332
|
+
let nextId$f = 0;
|
|
2759
3333
|
/**
|
|
2760
3334
|
* Mounted radios by group name. A pick updates the rest of its group, because a native radio says
|
|
2761
3335
|
* nothing when the browser unchecks it — without this a reactive form would leave the old choice drawn.
|
|
@@ -2781,7 +3355,7 @@ const groups = new Map();
|
|
|
2781
3355
|
* <sds-radio name="size" value="large" label="Grand" [(ngModel)]="size" />
|
|
2782
3356
|
*/
|
|
2783
3357
|
class SdsRadio {
|
|
2784
|
-
id = `sds-radio-${nextId$
|
|
3358
|
+
id = `sds-radio-${nextId$f++}`;
|
|
2785
3359
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2786
3360
|
/** Accessible name used when no visible [label] is provided. */
|
|
2787
3361
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -2964,8 +3538,30 @@ const STATUS_COLOR = {
|
|
|
2964
3538
|
busy: 'bg-danger',
|
|
2965
3539
|
away: 'bg-warning',
|
|
2966
3540
|
};
|
|
3541
|
+
const SHAPE = {
|
|
3542
|
+
circle: 'rounded-full',
|
|
3543
|
+
rounded: 'rounded-control',
|
|
3544
|
+
square: 'rounded-none',
|
|
3545
|
+
};
|
|
2967
3546
|
/**
|
|
2968
|
-
*
|
|
3547
|
+
* Avatar showing an image, initials or a placeholder icon, with an optional status dot.
|
|
3548
|
+
*
|
|
3549
|
+
* - `shape`: `circle` (default, people), `rounded` (things: a dish photo, a product, a logo) or `square`.
|
|
3550
|
+
* - `fallbackIcon`: shown instead of initials when there is no image (or it fails to load) — e.g.
|
|
3551
|
+
* `utensils` or `image` for a menu item without a photo. The placeholder is drawn on `placeholderClass`
|
|
3552
|
+
* (a muted tile by default), not on the initials' brand fill.
|
|
3553
|
+
* - A broken `src` falls back to the icon or the initials instead of showing the browser's broken-image
|
|
3554
|
+
* glyph; a new `src` retries.
|
|
3555
|
+
* - `decorative`: the avatar only repeats a name that is already written next to it (a list row, a select
|
|
3556
|
+
* option), so the image gets `alt=""` and the whole avatar is hidden from assistive technology.
|
|
3557
|
+
*
|
|
3558
|
+
* @example
|
|
3559
|
+
* <sds-avatar name="Ada Lovelace" [src]="user.photoUrl" status="online" />
|
|
3560
|
+
*
|
|
3561
|
+
* @example
|
|
3562
|
+
* <!-- a menu item in a list: rounded photo, dish placeholder when there is none -->
|
|
3563
|
+
* <sds-avatar shape="rounded" [size]="32" [src]="item.thumbnailUrl" [name]="item.name"
|
|
3564
|
+
* fallbackIcon="utensils" decorative />
|
|
2969
3565
|
*/
|
|
2970
3566
|
class SdsAvatar {
|
|
2971
3567
|
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : []));
|
|
@@ -2973,8 +3569,48 @@ class SdsAvatar {
|
|
|
2973
3569
|
src = input(null, ...(ngDevMode ? [{ debugName: "src" }] : []));
|
|
2974
3570
|
size = input(36, ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
2975
3571
|
status = input(null, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
3572
|
+
/** `circle` (default), `rounded` (radius of a control) or `square`. */
|
|
3573
|
+
shape = input('circle', ...(ngDevMode ? [{ debugName: "shape" }] : []));
|
|
2976
3574
|
/** Tailwind bg utility for the initials background. */
|
|
2977
3575
|
bgClass = input('bg-brand-400', ...(ngDevMode ? [{ debugName: "bgClass" }] : []));
|
|
3576
|
+
/**
|
|
3577
|
+
* Icon shown instead of initials when there is no usable image (e.g. `utensils` or `image` for a dish).
|
|
3578
|
+
* Null (default) keeps the initials.
|
|
3579
|
+
*/
|
|
3580
|
+
fallbackIcon = input(null, ...(ngDevMode ? [{ debugName: "fallbackIcon" }] : []));
|
|
3581
|
+
/** Classes of the placeholder tile behind {@link fallbackIcon}: background and icon colour. */
|
|
3582
|
+
placeholderClass = input('bg-muted text-ink-faint', ...(ngDevMode ? [{ debugName: "placeholderClass" }] : []));
|
|
3583
|
+
/**
|
|
3584
|
+
* The avatar repeats a name already visible beside it: `alt=""` and `aria-hidden`, so a screen reader
|
|
3585
|
+
* does not read the name twice.
|
|
3586
|
+
*/
|
|
3587
|
+
decorative = input(false, ...(ngDevMode ? [{ debugName: "decorative", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
3588
|
+
/** Native lazy loading for the image (default on — avatars are often in long lists). */
|
|
3589
|
+
lazy = input(true, ...(ngDevMode ? [{ debugName: "lazy", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
3590
|
+
/** The `src` that failed to load. Any other `src` is tried (so a new photo URL retries). */
|
|
3591
|
+
failedSrc = signal(undefined, ...(ngDevMode ? [{ debugName: "failedSrc" }] : []));
|
|
3592
|
+
showImage = computed(() => {
|
|
3593
|
+
const src = this.src();
|
|
3594
|
+
return !!src && src !== this.failedSrc();
|
|
3595
|
+
}, ...(ngDevMode ? [{ debugName: "showImage" }] : []));
|
|
3596
|
+
shapeClass = computed(() => SHAPE[this.shape()], ...(ngDevMode ? [{ debugName: "shapeClass" }] : []));
|
|
3597
|
+
frameClass = computed(() => {
|
|
3598
|
+
const parts = [this.shapeClass()];
|
|
3599
|
+
if (this.showImage()) {
|
|
3600
|
+
parts.push('bg-muted');
|
|
3601
|
+
}
|
|
3602
|
+
else if (this.fallbackIcon()) {
|
|
3603
|
+
parts.push(this.placeholderClass());
|
|
3604
|
+
}
|
|
3605
|
+
else {
|
|
3606
|
+
parts.push(this.bgClass(), 'text-white');
|
|
3607
|
+
}
|
|
3608
|
+
// People get the soft ring the avatar always had; things get a hairline so a white plate on a white
|
|
3609
|
+
// page still has an edge.
|
|
3610
|
+
parts.push(this.shape() === 'circle' ? 'ring-2 ring-white/20' : 'ring-1 ring-inset ring-border');
|
|
3611
|
+
return parts.join(' ');
|
|
3612
|
+
}, ...(ngDevMode ? [{ debugName: "frameClass" }] : []));
|
|
3613
|
+
iconSize = computed(() => Math.max(12, Math.round(this.size() * 0.5)), ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
|
|
2978
3614
|
dotSize = computed(() => Math.max(8, Math.round(this.size() * 0.28)), ...(ngDevMode ? [{ debugName: "dotSize" }] : []));
|
|
2979
3615
|
statusColor = computed(() => this.status() ? STATUS_COLOR[this.status()] : '', ...(ngDevMode ? [{ debugName: "statusColor" }] : []));
|
|
2980
3616
|
resolvedInitials = computed(() => {
|
|
@@ -2988,19 +3624,31 @@ class SdsAvatar {
|
|
|
2988
3624
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
2989
3625
|
}, ...(ngDevMode ? [{ debugName: "resolvedInitials" }] : []));
|
|
2990
3626
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2991
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsAvatar, isStandalone: true, selector: "sds-avatar", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, bgClass: { classPropertyName: "bgClass", publicName: "bgClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "inline-block shrink-0 align-middle" }, ngImport: i0, template: `
|
|
3627
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsAvatar, isStandalone: true, selector: "sds-avatar", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, bgClass: { classPropertyName: "bgClass", publicName: "bgClass", isSignal: true, isRequired: false, transformFunction: null }, fallbackIcon: { classPropertyName: "fallbackIcon", publicName: "fallbackIcon", isSignal: true, isRequired: false, transformFunction: null }, placeholderClass: { classPropertyName: "placeholderClass", publicName: "placeholderClass", isSignal: true, isRequired: false, transformFunction: null }, decorative: { classPropertyName: "decorative", publicName: "decorative", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.aria-hidden": "decorative() ? 'true' : null" }, classAttribute: "inline-block shrink-0 align-middle" }, ngImport: i0, template: `
|
|
2992
3628
|
<div
|
|
2993
|
-
class="relative grid place-items-center
|
|
2994
|
-
[class]="
|
|
3629
|
+
class="relative grid place-items-center font-semibold"
|
|
3630
|
+
[class]="frameClass()"
|
|
2995
3631
|
[style.width.px]="size()"
|
|
2996
3632
|
[style.height.px]="size()"
|
|
2997
3633
|
[style.fontSize.px]="size() * 0.4"
|
|
2998
3634
|
>
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3635
|
+
<!-- The image and placeholder are clipped to the shape; the status dot is not (it straddles the edge). -->
|
|
3636
|
+
<div class="absolute inset-0 grid place-items-center overflow-hidden" [class]="shapeClass()">
|
|
3637
|
+
@if (showImage()) {
|
|
3638
|
+
<img
|
|
3639
|
+
[src]="src()"
|
|
3640
|
+
[alt]="decorative() ? '' : name()"
|
|
3641
|
+
[attr.loading]="lazy() ? 'lazy' : null"
|
|
3642
|
+
decoding="async"
|
|
3643
|
+
class="h-full w-full object-cover"
|
|
3644
|
+
(error)="failedSrc.set(src())"
|
|
3645
|
+
/>
|
|
3646
|
+
} @else if (fallbackIcon()) {
|
|
3647
|
+
<sds-icon [name]="fallbackIcon()!" [size]="iconSize()" />
|
|
3648
|
+
} @else {
|
|
3649
|
+
<span>{{ resolvedInitials() }}</span>
|
|
3650
|
+
}
|
|
3651
|
+
</div>
|
|
3004
3652
|
|
|
3005
3653
|
@if (status()) {
|
|
3006
3654
|
<span
|
|
@@ -3011,27 +3659,43 @@ class SdsAvatar {
|
|
|
3011
3659
|
></span>
|
|
3012
3660
|
}
|
|
3013
3661
|
</div>
|
|
3014
|
-
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3662
|
+
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3015
3663
|
}
|
|
3016
3664
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsAvatar, decorators: [{
|
|
3017
3665
|
type: Component,
|
|
3018
3666
|
args: [{
|
|
3019
3667
|
selector: 'sds-avatar',
|
|
3020
3668
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3021
|
-
|
|
3669
|
+
imports: [SdsIcon],
|
|
3670
|
+
host: {
|
|
3671
|
+
class: 'inline-block shrink-0 align-middle',
|
|
3672
|
+
'[attr.aria-hidden]': "decorative() ? 'true' : null",
|
|
3673
|
+
},
|
|
3022
3674
|
template: `
|
|
3023
3675
|
<div
|
|
3024
|
-
class="relative grid place-items-center
|
|
3025
|
-
[class]="
|
|
3676
|
+
class="relative grid place-items-center font-semibold"
|
|
3677
|
+
[class]="frameClass()"
|
|
3026
3678
|
[style.width.px]="size()"
|
|
3027
3679
|
[style.height.px]="size()"
|
|
3028
3680
|
[style.fontSize.px]="size() * 0.4"
|
|
3029
3681
|
>
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3682
|
+
<!-- The image and placeholder are clipped to the shape; the status dot is not (it straddles the edge). -->
|
|
3683
|
+
<div class="absolute inset-0 grid place-items-center overflow-hidden" [class]="shapeClass()">
|
|
3684
|
+
@if (showImage()) {
|
|
3685
|
+
<img
|
|
3686
|
+
[src]="src()"
|
|
3687
|
+
[alt]="decorative() ? '' : name()"
|
|
3688
|
+
[attr.loading]="lazy() ? 'lazy' : null"
|
|
3689
|
+
decoding="async"
|
|
3690
|
+
class="h-full w-full object-cover"
|
|
3691
|
+
(error)="failedSrc.set(src())"
|
|
3692
|
+
/>
|
|
3693
|
+
} @else if (fallbackIcon()) {
|
|
3694
|
+
<sds-icon [name]="fallbackIcon()!" [size]="iconSize()" />
|
|
3695
|
+
} @else {
|
|
3696
|
+
<span>{{ resolvedInitials() }}</span>
|
|
3697
|
+
}
|
|
3698
|
+
</div>
|
|
3035
3699
|
|
|
3036
3700
|
@if (status()) {
|
|
3037
3701
|
<span
|
|
@@ -3044,7 +3708,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3044
3708
|
</div>
|
|
3045
3709
|
`,
|
|
3046
3710
|
}]
|
|
3047
|
-
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], bgClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "bgClass", required: false }] }] } });
|
|
3711
|
+
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], bgClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "bgClass", required: false }] }], fallbackIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "fallbackIcon", required: false }] }], placeholderClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderClass", required: false }] }], decorative: [{ type: i0.Input, args: [{ isSignal: true, alias: "decorative", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }] } });
|
|
3048
3712
|
|
|
3049
3713
|
const VARIANTS$1 = {
|
|
3050
3714
|
neutral: 'bg-muted text-ink-soft border-border',
|
|
@@ -3267,7 +3931,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3267
3931
|
|
|
3268
3932
|
/** Activation order: none → contains → may-contain → none. */
|
|
3269
3933
|
const ORDER = ['none', 'contains', 'may-contain'];
|
|
3270
|
-
let nextId$
|
|
3934
|
+
let nextId$e = 0;
|
|
3271
3935
|
/**
|
|
3272
3936
|
* A chip that cycles through three states — `none`, `contains`, `may-contain` — built for the 14-tile
|
|
3273
3937
|
* allergen declaration grid, but generic (any "no / yes / maybe" declaration).
|
|
@@ -3287,7 +3951,7 @@ let nextId$d = 0;
|
|
|
3287
3951
|
* containsLabel="Contains" mayContainLabel="May contain" noneLabel="Not present" />
|
|
3288
3952
|
*/
|
|
3289
3953
|
class SdsTriStateChip {
|
|
3290
|
-
chipId = `sds-tri-state-chip-${nextId$
|
|
3954
|
+
chipId = `sds-tri-state-chip-${nextId$e++}`;
|
|
3291
3955
|
/** Current state. Two-way: `[(value)]`. */
|
|
3292
3956
|
value = model('none', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
3293
3957
|
/** Visible name (e.g. the allergen). Required — the chip has no other accessible name. */
|
|
@@ -3509,7 +4173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3509
4173
|
}]
|
|
3510
4174
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showState: [{ type: i0.Input, args: [{ isSignal: true, alias: "showState", required: false }] }], noneLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noneLabel", required: false }] }], containsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "containsLabel", required: false }] }], mayContainLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mayContainLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }] } });
|
|
3511
4175
|
|
|
3512
|
-
let nextId$
|
|
4176
|
+
let nextId$d = 0;
|
|
3513
4177
|
/**
|
|
3514
4178
|
* Segmented control: a small set of mutually exclusive options shown side by side (e.g. "Pick exactly /
|
|
3515
4179
|
* at least / up to"). Radio-group semantics: `role="radiogroup"` with `role="radio"` segments, one tab
|
|
@@ -3525,7 +4189,7 @@ let nextId$c = 0;
|
|
|
3525
4189
|
*/
|
|
3526
4190
|
class SdsSegmented {
|
|
3527
4191
|
host = inject(ElementRef);
|
|
3528
|
-
baseId = `sds-segmented-${nextId$
|
|
4192
|
+
baseId = `sds-segmented-${nextId$d++}`;
|
|
3529
4193
|
/** Options: `{ value, label, icon?, disabled? }` objects, or bare strings/numbers. */
|
|
3530
4194
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
3531
4195
|
/** Selected value. Two-way: `[(value)]`. */
|
|
@@ -3703,6 +4367,374 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3703
4367
|
}]
|
|
3704
4368
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledby", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }] } });
|
|
3705
4369
|
|
|
4370
|
+
const SIZE = {
|
|
4371
|
+
sm: 'h-7 gap-1 px-2.5 text-xs',
|
|
4372
|
+
md: 'h-8 gap-1.5 px-3 text-sm',
|
|
4373
|
+
};
|
|
4374
|
+
/**
|
|
4375
|
+
* Chip look shared by sds-chip and sds-chip-group. Selected is more than a tint — a brand border, bolder
|
|
4376
|
+
* text and (by default) a check — so it reads in greyscale too. In dark mode the brand text/tint are
|
|
4377
|
+
* swapped for ink/muted (the library's rule for a monochrome brand's dark ramp).
|
|
4378
|
+
*/
|
|
4379
|
+
function chipClass(size, selected) {
|
|
4380
|
+
const base = 'inline-flex shrink-0 select-none items-center whitespace-nowrap rounded-full border font-medium ' +
|
|
4381
|
+
'transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 ' +
|
|
4382
|
+
'focus-visible:ring-offset-1 focus-visible:ring-offset-surface disabled:cursor-not-allowed disabled:opacity-50 ' +
|
|
4383
|
+
SIZE[size];
|
|
4384
|
+
return selected
|
|
4385
|
+
? `${base} cursor-pointer border-brand-600 bg-brand-50 font-semibold text-brand-700 ` +
|
|
4386
|
+
'dark:border-ink-soft dark:bg-muted dark:text-ink'
|
|
4387
|
+
: `${base} cursor-pointer border-border bg-surface text-ink-soft hover:border-ink-faint hover:text-ink`;
|
|
4388
|
+
}
|
|
4389
|
+
const COUNT_CLASS = 'inline-flex min-w-5 items-center justify-center rounded-full bg-ink/5 px-1.5 text-[11px] font-semibold tabular-nums dark:bg-white/10';
|
|
4390
|
+
/**
|
|
4391
|
+
* A single on/off filter chip (`aria-pressed`), e.g. "Sold out only" or "With comments". Two-way
|
|
4392
|
+
* `[(selected)]`. For a set of chips — one or several picked — use `sds-chip-group`.
|
|
4393
|
+
*
|
|
4394
|
+
* @example
|
|
4395
|
+
* <sds-chip label="Sold out only" icon="ban" [(selected)]="soldOutOnly" />
|
|
4396
|
+
*/
|
|
4397
|
+
class SdsChip {
|
|
4398
|
+
/** Visible text — also the chip's accessible name. */
|
|
4399
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
4400
|
+
/** On/off. Two-way: `[(selected)]`. */
|
|
4401
|
+
selected = model(false, ...(ngDevMode ? [{ debugName: "selected" }] : []));
|
|
4402
|
+
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
4403
|
+
count = input(null, ...(ngDevMode ? [{ debugName: "count" }] : []));
|
|
4404
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
4405
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
4406
|
+
/** Replace the icon with a check while selected. */
|
|
4407
|
+
showCheck = input(true, ...(ngDevMode ? [{ debugName: "showCheck", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
4408
|
+
countClass = COUNT_CLASS;
|
|
4409
|
+
classes = computed(() => chipClass(this.size(), this.selected()), ...(ngDevMode ? [{ debugName: "classes" }] : []));
|
|
4410
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4411
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsChip, isStandalone: true, selector: "sds-chip", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showCheck: { classPropertyName: "showCheck", publicName: "showCheck", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange" }, host: { classAttribute: "inline-flex" }, ngImport: i0, template: `
|
|
4412
|
+
<button
|
|
4413
|
+
type="button"
|
|
4414
|
+
[attr.aria-pressed]="selected()"
|
|
4415
|
+
[disabled]="disabled()"
|
|
4416
|
+
[class]="classes()"
|
|
4417
|
+
(click)="selected.set(!selected())"
|
|
4418
|
+
>
|
|
4419
|
+
@if (selected() && showCheck()) {
|
|
4420
|
+
<sds-icon
|
|
4421
|
+
name="check"
|
|
4422
|
+
[size]="size() === 'sm' ? 12 : 14"
|
|
4423
|
+
[strokeWidth]="3"
|
|
4424
|
+
class="shrink-0"
|
|
4425
|
+
/>
|
|
4426
|
+
} @else if (icon()) {
|
|
4427
|
+
<sds-icon [name]="icon()!" [size]="size() === 'sm' ? 13 : 15" class="shrink-0" />
|
|
4428
|
+
}
|
|
4429
|
+
<span class="truncate">{{ label() }}</span>
|
|
4430
|
+
@if (count() !== null && count() !== undefined) {
|
|
4431
|
+
<span [class]="countClass">{{ count() }}</span>
|
|
4432
|
+
}
|
|
4433
|
+
</button>
|
|
4434
|
+
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4435
|
+
}
|
|
4436
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsChip, decorators: [{
|
|
4437
|
+
type: Component,
|
|
4438
|
+
args: [{
|
|
4439
|
+
selector: 'sds-chip',
|
|
4440
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4441
|
+
imports: [SdsIcon],
|
|
4442
|
+
host: { class: 'inline-flex' },
|
|
4443
|
+
template: `
|
|
4444
|
+
<button
|
|
4445
|
+
type="button"
|
|
4446
|
+
[attr.aria-pressed]="selected()"
|
|
4447
|
+
[disabled]="disabled()"
|
|
4448
|
+
[class]="classes()"
|
|
4449
|
+
(click)="selected.set(!selected())"
|
|
4450
|
+
>
|
|
4451
|
+
@if (selected() && showCheck()) {
|
|
4452
|
+
<sds-icon
|
|
4453
|
+
name="check"
|
|
4454
|
+
[size]="size() === 'sm' ? 12 : 14"
|
|
4455
|
+
[strokeWidth]="3"
|
|
4456
|
+
class="shrink-0"
|
|
4457
|
+
/>
|
|
4458
|
+
} @else if (icon()) {
|
|
4459
|
+
<sds-icon [name]="icon()!" [size]="size() === 'sm' ? 13 : 15" class="shrink-0" />
|
|
4460
|
+
}
|
|
4461
|
+
<span class="truncate">{{ label() }}</span>
|
|
4462
|
+
@if (count() !== null && count() !== undefined) {
|
|
4463
|
+
<span [class]="countClass">{{ count() }}</span>
|
|
4464
|
+
}
|
|
4465
|
+
</button>
|
|
4466
|
+
`,
|
|
4467
|
+
}]
|
|
4468
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCheck", required: false }] }] } });
|
|
4469
|
+
let nextId$c = 0;
|
|
4470
|
+
/**
|
|
4471
|
+
* A set of chips: pick ONE (a filter row such as "All · Missing photo · Hidden", VAT presets, a date
|
|
4472
|
+
* range) or, with `multiple`, SEVERAL (categories of an item, days of the week, dietary tags). Unlike
|
|
4473
|
+
* sds-segmented (a compact joined bar), chips wrap onto several lines and can carry a count.
|
|
4474
|
+
*
|
|
4475
|
+
* Value: two-way `[(value)]`, or a form control (`formControlName` / `[(ngModel)]` —
|
|
4476
|
+
* ControlValueAccessor). Single mode holds the picked value (or null); `multiple` holds an array, in the
|
|
4477
|
+
* order of the options.
|
|
4478
|
+
*
|
|
4479
|
+
* Accessibility: single mode is a `radiogroup` (one tab stop, arrows/Home/End move and select, like
|
|
4480
|
+
* native radios); `multiple` is a `group` of `aria-pressed` toggle buttons. Name it with [ariaLabel] or
|
|
4481
|
+
* [ariaLabelledby].
|
|
4482
|
+
*
|
|
4483
|
+
* @example
|
|
4484
|
+
* <sds-chip-group ariaLabel="Filter" [options]="filters()" [(value)]="issue" />
|
|
4485
|
+
* <!-- filters = [{ value: null, label: 'All', count: 34 }, { value: 'NO_PHOTO', label: 'Missing photo', count: 5 }] -->
|
|
4486
|
+
*
|
|
4487
|
+
* @example
|
|
4488
|
+
* <sds-chip-group ariaLabel="Categories" multiple [options]="categories()" formControlName="categoryIds" />
|
|
4489
|
+
*/
|
|
4490
|
+
class SdsChipGroup {
|
|
4491
|
+
host = inject(ElementRef);
|
|
4492
|
+
baseId = `sds-chip-group-${nextId$c++}`;
|
|
4493
|
+
/** Options: `{ value, label, icon?, count?, disabled? }` objects, or bare strings/numbers. */
|
|
4494
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
4495
|
+
/** Picked value (single) or values (multiple). Two-way: `[(value)]`. */
|
|
4496
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
4497
|
+
/** Allow several chips at once; the value becomes an array. */
|
|
4498
|
+
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
4499
|
+
/** Single mode: clicking the picked chip again clears the value to null. */
|
|
4500
|
+
deselectable = input(false, ...(ngDevMode ? [{ debugName: "deselectable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
4501
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
4502
|
+
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
4503
|
+
ariaLabelledby = input('', ...(ngDevMode ? [{ debugName: "ariaLabelledby" }] : []));
|
|
4504
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
4505
|
+
/** Wrap onto several lines (default) or scroll horizontally on one line. */
|
|
4506
|
+
wrap = input(true, ...(ngDevMode ? [{ debugName: "wrap", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
4507
|
+
/** `multiple`: a check replaces the icon on picked chips. */
|
|
4508
|
+
showCheck = input(true, ...(ngDevMode ? [{ debugName: "showCheck", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
4509
|
+
countClass = COUNT_CLASS;
|
|
4510
|
+
cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
|
|
4511
|
+
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
4512
|
+
chips = computed(() => this.options().map((o) => o !== null && typeof o === 'object'
|
|
4513
|
+
? {
|
|
4514
|
+
value: o.value,
|
|
4515
|
+
label: o.label,
|
|
4516
|
+
icon: o.icon ?? null,
|
|
4517
|
+
count: o.count ?? null,
|
|
4518
|
+
disabled: !!o.disabled,
|
|
4519
|
+
}
|
|
4520
|
+
: { value: o, label: String(o), icon: null, count: null, disabled: false }), ...(ngDevMode ? [{ debugName: "chips" }] : []));
|
|
4521
|
+
selectedValues = computed(() => {
|
|
4522
|
+
const v = this.value();
|
|
4523
|
+
if (this.multiple())
|
|
4524
|
+
return Array.isArray(v) ? v : [];
|
|
4525
|
+
return [v];
|
|
4526
|
+
}, ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
|
|
4527
|
+
/** Single mode's roving tab stop: the picked chip, else the first enabled one. */
|
|
4528
|
+
tabStop = computed(() => {
|
|
4529
|
+
const chips = this.chips();
|
|
4530
|
+
const sel = chips.findIndex((c) => this.isSelected(c));
|
|
4531
|
+
if (sel >= 0 && !chips[sel].disabled)
|
|
4532
|
+
return sel;
|
|
4533
|
+
return chips.findIndex((c) => !c.disabled);
|
|
4534
|
+
}, ...(ngDevMode ? [{ debugName: "tabStop" }] : []));
|
|
4535
|
+
isSelected(chip) {
|
|
4536
|
+
return this.selectedValues().includes(chip.value);
|
|
4537
|
+
}
|
|
4538
|
+
chipId(i) {
|
|
4539
|
+
return `${this.baseId}-${i}`;
|
|
4540
|
+
}
|
|
4541
|
+
classFor(chip) {
|
|
4542
|
+
return chipClass(this.size(), this.isSelected(chip));
|
|
4543
|
+
}
|
|
4544
|
+
toggle(i) {
|
|
4545
|
+
const chip = this.chips()[i];
|
|
4546
|
+
if (!chip || chip.disabled || this.isDisabled())
|
|
4547
|
+
return;
|
|
4548
|
+
let next;
|
|
4549
|
+
if (this.multiple()) {
|
|
4550
|
+
const picked = new Set(this.selectedValues());
|
|
4551
|
+
if (picked.has(chip.value))
|
|
4552
|
+
picked.delete(chip.value);
|
|
4553
|
+
else
|
|
4554
|
+
picked.add(chip.value);
|
|
4555
|
+
// Keep the options' order, whatever the click order.
|
|
4556
|
+
next = this.chips()
|
|
4557
|
+
.map((c) => c.value)
|
|
4558
|
+
.filter((v) => picked.has(v));
|
|
4559
|
+
}
|
|
4560
|
+
else {
|
|
4561
|
+
if (this.isSelected(chip)) {
|
|
4562
|
+
if (!this.deselectable())
|
|
4563
|
+
return;
|
|
4564
|
+
next = null;
|
|
4565
|
+
}
|
|
4566
|
+
else {
|
|
4567
|
+
next = chip.value;
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4570
|
+
this.value.set(next);
|
|
4571
|
+
this.onChange(next);
|
|
4572
|
+
}
|
|
4573
|
+
onKeydown(event) {
|
|
4574
|
+
if (this.multiple() || this.isDisabled())
|
|
4575
|
+
return;
|
|
4576
|
+
const chips = this.chips();
|
|
4577
|
+
if (!chips.length)
|
|
4578
|
+
return;
|
|
4579
|
+
const current = Number(event.target.dataset['index'] ?? this.tabStop());
|
|
4580
|
+
let next = null;
|
|
4581
|
+
switch (event.key) {
|
|
4582
|
+
case 'ArrowRight':
|
|
4583
|
+
case 'ArrowDown':
|
|
4584
|
+
next = this.step(current, 1);
|
|
4585
|
+
break;
|
|
4586
|
+
case 'ArrowLeft':
|
|
4587
|
+
case 'ArrowUp':
|
|
4588
|
+
next = this.step(current, -1);
|
|
4589
|
+
break;
|
|
4590
|
+
case 'Home':
|
|
4591
|
+
next = chips.findIndex((c) => !c.disabled);
|
|
4592
|
+
break;
|
|
4593
|
+
case 'End':
|
|
4594
|
+
for (let i = chips.length - 1; i >= 0; i--) {
|
|
4595
|
+
if (!chips[i].disabled) {
|
|
4596
|
+
next = i;
|
|
4597
|
+
break;
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
break;
|
|
4601
|
+
default:
|
|
4602
|
+
return;
|
|
4603
|
+
}
|
|
4604
|
+
event.preventDefault();
|
|
4605
|
+
if (next === null || next < 0)
|
|
4606
|
+
return;
|
|
4607
|
+
if (!this.isSelected(chips[next]))
|
|
4608
|
+
this.toggle(next);
|
|
4609
|
+
this.host.nativeElement.querySelector(`#${this.chipId(next)}`)?.focus();
|
|
4610
|
+
}
|
|
4611
|
+
step(from, delta) {
|
|
4612
|
+
const chips = this.chips();
|
|
4613
|
+
let i = from;
|
|
4614
|
+
for (let n = 0; n < chips.length; n++) {
|
|
4615
|
+
i = (i + delta + chips.length) % chips.length;
|
|
4616
|
+
if (!chips[i].disabled)
|
|
4617
|
+
return i;
|
|
4618
|
+
}
|
|
4619
|
+
return null;
|
|
4620
|
+
}
|
|
4621
|
+
// --- ControlValueAccessor -------------------------------------------------
|
|
4622
|
+
onChange = () => { };
|
|
4623
|
+
onTouched = () => { };
|
|
4624
|
+
writeValue(value) {
|
|
4625
|
+
// Normalised on read (selectedValues), so a null written to a `multiple` group is simply "none".
|
|
4626
|
+
this.value.set(value ?? null);
|
|
4627
|
+
}
|
|
4628
|
+
registerOnChange(fn) {
|
|
4629
|
+
this.onChange = fn;
|
|
4630
|
+
}
|
|
4631
|
+
registerOnTouched(fn) {
|
|
4632
|
+
this.onTouched = fn;
|
|
4633
|
+
}
|
|
4634
|
+
setDisabledState(isDisabled) {
|
|
4635
|
+
this.cvaDisabled.set(isDisabled);
|
|
4636
|
+
}
|
|
4637
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsChipGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4638
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsChipGroup, isStandalone: true, selector: "sds-chip-group", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, deselectable: { classPropertyName: "deselectable", publicName: "deselectable", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "ariaLabelledby", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, wrap: { classPropertyName: "wrap", publicName: "wrap", isSignal: true, isRequired: false, transformFunction: null }, showCheck: { classPropertyName: "showCheck", publicName: "showCheck", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { classAttribute: "block" }, providers: [
|
|
4639
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsChipGroup), multi: true },
|
|
4640
|
+
], ngImport: i0, template: `
|
|
4641
|
+
<div
|
|
4642
|
+
[attr.role]="multiple() ? 'group' : 'radiogroup'"
|
|
4643
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
4644
|
+
[attr.aria-labelledby]="ariaLabelledby() || null"
|
|
4645
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : null"
|
|
4646
|
+
class="flex gap-2"
|
|
4647
|
+
[class]="wrap() ? 'flex-wrap' : 'overflow-x-auto pb-1'"
|
|
4648
|
+
(keydown)="onKeydown($event)"
|
|
4649
|
+
(focusout)="onTouched()"
|
|
4650
|
+
>
|
|
4651
|
+
@for (chip of chips(); track $index; let i = $index) {
|
|
4652
|
+
<button
|
|
4653
|
+
type="button"
|
|
4654
|
+
[id]="chipId(i)"
|
|
4655
|
+
[attr.role]="multiple() ? null : 'radio'"
|
|
4656
|
+
[attr.aria-checked]="multiple() ? null : isSelected(chip)"
|
|
4657
|
+
[attr.aria-pressed]="multiple() ? isSelected(chip) : null"
|
|
4658
|
+
[attr.tabindex]="multiple() || i === tabStop() ? 0 : -1"
|
|
4659
|
+
[attr.data-index]="i"
|
|
4660
|
+
[disabled]="isDisabled() || chip.disabled"
|
|
4661
|
+
[class]="classFor(chip)"
|
|
4662
|
+
(click)="toggle(i)"
|
|
4663
|
+
>
|
|
4664
|
+
@if (isSelected(chip) && multiple() && showCheck()) {
|
|
4665
|
+
<sds-icon
|
|
4666
|
+
name="check"
|
|
4667
|
+
[size]="size() === 'sm' ? 12 : 14"
|
|
4668
|
+
[strokeWidth]="3"
|
|
4669
|
+
class="shrink-0"
|
|
4670
|
+
/>
|
|
4671
|
+
} @else if (chip.icon) {
|
|
4672
|
+
<sds-icon [name]="chip.icon" [size]="size() === 'sm' ? 13 : 15" class="shrink-0" />
|
|
4673
|
+
}
|
|
4674
|
+
<span class="truncate">{{ chip.label }}</span>
|
|
4675
|
+
@if (chip.count !== null) {
|
|
4676
|
+
<span [class]="countClass">{{ chip.count }}</span>
|
|
4677
|
+
}
|
|
4678
|
+
</button>
|
|
4679
|
+
}
|
|
4680
|
+
</div>
|
|
4681
|
+
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4682
|
+
}
|
|
4683
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsChipGroup, decorators: [{
|
|
4684
|
+
type: Component,
|
|
4685
|
+
args: [{
|
|
4686
|
+
selector: 'sds-chip-group',
|
|
4687
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4688
|
+
imports: [SdsIcon],
|
|
4689
|
+
providers: [
|
|
4690
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsChipGroup), multi: true },
|
|
4691
|
+
],
|
|
4692
|
+
host: { class: 'block' },
|
|
4693
|
+
template: `
|
|
4694
|
+
<div
|
|
4695
|
+
[attr.role]="multiple() ? 'group' : 'radiogroup'"
|
|
4696
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
4697
|
+
[attr.aria-labelledby]="ariaLabelledby() || null"
|
|
4698
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : null"
|
|
4699
|
+
class="flex gap-2"
|
|
4700
|
+
[class]="wrap() ? 'flex-wrap' : 'overflow-x-auto pb-1'"
|
|
4701
|
+
(keydown)="onKeydown($event)"
|
|
4702
|
+
(focusout)="onTouched()"
|
|
4703
|
+
>
|
|
4704
|
+
@for (chip of chips(); track $index; let i = $index) {
|
|
4705
|
+
<button
|
|
4706
|
+
type="button"
|
|
4707
|
+
[id]="chipId(i)"
|
|
4708
|
+
[attr.role]="multiple() ? null : 'radio'"
|
|
4709
|
+
[attr.aria-checked]="multiple() ? null : isSelected(chip)"
|
|
4710
|
+
[attr.aria-pressed]="multiple() ? isSelected(chip) : null"
|
|
4711
|
+
[attr.tabindex]="multiple() || i === tabStop() ? 0 : -1"
|
|
4712
|
+
[attr.data-index]="i"
|
|
4713
|
+
[disabled]="isDisabled() || chip.disabled"
|
|
4714
|
+
[class]="classFor(chip)"
|
|
4715
|
+
(click)="toggle(i)"
|
|
4716
|
+
>
|
|
4717
|
+
@if (isSelected(chip) && multiple() && showCheck()) {
|
|
4718
|
+
<sds-icon
|
|
4719
|
+
name="check"
|
|
4720
|
+
[size]="size() === 'sm' ? 12 : 14"
|
|
4721
|
+
[strokeWidth]="3"
|
|
4722
|
+
class="shrink-0"
|
|
4723
|
+
/>
|
|
4724
|
+
} @else if (chip.icon) {
|
|
4725
|
+
<sds-icon [name]="chip.icon" [size]="size() === 'sm' ? 13 : 15" class="shrink-0" />
|
|
4726
|
+
}
|
|
4727
|
+
<span class="truncate">{{ chip.label }}</span>
|
|
4728
|
+
@if (chip.count !== null) {
|
|
4729
|
+
<span [class]="countClass">{{ chip.count }}</span>
|
|
4730
|
+
}
|
|
4731
|
+
</button>
|
|
4732
|
+
}
|
|
4733
|
+
</div>
|
|
4734
|
+
`,
|
|
4735
|
+
}]
|
|
4736
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], deselectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "deselectable", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledby", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], wrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrap", required: false }] }], showCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCheck", required: false }] }] } });
|
|
4737
|
+
|
|
3706
4738
|
/**
|
|
3707
4739
|
* Each status has its own glyph SHAPE (circle-check, triangle, octagon, circle-i) as well as its own
|
|
3708
4740
|
* tint, so the row still reads in greyscale or for a colour-blind reader. `label` is the English
|
|
@@ -10727,8 +11759,13 @@ class SdsTabsStore {
|
|
|
10727
11759
|
id = `sds-tabs-${nextId$3++}`;
|
|
10728
11760
|
/** Whether the tab list scrolls horizontally (mirrors [scrollable]). */
|
|
10729
11761
|
scrollable = signal(false, ...(ngDevMode ? [{ debugName: "scrollable" }] : []));
|
|
11762
|
+
/** Controlled mode (mirrors [controlled]): a click only REQUESTS a tab, the host sets [value]. */
|
|
11763
|
+
controlled = signal(false, ...(ngDevMode ? [{ debugName: "controlled" }] : []));
|
|
11764
|
+
/** Called with every tab the user picks (wired to the host's (tabSelect) output). */
|
|
11765
|
+
onSelect = () => { };
|
|
10730
11766
|
value;
|
|
10731
11767
|
registered = signal([], ...(ngDevMode ? [{ debugName: "registered" }] : []));
|
|
11768
|
+
panels = signal([], ...(ngDevMode ? [{ debugName: "panels" }] : []));
|
|
10732
11769
|
/** Called once by <sds-tabs> to share its two-way `value` signal. */
|
|
10733
11770
|
connect(value) {
|
|
10734
11771
|
this.value = value;
|
|
@@ -10739,8 +11776,11 @@ class SdsTabsStore {
|
|
|
10739
11776
|
isActive(value) {
|
|
10740
11777
|
return this.value() === value;
|
|
10741
11778
|
}
|
|
11779
|
+
/** A user pick. Uncontrolled: becomes the active tab. Controlled: only reported to the host. */
|
|
10742
11780
|
select(value) {
|
|
10743
|
-
this.
|
|
11781
|
+
this.onSelect(value);
|
|
11782
|
+
if (!this.controlled())
|
|
11783
|
+
this.value.set(value);
|
|
10744
11784
|
}
|
|
10745
11785
|
registerTab(value) {
|
|
10746
11786
|
this.registered.update((list) => (list.includes(value) ? list : [...list, value]));
|
|
@@ -10751,6 +11791,16 @@ class SdsTabsStore {
|
|
|
10751
11791
|
unregisterTab(value) {
|
|
10752
11792
|
this.registered.update((list) => list.filter((v) => v !== value));
|
|
10753
11793
|
}
|
|
11794
|
+
registerPanel(value) {
|
|
11795
|
+
this.panels.update((list) => (list.includes(value) ? list : [...list, value]));
|
|
11796
|
+
}
|
|
11797
|
+
unregisterPanel(value) {
|
|
11798
|
+
this.panels.update((list) => list.filter((v) => v !== value));
|
|
11799
|
+
}
|
|
11800
|
+
/** Whether an <sds-tab-panel> exists for this value (tabs whose content lives elsewhere have none). */
|
|
11801
|
+
hasPanel(value) {
|
|
11802
|
+
return this.panels().includes(value);
|
|
11803
|
+
}
|
|
10754
11804
|
tabId(value) {
|
|
10755
11805
|
return `${this.id}-tab-${value}`;
|
|
10756
11806
|
}
|
|
@@ -10770,6 +11820,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10770
11820
|
* <sds-tab-panel> [value]; it is two-way bindable via [(value)]. When omitted,
|
|
10771
11821
|
* the first registered tab is selected.
|
|
10772
11822
|
*
|
|
11823
|
+
* **Controlled tabs** (`controlled`): a click, arrow key or Home/End only emits `(tabSelect)`; the active
|
|
11824
|
+
* tab changes when the host changes `[value]`. Use it when the active tab lives somewhere else — a
|
|
11825
|
+
* `?tab=` query param — or when switching can be refused (an unsaved-changes guard): the tab never
|
|
11826
|
+
* shows as selected before the host agrees. `(tabSelect)` also fires in the default mode.
|
|
11827
|
+
*
|
|
11828
|
+
* **Panels are optional.** A tab set whose content is rendered by the host (an `@switch` on the value, a
|
|
11829
|
+
* router outlet) can omit <sds-tab-panels>; a tab then carries no `aria-controls` to a missing panel.
|
|
11830
|
+
*
|
|
10773
11831
|
* @example
|
|
10774
11832
|
* <sds-tabs [(value)]="active">
|
|
10775
11833
|
* <sds-tab-list>
|
|
@@ -10781,6 +11839,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10781
11839
|
* <sds-tab-panel value="1">…</sds-tab-panel>
|
|
10782
11840
|
* </sds-tab-panels>
|
|
10783
11841
|
* </sds-tabs>
|
|
11842
|
+
*
|
|
11843
|
+
* @example
|
|
11844
|
+
* <!-- driven by a query param, content rendered by the host -->
|
|
11845
|
+
* <sds-tabs controlled [value]="activeTab()" (tabSelect)="selectTab($event)">
|
|
11846
|
+
* <sds-tab-list>
|
|
11847
|
+
* @for (tab of tabs; track tab) {
|
|
11848
|
+
* <sds-tab [value]="tab">{{ 'menu.tabs.' + tab | translate }}</sds-tab>
|
|
11849
|
+
* }
|
|
11850
|
+
* </sds-tab-list>
|
|
11851
|
+
* </sds-tabs>
|
|
10784
11852
|
*/
|
|
10785
11853
|
class SdsTabs {
|
|
10786
11854
|
store = inject(SdsTabsStore);
|
|
@@ -10788,12 +11856,21 @@ class SdsTabs {
|
|
|
10788
11856
|
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
10789
11857
|
/** Let the tab list scroll horizontally instead of overflowing. */
|
|
10790
11858
|
scrollable = input(false, ...(ngDevMode ? [{ debugName: "scrollable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
11859
|
+
/**
|
|
11860
|
+
* Controlled mode: a user pick only emits (tabSelect); the host decides by setting [value]. See the
|
|
11861
|
+
* class note.
|
|
11862
|
+
*/
|
|
11863
|
+
controlled = input(false, ...(ngDevMode ? [{ debugName: "controlled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
11864
|
+
/** Emits the value of the tab the user picked (in both modes). */
|
|
11865
|
+
tabSelect = output();
|
|
10791
11866
|
constructor() {
|
|
10792
11867
|
this.store.connect(this.value);
|
|
11868
|
+
this.store.onSelect = (value) => this.tabSelect.emit(value);
|
|
10793
11869
|
effect(() => this.store.scrollable.set(this.scrollable()));
|
|
11870
|
+
effect(() => this.store.controlled.set(this.controlled()));
|
|
10794
11871
|
}
|
|
10795
11872
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10796
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.25", type: SdsTabs, isStandalone: true, selector: "sds-tabs", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, scrollable: { classPropertyName: "scrollable", publicName: "scrollable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { classAttribute: "block" }, providers: [SdsTabsStore], ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11873
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.25", type: SdsTabs, isStandalone: true, selector: "sds-tabs", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, scrollable: { classPropertyName: "scrollable", publicName: "scrollable", isSignal: true, isRequired: false, transformFunction: null }, controlled: { classPropertyName: "controlled", publicName: "controlled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", tabSelect: "tabSelect" }, host: { classAttribute: "block" }, providers: [SdsTabsStore], ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10797
11874
|
}
|
|
10798
11875
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTabs, decorators: [{
|
|
10799
11876
|
type: Component,
|
|
@@ -10804,7 +11881,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10804
11881
|
host: { class: 'block' },
|
|
10805
11882
|
template: `<ng-content />`,
|
|
10806
11883
|
}]
|
|
10807
|
-
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], scrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollable", required: false }] }] } });
|
|
11884
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], scrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollable", required: false }] }], controlled: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlled", required: false }] }], tabSelect: [{ type: i0.Output, args: ["tabSelect"] }] } });
|
|
10808
11885
|
|
|
10809
11886
|
/**
|
|
10810
11887
|
* Container (role="tablist") for the <sds-tab> headers. Renders the bottom rule
|
|
@@ -10901,7 +11978,7 @@ class SdsTab {
|
|
|
10901
11978
|
role="tab"
|
|
10902
11979
|
[id]="store.tabId(value())"
|
|
10903
11980
|
[attr.aria-selected]="active()"
|
|
10904
|
-
[attr.aria-controls]="store.panelId(value())"
|
|
11981
|
+
[attr.aria-controls]="store.hasPanel(value()) ? store.panelId(value()) : null"
|
|
10905
11982
|
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
10906
11983
|
[attr.tabindex]="active() && !disabled() ? 0 : -1"
|
|
10907
11984
|
[disabled]="disabled()"
|
|
@@ -10924,7 +12001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10924
12001
|
role="tab"
|
|
10925
12002
|
[id]="store.tabId(value())"
|
|
10926
12003
|
[attr.aria-selected]="active()"
|
|
10927
|
-
[attr.aria-controls]="store.panelId(value())"
|
|
12004
|
+
[attr.aria-controls]="store.hasPanel(value()) ? store.panelId(value()) : null"
|
|
10928
12005
|
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
10929
12006
|
[attr.tabindex]="active() && !disabled() ? 0 : -1"
|
|
10930
12007
|
[disabled]="disabled()"
|
|
@@ -10969,6 +12046,12 @@ class SdsTabPanel {
|
|
|
10969
12046
|
store = inject(SdsTabsStore);
|
|
10970
12047
|
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
10971
12048
|
active = computed(() => this.store.isActive(this.value()), ...(ngDevMode ? [{ debugName: "active" }] : []));
|
|
12049
|
+
ngOnInit() {
|
|
12050
|
+
this.store.registerPanel(this.value());
|
|
12051
|
+
}
|
|
12052
|
+
ngOnDestroy() {
|
|
12053
|
+
this.store.unregisterPanel(this.value());
|
|
12054
|
+
}
|
|
10972
12055
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTabPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10973
12056
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTabPanel, isStandalone: true, selector: "sds-tab-panel", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
10974
12057
|
@if (active()) {
|
|
@@ -11382,6 +12465,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
11382
12465
|
}]
|
|
11383
12466
|
}] });
|
|
11384
12467
|
|
|
12468
|
+
/**
|
|
12469
|
+
* Replaces the table's plain `emptyMessage` with rich content — an explanation and a call to action,
|
|
12470
|
+
* a "no results for …" line. Rendered in the full-width empty row, only when not `loading`.
|
|
12471
|
+
*
|
|
12472
|
+
* @example
|
|
12473
|
+
* <sds-table [value]="categories()" [columns]="cols">
|
|
12474
|
+
* <ng-template sdsTableEmpty>
|
|
12475
|
+
* <p>No categories yet.</p>
|
|
12476
|
+
* <sds-button size="sm" (click)="create()">Add a category</sds-button>
|
|
12477
|
+
* </ng-template>
|
|
12478
|
+
* </sds-table>
|
|
12479
|
+
*/
|
|
12480
|
+
class SdsTableEmpty {
|
|
12481
|
+
/** The wrapped template, rendered by the host table via ngTemplateOutlet. */
|
|
12482
|
+
template = inject(TemplateRef);
|
|
12483
|
+
/** Lets the compiler type-check `let-*` bindings against SdsTableEmptyContext. */
|
|
12484
|
+
static ngTemplateContextGuard(_dir, _ctx) {
|
|
12485
|
+
return true;
|
|
12486
|
+
}
|
|
12487
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTableEmpty, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
12488
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.25", type: SdsTableEmpty, isStandalone: true, selector: "ng-template[sdsTableEmpty]", ngImport: i0 });
|
|
12489
|
+
}
|
|
12490
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTableEmpty, decorators: [{
|
|
12491
|
+
type: Directive,
|
|
12492
|
+
args: [{
|
|
12493
|
+
selector: 'ng-template[sdsTableEmpty]',
|
|
12494
|
+
standalone: true,
|
|
12495
|
+
}]
|
|
12496
|
+
}] });
|
|
12497
|
+
|
|
11385
12498
|
const SIZES = {
|
|
11386
12499
|
sm: { cell: 'px-3 py-2 text-sm', head: 'px-3 py-2' },
|
|
11387
12500
|
md: { cell: 'px-4 py-2.5 text-sm', head: 'px-4 py-2.5' },
|
|
@@ -11413,6 +12526,11 @@ let nextId$1 = 0;
|
|
|
11413
12526
|
* - **Custom headers:** `<ng-template sdsHeader="field">` replaces a column's header content (label and
|
|
11414
12527
|
* sort button) — e.g. a "select all" checkbox above your own checkbox column. Its context carries the
|
|
11415
12528
|
* filtered `rows` (all pages) and the displayed `pageRows` (see {@link SdsTableHeaderContext}).
|
|
12529
|
+
* - **Clickable rows:** `rowClickable` makes each row an action (pointer, tab stop, Enter/Space) that
|
|
12530
|
+
* emits `(rowClick)`; clicks on buttons, links and fields inside a cell are not row clicks, so no
|
|
12531
|
+
* `stopPropagation()` is needed. `[rowClass]` adds per-row classes (e.g. dim a blocked row).
|
|
12532
|
+
* - **Empty state:** `<ng-template sdsTableEmpty let-query>` replaces the plain `emptyMessage` (e.g. a
|
|
12533
|
+
* sentence and a "create" button); it is not shown while `loading`.
|
|
11416
12534
|
* - **Labels:** every visible and spoken string is an input with an English default (paginator,
|
|
11417
12535
|
* filter, selection, expansion, editor). An app serving more than one language passes translations.
|
|
11418
12536
|
*
|
|
@@ -11484,6 +12602,14 @@ class SdsTable {
|
|
|
11484
12602
|
selection = model(null, ...(ngDevMode ? [{ debugName: "selection" }] : []));
|
|
11485
12603
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
11486
12604
|
emptyMessage = input('No data', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
|
|
12605
|
+
/**
|
|
12606
|
+
* Rows are actions: a pointer cursor, a tab stop per row, and Enter/Space emit `(rowClick)` like a
|
|
12607
|
+
* click. Clicks that land on a control inside a cell (button, link, input, checkbox…) do not count as
|
|
12608
|
+
* a row click, so a row can open a drawer while its cells keep their own buttons.
|
|
12609
|
+
*/
|
|
12610
|
+
rowClickable = input(false, ...(ngDevMode ? [{ debugName: "rowClickable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
12611
|
+
/** Extra classes per body row, e.g. `(row) => row.blocked ? 'opacity-60' : ''`. */
|
|
12612
|
+
rowClass = input(null, ...(ngDevMode ? [{ debugName: "rowClass" }] : []));
|
|
11487
12613
|
caption = input('', ...(ngDevMode ? [{ debugName: "caption" }] : []));
|
|
11488
12614
|
/** Fallback accessible name for the `<table>` when no `caption` is set. */
|
|
11489
12615
|
ariaLabel = input('Data table', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -11574,6 +12700,11 @@ class SdsTable {
|
|
|
11574
12700
|
expansionTemplate() {
|
|
11575
12701
|
return this.rowExpansion()?.template ?? null;
|
|
11576
12702
|
}
|
|
12703
|
+
// --- empty-state template -------------------------------------------------
|
|
12704
|
+
emptyTpl = contentChild(SdsTableEmpty, ...(ngDevMode ? [{ debugName: "emptyTpl" }] : []));
|
|
12705
|
+
emptyTemplate() {
|
|
12706
|
+
return this.emptyTpl()?.template ?? null;
|
|
12707
|
+
}
|
|
11577
12708
|
// --- pipeline state -------------------------------------------------------
|
|
11578
12709
|
filterText = signal('', ...(ngDevMode ? [{ debugName: "filterText" }] : []));
|
|
11579
12710
|
sortField = signal(null, ...(ngDevMode ? [{ debugName: "sortField" }] : []));
|
|
@@ -11809,9 +12940,14 @@ class SdsTable {
|
|
|
11809
12940
|
this.toggleRowSelection(row);
|
|
11810
12941
|
}
|
|
11811
12942
|
}
|
|
11812
|
-
/** Enter/Space on a (single
|
|
12943
|
+
/** Enter/Space on a focusable row (single selection or `rowClickable`) acts like a click on it. */
|
|
11813
12944
|
onRowKeydown(event, row) {
|
|
11814
|
-
if (this.
|
|
12945
|
+
if (this.loading() || this.editable())
|
|
12946
|
+
return;
|
|
12947
|
+
if (this.selectionMode() !== 'single' && !this.rowClickable())
|
|
12948
|
+
return;
|
|
12949
|
+
// Only the row itself: Enter on a button inside a cell belongs to that button.
|
|
12950
|
+
if (event.target !== event.currentTarget)
|
|
11815
12951
|
return;
|
|
11816
12952
|
event.preventDefault();
|
|
11817
12953
|
this.onRowClick(row);
|
|
@@ -11830,9 +12966,11 @@ class SdsTable {
|
|
|
11830
12966
|
this.rowSelect.emit(row);
|
|
11831
12967
|
}
|
|
11832
12968
|
}
|
|
11833
|
-
onRowClick(row) {
|
|
12969
|
+
onRowClick(row, event) {
|
|
11834
12970
|
if (this.loading())
|
|
11835
12971
|
return;
|
|
12972
|
+
if (event && this.fromInnerControl(event))
|
|
12973
|
+
return;
|
|
11836
12974
|
this.rowClick.emit(row);
|
|
11837
12975
|
if (this.selectionMode() === 'single') {
|
|
11838
12976
|
if (this.equals(this.selection(), row)) {
|
|
@@ -11845,6 +12983,16 @@ class SdsTable {
|
|
|
11845
12983
|
}
|
|
11846
12984
|
}
|
|
11847
12985
|
}
|
|
12986
|
+
/** Whether a click started on an interactive element inside the row (not on the row itself). */
|
|
12987
|
+
fromInnerControl(event) {
|
|
12988
|
+
const row = event.currentTarget;
|
|
12989
|
+
const target = event.target;
|
|
12990
|
+
if (!row || !target || !(target instanceof Element))
|
|
12991
|
+
return false;
|
|
12992
|
+
const control = target.closest('button, a[href], input, select, textarea, label, [contenteditable="true"], ' +
|
|
12993
|
+
'[role="button"], [role="checkbox"], [role="switch"], [role="radio"], [role="combobox"], [role="menuitem"]');
|
|
12994
|
+
return !!control && control !== row && row.contains(control);
|
|
12995
|
+
}
|
|
11848
12996
|
// --- paginator ------------------------------------------------------------
|
|
11849
12997
|
onPageChange(state) {
|
|
11850
12998
|
this.editing.set(null);
|
|
@@ -12378,7 +13526,7 @@ class SdsTable {
|
|
|
12378
13526
|
const align = ALIGN[col?.align ?? 'left'];
|
|
12379
13527
|
return `${SIZES[this.size()].cell} ${align} text-ink align-middle`;
|
|
12380
13528
|
}
|
|
12381
|
-
|
|
13529
|
+
bodyRowClass(row, index) {
|
|
12382
13530
|
const parts = ['transition-colors'];
|
|
12383
13531
|
if (this.gridlines())
|
|
12384
13532
|
parts.push('divide-x divide-border');
|
|
@@ -12390,9 +13538,12 @@ class SdsTable {
|
|
|
12390
13538
|
}
|
|
12391
13539
|
if (this.hoverable() && !this.isRowSelected(row))
|
|
12392
13540
|
parts.push('hover:bg-muted/60');
|
|
12393
|
-
if (this.selectionMode() === 'single') {
|
|
13541
|
+
if (this.selectionMode() === 'single' || (this.rowClickable() && !this.editable())) {
|
|
12394
13542
|
parts.push('cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-brand-500');
|
|
12395
13543
|
}
|
|
13544
|
+
const extra = this.rowClass()?.(row, index);
|
|
13545
|
+
if (extra)
|
|
13546
|
+
parts.push(extra);
|
|
12396
13547
|
return parts.join(' ');
|
|
12397
13548
|
}
|
|
12398
13549
|
checkboxClass(checked, indeterminate) {
|
|
@@ -12401,7 +13552,7 @@ class SdsTable {
|
|
|
12401
13552
|
: 'border-border bg-surface';
|
|
12402
13553
|
}
|
|
12403
13554
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12404
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTable, isStandalone: true, selector: "sds-table", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, gridlines: { classPropertyName: "gridlines", publicName: "gridlines", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, paginator: { classPropertyName: "paginator", publicName: "paginator", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, showCurrentPageReport: { classPropertyName: "showCurrentPageReport", publicName: "showCurrentPageReport", isSignal: true, isRequired: false, transformFunction: null }, currentPageReportTemplate: { classPropertyName: "currentPageReportTemplate", publicName: "currentPageReportTemplate", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageLabel: { classPropertyName: "rowsPerPageLabel", publicName: "rowsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationLabel: { classPropertyName: "paginationLabel", publicName: "paginationLabel", isSignal: true, isRequired: false, transformFunction: null }, firstPageLabel: { classPropertyName: "firstPageLabel", publicName: "firstPageLabel", isSignal: true, isRequired: false, transformFunction: null }, previousPageLabel: { classPropertyName: "previousPageLabel", publicName: "previousPageLabel", isSignal: true, isRequired: false, transformFunction: null }, nextPageLabel: { classPropertyName: "nextPageLabel", publicName: "nextPageLabel", isSignal: true, isRequired: false, transformFunction: null }, lastPageLabel: { classPropertyName: "lastPageLabel", publicName: "lastPageLabel", isSignal: true, isRequired: false, transformFunction: null }, pageLinkLabel: { classPropertyName: "pageLinkLabel", publicName: "pageLinkLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilter: { classPropertyName: "globalFilter", publicName: "globalFilter", isSignal: true, isRequired: false, transformFunction: null }, globalFilterPlaceholder: { classPropertyName: "globalFilterPlaceholder", publicName: "globalFilterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, globalFilterAriaLabel: { classPropertyName: "globalFilterAriaLabel", publicName: "globalFilterAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilterFields: { classPropertyName: "globalFilterFields", publicName: "globalFilterFields", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, scrollHeight: { classPropertyName: "scrollHeight", publicName: "scrollHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, totalRecords: { classPropertyName: "totalRecords", publicName: "totalRecords", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, editOn: { classPropertyName: "editOn", publicName: "editOn", isSignal: true, isRequired: false, transformFunction: null }, cellErrors: { classPropertyName: "cellErrors", publicName: "cellErrors", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, dirtyLabel: { classPropertyName: "dirtyLabel", publicName: "dirtyLabel", isSignal: true, isRequired: false, transformFunction: null }, selectPlaceholder: { classPropertyName: "selectPlaceholder", publicName: "selectPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null }, selectRowLabel: { classPropertyName: "selectRowLabel", publicName: "selectRowLabel", isSignal: true, isRequired: false, transformFunction: null }, selectionColumnLabel: { classPropertyName: "selectionColumnLabel", publicName: "selectionColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, expandColumnLabel: { classPropertyName: "expandColumnLabel", publicName: "expandColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, expandRowLabel: { classPropertyName: "expandRowLabel", publicName: "expandRowLabel", isSignal: true, isRequired: false, transformFunction: null }, collapseRowLabel: { classPropertyName: "collapseRowLabel", publicName: "collapseRowLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange", sortChange: "sortChange", pageChange: "pageChange", rowSelect: "rowSelect", rowUnselect: "rowUnselect", lazyLoad: "lazyLoad", rowClick: "rowClick", rowExpand: "rowExpand", rowCollapse: "rowCollapse", colReorder: "colReorder", cellCommit: "cellCommit" }, host: { classAttribute: "block" }, queries: [{ propertyName: "cellTemplates", predicate: SdsTableCell, isSignal: true }, { propertyName: "headerTemplates", predicate: SdsTableHeader, isSignal: true }, { propertyName: "rowExpansion", first: true, predicate: SdsTableRowExpansion, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "numberEditor", first: true, predicate: SdsInputNumber, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
13555
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTable, isStandalone: true, selector: "sds-table", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, gridlines: { classPropertyName: "gridlines", publicName: "gridlines", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, paginator: { classPropertyName: "paginator", publicName: "paginator", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, showCurrentPageReport: { classPropertyName: "showCurrentPageReport", publicName: "showCurrentPageReport", isSignal: true, isRequired: false, transformFunction: null }, currentPageReportTemplate: { classPropertyName: "currentPageReportTemplate", publicName: "currentPageReportTemplate", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageLabel: { classPropertyName: "rowsPerPageLabel", publicName: "rowsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationLabel: { classPropertyName: "paginationLabel", publicName: "paginationLabel", isSignal: true, isRequired: false, transformFunction: null }, firstPageLabel: { classPropertyName: "firstPageLabel", publicName: "firstPageLabel", isSignal: true, isRequired: false, transformFunction: null }, previousPageLabel: { classPropertyName: "previousPageLabel", publicName: "previousPageLabel", isSignal: true, isRequired: false, transformFunction: null }, nextPageLabel: { classPropertyName: "nextPageLabel", publicName: "nextPageLabel", isSignal: true, isRequired: false, transformFunction: null }, lastPageLabel: { classPropertyName: "lastPageLabel", publicName: "lastPageLabel", isSignal: true, isRequired: false, transformFunction: null }, pageLinkLabel: { classPropertyName: "pageLinkLabel", publicName: "pageLinkLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilter: { classPropertyName: "globalFilter", publicName: "globalFilter", isSignal: true, isRequired: false, transformFunction: null }, globalFilterPlaceholder: { classPropertyName: "globalFilterPlaceholder", publicName: "globalFilterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, globalFilterAriaLabel: { classPropertyName: "globalFilterAriaLabel", publicName: "globalFilterAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilterFields: { classPropertyName: "globalFilterFields", publicName: "globalFilterFields", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, rowClickable: { classPropertyName: "rowClickable", publicName: "rowClickable", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, scrollHeight: { classPropertyName: "scrollHeight", publicName: "scrollHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, totalRecords: { classPropertyName: "totalRecords", publicName: "totalRecords", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, editOn: { classPropertyName: "editOn", publicName: "editOn", isSignal: true, isRequired: false, transformFunction: null }, cellErrors: { classPropertyName: "cellErrors", publicName: "cellErrors", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, dirtyLabel: { classPropertyName: "dirtyLabel", publicName: "dirtyLabel", isSignal: true, isRequired: false, transformFunction: null }, selectPlaceholder: { classPropertyName: "selectPlaceholder", publicName: "selectPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null }, selectRowLabel: { classPropertyName: "selectRowLabel", publicName: "selectRowLabel", isSignal: true, isRequired: false, transformFunction: null }, selectionColumnLabel: { classPropertyName: "selectionColumnLabel", publicName: "selectionColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, expandColumnLabel: { classPropertyName: "expandColumnLabel", publicName: "expandColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, expandRowLabel: { classPropertyName: "expandRowLabel", publicName: "expandRowLabel", isSignal: true, isRequired: false, transformFunction: null }, collapseRowLabel: { classPropertyName: "collapseRowLabel", publicName: "collapseRowLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange", sortChange: "sortChange", pageChange: "pageChange", rowSelect: "rowSelect", rowUnselect: "rowUnselect", lazyLoad: "lazyLoad", rowClick: "rowClick", rowExpand: "rowExpand", rowCollapse: "rowCollapse", colReorder: "colReorder", cellCommit: "cellCommit" }, host: { classAttribute: "block" }, queries: [{ propertyName: "cellTemplates", predicate: SdsTableCell, isSignal: true }, { propertyName: "headerTemplates", predicate: SdsTableHeader, isSignal: true }, { propertyName: "rowExpansion", first: true, predicate: SdsTableRowExpansion, descendants: true, isSignal: true }, { propertyName: "emptyTpl", first: true, predicate: SdsTableEmpty, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "numberEditor", first: true, predicate: SdsInputNumber, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
12405
13556
|
<div class="rounded-card border border-border bg-surface overflow-hidden">
|
|
12406
13557
|
<!-- Toolbar: caption + global filter -->
|
|
12407
13558
|
@if (caption() || globalFilter()) {
|
|
@@ -12555,10 +13706,10 @@ class SdsTable {
|
|
|
12555
13706
|
<tbody class="divide-y divide-border">
|
|
12556
13707
|
@for (row of displayRows(); track trackRow($index, row); let i = $index) {
|
|
12557
13708
|
<tr
|
|
12558
|
-
[class]="
|
|
12559
|
-
[attr.tabindex]="selectionMode() === 'single' && !loading() && !editable() ? 0 : null"
|
|
13709
|
+
[class]="bodyRowClass(row, i)"
|
|
13710
|
+
[attr.tabindex]="(selectionMode() === 'single' || rowClickable()) && !loading() && !editable() ? 0 : null"
|
|
12560
13711
|
[attr.aria-selected]="selectionMode() === 'single' ? (isRowSelected(row) ? 'true' : 'false') : null"
|
|
12561
|
-
(click)="onRowClick(row)"
|
|
13712
|
+
(click)="onRowClick(row, $event)"
|
|
12562
13713
|
(keydown.enter)="onRowKeydown($event, row)"
|
|
12563
13714
|
(keydown.space)="onRowKeydown($event, row)"
|
|
12564
13715
|
>
|
|
@@ -12783,7 +13934,14 @@ class SdsTable {
|
|
|
12783
13934
|
[attr.colspan]="totalColumnCount()"
|
|
12784
13935
|
class="py-10 text-center text-ink-faint"
|
|
12785
13936
|
>
|
|
12786
|
-
|
|
13937
|
+
@if (emptyTemplate(); as tpl) {
|
|
13938
|
+
<ng-container
|
|
13939
|
+
[ngTemplateOutlet]="tpl"
|
|
13940
|
+
[ngTemplateOutletContext]="{ $implicit: filterText(), filterText: filterText() }"
|
|
13941
|
+
/>
|
|
13942
|
+
} @else {
|
|
13943
|
+
{{ emptyMessage() }}
|
|
13944
|
+
}
|
|
12787
13945
|
</td>
|
|
12788
13946
|
</tr>
|
|
12789
13947
|
}
|
|
@@ -12990,10 +14148,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12990
14148
|
<tbody class="divide-y divide-border">
|
|
12991
14149
|
@for (row of displayRows(); track trackRow($index, row); let i = $index) {
|
|
12992
14150
|
<tr
|
|
12993
|
-
[class]="
|
|
12994
|
-
[attr.tabindex]="selectionMode() === 'single' && !loading() && !editable() ? 0 : null"
|
|
14151
|
+
[class]="bodyRowClass(row, i)"
|
|
14152
|
+
[attr.tabindex]="(selectionMode() === 'single' || rowClickable()) && !loading() && !editable() ? 0 : null"
|
|
12995
14153
|
[attr.aria-selected]="selectionMode() === 'single' ? (isRowSelected(row) ? 'true' : 'false') : null"
|
|
12996
|
-
(click)="onRowClick(row)"
|
|
14154
|
+
(click)="onRowClick(row, $event)"
|
|
12997
14155
|
(keydown.enter)="onRowKeydown($event, row)"
|
|
12998
14156
|
(keydown.space)="onRowKeydown($event, row)"
|
|
12999
14157
|
>
|
|
@@ -13218,7 +14376,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
13218
14376
|
[attr.colspan]="totalColumnCount()"
|
|
13219
14377
|
class="py-10 text-center text-ink-faint"
|
|
13220
14378
|
>
|
|
13221
|
-
|
|
14379
|
+
@if (emptyTemplate(); as tpl) {
|
|
14380
|
+
<ng-container
|
|
14381
|
+
[ngTemplateOutlet]="tpl"
|
|
14382
|
+
[ngTemplateOutletContext]="{ $implicit: filterText(), filterText: filterText() }"
|
|
14383
|
+
/>
|
|
14384
|
+
} @else {
|
|
14385
|
+
{{ emptyMessage() }}
|
|
14386
|
+
}
|
|
13222
14387
|
</td>
|
|
13223
14388
|
</tr>
|
|
13224
14389
|
}
|
|
@@ -13264,7 +14429,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
13264
14429
|
</div>
|
|
13265
14430
|
`,
|
|
13266
14431
|
}]
|
|
13267
|
-
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], gridlines: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridlines", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], paginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginator", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], showCurrentPageReport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCurrentPageReport", required: false }] }], currentPageReportTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPageReportTemplate", required: false }] }], rowsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageLabel", required: false }] }], paginationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationLabel", required: false }] }], firstPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstPageLabel", required: false }] }], previousPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousPageLabel", required: false }] }], nextPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextPageLabel", required: false }] }], lastPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastPageLabel", required: false }] }], pageLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLinkLabel", required: false }] }], globalFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilter", required: false }] }], globalFilterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterPlaceholder", required: false }] }], globalFilterAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterAriaLabel", required: false }] }], globalFilterFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterFields", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], editOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "editOn", required: false }] }], cellErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellErrors", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], dirtyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirtyLabel", required: false }] }], selectPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectPlaceholder", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], selectRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectRowLabel", required: false }] }], selectionColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionColumnLabel", required: false }] }], expandColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandColumnLabel", required: false }] }], expandRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandRowLabel", required: false }] }], collapseRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseRowLabel", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], rowSelect: [{ type: i0.Output, args: ["rowSelect"] }], rowUnselect: [{ type: i0.Output, args: ["rowUnselect"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowExpand: [{ type: i0.Output, args: ["rowExpand"] }], rowCollapse: [{ type: i0.Output, args: ["rowCollapse"] }], colReorder: [{ type: i0.Output, args: ["colReorder"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdsTableCell), { isSignal: true }] }], headerTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdsTableHeader), { isSignal: true }] }], rowExpansion: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsTableRowExpansion), { isSignal: true }] }], numberEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdsInputNumber), { isSignal: true }] }] } });
|
|
14432
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], gridlines: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridlines", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], paginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginator", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], showCurrentPageReport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCurrentPageReport", required: false }] }], currentPageReportTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPageReportTemplate", required: false }] }], rowsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageLabel", required: false }] }], paginationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationLabel", required: false }] }], firstPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstPageLabel", required: false }] }], previousPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousPageLabel", required: false }] }], nextPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextPageLabel", required: false }] }], lastPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastPageLabel", required: false }] }], pageLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLinkLabel", required: false }] }], globalFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilter", required: false }] }], globalFilterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterPlaceholder", required: false }] }], globalFilterAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterAriaLabel", required: false }] }], globalFilterFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterFields", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], rowClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClickable", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], editOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "editOn", required: false }] }], cellErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellErrors", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], dirtyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirtyLabel", required: false }] }], selectPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectPlaceholder", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], selectRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectRowLabel", required: false }] }], selectionColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionColumnLabel", required: false }] }], expandColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandColumnLabel", required: false }] }], expandRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandRowLabel", required: false }] }], collapseRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseRowLabel", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], rowSelect: [{ type: i0.Output, args: ["rowSelect"] }], rowUnselect: [{ type: i0.Output, args: ["rowUnselect"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowExpand: [{ type: i0.Output, args: ["rowExpand"] }], rowCollapse: [{ type: i0.Output, args: ["rowCollapse"] }], colReorder: [{ type: i0.Output, args: ["colReorder"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdsTableCell), { isSignal: true }] }], headerTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdsTableHeader), { isSignal: true }] }], rowExpansion: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsTableRowExpansion), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsTableEmpty), { isSignal: true }] }], numberEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdsInputNumber), { isSignal: true }] }] } });
|
|
13268
14433
|
|
|
13269
14434
|
/**
|
|
13270
14435
|
* A tiny transient-notification bus. Application code calls {@link success} / {@link error} / {@link info}
|
|
@@ -14828,7 +15993,7 @@ class SdsUserMenu {
|
|
|
14828
15993
|
</div>
|
|
14829
15994
|
</div>
|
|
14830
15995
|
}
|
|
14831
|
-
`, isInline: true, styles: [".animate-sds-menu{animation:sds-menu-in .14s ease-out}@keyframes sds-menu-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.animate-sds-menu{animation:none}}\n"], dependencies: [{ kind: "component", type: SdsAvatar, selector: "sds-avatar", inputs: ["name", "initials", "src", "size", "status", "bgClass"] }, { kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
15996
|
+
`, isInline: true, styles: [".animate-sds-menu{animation:sds-menu-in .14s ease-out}@keyframes sds-menu-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.animate-sds-menu{animation:none}}\n"], dependencies: [{ kind: "component", type: SdsAvatar, selector: "sds-avatar", inputs: ["name", "initials", "src", "size", "status", "shape", "bgClass", "fallbackIcon", "placeholderClass", "decorative", "lazy"] }, { kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14832
15997
|
}
|
|
14833
15998
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsUserMenu, decorators: [{
|
|
14834
15999
|
type: Component,
|
|
@@ -15902,5 +17067,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
15902
17067
|
* Generated bundle index. Do not edit.
|
|
15903
17068
|
*/
|
|
15904
17069
|
|
|
15905
|
-
export { SDS_ALLERGENS, SDS_ALLERGEN_ICONS, SDS_ALLERGEN_LABELS_EN, SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAllergenIcon, SdsAvatar, SdsBadge, SdsBulkBar, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsChecklistRow, SdsDatePicker, SdsFileDrop, SdsIcon, SdsImageCropper, SdsInput, SdsInputNumber, SdsLanguageSwitcher, SdsLocalizedInput, SdsMenu, SdsMenuItem, SdsMenuTrigger, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsOtpInput, SdsPaginator, SdsPhoneInput, SdsRadio, SdsScore, SdsSearchCommand, SdsSegmented, SdsSelect, SdsSelectEmpty, SdsSelectFooter, SdsSelectOption, SdsShell, SdsSidebar, SdsSortableHandle, SdsSortableItem, SdsSortableList, SdsStatusTile, SdsTab, SdsTabList, SdsTabPanel, SdsTabPanels, SdsTable, SdsTableCell, SdsTableHeader, SdsTableRowExpansion, SdsTabs, SdsTabsStore, SdsTextarea, SdsThemeService, SdsThemeToggle, SdsToastHost, SdsToastService, SdsToggleSwitch, SdsTopbar, SdsTriStateChip, SdsUserMenu, SidebarStore, addDays, addMonths, addMonthsKeepDay, formatDdMmYyyy, formatHhMm, isOutOfRange, isSameDay, isoDay, pad2, sdsFileMatchesAccept, sdsFormatBytes, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
|
|
17070
|
+
export { SDS_ALLERGENS, SDS_ALLERGEN_ICONS, SDS_ALLERGEN_LABELS_EN, SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAllergenIcon, SdsAvatar, SdsBadge, SdsBulkBar, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsChecklistRow, SdsChip, SdsChipGroup, SdsDatePicker, SdsFileDrop, SdsIcon, SdsImageCropper, SdsInput, SdsInputNumber, SdsLanguageSwitcher, SdsLocalizedInput, SdsMenu, SdsMenuItem, SdsMenuTrigger, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsOtpInput, SdsPaginator, SdsPhoneInput, SdsRadio, SdsScore, SdsSearchCommand, SdsSegmented, SdsSelect, SdsSelectEmpty, SdsSelectFooter, SdsSelectOption, SdsShell, SdsSidebar, SdsSortableHandle, SdsSortableItem, SdsSortableList, SdsStatusTile, SdsTab, SdsTabList, SdsTabPanel, SdsTabPanels, SdsTable, SdsTableCell, SdsTableEmpty, SdsTableHeader, SdsTableRowExpansion, SdsTabs, SdsTabsStore, SdsTextarea, SdsThemeService, SdsThemeToggle, SdsTimeInput, SdsToastHost, SdsToastService, SdsToggleSwitch, SdsTopbar, SdsTriStateChip, SdsUserMenu, SidebarStore, addDays, addMonths, addMonthsKeepDay, formatDdMmYyyy, formatHhMm, isOutOfRange, isSameDay, isoDay, pad2, sdsFileMatchesAccept, sdsFormatBytes, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
|
|
15906
17071
|
//# sourceMappingURL=besaitech-ng-design-system.mjs.map
|