@besaitech/ng-design-system 0.0.53 → 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 +17 -3
- package/fesm2022/besaitech-ng-design-system.mjs +1976 -359
- package/fesm2022/besaitech-ng-design-system.mjs.map +1 -1
- package/index.d.ts +604 -92
- package/package.json +1 -1
- package/themes/belvigo-emerald.css +73 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, numberAttribute, output, signal, forwardRef, viewChild, viewChildren, afterRenderEffect, model, ElementRef, Directive, Injector, contentChild, untracked, afterNextRender, TemplateRef, linkedSignal, Injectable, contentChildren
|
|
2
|
+
import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, numberAttribute, output, signal, forwardRef, viewChild, viewChildren, afterRenderEffect, model, ElementRef, Directive, Injector, contentChild, untracked, afterNextRender, TemplateRef, linkedSignal, DestroyRef, Injectable, contentChildren } from '@angular/core';
|
|
3
3
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule } from '@angular/forms';
|
|
@@ -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" }] : []));
|
|
@@ -380,11 +384,10 @@ class SdsInput {
|
|
|
380
384
|
/** Hard character cap on the native field; 0 means no limit. */
|
|
381
385
|
maxLength = input(0, ...(ngDevMode ? [{ debugName: "maxLength", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
382
386
|
/**
|
|
383
|
-
* Accessible name for the clear button.
|
|
384
|
-
*
|
|
385
|
-
* is its only name.
|
|
387
|
+
* Accessible name for the clear button. English default; an app serving more than one language MUST
|
|
388
|
+
* translate it — it is an icon-only control, so this string is its only name.
|
|
386
389
|
*/
|
|
387
|
-
clearLabel = input('
|
|
390
|
+
clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
388
391
|
leadingIcon = input(null, ...(ngDevMode ? [{ debugName: "leadingIcon" }] : []));
|
|
389
392
|
trailingIcon = input(null, ...(ngDevMode ? [{ debugName: "trailingIcon" }] : []));
|
|
390
393
|
/**
|
|
@@ -428,7 +431,7 @@ class SdsInput {
|
|
|
428
431
|
return `${left} ${right}`;
|
|
429
432
|
}, ...(ngDevMode ? [{ debugName: "fieldPadding" }] : []));
|
|
430
433
|
wrapperClasses = computed(() => {
|
|
431
|
-
const parts = [SIZES$
|
|
434
|
+
const parts = [SIZES$b[this.size()], this.pill() ? 'rounded-full' : 'rounded-control'];
|
|
432
435
|
if (this.isDisabled())
|
|
433
436
|
parts.push('opacity-60 cursor-not-allowed');
|
|
434
437
|
if (this.filled()) {
|
|
@@ -676,7 +679,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
676
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"] }]
|
|
677
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"] }] } });
|
|
678
681
|
|
|
679
|
-
let nextId$
|
|
682
|
+
let nextId$m = 0;
|
|
680
683
|
const HEIGHTS = {
|
|
681
684
|
sm: 'h-9',
|
|
682
685
|
md: 'h-10',
|
|
@@ -697,9 +700,14 @@ const TEXT = {
|
|
|
697
700
|
* The field formats **live as you type**: the currency symbol, grouping separators and prefix/suffix
|
|
698
701
|
* stay visible on every keystroke, and the caret is kept where it belongs. The value is clamped to
|
|
699
702
|
* {@link min}/{@link max} on blur and on every spinner step; ArrowUp / ArrowDown also step it.
|
|
703
|
+
*
|
|
704
|
+
* In a locale whose decimal separator is a comma (fr-BE, nl-BE, de-DE…) a typed "." — the key most
|
|
705
|
+
* keyboards and numpads offer — is taken as the decimal separator: "12.50" becomes "12,50". Pasted
|
|
706
|
+
* text works the same way, except that a "." followed by exactly three digits in a locale that groups
|
|
707
|
+
* with "." ("1.234" in nl-BE) stays a thousands separator.
|
|
700
708
|
*/
|
|
701
709
|
class SdsInputNumber {
|
|
702
|
-
inputId = `sds-input-number-${nextId$
|
|
710
|
+
inputId = `sds-input-number-${nextId$m++}`;
|
|
703
711
|
fieldRef = viewChild('field', ...(ngDevMode ? [{ debugName: "fieldRef" }] : []));
|
|
704
712
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
705
713
|
/** Accessible name used when no visible [label] is provided. */
|
|
@@ -707,6 +715,13 @@ class SdsInputNumber {
|
|
|
707
715
|
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
708
716
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
709
717
|
error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
718
|
+
/**
|
|
719
|
+
* Mark the field invalid (danger frame + `aria-invalid`) without showing an [error] message — for a
|
|
720
|
+
* host that renders the message itself, e.g. an editable table cell.
|
|
721
|
+
*/
|
|
722
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
723
|
+
/** Extra id(s) for the field's `aria-describedby`, added to its own hint/error message id. */
|
|
724
|
+
ariaDescribedby = input('', ...(ngDevMode ? [{ debugName: "ariaDescribedby" }] : []));
|
|
710
725
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
711
726
|
/** `filled` is a borderless field on a muted ground; `default` is the bordered white field. */
|
|
712
727
|
appearance = input('default', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
@@ -743,22 +758,25 @@ class SdsInputNumber {
|
|
|
743
758
|
allowEmpty = input(true, ...(ngDevMode ? [{ debugName: "allowEmpty", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
744
759
|
clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
745
760
|
/**
|
|
746
|
-
* Accessible names for the icon-only controls.
|
|
747
|
-
*
|
|
761
|
+
* Accessible names for the icon-only controls. English defaults; translate them in a
|
|
762
|
+
* multi-language app.
|
|
748
763
|
*/
|
|
749
|
-
clearLabel = input('
|
|
750
|
-
incrementLabel = input('
|
|
751
|
-
decrementLabel = input('
|
|
764
|
+
clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
765
|
+
incrementLabel = input('Increase', ...(ngDevMode ? [{ debugName: "incrementLabel" }] : []));
|
|
766
|
+
decrementLabel = input('Decrease', ...(ngDevMode ? [{ debugName: "decrementLabel" }] : []));
|
|
752
767
|
/** The committed numeric value (driven by CVA + user input). */
|
|
753
768
|
value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
754
769
|
cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
|
|
755
770
|
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
756
771
|
describedBy = computed(() => {
|
|
772
|
+
const ids = [];
|
|
757
773
|
if (this.error())
|
|
758
|
-
|
|
759
|
-
if (this.hint())
|
|
760
|
-
|
|
761
|
-
|
|
774
|
+
ids.push(`${this.inputId}-err`);
|
|
775
|
+
else if (this.hint())
|
|
776
|
+
ids.push(`${this.inputId}-hint`);
|
|
777
|
+
if (this.ariaDescribedby())
|
|
778
|
+
ids.push(this.ariaDescribedby());
|
|
779
|
+
return ids.length ? ids.join(' ') : null;
|
|
762
780
|
}, ...(ngDevMode ? [{ debugName: "describedBy" }] : []));
|
|
763
781
|
clearVisible = computed(() => this.clearable() && this.value() !== null && !this.isDisabled() && !this.readonly(), ...(ngDevMode ? [{ debugName: "clearVisible" }] : []));
|
|
764
782
|
incrementIconName = computed(() => this.incrementIcon() ?? (this.buttonLayout() === 'stacked' ? 'chevron-up' : 'plus'), ...(ngDevMode ? [{ debugName: "incrementIconName" }] : []));
|
|
@@ -829,13 +847,13 @@ class SdsInputNumber {
|
|
|
829
847
|
parts.push('opacity-60 cursor-not-allowed');
|
|
830
848
|
if (this.appearance() === 'filled') {
|
|
831
849
|
parts.push('border-transparent bg-muted text-ink');
|
|
832
|
-
parts.push(this.error()
|
|
850
|
+
parts.push(this.error() || this.invalid()
|
|
833
851
|
? 'border-danger focus-within:ring-2 focus-within:ring-danger/30'
|
|
834
852
|
: 'focus-within:ring-2 focus-within:ring-brand-500/25');
|
|
835
853
|
}
|
|
836
854
|
else {
|
|
837
855
|
parts.push('bg-surface text-ink');
|
|
838
|
-
parts.push(this.error()
|
|
856
|
+
parts.push(this.error() || this.invalid()
|
|
839
857
|
? 'border-danger focus-within:border-danger focus-within:ring-2 focus-within:ring-danger/25'
|
|
840
858
|
: 'border-border focus-within:border-brand-500 focus-within:ring-2 focus-within:ring-brand-500/25');
|
|
841
859
|
}
|
|
@@ -964,6 +982,38 @@ class SdsInputNumber {
|
|
|
964
982
|
const n = Number(s);
|
|
965
983
|
return Number.isFinite(n) ? n : null;
|
|
966
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
* In a locale whose decimal separator is not "." (fr-BE, nl-BE, de-DE…), turn the "." people type
|
|
987
|
+
* for a decimal point into the locale separator before parsing, so "12.50" reads as 12.5.
|
|
988
|
+
* - `typed` is the text of the keystroke: a "." just typed sits right before the caret and is
|
|
989
|
+
* always the decimal point (even in a locale that groups with ".", whose group marks come from
|
|
990
|
+
* the formatter, never from the keyboard).
|
|
991
|
+
* - Otherwise (paste, autofill, programmatic input) and only when the text holds no locale decimal
|
|
992
|
+
* separator, the last "." is the decimal point — unless the locale groups with "." and exactly
|
|
993
|
+
* three digits follow it ("1.234" in nl-BE is one thousand two hundred thirty-four).
|
|
994
|
+
*/
|
|
995
|
+
localizeDecimalPoint(raw, caret, typed) {
|
|
996
|
+
const { group, decimal } = this.separators();
|
|
997
|
+
if (decimal === '.' || !raw.includes('.') || this.maxFrac() === 0)
|
|
998
|
+
return raw;
|
|
999
|
+
if (typed === '.' && raw[caret - 1] === '.') {
|
|
1000
|
+
return raw.slice(0, caret - 1) + decimal + raw.slice(caret);
|
|
1001
|
+
}
|
|
1002
|
+
// A keystroke without a "." leaves the formatter's own "." group marks alone.
|
|
1003
|
+
if ((typed !== null && !typed.includes('.')) || raw.includes(decimal))
|
|
1004
|
+
return raw;
|
|
1005
|
+
// Only a "." inside the number counts, not one in a prefix/suffix (" sq.ft").
|
|
1006
|
+
const prefix = this.prefix();
|
|
1007
|
+
const suffix = this.suffix();
|
|
1008
|
+
const start = prefix && raw.startsWith(prefix) ? prefix.length : 0;
|
|
1009
|
+
const end = suffix && raw.endsWith(suffix) ? raw.length - suffix.length : raw.length;
|
|
1010
|
+
const last = raw.lastIndexOf('.', end - 1);
|
|
1011
|
+
if (last < start)
|
|
1012
|
+
return raw;
|
|
1013
|
+
if (group === '.' && /^\d{3}(?!\d)/.test(raw.slice(last + 1, end)))
|
|
1014
|
+
return raw;
|
|
1015
|
+
return raw.slice(0, last) + decimal + raw.slice(last + 1);
|
|
1016
|
+
}
|
|
967
1017
|
/** Pull the sign / integer / fraction fragments out of a formatted, partially-typed string. */
|
|
968
1018
|
parseInput(raw) {
|
|
969
1019
|
const { group, decimal } = this.separators();
|
|
@@ -1032,8 +1082,12 @@ class SdsInputNumber {
|
|
|
1032
1082
|
// --- Interaction ----------------------------------------------------------
|
|
1033
1083
|
onInput(event) {
|
|
1034
1084
|
const el = event.target;
|
|
1035
|
-
const
|
|
1036
|
-
|
|
1085
|
+
const caret = el.selectionStart ?? el.value.length;
|
|
1086
|
+
// `data` is the keystroke's text; null/undefined for a paste, deletion or a synthetic event.
|
|
1087
|
+
const data = event.data;
|
|
1088
|
+
const kind = event.inputType;
|
|
1089
|
+
const typed = data != null && (kind === 'insertText' || kind === 'insertCompositionText') ? data : null;
|
|
1090
|
+
const raw = this.localizeDecimalPoint(el.value, caret, typed);
|
|
1037
1091
|
const target = this.significantBefore(raw, caret);
|
|
1038
1092
|
const parsed = this.parseInput(raw);
|
|
1039
1093
|
if (parsed.intDigits === '' && parsed.fracDigits === '' && !parsed.hadDecimal) {
|
|
@@ -1116,7 +1170,7 @@ class SdsInputNumber {
|
|
|
1116
1170
|
this.cvaDisabled.set(isDisabled);
|
|
1117
1171
|
}
|
|
1118
1172
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsInputNumber, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1119
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsInputNumber, isStandalone: true, selector: "sds-input-number", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", 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 }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, currencyDisplay: { classPropertyName: "currencyDisplay", publicName: "currencyDisplay", isSignal: true, isRequired: false, transformFunction: null }, useGrouping: { classPropertyName: "useGrouping", publicName: "useGrouping", isSignal: true, isRequired: false, transformFunction: null }, minFractionDigits: { classPropertyName: "minFractionDigits", publicName: "minFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, maxFractionDigits: { classPropertyName: "maxFractionDigits", publicName: "maxFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, buttonLayout: { classPropertyName: "buttonLayout", publicName: "buttonLayout", isSignal: true, isRequired: false, transformFunction: null }, incrementIcon: { classPropertyName: "incrementIcon", publicName: "incrementIcon", isSignal: true, isRequired: false, transformFunction: null }, decrementIcon: { classPropertyName: "decrementIcon", publicName: "decrementIcon", isSignal: true, isRequired: false, transformFunction: null }, allowEmpty: { classPropertyName: "allowEmpty", publicName: "allowEmpty", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, incrementLabel: { classPropertyName: "incrementLabel", publicName: "incrementLabel", isSignal: true, isRequired: false, transformFunction: null }, decrementLabel: { classPropertyName: "decrementLabel", publicName: "decrementLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
|
|
1173
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsInputNumber, isStandalone: true, selector: "sds-input-number", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", 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 }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "ariaDescribedby", 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 }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, currencyDisplay: { classPropertyName: "currencyDisplay", publicName: "currencyDisplay", isSignal: true, isRequired: false, transformFunction: null }, useGrouping: { classPropertyName: "useGrouping", publicName: "useGrouping", isSignal: true, isRequired: false, transformFunction: null }, minFractionDigits: { classPropertyName: "minFractionDigits", publicName: "minFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, maxFractionDigits: { classPropertyName: "maxFractionDigits", publicName: "maxFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, buttonLayout: { classPropertyName: "buttonLayout", publicName: "buttonLayout", isSignal: true, isRequired: false, transformFunction: null }, incrementIcon: { classPropertyName: "incrementIcon", publicName: "incrementIcon", isSignal: true, isRequired: false, transformFunction: null }, decrementIcon: { classPropertyName: "decrementIcon", publicName: "decrementIcon", isSignal: true, isRequired: false, transformFunction: null }, allowEmpty: { classPropertyName: "allowEmpty", publicName: "allowEmpty", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, incrementLabel: { classPropertyName: "incrementLabel", publicName: "incrementLabel", isSignal: true, isRequired: false, transformFunction: null }, decrementLabel: { classPropertyName: "decrementLabel", publicName: "decrementLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
|
|
1120
1174
|
{
|
|
1121
1175
|
provide: NG_VALUE_ACCESSOR,
|
|
1122
1176
|
useExisting: forwardRef(() => SdsInputNumber),
|
|
@@ -1169,7 +1223,7 @@ class SdsInputNumber {
|
|
|
1169
1223
|
[disabled]="isDisabled()"
|
|
1170
1224
|
[readOnly]="readonly()"
|
|
1171
1225
|
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
1172
|
-
[attr.aria-invalid]="error() ? 'true' : null"
|
|
1226
|
+
[attr.aria-invalid]="error() || invalid() ? 'true' : null"
|
|
1173
1227
|
[attr.aria-describedby]="describedBy()"
|
|
1174
1228
|
[attr.aria-valuenow]="value()"
|
|
1175
1229
|
[attr.aria-valuemin]="min()"
|
|
@@ -1324,7 +1378,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
1324
1378
|
[disabled]="isDisabled()"
|
|
1325
1379
|
[readOnly]="readonly()"
|
|
1326
1380
|
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
1327
|
-
[attr.aria-invalid]="error() ? 'true' : null"
|
|
1381
|
+
[attr.aria-invalid]="error() || invalid() ? 'true' : null"
|
|
1328
1382
|
[attr.aria-describedby]="describedBy()"
|
|
1329
1383
|
[attr.aria-valuenow]="value()"
|
|
1330
1384
|
[attr.aria-valuemin]="min()"
|
|
@@ -1418,9 +1472,579 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
1418
1472
|
}
|
|
1419
1473
|
`,
|
|
1420
1474
|
}]
|
|
1421
|
-
}], 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 }] }], 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 }] }] } });
|
|
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 }] }] } });
|
|
1422
1476
|
|
|
1423
|
-
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;
|
|
1424
2048
|
const SIZES$9 = {
|
|
1425
2049
|
sm: 'min-h-9 text-sm',
|
|
1426
2050
|
md: 'min-h-10 text-sm',
|
|
@@ -1440,7 +2064,7 @@ const SIZES$9 = {
|
|
|
1440
2064
|
* `<sds-localized-input [languages]="['fr','nl','en']" [(ngModel)]="title" />`.
|
|
1441
2065
|
*/
|
|
1442
2066
|
class SdsLocalizedInput {
|
|
1443
|
-
inputId = `sds-localized-input-${nextId$
|
|
2067
|
+
inputId = `sds-localized-input-${nextId$k++}`;
|
|
1444
2068
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
1445
2069
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
1446
2070
|
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
@@ -1454,11 +2078,11 @@ class SdsLocalizedInput {
|
|
|
1454
2078
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
1455
2079
|
/**
|
|
1456
2080
|
* Accessible name for the in-field language switcher, and the "no translation yet" title suffix on each
|
|
1457
|
-
* language button.
|
|
1458
|
-
*
|
|
2081
|
+
* language button. English defaults; translate them in a multi-language app (the buttons are
|
|
2082
|
+
* letter-only, so the title carries their meaning).
|
|
1459
2083
|
*/
|
|
1460
|
-
languageSwitcherLabel = input('
|
|
1461
|
-
untranslatedLabel = input('
|
|
2084
|
+
languageSwitcherLabel = input('Language', ...(ngDevMode ? [{ debugName: "languageSwitcherLabel" }] : []));
|
|
2085
|
+
untranslatedLabel = input('not translated yet', ...(ngDevMode ? [{ debugName: "untranslatedLabel" }] : []));
|
|
1462
2086
|
valueMap = signal({}, ...(ngDevMode ? [{ debugName: "valueMap" }] : []));
|
|
1463
2087
|
/** Language chosen via the switcher; null means "follow currentLanguage / the first language". */
|
|
1464
2088
|
manual = signal(null, ...(ngDevMode ? [{ debugName: "manual" }] : []));
|
|
@@ -1696,7 +2320,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
1696
2320
|
}]
|
|
1697
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 }] }] } });
|
|
1698
2322
|
|
|
1699
|
-
let nextId$
|
|
2323
|
+
let nextId$j = 0;
|
|
1700
2324
|
const SIZES$8 = {
|
|
1701
2325
|
md: 'h-12 w-11 text-lg',
|
|
1702
2326
|
lg: 'h-14 w-12 text-xl',
|
|
@@ -1713,7 +2337,7 @@ const SIZES$8 = {
|
|
|
1713
2337
|
* first box and have it land correctly.
|
|
1714
2338
|
*/
|
|
1715
2339
|
class SdsOtpInput {
|
|
1716
|
-
groupId = `sds-otp-${nextId$
|
|
2340
|
+
groupId = `sds-otp-${nextId$j++}`;
|
|
1717
2341
|
/** How many boxes / characters the code has. */
|
|
1718
2342
|
length = input(6, ...(ngDevMode ? [{ debugName: "length", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
1719
2343
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
@@ -1729,10 +2353,10 @@ class SdsOtpInput {
|
|
|
1729
2353
|
autoFocus = input(false, ...(ngDevMode ? [{ debugName: "autoFocus", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
1730
2354
|
/**
|
|
1731
2355
|
* Accessible name for an individual box, suffixed with its 1-based position ("Digit 1", "Digit
|
|
1732
|
-
* 2", …).
|
|
1733
|
-
*
|
|
2356
|
+
* 2", …). English default; translate it in an app serving more than one language, since each box
|
|
2357
|
+
* is an icon-less control whose only name this is.
|
|
1734
2358
|
*/
|
|
1735
|
-
cellLabel = input('
|
|
2359
|
+
cellLabel = input('Digit', ...(ngDevMode ? [{ debugName: "cellLabel" }] : []));
|
|
1736
2360
|
/** Emitted with the full value the moment the last box is filled. */
|
|
1737
2361
|
completed = output();
|
|
1738
2362
|
cells = viewChildren('cell', ...(ngDevMode ? [{ debugName: "cells" }] : []));
|
|
@@ -2013,7 +2637,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2013
2637
|
}]
|
|
2014
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 }] }] } });
|
|
2015
2639
|
|
|
2016
|
-
let nextId$
|
|
2640
|
+
let nextId$i = 0;
|
|
2017
2641
|
const SIZES$7 = {
|
|
2018
2642
|
sm: 'text-sm px-3 py-2',
|
|
2019
2643
|
md: 'text-sm px-3.5 py-2.5',
|
|
@@ -2025,7 +2649,7 @@ const SIZES$7 = {
|
|
|
2025
2649
|
* [(ngModel)].
|
|
2026
2650
|
*/
|
|
2027
2651
|
class SdsTextarea {
|
|
2028
|
-
fieldId = `sds-textarea-${nextId$
|
|
2652
|
+
fieldId = `sds-textarea-${nextId$i++}`;
|
|
2029
2653
|
field = viewChild('field', ...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
2030
2654
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2031
2655
|
/** Accessible name used when no visible [label] is provided. */
|
|
@@ -2050,6 +2674,13 @@ class SdsTextarea {
|
|
|
2050
2674
|
maxLength = input(0, ...(ngDevMode ? [{ debugName: "maxLength", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
2051
2675
|
/** Show a character counter row. */
|
|
2052
2676
|
showCount = input(false, ...(ngDevMode ? [{ debugName: "showCount", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
2677
|
+
/**
|
|
2678
|
+
* Spoken text of the counter when {@link maxLength} is set; tokens `{count}` and `{max}`. English
|
|
2679
|
+
* default — translate it in a multi-language app.
|
|
2680
|
+
*/
|
|
2681
|
+
countLimitLabel = input('{count} of {max} characters used', ...(ngDevMode ? [{ debugName: "countLimitLabel" }] : []));
|
|
2682
|
+
/** Spoken text of the counter without a {@link maxLength}; token `{count}`. */
|
|
2683
|
+
countLabelTemplate = input('{count} characters', ...(ngDevMode ? [{ debugName: "countLabelTemplate" }] : []));
|
|
2053
2684
|
resize = input('vertical', ...(ngDevMode ? [{ debugName: "resize" }] : []));
|
|
2054
2685
|
/** Current value (driven by CVA + user input). */
|
|
2055
2686
|
value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
@@ -2058,9 +2689,9 @@ class SdsTextarea {
|
|
|
2058
2689
|
count = computed(() => this.value().length, ...(ngDevMode ? [{ debugName: "count" }] : []));
|
|
2059
2690
|
hasCounter = computed(() => this.showCount() || this.maxLength() > 0, ...(ngDevMode ? [{ debugName: "hasCounter" }] : []));
|
|
2060
2691
|
/** Spoken description of the counter for assistive tech. */
|
|
2061
|
-
countLabel = computed(() => this.maxLength()
|
|
2062
|
-
|
|
2063
|
-
|
|
2692
|
+
countLabel = computed(() => (this.maxLength() ? this.countLimitLabel() : this.countLabelTemplate())
|
|
2693
|
+
.replace('{count}', String(this.count()))
|
|
2694
|
+
.replace('{max}', String(this.maxLength())), ...(ngDevMode ? [{ debugName: "countLabel" }] : []));
|
|
2064
2695
|
describedBy = computed(() => {
|
|
2065
2696
|
const ids = [];
|
|
2066
2697
|
if (this.error())
|
|
@@ -2137,7 +2768,7 @@ class SdsTextarea {
|
|
|
2137
2768
|
el.style.height = `${el.scrollHeight}px`;
|
|
2138
2769
|
}
|
|
2139
2770
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2140
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTextarea, isStandalone: true, selector: "sds-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", 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 }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
|
|
2771
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTextarea, isStandalone: true, selector: "sds-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", 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 }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null }, countLimitLabel: { classPropertyName: "countLimitLabel", publicName: "countLimitLabel", isSignal: true, isRequired: false, transformFunction: null }, countLabelTemplate: { classPropertyName: "countLabelTemplate", publicName: "countLabelTemplate", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
|
|
2141
2772
|
{
|
|
2142
2773
|
provide: NG_VALUE_ACCESSOR,
|
|
2143
2774
|
useExisting: forwardRef(() => SdsTextarea),
|
|
@@ -2276,9 +2907,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2276
2907
|
}
|
|
2277
2908
|
`,
|
|
2278
2909
|
}]
|
|
2279
|
-
}], 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 }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }] } });
|
|
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 }] }] } });
|
|
2280
2911
|
|
|
2281
|
-
let nextId$
|
|
2912
|
+
let nextId$h = 0;
|
|
2282
2913
|
const SIZES$6 = {
|
|
2283
2914
|
sm: { track: 'h-5 w-9', knob: 'h-4 w-4', on: 'translate-x-4', icon: 11 },
|
|
2284
2915
|
md: { track: 'h-6 w-11', knob: 'h-5 w-5', on: 'translate-x-5', icon: 13 },
|
|
@@ -2291,7 +2922,7 @@ const SIZES$6 = {
|
|
|
2291
2922
|
* states.
|
|
2292
2923
|
*/
|
|
2293
2924
|
class SdsToggleSwitch {
|
|
2294
|
-
fieldId = `sds-toggle-switch-${nextId$
|
|
2925
|
+
fieldId = `sds-toggle-switch-${nextId$h++}`;
|
|
2295
2926
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2296
2927
|
/** Accessible name used when no visible [label] is provided. */
|
|
2297
2928
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -2535,7 +3166,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2535
3166
|
}]
|
|
2536
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 }] }] } });
|
|
2537
3168
|
|
|
2538
|
-
let nextId$
|
|
3169
|
+
let nextId$g = 0;
|
|
2539
3170
|
/**
|
|
2540
3171
|
* Boolean checkbox. Implements ControlValueAccessor — use with reactive forms
|
|
2541
3172
|
* or `[(ngModel)]`. Renders a styled box (brand-filled with a check when on)
|
|
@@ -2543,24 +3174,33 @@ let nextId$f = 0;
|
|
|
2543
3174
|
* of its own, so it can sit inside the consumer's `<label>` (a whole clickable
|
|
2544
3175
|
* row), whose text then names it.
|
|
2545
3176
|
*
|
|
3177
|
+
* Set [indeterminate] for a "some but not all" state (e.g. a select-all box over a partial
|
|
3178
|
+
* selection): the box shows a bar and reads as "mixed"; a click checks it.
|
|
3179
|
+
*
|
|
2546
3180
|
* @example
|
|
2547
|
-
* <sds-checkbox label="
|
|
3181
|
+
* <sds-checkbox label="Auto-merge" [(ngModel)]="autoMerge" />
|
|
2548
3182
|
*/
|
|
2549
3183
|
class SdsCheckbox {
|
|
2550
|
-
id = `sds-checkbox-${nextId$
|
|
3184
|
+
id = `sds-checkbox-${nextId$g++}`;
|
|
2551
3185
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2552
3186
|
/** Accessible name used when no visible [label] is provided. */
|
|
2553
3187
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
2554
3188
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
2555
3189
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
3190
|
+
/**
|
|
3191
|
+
* "Some but not all": shows a bar and is announced as mixed while the value is false. Clicking
|
|
3192
|
+
* checks it (the native behaviour); the host then decides the next [indeterminate].
|
|
3193
|
+
*/
|
|
3194
|
+
indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
2556
3195
|
checked = signal(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
|
|
3196
|
+
mixed = computed(() => this.indeterminate() && !this.checked(), ...(ngDevMode ? [{ debugName: "mixed" }] : []));
|
|
2557
3197
|
cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
|
|
2558
3198
|
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
2559
3199
|
iconSize = computed(() => (this.size() === 'sm' ? 11 : 13), ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
|
|
2560
3200
|
stateClasses = computed(() => this.isDisabled() ? 'cursor-not-allowed opacity-60' : 'cursor-pointer', ...(ngDevMode ? [{ debugName: "stateClasses" }] : []));
|
|
2561
3201
|
boxClasses = computed(() => {
|
|
2562
3202
|
const size = this.size() === 'sm' ? 'h-4 w-4' : 'h-5 w-5';
|
|
2563
|
-
const state = this.checked()
|
|
3203
|
+
const state = this.checked() || this.mixed()
|
|
2564
3204
|
? 'border-brand-600 bg-brand-600 text-white'
|
|
2565
3205
|
: 'border-border bg-surface text-transparent';
|
|
2566
3206
|
const focus = 'focus-within:ring-2 focus-within:ring-brand-500/30 focus-within:border-brand-500';
|
|
@@ -2587,7 +3227,7 @@ class SdsCheckbox {
|
|
|
2587
3227
|
this.onChange(next);
|
|
2588
3228
|
}
|
|
2589
3229
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2590
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsCheckbox, isStandalone: true, selector: "sds-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", 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 } }, host: { classAttribute: "inline-flex" }, providers: [
|
|
3230
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsCheckbox, isStandalone: true, selector: "sds-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", 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 }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "inline-flex align-middle" }, providers: [
|
|
2591
3231
|
{
|
|
2592
3232
|
provide: NG_VALUE_ACCESSOR,
|
|
2593
3233
|
useExisting: forwardRef(() => SdsCheckbox),
|
|
@@ -2617,6 +3257,7 @@ class SdsCheckbox {
|
|
|
2617
3257
|
class="absolute inset-0 m-0 cursor-[inherit] opacity-0"
|
|
2618
3258
|
[id]="id"
|
|
2619
3259
|
[checked]="checked()"
|
|
3260
|
+
[indeterminate]="mixed()"
|
|
2620
3261
|
[disabled]="isDisabled()"
|
|
2621
3262
|
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
2622
3263
|
(change)="onInput($event)"
|
|
@@ -2624,6 +3265,8 @@ class SdsCheckbox {
|
|
|
2624
3265
|
/>
|
|
2625
3266
|
@if (checked()) {
|
|
2626
3267
|
<sds-icon name="check" [size]="iconSize()" [strokeWidth]="3" />
|
|
3268
|
+
} @else if (mixed()) {
|
|
3269
|
+
<span class="h-0.5 w-2.5 rounded-full bg-current" aria-hidden="true"></span>
|
|
2627
3270
|
}
|
|
2628
3271
|
</span>
|
|
2629
3272
|
</ng-template>
|
|
@@ -2642,7 +3285,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2642
3285
|
multi: true,
|
|
2643
3286
|
},
|
|
2644
3287
|
],
|
|
2645
|
-
|
|
3288
|
+
// align-middle: in an inline context (a table cell) an empty box and a checked one would otherwise
|
|
3289
|
+
// sit on different baselines, and the row would jump by a few pixels on every toggle.
|
|
3290
|
+
host: { class: 'inline-flex align-middle' },
|
|
2646
3291
|
template: `
|
|
2647
3292
|
<!-- With a visible label the whole thing is a <label>. Without one it is a plain span, so the box can
|
|
2648
3293
|
sit inside the consumer's own <label> (a clickable row, say) without nesting labels. -->
|
|
@@ -2667,6 +3312,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2667
3312
|
class="absolute inset-0 m-0 cursor-[inherit] opacity-0"
|
|
2668
3313
|
[id]="id"
|
|
2669
3314
|
[checked]="checked()"
|
|
3315
|
+
[indeterminate]="mixed()"
|
|
2670
3316
|
[disabled]="isDisabled()"
|
|
2671
3317
|
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
2672
3318
|
(change)="onInput($event)"
|
|
@@ -2674,14 +3320,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2674
3320
|
/>
|
|
2675
3321
|
@if (checked()) {
|
|
2676
3322
|
<sds-icon name="check" [size]="iconSize()" [strokeWidth]="3" />
|
|
3323
|
+
} @else if (mixed()) {
|
|
3324
|
+
<span class="h-0.5 w-2.5 rounded-full bg-current" aria-hidden="true"></span>
|
|
2677
3325
|
}
|
|
2678
3326
|
</span>
|
|
2679
3327
|
</ng-template>
|
|
2680
3328
|
`,
|
|
2681
3329
|
}]
|
|
2682
|
-
}], 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 }] }] } });
|
|
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 }] }] } });
|
|
2683
3331
|
|
|
2684
|
-
let nextId$
|
|
3332
|
+
let nextId$f = 0;
|
|
2685
3333
|
/**
|
|
2686
3334
|
* Mounted radios by group name. A pick updates the rest of its group, because a native radio says
|
|
2687
3335
|
* nothing when the browser unchecks it — without this a reactive form would leave the old choice drawn.
|
|
@@ -2707,7 +3355,7 @@ const groups = new Map();
|
|
|
2707
3355
|
* <sds-radio name="size" value="large" label="Grand" [(ngModel)]="size" />
|
|
2708
3356
|
*/
|
|
2709
3357
|
class SdsRadio {
|
|
2710
|
-
id = `sds-radio-${nextId$
|
|
3358
|
+
id = `sds-radio-${nextId$f++}`;
|
|
2711
3359
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2712
3360
|
/** Accessible name used when no visible [label] is provided. */
|
|
2713
3361
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -2890,8 +3538,30 @@ const STATUS_COLOR = {
|
|
|
2890
3538
|
busy: 'bg-danger',
|
|
2891
3539
|
away: 'bg-warning',
|
|
2892
3540
|
};
|
|
3541
|
+
const SHAPE = {
|
|
3542
|
+
circle: 'rounded-full',
|
|
3543
|
+
rounded: 'rounded-control',
|
|
3544
|
+
square: 'rounded-none',
|
|
3545
|
+
};
|
|
2893
3546
|
/**
|
|
2894
|
-
*
|
|
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 />
|
|
2895
3565
|
*/
|
|
2896
3566
|
class SdsAvatar {
|
|
2897
3567
|
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : []));
|
|
@@ -2899,8 +3569,48 @@ class SdsAvatar {
|
|
|
2899
3569
|
src = input(null, ...(ngDevMode ? [{ debugName: "src" }] : []));
|
|
2900
3570
|
size = input(36, ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
2901
3571
|
status = input(null, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
3572
|
+
/** `circle` (default), `rounded` (radius of a control) or `square`. */
|
|
3573
|
+
shape = input('circle', ...(ngDevMode ? [{ debugName: "shape" }] : []));
|
|
2902
3574
|
/** Tailwind bg utility for the initials background. */
|
|
2903
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" }] : []));
|
|
2904
3614
|
dotSize = computed(() => Math.max(8, Math.round(this.size() * 0.28)), ...(ngDevMode ? [{ debugName: "dotSize" }] : []));
|
|
2905
3615
|
statusColor = computed(() => this.status() ? STATUS_COLOR[this.status()] : '', ...(ngDevMode ? [{ debugName: "statusColor" }] : []));
|
|
2906
3616
|
resolvedInitials = computed(() => {
|
|
@@ -2914,19 +3624,31 @@ class SdsAvatar {
|
|
|
2914
3624
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
2915
3625
|
}, ...(ngDevMode ? [{ debugName: "resolvedInitials" }] : []));
|
|
2916
3626
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2917
|
-
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: `
|
|
2918
3628
|
<div
|
|
2919
|
-
class="relative grid place-items-center
|
|
2920
|
-
[class]="
|
|
3629
|
+
class="relative grid place-items-center font-semibold"
|
|
3630
|
+
[class]="frameClass()"
|
|
2921
3631
|
[style.width.px]="size()"
|
|
2922
3632
|
[style.height.px]="size()"
|
|
2923
3633
|
[style.fontSize.px]="size() * 0.4"
|
|
2924
3634
|
>
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
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>
|
|
2930
3652
|
|
|
2931
3653
|
@if (status()) {
|
|
2932
3654
|
<span
|
|
@@ -2937,27 +3659,43 @@ class SdsAvatar {
|
|
|
2937
3659
|
></span>
|
|
2938
3660
|
}
|
|
2939
3661
|
</div>
|
|
2940
|
-
`, 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 });
|
|
2941
3663
|
}
|
|
2942
3664
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsAvatar, decorators: [{
|
|
2943
3665
|
type: Component,
|
|
2944
3666
|
args: [{
|
|
2945
3667
|
selector: 'sds-avatar',
|
|
2946
3668
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2947
|
-
|
|
3669
|
+
imports: [SdsIcon],
|
|
3670
|
+
host: {
|
|
3671
|
+
class: 'inline-block shrink-0 align-middle',
|
|
3672
|
+
'[attr.aria-hidden]': "decorative() ? 'true' : null",
|
|
3673
|
+
},
|
|
2948
3674
|
template: `
|
|
2949
3675
|
<div
|
|
2950
|
-
class="relative grid place-items-center
|
|
2951
|
-
[class]="
|
|
3676
|
+
class="relative grid place-items-center font-semibold"
|
|
3677
|
+
[class]="frameClass()"
|
|
2952
3678
|
[style.width.px]="size()"
|
|
2953
3679
|
[style.height.px]="size()"
|
|
2954
3680
|
[style.fontSize.px]="size() * 0.4"
|
|
2955
3681
|
>
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
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>
|
|
2961
3699
|
|
|
2962
3700
|
@if (status()) {
|
|
2963
3701
|
<span
|
|
@@ -2970,7 +3708,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2970
3708
|
</div>
|
|
2971
3709
|
`,
|
|
2972
3710
|
}]
|
|
2973
|
-
}], 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 }] }] } });
|
|
2974
3712
|
|
|
2975
3713
|
const VARIANTS$1 = {
|
|
2976
3714
|
neutral: 'bg-muted text-ink-soft border-border',
|
|
@@ -3193,7 +3931,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3193
3931
|
|
|
3194
3932
|
/** Activation order: none → contains → may-contain → none. */
|
|
3195
3933
|
const ORDER = ['none', 'contains', 'may-contain'];
|
|
3196
|
-
let nextId$
|
|
3934
|
+
let nextId$e = 0;
|
|
3197
3935
|
/**
|
|
3198
3936
|
* A chip that cycles through three states — `none`, `contains`, `may-contain` — built for the 14-tile
|
|
3199
3937
|
* allergen declaration grid, but generic (any "no / yes / maybe" declaration).
|
|
@@ -3213,7 +3951,7 @@ let nextId$d = 0;
|
|
|
3213
3951
|
* containsLabel="Contains" mayContainLabel="May contain" noneLabel="Not present" />
|
|
3214
3952
|
*/
|
|
3215
3953
|
class SdsTriStateChip {
|
|
3216
|
-
chipId = `sds-tri-state-chip-${nextId$
|
|
3954
|
+
chipId = `sds-tri-state-chip-${nextId$e++}`;
|
|
3217
3955
|
/** Current state. Two-way: `[(value)]`. */
|
|
3218
3956
|
value = model('none', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
3219
3957
|
/** Visible name (e.g. the allergen). Required — the chip has no other accessible name. */
|
|
@@ -3435,7 +4173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3435
4173
|
}]
|
|
3436
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 }] }] } });
|
|
3437
4175
|
|
|
3438
|
-
let nextId$
|
|
4176
|
+
let nextId$d = 0;
|
|
3439
4177
|
/**
|
|
3440
4178
|
* Segmented control: a small set of mutually exclusive options shown side by side (e.g. "Pick exactly /
|
|
3441
4179
|
* at least / up to"). Radio-group semantics: `role="radiogroup"` with `role="radio"` segments, one tab
|
|
@@ -3451,7 +4189,7 @@ let nextId$c = 0;
|
|
|
3451
4189
|
*/
|
|
3452
4190
|
class SdsSegmented {
|
|
3453
4191
|
host = inject(ElementRef);
|
|
3454
|
-
baseId = `sds-segmented-${nextId$
|
|
4192
|
+
baseId = `sds-segmented-${nextId$d++}`;
|
|
3455
4193
|
/** Options: `{ value, label, icon?, disabled? }` objects, or bare strings/numbers. */
|
|
3456
4194
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
3457
4195
|
/** Selected value. Two-way: `[(value)]`. */
|
|
@@ -3496,17 +4234,347 @@ class SdsSegmented {
|
|
|
3496
4234
|
? `${base} bg-surface font-semibold text-ink shadow-sm ring-1 ring-border dark:bg-border`
|
|
3497
4235
|
: `${base} cursor-pointer text-ink-soft hover:bg-surface/60 hover:text-ink`;
|
|
3498
4236
|
}
|
|
3499
|
-
choose(i) {
|
|
3500
|
-
const seg = this.segments()[i];
|
|
3501
|
-
if (!seg || seg.disabled || this.disabled())
|
|
4237
|
+
choose(i) {
|
|
4238
|
+
const seg = this.segments()[i];
|
|
4239
|
+
if (!seg || seg.disabled || this.disabled())
|
|
4240
|
+
return;
|
|
4241
|
+
this.value.set(seg.value);
|
|
4242
|
+
}
|
|
4243
|
+
onKeydown(event) {
|
|
4244
|
+
if (this.disabled())
|
|
4245
|
+
return;
|
|
4246
|
+
const segs = this.segments();
|
|
4247
|
+
if (!segs.length)
|
|
4248
|
+
return;
|
|
4249
|
+
const current = Number(event.target.dataset['index'] ?? this.tabStop());
|
|
4250
|
+
let next = null;
|
|
4251
|
+
switch (event.key) {
|
|
4252
|
+
case 'ArrowRight':
|
|
4253
|
+
case 'ArrowDown':
|
|
4254
|
+
next = this.step(current, 1);
|
|
4255
|
+
break;
|
|
4256
|
+
case 'ArrowLeft':
|
|
4257
|
+
case 'ArrowUp':
|
|
4258
|
+
next = this.step(current, -1);
|
|
4259
|
+
break;
|
|
4260
|
+
case 'Home':
|
|
4261
|
+
next = segs.findIndex((s) => !s.disabled);
|
|
4262
|
+
break;
|
|
4263
|
+
case 'End':
|
|
4264
|
+
for (let i = segs.length - 1; i >= 0; i--) {
|
|
4265
|
+
if (!segs[i].disabled) {
|
|
4266
|
+
next = i;
|
|
4267
|
+
break;
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
break;
|
|
4271
|
+
default:
|
|
4272
|
+
return;
|
|
4273
|
+
}
|
|
4274
|
+
event.preventDefault();
|
|
4275
|
+
if (next === null || next < 0)
|
|
4276
|
+
return;
|
|
4277
|
+
this.choose(next);
|
|
4278
|
+
this.host.nativeElement.querySelector(`#${this.segmentId(next)}`)?.focus();
|
|
4279
|
+
}
|
|
4280
|
+
step(from, delta) {
|
|
4281
|
+
const segs = this.segments();
|
|
4282
|
+
let i = from;
|
|
4283
|
+
for (let n = 0; n < segs.length; n++) {
|
|
4284
|
+
i = (i + delta + segs.length) % segs.length;
|
|
4285
|
+
if (!segs[i].disabled)
|
|
4286
|
+
return i;
|
|
4287
|
+
}
|
|
4288
|
+
return null;
|
|
4289
|
+
}
|
|
4290
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSegmented, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4291
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSegmented, isStandalone: true, selector: "sds-segmented", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", 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 }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class.w-full": "fullWidth()" }, classAttribute: "inline-flex max-w-full" }, ngImport: i0, template: `
|
|
4292
|
+
<div
|
|
4293
|
+
role="radiogroup"
|
|
4294
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
4295
|
+
[attr.aria-labelledby]="ariaLabelledby() || null"
|
|
4296
|
+
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
4297
|
+
class="flex max-w-full items-stretch gap-0.5 overflow-x-auto rounded-control border border-border bg-muted p-0.5"
|
|
4298
|
+
[class.w-full]="fullWidth()"
|
|
4299
|
+
(keydown)="onKeydown($event)"
|
|
4300
|
+
>
|
|
4301
|
+
@for (seg of segments(); track $index; let i = $index) {
|
|
4302
|
+
<button
|
|
4303
|
+
type="button"
|
|
4304
|
+
role="radio"
|
|
4305
|
+
[id]="segmentId(i)"
|
|
4306
|
+
[attr.aria-checked]="isSelected(seg)"
|
|
4307
|
+
[attr.aria-label]="iconOnly() ? seg.label : null"
|
|
4308
|
+
[attr.title]="iconOnly() ? seg.label : null"
|
|
4309
|
+
[attr.tabindex]="i === tabStop() ? 0 : -1"
|
|
4310
|
+
[attr.data-index]="i"
|
|
4311
|
+
[disabled]="disabled() || seg.disabled"
|
|
4312
|
+
[class]="segmentClass(seg)"
|
|
4313
|
+
(click)="choose(i)"
|
|
4314
|
+
>
|
|
4315
|
+
@if (seg.icon) {
|
|
4316
|
+
<sds-icon [name]="seg.icon" [size]="size() === 'sm' ? 15 : 17" class="shrink-0" />
|
|
4317
|
+
}
|
|
4318
|
+
@if (!iconOnly()) {
|
|
4319
|
+
<span class="truncate">{{ seg.label }}</span>
|
|
4320
|
+
}
|
|
4321
|
+
</button>
|
|
4322
|
+
}
|
|
4323
|
+
</div>
|
|
4324
|
+
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4325
|
+
}
|
|
4326
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSegmented, decorators: [{
|
|
4327
|
+
type: Component,
|
|
4328
|
+
args: [{
|
|
4329
|
+
selector: 'sds-segmented',
|
|
4330
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4331
|
+
imports: [SdsIcon],
|
|
4332
|
+
host: { class: 'inline-flex max-w-full', '[class.w-full]': 'fullWidth()' },
|
|
4333
|
+
template: `
|
|
4334
|
+
<div
|
|
4335
|
+
role="radiogroup"
|
|
4336
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
4337
|
+
[attr.aria-labelledby]="ariaLabelledby() || null"
|
|
4338
|
+
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
4339
|
+
class="flex max-w-full items-stretch gap-0.5 overflow-x-auto rounded-control border border-border bg-muted p-0.5"
|
|
4340
|
+
[class.w-full]="fullWidth()"
|
|
4341
|
+
(keydown)="onKeydown($event)"
|
|
4342
|
+
>
|
|
4343
|
+
@for (seg of segments(); track $index; let i = $index) {
|
|
4344
|
+
<button
|
|
4345
|
+
type="button"
|
|
4346
|
+
role="radio"
|
|
4347
|
+
[id]="segmentId(i)"
|
|
4348
|
+
[attr.aria-checked]="isSelected(seg)"
|
|
4349
|
+
[attr.aria-label]="iconOnly() ? seg.label : null"
|
|
4350
|
+
[attr.title]="iconOnly() ? seg.label : null"
|
|
4351
|
+
[attr.tabindex]="i === tabStop() ? 0 : -1"
|
|
4352
|
+
[attr.data-index]="i"
|
|
4353
|
+
[disabled]="disabled() || seg.disabled"
|
|
4354
|
+
[class]="segmentClass(seg)"
|
|
4355
|
+
(click)="choose(i)"
|
|
4356
|
+
>
|
|
4357
|
+
@if (seg.icon) {
|
|
4358
|
+
<sds-icon [name]="seg.icon" [size]="size() === 'sm' ? 15 : 17" class="shrink-0" />
|
|
4359
|
+
}
|
|
4360
|
+
@if (!iconOnly()) {
|
|
4361
|
+
<span class="truncate">{{ seg.label }}</span>
|
|
4362
|
+
}
|
|
4363
|
+
</button>
|
|
4364
|
+
}
|
|
4365
|
+
</div>
|
|
4366
|
+
`,
|
|
4367
|
+
}]
|
|
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 }] }] } });
|
|
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())
|
|
3502
4547
|
return;
|
|
3503
|
-
|
|
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);
|
|
3504
4572
|
}
|
|
3505
4573
|
onKeydown(event) {
|
|
3506
|
-
if (this.
|
|
4574
|
+
if (this.multiple() || this.isDisabled())
|
|
3507
4575
|
return;
|
|
3508
|
-
const
|
|
3509
|
-
if (!
|
|
4576
|
+
const chips = this.chips();
|
|
4577
|
+
if (!chips.length)
|
|
3510
4578
|
return;
|
|
3511
4579
|
const current = Number(event.target.dataset['index'] ?? this.tabStop());
|
|
3512
4580
|
let next = null;
|
|
@@ -3520,11 +4588,11 @@ class SdsSegmented {
|
|
|
3520
4588
|
next = this.step(current, -1);
|
|
3521
4589
|
break;
|
|
3522
4590
|
case 'Home':
|
|
3523
|
-
next =
|
|
4591
|
+
next = chips.findIndex((c) => !c.disabled);
|
|
3524
4592
|
break;
|
|
3525
4593
|
case 'End':
|
|
3526
|
-
for (let i =
|
|
3527
|
-
if (!
|
|
4594
|
+
for (let i = chips.length - 1; i >= 0; i--) {
|
|
4595
|
+
if (!chips[i].disabled) {
|
|
3528
4596
|
next = i;
|
|
3529
4597
|
break;
|
|
3530
4598
|
}
|
|
@@ -3536,98 +4604,136 @@ class SdsSegmented {
|
|
|
3536
4604
|
event.preventDefault();
|
|
3537
4605
|
if (next === null || next < 0)
|
|
3538
4606
|
return;
|
|
3539
|
-
this.
|
|
3540
|
-
|
|
4607
|
+
if (!this.isSelected(chips[next]))
|
|
4608
|
+
this.toggle(next);
|
|
4609
|
+
this.host.nativeElement.querySelector(`#${this.chipId(next)}`)?.focus();
|
|
3541
4610
|
}
|
|
3542
4611
|
step(from, delta) {
|
|
3543
|
-
const
|
|
4612
|
+
const chips = this.chips();
|
|
3544
4613
|
let i = from;
|
|
3545
|
-
for (let n = 0; n <
|
|
3546
|
-
i = (i + delta +
|
|
3547
|
-
if (!
|
|
4614
|
+
for (let n = 0; n < chips.length; n++) {
|
|
4615
|
+
i = (i + delta + chips.length) % chips.length;
|
|
4616
|
+
if (!chips[i].disabled)
|
|
3548
4617
|
return i;
|
|
3549
4618
|
}
|
|
3550
4619
|
return null;
|
|
3551
4620
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
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: `
|
|
3554
4641
|
<div
|
|
3555
|
-
role="radiogroup"
|
|
4642
|
+
[attr.role]="multiple() ? 'group' : 'radiogroup'"
|
|
3556
4643
|
[attr.aria-label]="ariaLabel() || null"
|
|
3557
4644
|
[attr.aria-labelledby]="ariaLabelledby() || null"
|
|
3558
|
-
[attr.aria-disabled]="
|
|
3559
|
-
class="flex
|
|
3560
|
-
[class
|
|
4645
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : null"
|
|
4646
|
+
class="flex gap-2"
|
|
4647
|
+
[class]="wrap() ? 'flex-wrap' : 'overflow-x-auto pb-1'"
|
|
3561
4648
|
(keydown)="onKeydown($event)"
|
|
4649
|
+
(focusout)="onTouched()"
|
|
3562
4650
|
>
|
|
3563
|
-
@for (
|
|
4651
|
+
@for (chip of chips(); track $index; let i = $index) {
|
|
3564
4652
|
<button
|
|
3565
4653
|
type="button"
|
|
3566
|
-
|
|
3567
|
-
[
|
|
3568
|
-
[attr.aria-checked]="isSelected(
|
|
3569
|
-
[attr.aria-
|
|
3570
|
-
[attr.
|
|
3571
|
-
[attr.tabindex]="i === tabStop() ? 0 : -1"
|
|
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"
|
|
3572
4659
|
[attr.data-index]="i"
|
|
3573
|
-
[disabled]="
|
|
3574
|
-
[class]="
|
|
3575
|
-
(click)="
|
|
4660
|
+
[disabled]="isDisabled() || chip.disabled"
|
|
4661
|
+
[class]="classFor(chip)"
|
|
4662
|
+
(click)="toggle(i)"
|
|
3576
4663
|
>
|
|
3577
|
-
@if (
|
|
3578
|
-
<sds-icon
|
|
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" />
|
|
3579
4673
|
}
|
|
3580
|
-
|
|
3581
|
-
|
|
4674
|
+
<span class="truncate">{{ chip.label }}</span>
|
|
4675
|
+
@if (chip.count !== null) {
|
|
4676
|
+
<span [class]="countClass">{{ chip.count }}</span>
|
|
3582
4677
|
}
|
|
3583
4678
|
</button>
|
|
3584
4679
|
}
|
|
3585
4680
|
</div>
|
|
3586
4681
|
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3587
4682
|
}
|
|
3588
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type:
|
|
4683
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsChipGroup, decorators: [{
|
|
3589
4684
|
type: Component,
|
|
3590
4685
|
args: [{
|
|
3591
|
-
selector: 'sds-
|
|
4686
|
+
selector: 'sds-chip-group',
|
|
3592
4687
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3593
4688
|
imports: [SdsIcon],
|
|
3594
|
-
|
|
4689
|
+
providers: [
|
|
4690
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsChipGroup), multi: true },
|
|
4691
|
+
],
|
|
4692
|
+
host: { class: 'block' },
|
|
3595
4693
|
template: `
|
|
3596
4694
|
<div
|
|
3597
|
-
role="radiogroup"
|
|
4695
|
+
[attr.role]="multiple() ? 'group' : 'radiogroup'"
|
|
3598
4696
|
[attr.aria-label]="ariaLabel() || null"
|
|
3599
4697
|
[attr.aria-labelledby]="ariaLabelledby() || null"
|
|
3600
|
-
[attr.aria-disabled]="
|
|
3601
|
-
class="flex
|
|
3602
|
-
[class
|
|
4698
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : null"
|
|
4699
|
+
class="flex gap-2"
|
|
4700
|
+
[class]="wrap() ? 'flex-wrap' : 'overflow-x-auto pb-1'"
|
|
3603
4701
|
(keydown)="onKeydown($event)"
|
|
4702
|
+
(focusout)="onTouched()"
|
|
3604
4703
|
>
|
|
3605
|
-
@for (
|
|
4704
|
+
@for (chip of chips(); track $index; let i = $index) {
|
|
3606
4705
|
<button
|
|
3607
4706
|
type="button"
|
|
3608
|
-
|
|
3609
|
-
[
|
|
3610
|
-
[attr.aria-checked]="isSelected(
|
|
3611
|
-
[attr.aria-
|
|
3612
|
-
[attr.
|
|
3613
|
-
[attr.tabindex]="i === tabStop() ? 0 : -1"
|
|
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"
|
|
3614
4712
|
[attr.data-index]="i"
|
|
3615
|
-
[disabled]="
|
|
3616
|
-
[class]="
|
|
3617
|
-
(click)="
|
|
4713
|
+
[disabled]="isDisabled() || chip.disabled"
|
|
4714
|
+
[class]="classFor(chip)"
|
|
4715
|
+
(click)="toggle(i)"
|
|
3618
4716
|
>
|
|
3619
|
-
@if (
|
|
3620
|
-
<sds-icon
|
|
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" />
|
|
3621
4726
|
}
|
|
3622
|
-
|
|
3623
|
-
|
|
4727
|
+
<span class="truncate">{{ chip.label }}</span>
|
|
4728
|
+
@if (chip.count !== null) {
|
|
4729
|
+
<span [class]="countClass">{{ chip.count }}</span>
|
|
3624
4730
|
}
|
|
3625
4731
|
</button>
|
|
3626
4732
|
}
|
|
3627
4733
|
</div>
|
|
3628
4734
|
`,
|
|
3629
4735
|
}]
|
|
3630
|
-
}], 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 }] }],
|
|
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 }] }] } });
|
|
3631
4737
|
|
|
3632
4738
|
/**
|
|
3633
4739
|
* Each status has its own glyph SHAPE (circle-check, triangle, octagon, circle-i) as well as its own
|
|
@@ -4053,6 +5159,9 @@ const STATES = {
|
|
|
4053
5159
|
* for multi-select ("select all matches"): it then carries `aria-pressed` and a corner check. [busy]
|
|
4054
5160
|
* shows a spinner and sets `aria-busy` while a save is in flight.
|
|
4055
5161
|
*
|
|
5162
|
+
* A photo that fails to load (404, blocked, not an image) falls back to the no-photo layout — never
|
|
5163
|
+
* a broken-image icon — and `(imageError)` reports the URL. A new [image] URL is tried again.
|
|
5164
|
+
*
|
|
4056
5165
|
* @example
|
|
4057
5166
|
* <sds-status-tile title="Bacon" subtitle="Extras" state="sold-out" note="Back at 22:00"
|
|
4058
5167
|
* soldOutLabel="Sold out" (activate)="toggle(item)" />
|
|
@@ -4077,6 +5186,21 @@ class SdsStatusTile {
|
|
|
4077
5186
|
hiddenLabel = input('Hidden', ...(ngDevMode ? [{ debugName: "hiddenLabel" }] : []));
|
|
4078
5187
|
/** The tile was pressed (click, tap, Enter or Space). */
|
|
4079
5188
|
activate = output();
|
|
5189
|
+
/** The [image] URL failed to load; the tile has fallen back to its no-photo layout. */
|
|
5190
|
+
imageError = output();
|
|
5191
|
+
/** The URL that last failed to load — hidden until [image] changes to another URL. */
|
|
5192
|
+
failedImage = signal(null, ...(ngDevMode ? [{ debugName: "failedImage" }] : []));
|
|
5193
|
+
showImage = computed(() => {
|
|
5194
|
+
const src = this.image();
|
|
5195
|
+
return !!src && src !== this.failedImage();
|
|
5196
|
+
}, ...(ngDevMode ? [{ debugName: "showImage" }] : []));
|
|
5197
|
+
onImageError() {
|
|
5198
|
+
const src = this.image();
|
|
5199
|
+
if (!src)
|
|
5200
|
+
return;
|
|
5201
|
+
this.failedImage.set(src);
|
|
5202
|
+
this.imageError.emit(src);
|
|
5203
|
+
}
|
|
4080
5204
|
style = computed(() => STATES[this.state()] ?? STATES.available, ...(ngDevMode ? [{ debugName: "style" }] : []));
|
|
4081
5205
|
stateText = computed(() => {
|
|
4082
5206
|
switch (this.state()) {
|
|
@@ -4107,7 +5231,7 @@ class SdsStatusTile {
|
|
|
4107
5231
|
ring);
|
|
4108
5232
|
}, ...(ngDevMode ? [{ debugName: "tileClass" }] : []));
|
|
4109
5233
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsStatusTile, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4110
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsStatusTile, isStandalone: true, selector: "sds-status-tile", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, availableLabel: { classPropertyName: "availableLabel", publicName: "availableLabel", isSignal: true, isRequired: false, transformFunction: null }, soldOutLabel: { classPropertyName: "soldOutLabel", publicName: "soldOutLabel", isSignal: true, isRequired: false, transformFunction: null }, hiddenLabel: { classPropertyName: "hiddenLabel", publicName: "hiddenLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activate: "activate" }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
5234
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsStatusTile, isStandalone: true, selector: "sds-status-tile", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, availableLabel: { classPropertyName: "availableLabel", publicName: "availableLabel", isSignal: true, isRequired: false, transformFunction: null }, soldOutLabel: { classPropertyName: "soldOutLabel", publicName: "soldOutLabel", isSignal: true, isRequired: false, transformFunction: null }, hiddenLabel: { classPropertyName: "hiddenLabel", publicName: "hiddenLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activate: "activate", imageError: "imageError" }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
4111
5235
|
<button
|
|
4112
5236
|
type="button"
|
|
4113
5237
|
[class]="tileClass()"
|
|
@@ -4118,11 +5242,12 @@ class SdsStatusTile {
|
|
|
4118
5242
|
[style.background-image]="hatch()"
|
|
4119
5243
|
(click)="activate.emit()"
|
|
4120
5244
|
>
|
|
4121
|
-
@if (
|
|
5245
|
+
@if (showImage()) {
|
|
4122
5246
|
<span class="relative block h-[45%] w-full shrink-0 overflow-hidden bg-muted">
|
|
4123
5247
|
<img
|
|
4124
5248
|
[src]="image()"
|
|
4125
5249
|
[alt]="imageAlt()"
|
|
5250
|
+
(error)="onImageError()"
|
|
4126
5251
|
class="h-full w-full object-cover"
|
|
4127
5252
|
[class.grayscale]="state() !== 'available'"
|
|
4128
5253
|
[class.opacity-60]="state() !== 'available'"
|
|
@@ -4135,7 +5260,7 @@ class SdsStatusTile {
|
|
|
4135
5260
|
<span class="flex min-h-0 w-full flex-1 flex-col gap-1 p-3 text-left">
|
|
4136
5261
|
<span
|
|
4137
5262
|
class="line-clamp-2 break-words font-bold leading-tight text-ink"
|
|
4138
|
-
[class]="
|
|
5263
|
+
[class]="showImage() ? 'text-base' : 'text-lg'"
|
|
4139
5264
|
[class.line-through]="state() === 'sold-out'"
|
|
4140
5265
|
[class.decoration-2]="state() === 'sold-out'"
|
|
4141
5266
|
>{{ title() }}</span
|
|
@@ -4198,11 +5323,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4198
5323
|
[style.background-image]="hatch()"
|
|
4199
5324
|
(click)="activate.emit()"
|
|
4200
5325
|
>
|
|
4201
|
-
@if (
|
|
5326
|
+
@if (showImage()) {
|
|
4202
5327
|
<span class="relative block h-[45%] w-full shrink-0 overflow-hidden bg-muted">
|
|
4203
5328
|
<img
|
|
4204
5329
|
[src]="image()"
|
|
4205
5330
|
[alt]="imageAlt()"
|
|
5331
|
+
(error)="onImageError()"
|
|
4206
5332
|
class="h-full w-full object-cover"
|
|
4207
5333
|
[class.grayscale]="state() !== 'available'"
|
|
4208
5334
|
[class.opacity-60]="state() !== 'available'"
|
|
@@ -4215,7 +5341,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4215
5341
|
<span class="flex min-h-0 w-full flex-1 flex-col gap-1 p-3 text-left">
|
|
4216
5342
|
<span
|
|
4217
5343
|
class="line-clamp-2 break-words font-bold leading-tight text-ink"
|
|
4218
|
-
[class]="
|
|
5344
|
+
[class]="showImage() ? 'text-base' : 'text-lg'"
|
|
4219
5345
|
[class.line-through]="state() === 'sold-out'"
|
|
4220
5346
|
[class.decoration-2]="state() === 'sold-out'"
|
|
4221
5347
|
>{{ title() }}</span
|
|
@@ -4260,7 +5386,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4260
5386
|
</button>
|
|
4261
5387
|
`,
|
|
4262
5388
|
}]
|
|
4263
|
-
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], availableLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableLabel", required: false }] }], soldOutLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "soldOutLabel", required: false }] }], hiddenLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenLabel", required: false }] }], activate: [{ type: i0.Output, args: ["activate"] }] } });
|
|
5389
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], availableLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableLabel", required: false }] }], soldOutLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "soldOutLabel", required: false }] }], hiddenLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenLabel", required: false }] }], activate: [{ type: i0.Output, args: ["activate"] }], imageError: [{ type: i0.Output, args: ["imageError"] }] } });
|
|
4264
5390
|
|
|
4265
5391
|
let nextId$b = 0;
|
|
4266
5392
|
/**
|
|
@@ -4904,6 +6030,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4904
6030
|
}]
|
|
4905
6031
|
}] });
|
|
4906
6032
|
let nextId$a = 0;
|
|
6033
|
+
/** Fastest auto-scroll step, in px per animation frame (reached at the very edge). */
|
|
6034
|
+
const AUTO_SCROLL_MAX_STEP = 18;
|
|
6035
|
+
/** The nearest ancestor that scrolls vertically (below the document, which is handled as the window). */
|
|
6036
|
+
function scrollParentOf(el) {
|
|
6037
|
+
const doc = el.ownerDocument;
|
|
6038
|
+
for (let node = el.parentElement; node; node = node.parentElement) {
|
|
6039
|
+
if (node === doc.body || node === doc.documentElement)
|
|
6040
|
+
break;
|
|
6041
|
+
const overflowY = getComputedStyle(node).overflowY;
|
|
6042
|
+
if (/(auto|scroll|overlay)/.test(overflowY) && node.scrollHeight > node.clientHeight)
|
|
6043
|
+
return node;
|
|
6044
|
+
}
|
|
6045
|
+
return null;
|
|
6046
|
+
}
|
|
6047
|
+
/**
|
|
6048
|
+
* Signed scroll step for a pointer at `y` inside the band [top, bottom]: negative near the top edge,
|
|
6049
|
+
* positive near the bottom, faster the closer it gets, 0 elsewhere.
|
|
6050
|
+
*/
|
|
6051
|
+
function edgeStep(y, top, bottom, edge) {
|
|
6052
|
+
if (bottom - top < edge * 2)
|
|
6053
|
+
edge = (bottom - top) / 3;
|
|
6054
|
+
if (edge <= 0)
|
|
6055
|
+
return 0;
|
|
6056
|
+
const speed = (depth) => Math.ceil(AUTO_SCROLL_MAX_STEP * Math.min(1, depth / edge));
|
|
6057
|
+
if (y < top + edge)
|
|
6058
|
+
return -speed(top + edge - y);
|
|
6059
|
+
if (y > bottom - edge)
|
|
6060
|
+
return speed(y - (bottom - edge));
|
|
6061
|
+
return 0;
|
|
6062
|
+
}
|
|
4907
6063
|
/** Move one entry of `list` from `from` to `to`, returning a new array. */
|
|
4908
6064
|
function moveItem(list, from, to) {
|
|
4909
6065
|
const next = [...list];
|
|
@@ -4919,6 +6075,10 @@ function moveItem(list, from, to) {
|
|
|
4919
6075
|
* - **Keyboard**: focus a handle, **Space/Enter** picks the item up, **↑/↓** (and Home/End) move it,
|
|
4920
6076
|
* **Space/Enter** drops it, **Escape** cancels (the event is stopped, so an enclosing drawer stays open).
|
|
4921
6077
|
* Moving focus away also cancels.
|
|
6078
|
+
* - **Long lists**: while a pointer drag nears the top or bottom edge of the nearest scrollable
|
|
6079
|
+
* ancestor (a drawer body, a panel) — or of the window — that container scrolls, faster closer to
|
|
6080
|
+
* the edge, and the dragged row stays under the pointer. A keyboard move scrolls just enough to keep
|
|
6081
|
+
* the moving row in view. Turn off with `[autoScroll]="false"`.
|
|
4922
6082
|
* - **Screen readers**: every handle is named ("Reorder Burgers") and described by the instructions; an
|
|
4923
6083
|
* assertive live region announces pick-up, each move ("moved to position 3 of 8"), the drop and a cancel.
|
|
4924
6084
|
*
|
|
@@ -4955,6 +6115,13 @@ class SdsSortableList {
|
|
|
4955
6115
|
appearance = input('card', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
4956
6116
|
/** Accessible name of the list. */
|
|
4957
6117
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
6118
|
+
/**
|
|
6119
|
+
* Scroll the nearest scrollable ancestor (then the window) while dragging near its top or bottom
|
|
6120
|
+
* edge, and keep a keyboard-moved row in view.
|
|
6121
|
+
*/
|
|
6122
|
+
autoScroll = input(true, ...(ngDevMode ? [{ debugName: "autoScroll", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
6123
|
+
/** Height (px) of the band along each scroll edge where a pointer drag starts auto-scrolling. */
|
|
6124
|
+
autoScrollEdge = input(56, ...(ngDevMode ? [{ debugName: "autoScrollEdge", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
4958
6125
|
/** Name of each handle; `{item}` is the item's label. */
|
|
4959
6126
|
handleLabel = input('Reorder {item}', ...(ngDevMode ? [{ debugName: "handleLabel" }] : []));
|
|
4960
6127
|
/** Read after a handle's name (aria-describedby). */
|
|
@@ -4985,6 +6152,16 @@ class SdsSortableList {
|
|
|
4985
6152
|
gap = 0;
|
|
4986
6153
|
pointerId = null;
|
|
4987
6154
|
startY = 0;
|
|
6155
|
+
/** Latest pointer position during a pointer drag (auto-scroll re-reads it every frame). */
|
|
6156
|
+
lastY = 0;
|
|
6157
|
+
/** The host's viewport top at drag start: the drift since then is how far its scrollers moved. */
|
|
6158
|
+
startHostTop = 0;
|
|
6159
|
+
/** Nearest scrollable ancestor, found at drag start. */
|
|
6160
|
+
scroller = null;
|
|
6161
|
+
frame = null;
|
|
6162
|
+
constructor() {
|
|
6163
|
+
inject(DestroyRef).onDestroy(() => this.stopAutoScroll());
|
|
6164
|
+
}
|
|
4988
6165
|
/** Per-row offsets that open a gap where the moving row will land. */
|
|
4989
6166
|
shifts = computed(() => {
|
|
4990
6167
|
const a = this.active();
|
|
@@ -5118,7 +6295,7 @@ class SdsSortableList {
|
|
|
5118
6295
|
case 'Escape':
|
|
5119
6296
|
event.preventDefault();
|
|
5120
6297
|
event.stopPropagation();
|
|
5121
|
-
this.cancel();
|
|
6298
|
+
this.cancel(true, true);
|
|
5122
6299
|
return;
|
|
5123
6300
|
case 'Tab':
|
|
5124
6301
|
this.cancel();
|
|
@@ -5130,6 +6307,7 @@ class SdsSortableList {
|
|
|
5130
6307
|
return;
|
|
5131
6308
|
this.target.set(to);
|
|
5132
6309
|
this.announce(this.movedMessage(), to);
|
|
6310
|
+
this.revealActive();
|
|
5133
6311
|
}
|
|
5134
6312
|
/** Focus leaving the list while an item is picked up cancels the move. */
|
|
5135
6313
|
onFocusOut(event) {
|
|
@@ -5152,17 +6330,39 @@ class SdsSortableList {
|
|
|
5152
6330
|
event.currentTarget.focus({ preventScroll: true });
|
|
5153
6331
|
this.pointerId = event.pointerId;
|
|
5154
6332
|
this.startY = event.clientY;
|
|
6333
|
+
this.lastY = event.clientY;
|
|
5155
6334
|
this.pointerDy.set(0);
|
|
5156
6335
|
this.begin(i, 'pointer');
|
|
6336
|
+
this.startAutoScroll();
|
|
5157
6337
|
}
|
|
5158
6338
|
onPointerMove(event) {
|
|
5159
6339
|
if (this.mode() !== 'pointer' || event.pointerId !== this.pointerId)
|
|
5160
6340
|
return;
|
|
6341
|
+
this.lastY = event.clientY;
|
|
6342
|
+
this.track();
|
|
6343
|
+
}
|
|
6344
|
+
/**
|
|
6345
|
+
* Place the dragged row under the pointer and pick its landing slot. Positions are compared in
|
|
6346
|
+
* drag-start coordinates: the pointer's travel plus however far the list has scrolled since.
|
|
6347
|
+
*/
|
|
6348
|
+
track() {
|
|
5161
6349
|
const a = this.active();
|
|
5162
|
-
if (a === null)
|
|
6350
|
+
if (a === null || !this.rects[a])
|
|
5163
6351
|
return;
|
|
5164
|
-
|
|
6352
|
+
// Keep the row inside the list: it can't be dropped beyond either end, and a row dragged past the
|
|
6353
|
+
// end would grow the scroll area under an auto-scroll that then never stops.
|
|
6354
|
+
const first = this.rects[0];
|
|
6355
|
+
const last = this.rects[this.rects.length - 1];
|
|
6356
|
+
const minDy = first.top - this.rects[a].top;
|
|
6357
|
+
const maxDy = last.top + last.height - (this.rects[a].top + this.rects[a].height);
|
|
6358
|
+
const dy = Math.min(maxDy, Math.max(minDy, this.lastY - this.startY + this.scrolledBy()));
|
|
5165
6359
|
this.pointerDy.set(dy);
|
|
6360
|
+
// Pinned at an end of the list: that end's slot (with equal row heights the centre test below
|
|
6361
|
+
// would stop one short of the last slot).
|
|
6362
|
+
if (dy >= maxDy)
|
|
6363
|
+
return this.target.set(this.rects.length - 1);
|
|
6364
|
+
if (dy <= minDy)
|
|
6365
|
+
return this.target.set(0);
|
|
5166
6366
|
const center = this.rects[a].top + this.rects[a].height / 2 + dy;
|
|
5167
6367
|
let t = 0;
|
|
5168
6368
|
this.rects.forEach((r, j) => {
|
|
@@ -5171,6 +6371,103 @@ class SdsSortableList {
|
|
|
5171
6371
|
});
|
|
5172
6372
|
this.target.set(t);
|
|
5173
6373
|
}
|
|
6374
|
+
/** How far (px) the list has moved up the viewport since the drag began — any ancestor or the window. */
|
|
6375
|
+
scrolledBy() {
|
|
6376
|
+
return this.startHostTop - this.host.nativeElement.getBoundingClientRect().top;
|
|
6377
|
+
}
|
|
6378
|
+
// --- auto-scroll ----------------------------------------------------------------
|
|
6379
|
+
startAutoScroll() {
|
|
6380
|
+
if (!this.autoScroll() || typeof requestAnimationFrame === 'undefined')
|
|
6381
|
+
return;
|
|
6382
|
+
this.stopAutoScroll();
|
|
6383
|
+
const tick = () => {
|
|
6384
|
+
this.frame = null;
|
|
6385
|
+
if (this.mode() !== 'pointer')
|
|
6386
|
+
return;
|
|
6387
|
+
this.scrollNearEdge(this.lastY);
|
|
6388
|
+
// Re-track every frame: auto-scroll, or a wheel/trackpad scroll, moves the list under a still pointer.
|
|
6389
|
+
this.track();
|
|
6390
|
+
this.frame = requestAnimationFrame(tick);
|
|
6391
|
+
};
|
|
6392
|
+
this.frame = requestAnimationFrame(tick);
|
|
6393
|
+
}
|
|
6394
|
+
stopAutoScroll() {
|
|
6395
|
+
if (this.frame !== null)
|
|
6396
|
+
cancelAnimationFrame(this.frame);
|
|
6397
|
+
this.frame = null;
|
|
6398
|
+
}
|
|
6399
|
+
/**
|
|
6400
|
+
* One auto-scroll step for a pointer at `y`: the scroll container first, then the window. A side
|
|
6401
|
+
* only scrolls while part of the list is still hidden past that edge.
|
|
6402
|
+
*/
|
|
6403
|
+
scrollNearEdge(y) {
|
|
6404
|
+
const edge = Math.max(0, this.autoScrollEdge());
|
|
6405
|
+
const view = this.host.nativeElement.ownerDocument.defaultView;
|
|
6406
|
+
const vh = view?.innerHeight ?? 0;
|
|
6407
|
+
const list = this.host.nativeElement.getBoundingClientRect();
|
|
6408
|
+
/** A step toward a side of the band [top, bottom], or 0 when the list doesn't extend past it. */
|
|
6409
|
+
const stepFor = (top, bottom) => {
|
|
6410
|
+
const step = edgeStep(y, top, bottom, edge);
|
|
6411
|
+
if (step < 0 && list.top >= top)
|
|
6412
|
+
return 0;
|
|
6413
|
+
if (step > 0 && list.bottom <= bottom)
|
|
6414
|
+
return 0;
|
|
6415
|
+
return step;
|
|
6416
|
+
};
|
|
6417
|
+
const el = this.scroller;
|
|
6418
|
+
if (el) {
|
|
6419
|
+
const box = el.getBoundingClientRect();
|
|
6420
|
+
const step = stepFor(Math.max(box.top, 0), Math.min(box.bottom, vh));
|
|
6421
|
+
const room = step < 0 ? el.scrollTop : el.scrollHeight - el.clientHeight - el.scrollTop;
|
|
6422
|
+
if (step !== 0 && room > 0.5) {
|
|
6423
|
+
el.scrollTop += step;
|
|
6424
|
+
return true;
|
|
6425
|
+
}
|
|
6426
|
+
}
|
|
6427
|
+
const doc = this.host.nativeElement.ownerDocument.scrollingElement;
|
|
6428
|
+
if (!view || !doc)
|
|
6429
|
+
return false;
|
|
6430
|
+
const step = stepFor(0, vh);
|
|
6431
|
+
const room = step < 0 ? doc.scrollTop : doc.scrollHeight - doc.clientHeight - doc.scrollTop;
|
|
6432
|
+
if (step === 0 || room <= 0.5)
|
|
6433
|
+
return false;
|
|
6434
|
+
view.scrollBy(0, step);
|
|
6435
|
+
return true;
|
|
6436
|
+
}
|
|
6437
|
+
/**
|
|
6438
|
+
* Keyboard move: scroll just enough (container, then window) to keep the moving row in view. Its
|
|
6439
|
+
* resting box comes from drag-start geometry, since its transform may still be animating.
|
|
6440
|
+
*/
|
|
6441
|
+
revealActive() {
|
|
6442
|
+
if (!this.autoScroll())
|
|
6443
|
+
return;
|
|
6444
|
+
afterNextRender(() => {
|
|
6445
|
+
const a = this.active();
|
|
6446
|
+
if (a === null || !this.rects[a] || this.mode() !== 'keyboard')
|
|
6447
|
+
return;
|
|
6448
|
+
const margin = 8;
|
|
6449
|
+
const view = this.host.nativeElement.ownerDocument.defaultView;
|
|
6450
|
+
const vh = view?.innerHeight ?? 0;
|
|
6451
|
+
/** How far the row sticks out of [lo, hi]: negative above, positive below, 0 inside. */
|
|
6452
|
+
const overflow = (lo, hi) => {
|
|
6453
|
+
const top = this.rects[a].top + this.activeOffset() - this.scrolledBy();
|
|
6454
|
+
const bottom = top + this.rects[a].height;
|
|
6455
|
+
return top < lo ? top - lo : bottom > hi ? bottom - hi : 0;
|
|
6456
|
+
};
|
|
6457
|
+
const el = this.scroller;
|
|
6458
|
+
if (el) {
|
|
6459
|
+
const box = el.getBoundingClientRect();
|
|
6460
|
+
const d = overflow(Math.max(box.top, 0) + margin, Math.min(box.bottom, vh) - margin);
|
|
6461
|
+
if (d)
|
|
6462
|
+
el.scrollTop += d;
|
|
6463
|
+
}
|
|
6464
|
+
if (view) {
|
|
6465
|
+
const d = overflow(margin, vh - margin);
|
|
6466
|
+
if (d)
|
|
6467
|
+
view.scrollBy(0, d);
|
|
6468
|
+
}
|
|
6469
|
+
}, { injector: this.injector });
|
|
6470
|
+
}
|
|
5174
6471
|
onPointerUp(event) {
|
|
5175
6472
|
if (this.mode() !== 'pointer' || event.pointerId !== this.pointerId)
|
|
5176
6473
|
return;
|
|
@@ -5183,6 +6480,8 @@ class SdsSortableList {
|
|
|
5183
6480
|
// --- lifecycle of a move -------------------------------------------------------
|
|
5184
6481
|
begin(i, mode) {
|
|
5185
6482
|
this.measure();
|
|
6483
|
+
this.startHostTop = this.host.nativeElement.getBoundingClientRect().top;
|
|
6484
|
+
this.scroller = this.autoScroll() ? scrollParentOf(this.host.nativeElement) : null;
|
|
5186
6485
|
this.active.set(i);
|
|
5187
6486
|
this.target.set(i);
|
|
5188
6487
|
this.mode.set(mode);
|
|
@@ -5223,20 +6522,29 @@ class SdsSortableList {
|
|
|
5223
6522
|
this.focusHandle(to);
|
|
5224
6523
|
}
|
|
5225
6524
|
/** Nothing was moved in the DOM while dragging, so focus is still where it should be. */
|
|
5226
|
-
cancel(announce = true) {
|
|
6525
|
+
cancel(announce = true, reveal = false) {
|
|
5227
6526
|
const from = this.active();
|
|
5228
6527
|
if (from === null)
|
|
5229
6528
|
return;
|
|
6529
|
+
const keyboard = this.mode() === 'keyboard';
|
|
5230
6530
|
this.reset();
|
|
5231
6531
|
if (announce)
|
|
5232
6532
|
this.announce(this.cancelledMessage(), from);
|
|
6533
|
+
// Escape after a keyboard move that scrolled away: bring the row (and its focused handle) back.
|
|
6534
|
+
if (reveal && keyboard && this.autoScroll()) {
|
|
6535
|
+
afterNextRender(() => this.host.nativeElement
|
|
6536
|
+
.querySelector(`[data-sortable-index="${from}"]`)
|
|
6537
|
+
?.scrollIntoView({ block: 'nearest' }), { injector: this.injector });
|
|
6538
|
+
}
|
|
5233
6539
|
}
|
|
5234
6540
|
reset() {
|
|
6541
|
+
this.stopAutoScroll();
|
|
5235
6542
|
this.active.set(null);
|
|
5236
6543
|
this.target.set(null);
|
|
5237
6544
|
this.mode.set(null);
|
|
5238
6545
|
this.pointerDy.set(0);
|
|
5239
6546
|
this.pointerId = null;
|
|
6547
|
+
this.scroller = null;
|
|
5240
6548
|
}
|
|
5241
6549
|
focusHandle(index) {
|
|
5242
6550
|
afterNextRender(() => {
|
|
@@ -5257,7 +6565,7 @@ class SdsSortableList {
|
|
|
5257
6565
|
queueMicrotask(() => this.liveMessage.set(text));
|
|
5258
6566
|
}
|
|
5259
6567
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSortableList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5260
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSortableList, isStandalone: true, selector: "sds-sortable-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, labelField: { classPropertyName: "labelField", publicName: "labelField", isSignal: true, isRequired: false, transformFunction: null }, itemLabel: { classPropertyName: "itemLabel", publicName: "itemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemDisabled: { classPropertyName: "itemDisabled", publicName: "itemDisabled", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, handleLabel: { classPropertyName: "handleLabel", publicName: "handleLabel", isSignal: true, isRequired: false, transformFunction: null }, instructions: { classPropertyName: "instructions", publicName: "instructions", isSignal: true, isRequired: false, transformFunction: null }, pickedUpMessage: { classPropertyName: "pickedUpMessage", publicName: "pickedUpMessage", isSignal: true, isRequired: false, transformFunction: null }, movedMessage: { classPropertyName: "movedMessage", publicName: "movedMessage", isSignal: true, isRequired: false, transformFunction: null }, droppedMessage: { classPropertyName: "droppedMessage", publicName: "droppedMessage", isSignal: true, isRequired: false, transformFunction: null }, cancelledMessage: { classPropertyName: "cancelledMessage", publicName: "cancelledMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { items: "itemsChange", reorder: "reorder" }, host: { classAttribute: "block" }, queries: [{ propertyName: "itemTpl", first: true, predicate: SdsSortableItem, descendants: true, isSignal: true }, { propertyName: "handleTpl", first: true, predicate: SdsSortableHandle, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
6568
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSortableList, isStandalone: true, selector: "sds-sortable-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, labelField: { classPropertyName: "labelField", publicName: "labelField", isSignal: true, isRequired: false, transformFunction: null }, itemLabel: { classPropertyName: "itemLabel", publicName: "itemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemDisabled: { classPropertyName: "itemDisabled", publicName: "itemDisabled", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, autoScroll: { classPropertyName: "autoScroll", publicName: "autoScroll", isSignal: true, isRequired: false, transformFunction: null }, autoScrollEdge: { classPropertyName: "autoScrollEdge", publicName: "autoScrollEdge", isSignal: true, isRequired: false, transformFunction: null }, handleLabel: { classPropertyName: "handleLabel", publicName: "handleLabel", isSignal: true, isRequired: false, transformFunction: null }, instructions: { classPropertyName: "instructions", publicName: "instructions", isSignal: true, isRequired: false, transformFunction: null }, pickedUpMessage: { classPropertyName: "pickedUpMessage", publicName: "pickedUpMessage", isSignal: true, isRequired: false, transformFunction: null }, movedMessage: { classPropertyName: "movedMessage", publicName: "movedMessage", isSignal: true, isRequired: false, transformFunction: null }, droppedMessage: { classPropertyName: "droppedMessage", publicName: "droppedMessage", isSignal: true, isRequired: false, transformFunction: null }, cancelledMessage: { classPropertyName: "cancelledMessage", publicName: "cancelledMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { items: "itemsChange", reorder: "reorder" }, host: { classAttribute: "block" }, queries: [{ propertyName: "itemTpl", first: true, predicate: SdsSortableItem, descendants: true, isSignal: true }, { propertyName: "handleTpl", first: true, predicate: SdsSortableHandle, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
5261
6569
|
<ul
|
|
5262
6570
|
role="list"
|
|
5263
6571
|
[attr.aria-label]="ariaLabel() || null"
|
|
@@ -5380,7 +6688,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
5380
6688
|
<div class="sr-only" aria-live="assertive" aria-atomic="true">{{ liveMessage() }}</div>
|
|
5381
6689
|
`,
|
|
5382
6690
|
}]
|
|
5383
|
-
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }, { type: i0.Output, args: ["itemsChange"] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], labelField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelField", required: false }] }], itemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemLabel", required: false }] }], itemDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDisabled", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], handleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "handleLabel", required: false }] }], instructions: [{ type: i0.Input, args: [{ isSignal: true, alias: "instructions", required: false }] }], pickedUpMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickedUpMessage", required: false }] }], movedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "movedMessage", required: false }] }], droppedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "droppedMessage", required: false }] }], cancelledMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelledMessage", required: false }] }], reorder: [{ type: i0.Output, args: ["reorder"] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableItem), { isSignal: true }] }], handleTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableHandle), { isSignal: true }] }] } });
|
|
6691
|
+
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }, { type: i0.Output, args: ["itemsChange"] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], labelField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelField", required: false }] }], itemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemLabel", required: false }] }], itemDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDisabled", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], autoScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoScroll", required: false }] }], autoScrollEdge: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoScrollEdge", required: false }] }], handleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "handleLabel", required: false }] }], instructions: [{ type: i0.Input, args: [{ isSignal: true, alias: "instructions", required: false }] }], pickedUpMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickedUpMessage", required: false }] }], movedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "movedMessage", required: false }] }], droppedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "droppedMessage", required: false }] }], cancelledMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelledMessage", required: false }] }], reorder: [{ type: i0.Output, args: ["reorder"] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableItem), { isSignal: true }] }], handleTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableHandle), { isSignal: true }] }] } });
|
|
5384
6692
|
|
|
5385
6693
|
let nextId$9 = 0;
|
|
5386
6694
|
/** "1.5 MB" style size (decimal units, like file managers show them), for messages. */
|
|
@@ -6282,41 +7590,41 @@ class SdsCalendar {
|
|
|
6282
7590
|
max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : []));
|
|
6283
7591
|
/** 0 = Sunday, 1 = Monday (default, European). */
|
|
6284
7592
|
firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : []));
|
|
6285
|
-
locale
|
|
7593
|
+
/** BCP 47 locale for month and weekday names. Defaults to `en-GB`; pass the app's locale. */
|
|
7594
|
+
locale = input('en-GB', ...(ngDevMode ? [{ debugName: "locale" }] : []));
|
|
6286
7595
|
showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions" }] : []));
|
|
6287
7596
|
/** When true, a time editor (HH:mm, 24h) is shown and the value keeps its time-of-day. */
|
|
6288
7597
|
showTime = input(false, ...(ngDevMode ? [{ debugName: "showTime", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
6289
7598
|
/** When true, a "done" action is shown (used by the overlay picker to close the panel). */
|
|
6290
7599
|
showDone = input(false, ...(ngDevMode ? [{ debugName: "showDone", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
6291
7600
|
/** Visible label of the time editor. Translate it in the consuming app. */
|
|
6292
|
-
timeLabel = input('
|
|
7601
|
+
timeLabel = input('Time', ...(ngDevMode ? [{ debugName: "timeLabel" }] : []));
|
|
6293
7602
|
/** Accessible name of the hours field (it is a bare numeric input). */
|
|
6294
|
-
hoursLabel = input('
|
|
7603
|
+
hoursLabel = input('Hours', ...(ngDevMode ? [{ debugName: "hoursLabel" }] : []));
|
|
6295
7604
|
/** Accessible name of the minutes field. */
|
|
6296
7605
|
minutesLabel = input('Minutes', ...(ngDevMode ? [{ debugName: "minutesLabel" }] : []));
|
|
6297
7606
|
/** Visible text of the "done" action (shown when {@link showDone} is true). */
|
|
6298
|
-
doneLabel = input('
|
|
7607
|
+
doneLabel = input('Done', ...(ngDevMode ? [{ debugName: "doneLabel" }] : []));
|
|
6299
7608
|
/**
|
|
6300
|
-
* Accessible name for the calendar container.
|
|
6301
|
-
*
|
|
7609
|
+
* Accessible name for the calendar container. English default; an app serving more than one
|
|
7610
|
+
* language MUST translate it.
|
|
6302
7611
|
*/
|
|
6303
|
-
calendarLabel = input('
|
|
7612
|
+
calendarLabel = input('Calendar', ...(ngDevMode ? [{ debugName: "calendarLabel" }] : []));
|
|
6304
7613
|
/**
|
|
6305
7614
|
* Accessible name for the "previous" nav button. It is icon-only, so this string is its ONLY
|
|
6306
|
-
* accessible name
|
|
6307
|
-
* the consuming app.
|
|
7615
|
+
* accessible name. English default; translate it in the consuming app.
|
|
6308
7616
|
*/
|
|
6309
|
-
previousLabel = input('
|
|
7617
|
+
previousLabel = input('Previous', ...(ngDevMode ? [{ debugName: "previousLabel" }] : []));
|
|
6310
7618
|
/** Accessible name for the icon-only "next" nav button. See {@link previousLabel}. */
|
|
6311
|
-
nextLabel = input('
|
|
7619
|
+
nextLabel = input('Next', ...(ngDevMode ? [{ debugName: "nextLabel" }] : []));
|
|
6312
7620
|
/**
|
|
6313
7621
|
* Visible text of the "today" action (shown when {@link showActions} is true). Translate it in the
|
|
6314
7622
|
* consuming app — the library ships no i18n of its own.
|
|
6315
7623
|
*/
|
|
6316
|
-
todayActionLabel = input(
|
|
7624
|
+
todayActionLabel = input('Today', ...(ngDevMode ? [{ debugName: "todayActionLabel" }] : []));
|
|
6317
7625
|
/** Visible text of the "clear" action. See {@link todayActionLabel}. */
|
|
6318
|
-
clearActionLabel = input('
|
|
6319
|
-
/** Emitted when a concrete date is picked (day click or "
|
|
7626
|
+
clearActionLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearActionLabel" }] : []));
|
|
7627
|
+
/** Emitted when a concrete date is picked (day click or "Today"). */
|
|
6320
7628
|
dateSelect = output();
|
|
6321
7629
|
/** Emitted when the "done" action is used (see {@link showDone}). */
|
|
6322
7630
|
done = output();
|
|
@@ -7079,7 +8387,7 @@ const SIZES$5 = {
|
|
|
7079
8387
|
* [(ngModel)]; the value is a `Date | null`.
|
|
7080
8388
|
*
|
|
7081
8389
|
* @example
|
|
7082
|
-
* <sds-date-picker label="
|
|
8390
|
+
* <sds-date-picker label="Delivery date" [(ngModel)]="date" />
|
|
7083
8391
|
*/
|
|
7084
8392
|
class SdsDatePicker {
|
|
7085
8393
|
host = inject(ElementRef);
|
|
@@ -7087,14 +8395,18 @@ class SdsDatePicker {
|
|
|
7087
8395
|
fieldId = `sds-date-${nextId$7++}`;
|
|
7088
8396
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
7089
8397
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
7090
|
-
placeholder = input('
|
|
8398
|
+
placeholder = input('dd/mm/yyyy', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
7091
8399
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
7092
8400
|
error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
7093
8401
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
7094
8402
|
min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : []));
|
|
7095
8403
|
max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : []));
|
|
7096
8404
|
firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : []));
|
|
7097
|
-
|
|
8405
|
+
/**
|
|
8406
|
+
* BCP 47 locale for the calendar's month and weekday names. Defaults to `en-GB` (English names, and
|
|
8407
|
+
* the same day-first order as the default dd/MM/yyyy display); pass the app's locale.
|
|
8408
|
+
*/
|
|
8409
|
+
locale = input('en-GB', ...(ngDevMode ? [{ debugName: "locale" }] : []));
|
|
7098
8410
|
inline = input(false, ...(ngDevMode ? [{ debugName: "inline", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
7099
8411
|
clearable = input(true, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
7100
8412
|
showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
@@ -7108,38 +8420,37 @@ class SdsDatePicker {
|
|
|
7108
8420
|
/** Custom display formatter for the DATE part (default dd/MM/yyyy). The time is appended as HH:mm. */
|
|
7109
8421
|
format = input(formatDdMmYyyy, ...(ngDevMode ? [{ debugName: "format" }] : []));
|
|
7110
8422
|
/** Visible label of the time editor (forwarded to the calendar). See {@link showTime}. */
|
|
7111
|
-
timeLabel = input('
|
|
8423
|
+
timeLabel = input('Time', ...(ngDevMode ? [{ debugName: "timeLabel" }] : []));
|
|
7112
8424
|
/** Accessible name of the hours field (forwarded to the calendar). */
|
|
7113
|
-
hoursLabel = input('
|
|
8425
|
+
hoursLabel = input('Hours', ...(ngDevMode ? [{ debugName: "hoursLabel" }] : []));
|
|
7114
8426
|
/** Accessible name of the minutes field (forwarded to the calendar). */
|
|
7115
8427
|
minutesLabel = input('Minutes', ...(ngDevMode ? [{ debugName: "minutesLabel" }] : []));
|
|
7116
8428
|
/** Visible text of the calendar's "done" action, shown in the overlay when {@link showTime}. */
|
|
7117
|
-
doneLabel = input('
|
|
8429
|
+
doneLabel = input('Done', ...(ngDevMode ? [{ debugName: "doneLabel" }] : []));
|
|
7118
8430
|
/**
|
|
7119
|
-
* Accessible name for the clear button.
|
|
7120
|
-
*
|
|
7121
|
-
* is its only name.
|
|
8431
|
+
* Accessible name for the clear button. English default; an app serving more than one language MUST
|
|
8432
|
+
* translate it — it is an icon-only control, so this string is its only name.
|
|
7122
8433
|
*/
|
|
7123
|
-
clearLabel = input('
|
|
8434
|
+
clearLabel = input('Clear date', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
7124
8435
|
/**
|
|
7125
8436
|
* Accessible name for the icon-only calendar toggle while the panel is CLOSED. See
|
|
7126
8437
|
* {@link clearLabel} for why this has to be translatable.
|
|
7127
8438
|
*/
|
|
7128
|
-
openCalendarLabel = input('
|
|
8439
|
+
openCalendarLabel = input('Open calendar', ...(ngDevMode ? [{ debugName: "openCalendarLabel" }] : []));
|
|
7129
8440
|
/** Accessible name for the calendar toggle while the panel is OPEN. See {@link openCalendarLabel}. */
|
|
7130
|
-
closeCalendarLabel = input('
|
|
8441
|
+
closeCalendarLabel = input('Close calendar', ...(ngDevMode ? [{ debugName: "closeCalendarLabel" }] : []));
|
|
7131
8442
|
/** Accessible name for the overlay dialog that holds the calendar. */
|
|
7132
|
-
panelLabel = input('
|
|
8443
|
+
panelLabel = input('Choose a date', ...(ngDevMode ? [{ debugName: "panelLabel" }] : []));
|
|
7133
8444
|
/**
|
|
7134
8445
|
* Labels forwarded to the embedded <sds-calendar>. They live here because the picker is how the
|
|
7135
8446
|
* calendar is normally reached — without forwarding, a consumer could translate the field but not
|
|
7136
8447
|
* the panel it opens. Defaults match SdsCalendar's own, so nothing changes for existing consumers.
|
|
7137
8448
|
*/
|
|
7138
|
-
calendarLabel = input('
|
|
7139
|
-
previousLabel = input('
|
|
7140
|
-
nextLabel = input('
|
|
7141
|
-
todayActionLabel = input(
|
|
7142
|
-
clearActionLabel = input('
|
|
8449
|
+
calendarLabel = input('Calendar', ...(ngDevMode ? [{ debugName: "calendarLabel" }] : []));
|
|
8450
|
+
previousLabel = input('Previous', ...(ngDevMode ? [{ debugName: "previousLabel" }] : []));
|
|
8451
|
+
nextLabel = input('Next', ...(ngDevMode ? [{ debugName: "nextLabel" }] : []));
|
|
8452
|
+
todayActionLabel = input('Today', ...(ngDevMode ? [{ debugName: "todayActionLabel" }] : []));
|
|
8453
|
+
clearActionLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearActionLabel" }] : []));
|
|
7143
8454
|
value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
7144
8455
|
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
7145
8456
|
cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
|
|
@@ -7705,7 +9016,7 @@ let nextId$6 = 0;
|
|
|
7705
9016
|
*
|
|
7706
9017
|
* @example
|
|
7707
9018
|
* <sds-select [options]="services" optionLabel="name" optionValue="id"
|
|
7708
|
-
* placeholder="
|
|
9019
|
+
* placeholder="Choose a service" [(ngModel)]="serviceId" filter clearable />
|
|
7709
9020
|
*
|
|
7710
9021
|
* @example
|
|
7711
9022
|
* <sds-select [options]="categories" optionLabel="name" optionValue="id" [(ngModel)]="categoryId">
|
|
@@ -7725,7 +9036,7 @@ class SdsSelect {
|
|
|
7725
9036
|
optionDisabled = input('disabled', ...(ngDevMode ? [{ debugName: "optionDisabled" }] : []));
|
|
7726
9037
|
/** Key used to compare object values for selection equality. */
|
|
7727
9038
|
dataKey = input('', ...(ngDevMode ? [{ debugName: "dataKey" }] : []));
|
|
7728
|
-
placeholder = input('
|
|
9039
|
+
placeholder = input('Select…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
7729
9040
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
7730
9041
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
7731
9042
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
@@ -7735,8 +9046,15 @@ class SdsSelect {
|
|
|
7735
9046
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
7736
9047
|
clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
7737
9048
|
filter = input(false, ...(ngDevMode ? [{ debugName: "filter", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
7738
|
-
filterPlaceholder = input('
|
|
7739
|
-
emptyMessage = input('
|
|
9049
|
+
filterPlaceholder = input('Search…', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : []));
|
|
9050
|
+
emptyMessage = input('No results', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
|
|
9051
|
+
/**
|
|
9052
|
+
* Accessible name of the icon-only clear button (see {@link clearable}). English default; an app
|
|
9053
|
+
* serving more than one language passes a translated value — it is the button's only name.
|
|
9054
|
+
*/
|
|
9055
|
+
clearLabel = input('Clear selection', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
9056
|
+
/** Accessible name of the filter field inside the panel (see {@link filter}). */
|
|
9057
|
+
filterLabel = input('Search', ...(ngDevMode ? [{ debugName: "filterLabel" }] : []));
|
|
7740
9058
|
/** Optional projected `<ng-template sdsSelectOption>` — custom option + selected-value rendering. */
|
|
7741
9059
|
optionTpl = contentChild(SdsSelectOption, ...(ngDevMode ? [{ debugName: "optionTpl" }] : []));
|
|
7742
9060
|
/** Optional projected `<ng-template sdsSelectEmpty>` — custom no-results content. */
|
|
@@ -8092,7 +9410,7 @@ class SdsSelect {
|
|
|
8092
9410
|
this.close();
|
|
8093
9411
|
}
|
|
8094
9412
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8095
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSelect, isStandalone: true, selector: "sds-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, 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 }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
|
|
9413
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSelect, isStandalone: true, selector: "sds-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, 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 }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, filterLabel: { classPropertyName: "filterLabel", publicName: "filterLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
|
|
8096
9414
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsSelect), multi: true },
|
|
8097
9415
|
], queries: [{ propertyName: "optionTpl", first: true, predicate: SdsSelectOption, descendants: true, isSignal: true }, { propertyName: "emptyTpl", first: true, predicate: SdsSelectEmpty, descendants: true, isSignal: true }, { propertyName: "footerTpl", first: true, predicate: SdsSelectFooter, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
8098
9416
|
@if (label()) {
|
|
@@ -8137,7 +9455,7 @@ class SdsSelect {
|
|
|
8137
9455
|
<button
|
|
8138
9456
|
type="button"
|
|
8139
9457
|
tabindex="-1"
|
|
8140
|
-
aria-label="
|
|
9458
|
+
[attr.aria-label]="clearLabel()"
|
|
8141
9459
|
class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
|
|
8142
9460
|
(click)="clear($event)"
|
|
8143
9461
|
>
|
|
@@ -8170,7 +9488,7 @@ class SdsSelect {
|
|
|
8170
9488
|
[value]="filterText()"
|
|
8171
9489
|
(input)="onFilter($event)"
|
|
8172
9490
|
(keydown)="onFilterKeydown($event)"
|
|
8173
|
-
aria-label="
|
|
9491
|
+
[attr.aria-label]="filterLabel()"
|
|
8174
9492
|
class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
|
|
8175
9493
|
/>
|
|
8176
9494
|
</div>
|
|
@@ -8293,7 +9611,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
8293
9611
|
<button
|
|
8294
9612
|
type="button"
|
|
8295
9613
|
tabindex="-1"
|
|
8296
|
-
aria-label="
|
|
9614
|
+
[attr.aria-label]="clearLabel()"
|
|
8297
9615
|
class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
|
|
8298
9616
|
(click)="clear($event)"
|
|
8299
9617
|
>
|
|
@@ -8326,7 +9644,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
8326
9644
|
[value]="filterText()"
|
|
8327
9645
|
(input)="onFilter($event)"
|
|
8328
9646
|
(keydown)="onFilterKeydown($event)"
|
|
8329
|
-
aria-label="
|
|
9647
|
+
[attr.aria-label]="filterLabel()"
|
|
8330
9648
|
class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
|
|
8331
9649
|
/>
|
|
8332
9650
|
</div>
|
|
@@ -8393,7 +9711,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
8393
9711
|
}
|
|
8394
9712
|
`,
|
|
8395
9713
|
}]
|
|
8396
|
-
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", 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 }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
|
|
9714
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", 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 }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], filterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLabel", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
|
|
8397
9715
|
|
|
8398
9716
|
const SIZES$3 = {
|
|
8399
9717
|
sm: 'min-h-9 text-sm',
|
|
@@ -8440,7 +9758,7 @@ class SdsMultiSelect {
|
|
|
8440
9758
|
optionValue = input('', ...(ngDevMode ? [{ debugName: "optionValue" }] : []));
|
|
8441
9759
|
optionDisabled = input('disabled', ...(ngDevMode ? [{ debugName: "optionDisabled" }] : []));
|
|
8442
9760
|
dataKey = input('', ...(ngDevMode ? [{ debugName: "dataKey" }] : []));
|
|
8443
|
-
placeholder = input('
|
|
9761
|
+
placeholder = input('Select…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
8444
9762
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
8445
9763
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
8446
9764
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
@@ -8449,13 +9767,24 @@ class SdsMultiSelect {
|
|
|
8449
9767
|
display = input('comma', ...(ngDevMode ? [{ debugName: "display" }] : []));
|
|
8450
9768
|
/** In comma mode, show a count label once more than this many are selected. */
|
|
8451
9769
|
maxSelectedLabels = input(3, ...(ngDevMode ? [{ debugName: "maxSelectedLabels", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
8452
|
-
selectedItemsLabel = input('{0}
|
|
9770
|
+
selectedItemsLabel = input('{0} items selected', ...(ngDevMode ? [{ debugName: "selectedItemsLabel" }] : []));
|
|
8453
9771
|
showToggleAll = input(true, ...(ngDevMode ? [{ debugName: "showToggleAll", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
8454
9772
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
8455
9773
|
clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
8456
9774
|
filter = input(false, ...(ngDevMode ? [{ debugName: "filter", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
8457
|
-
filterPlaceholder = input('
|
|
8458
|
-
emptyMessage = input('
|
|
9775
|
+
filterPlaceholder = input('Search…', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : []));
|
|
9776
|
+
emptyMessage = input('No results', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
|
|
9777
|
+
/**
|
|
9778
|
+
* Accessible name of a chip's icon-only remove button (`display="chip"`); `{label}` is the option's
|
|
9779
|
+
* label. English defaults throughout — an app serving more than one language passes translations.
|
|
9780
|
+
*/
|
|
9781
|
+
removeLabel = input('Remove {label}', ...(ngDevMode ? [{ debugName: "removeLabel" }] : []));
|
|
9782
|
+
/** Accessible name of the icon-only clear-all button (see {@link clearable}). */
|
|
9783
|
+
clearLabel = input('Clear all', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
9784
|
+
/** Accessible name of the filter field inside the panel (see {@link filter}). */
|
|
9785
|
+
filterLabel = input('Search', ...(ngDevMode ? [{ debugName: "filterLabel" }] : []));
|
|
9786
|
+
/** Visible text of the "select all" row (see {@link showToggleAll}). */
|
|
9787
|
+
selectAllLabel = input('Select all', ...(ngDevMode ? [{ debugName: "selectAllLabel" }] : []));
|
|
8459
9788
|
/** Optional projected `<ng-template sdsSelectOption>` — custom option-row rendering. */
|
|
8460
9789
|
optionTpl = contentChild(SdsSelectOption, ...(ngDevMode ? [{ debugName: "optionTpl" }] : []));
|
|
8461
9790
|
/** Optional projected `<ng-template sdsSelectEmpty>` — custom no-results content. */
|
|
@@ -8855,7 +10184,7 @@ class SdsMultiSelect {
|
|
|
8855
10184
|
this.close();
|
|
8856
10185
|
}
|
|
8857
10186
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsMultiSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8858
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsMultiSelect, isStandalone: true, selector: "sds-multi-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, 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 }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, maxSelectedLabels: { classPropertyName: "maxSelectedLabels", publicName: "maxSelectedLabels", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsLabel: { classPropertyName: "selectedItemsLabel", publicName: "selectedItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, showToggleAll: { classPropertyName: "showToggleAll", publicName: "showToggleAll", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
|
|
10187
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsMultiSelect, isStandalone: true, selector: "sds-multi-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, 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 }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, maxSelectedLabels: { classPropertyName: "maxSelectedLabels", publicName: "maxSelectedLabels", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsLabel: { classPropertyName: "selectedItemsLabel", publicName: "selectedItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, showToggleAll: { classPropertyName: "showToggleAll", publicName: "showToggleAll", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, filterLabel: { classPropertyName: "filterLabel", publicName: "filterLabel", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
|
|
8859
10188
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsMultiSelect), multi: true },
|
|
8860
10189
|
], queries: [{ propertyName: "optionTpl", first: true, predicate: SdsSelectOption, descendants: true, isSignal: true }, { propertyName: "emptyTpl", first: true, predicate: SdsSelectEmpty, descendants: true, isSignal: true }, { propertyName: "footerTpl", first: true, predicate: SdsSelectFooter, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
8861
10190
|
@if (label()) {
|
|
@@ -8888,7 +10217,7 @@ class SdsMultiSelect {
|
|
|
8888
10217
|
<button
|
|
8889
10218
|
type="button"
|
|
8890
10219
|
tabindex="-1"
|
|
8891
|
-
[attr.aria-label]="'
|
|
10220
|
+
[attr.aria-label]="removeLabel().replace('{label}', opt.label)"
|
|
8892
10221
|
class="inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-brand-100"
|
|
8893
10222
|
(click)="removeChip($event, opt)"
|
|
8894
10223
|
>
|
|
@@ -8910,7 +10239,7 @@ class SdsMultiSelect {
|
|
|
8910
10239
|
<button
|
|
8911
10240
|
type="button"
|
|
8912
10241
|
tabindex="-1"
|
|
8913
|
-
aria-label="
|
|
10242
|
+
[attr.aria-label]="clearLabel()"
|
|
8914
10243
|
class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center self-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
|
|
8915
10244
|
(click)="clear($event)"
|
|
8916
10245
|
>
|
|
@@ -8943,7 +10272,7 @@ class SdsMultiSelect {
|
|
|
8943
10272
|
[value]="filterText()"
|
|
8944
10273
|
(input)="onFilter($event)"
|
|
8945
10274
|
(keydown)="onFilterKeydown($event)"
|
|
8946
|
-
aria-label="
|
|
10275
|
+
[attr.aria-label]="filterLabel()"
|
|
8947
10276
|
class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
|
|
8948
10277
|
/>
|
|
8949
10278
|
</div>
|
|
@@ -8969,7 +10298,7 @@ class SdsMultiSelect {
|
|
|
8969
10298
|
<span class="h-0.5 w-2.5 rounded-full bg-white"></span>
|
|
8970
10299
|
}
|
|
8971
10300
|
</span>
|
|
8972
|
-
|
|
10301
|
+
{{ selectAllLabel() }}
|
|
8973
10302
|
</button>
|
|
8974
10303
|
}
|
|
8975
10304
|
|
|
@@ -9079,7 +10408,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9079
10408
|
<button
|
|
9080
10409
|
type="button"
|
|
9081
10410
|
tabindex="-1"
|
|
9082
|
-
[attr.aria-label]="'
|
|
10411
|
+
[attr.aria-label]="removeLabel().replace('{label}', opt.label)"
|
|
9083
10412
|
class="inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-brand-100"
|
|
9084
10413
|
(click)="removeChip($event, opt)"
|
|
9085
10414
|
>
|
|
@@ -9101,7 +10430,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9101
10430
|
<button
|
|
9102
10431
|
type="button"
|
|
9103
10432
|
tabindex="-1"
|
|
9104
|
-
aria-label="
|
|
10433
|
+
[attr.aria-label]="clearLabel()"
|
|
9105
10434
|
class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center self-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
|
|
9106
10435
|
(click)="clear($event)"
|
|
9107
10436
|
>
|
|
@@ -9134,7 +10463,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9134
10463
|
[value]="filterText()"
|
|
9135
10464
|
(input)="onFilter($event)"
|
|
9136
10465
|
(keydown)="onFilterKeydown($event)"
|
|
9137
|
-
aria-label="
|
|
10466
|
+
[attr.aria-label]="filterLabel()"
|
|
9138
10467
|
class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
|
|
9139
10468
|
/>
|
|
9140
10469
|
</div>
|
|
@@ -9160,7 +10489,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9160
10489
|
<span class="h-0.5 w-2.5 rounded-full bg-white"></span>
|
|
9161
10490
|
}
|
|
9162
10491
|
</span>
|
|
9163
|
-
|
|
10492
|
+
{{ selectAllLabel() }}
|
|
9164
10493
|
</button>
|
|
9165
10494
|
}
|
|
9166
10495
|
|
|
@@ -9226,29 +10555,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9226
10555
|
}
|
|
9227
10556
|
`,
|
|
9228
10557
|
}]
|
|
9229
|
-
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", 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 }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], maxSelectedLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelectedLabels", required: false }] }], selectedItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsLabel", required: false }] }], showToggleAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggleAll", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
|
|
10558
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", 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 }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], maxSelectedLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelectedLabels", required: false }] }], selectedItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsLabel", required: false }] }], showToggleAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggleAll", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], filterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLabel", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
|
|
9230
10559
|
|
|
9231
10560
|
const SDS_PHONE_COUNTRIES = [
|
|
9232
|
-
{ iso2: 'BE', name: '
|
|
10561
|
+
{ iso2: 'BE', name: 'Belgium', dialCode: '32', lengths: [9], format: '### ## ## ##', example: '470123456' },
|
|
9233
10562
|
{ iso2: 'FR', name: 'France', dialCode: '33', lengths: [9], format: '# ## ## ## ##', example: '612345678' },
|
|
9234
10563
|
{ iso2: 'LU', name: 'Luxembourg', dialCode: '352', lengths: [9, 8, 6], format: '### ### ###', example: '628123456' },
|
|
9235
|
-
{ iso2: 'NL', name: '
|
|
9236
|
-
{ iso2: 'DE', name: '
|
|
9237
|
-
{ iso2: 'GB', name: '
|
|
9238
|
-
{ iso2: 'IE', name: '
|
|
9239
|
-
{ iso2: 'CH', name: '
|
|
9240
|
-
{ iso2: 'ES', name: '
|
|
9241
|
-
{ iso2: 'IT', name: '
|
|
10564
|
+
{ iso2: 'NL', name: 'Netherlands', dialCode: '31', lengths: [9], format: '# ## ## ## ##', example: '612345678' },
|
|
10565
|
+
{ iso2: 'DE', name: 'Germany', dialCode: '49', lengths: [10, 11], format: '#### #######', example: '15123456789' },
|
|
10566
|
+
{ iso2: 'GB', name: 'United Kingdom', dialCode: '44', lengths: [10], format: '#### ######', example: '7400123456' },
|
|
10567
|
+
{ iso2: 'IE', name: 'Ireland', dialCode: '353', lengths: [9], format: '## ### ####', example: '850123456' },
|
|
10568
|
+
{ iso2: 'CH', name: 'Switzerland', dialCode: '41', lengths: [9], format: '## ### ## ##', example: '781234567' },
|
|
10569
|
+
{ iso2: 'ES', name: 'Spain', dialCode: '34', lengths: [9], format: '### ## ## ##', example: '612345678' },
|
|
10570
|
+
{ iso2: 'IT', name: 'Italy', dialCode: '39', lengths: [9, 10], format: '### ### ####', example: '3123456789' },
|
|
9242
10571
|
{ iso2: 'PT', name: 'Portugal', dialCode: '351', lengths: [9], format: '### ### ###', example: '912345678' },
|
|
9243
|
-
{ iso2: 'AT', name: '
|
|
9244
|
-
{ iso2: 'DK', name: '
|
|
9245
|
-
{ iso2: 'SE', name: '
|
|
9246
|
-
{ iso2: 'NO', name: '
|
|
9247
|
-
{ iso2: 'PL', name: '
|
|
9248
|
-
{ iso2: 'US', name: '
|
|
10572
|
+
{ iso2: 'AT', name: 'Austria', dialCode: '43', lengths: [10, 11], format: '### #######', example: '6641234567' },
|
|
10573
|
+
{ iso2: 'DK', name: 'Denmark', dialCode: '45', lengths: [8], format: '## ## ## ##', example: '20123456' },
|
|
10574
|
+
{ iso2: 'SE', name: 'Sweden', dialCode: '46', lengths: [9], format: '## ### ## ##', example: '701234567' },
|
|
10575
|
+
{ iso2: 'NO', name: 'Norway', dialCode: '47', lengths: [8], format: '### ## ###', example: '40612345' },
|
|
10576
|
+
{ iso2: 'PL', name: 'Poland', dialCode: '48', lengths: [9], format: '### ### ###', example: '512345678' },
|
|
10577
|
+
{ iso2: 'US', name: 'United States', dialCode: '1', lengths: [10], format: '(###) ###-####', example: '2015550123' },
|
|
9249
10578
|
{ iso2: 'CA', name: 'Canada', dialCode: '1', lengths: [10], format: '(###) ###-####', example: '2042345678' },
|
|
9250
|
-
{ iso2: 'MA', name: '
|
|
9251
|
-
{ iso2: 'TR', name: '
|
|
10579
|
+
{ iso2: 'MA', name: 'Morocco', dialCode: '212', lengths: [9], format: '### ## ## ##', example: '612345678' },
|
|
10580
|
+
{ iso2: 'TR', name: 'Turkey', dialCode: '90', lengths: [10], format: '### ### ## ##', example: '5012345678' },
|
|
9252
10581
|
];
|
|
9253
10582
|
/** Reduce raw input to national-significant digits (drops non-digits & leading trunk zeros). */
|
|
9254
10583
|
function sdsNormalizeSignificant(raw) {
|
|
@@ -9303,7 +10632,7 @@ let nextId$4 = 0;
|
|
|
9303
10632
|
* '+32470123456') and Validator (national length is checked per country).
|
|
9304
10633
|
*
|
|
9305
10634
|
* @example
|
|
9306
|
-
* <sds-phone-input label="
|
|
10635
|
+
* <sds-phone-input label="Phone" defaultCountry="BE"
|
|
9307
10636
|
* [preferredCountries]="['BE','FR','LU']"
|
|
9308
10637
|
* [(ngModel)]="phone" required />
|
|
9309
10638
|
*/
|
|
@@ -9328,43 +10657,67 @@ class SdsPhoneInput {
|
|
|
9328
10657
|
onlyCountries = input([], ...(ngDevMode ? [{ debugName: "onlyCountries" }] : []));
|
|
9329
10658
|
/** Show an example number as a hint when no [hint] is provided. */
|
|
9330
10659
|
showExampleHint = input(true, ...(ngDevMode ? [{ debugName: "showExampleHint", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
9331
|
-
|
|
10660
|
+
/**
|
|
10661
|
+
* BCP 47 locale for the country names (list, search and the selector's accessible name), resolved
|
|
10662
|
+
* with `Intl.DisplayNames` — e.g. `nl-BE` shows "België". Empty (default) uses the built-in English
|
|
10663
|
+
* names. The search also matches the English name.
|
|
10664
|
+
*/
|
|
10665
|
+
locale = input('', ...(ngDevMode ? [{ debugName: "locale" }] : []));
|
|
10666
|
+
requiredMessage = input('Phone number required', ...(ngDevMode ? [{ debugName: "requiredMessage" }] : []));
|
|
9332
10667
|
/**
|
|
9333
10668
|
* Accessible name of the country selector. `{country}` is replaced with the selected country's
|
|
9334
|
-
* name. A token rather than a prefix because word order differs per
|
|
9335
|
-
*
|
|
9336
|
-
*
|
|
9337
|
-
* Note the interpolated country NAME still comes from the library's built-in country table, which
|
|
9338
|
-
* is French-only — translating this template fixes the wrapper, not the name inside it.
|
|
10669
|
+
* name (localised by {@link locale}). A token rather than a prefix because word order differs per
|
|
10670
|
+
* language. English default; translate it in any app serving more than one language.
|
|
9339
10671
|
*/
|
|
9340
|
-
countryLabel = input('
|
|
10672
|
+
countryLabel = input('Country code: {country}', ...(ngDevMode ? [{ debugName: "countryLabel" }] : []));
|
|
9341
10673
|
/**
|
|
9342
10674
|
* Accessible name for the clear button. It is icon-only, so this string is its ONLY accessible
|
|
9343
|
-
* name —
|
|
10675
|
+
* name — translate it in any app serving more than one language.
|
|
9344
10676
|
*/
|
|
9345
|
-
clearLabel = input('
|
|
10677
|
+
clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
9346
10678
|
/** Accessible name for the country-search field inside the dropdown. */
|
|
9347
|
-
searchLabel = input('
|
|
10679
|
+
searchLabel = input('Search countries', ...(ngDevMode ? [{ debugName: "searchLabel" }] : []));
|
|
9348
10680
|
/** Placeholder text of the country-search field. */
|
|
9349
|
-
searchPlaceholder = input('
|
|
10681
|
+
searchPlaceholder = input('Search countries…', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
|
|
9350
10682
|
/** Shown in place of the list when no country matches the filter. */
|
|
9351
|
-
noResultsLabel = input('
|
|
10683
|
+
noResultsLabel = input('No countries found', ...(ngDevMode ? [{ debugName: "noResultsLabel" }] : []));
|
|
9352
10684
|
/**
|
|
9353
10685
|
* Built-in validation messages. `{lengths}` is replaced with the country's accepted national
|
|
9354
|
-
* lengths, joined with {@link lengthSeparator}.
|
|
9355
|
-
*
|
|
10686
|
+
* lengths, joined with {@link lengthSeparator}. English defaults; translate them alongside
|
|
10687
|
+
* {@link requiredMessage}.
|
|
9356
10688
|
*/
|
|
9357
|
-
incompleteMessage = input('
|
|
9358
|
-
invalidMessage = input('
|
|
9359
|
-
/** Joins the accepted lengths when a country allows more than one (e.g. "8
|
|
9360
|
-
lengthSeparator = input('
|
|
10689
|
+
incompleteMessage = input('Incomplete number — {lengths} digits expected', ...(ngDevMode ? [{ debugName: "incompleteMessage" }] : []));
|
|
10690
|
+
invalidMessage = input('Invalid number — {lengths} digits expected', ...(ngDevMode ? [{ debugName: "invalidMessage" }] : []));
|
|
10691
|
+
/** Joins the accepted lengths when a country allows more than one (e.g. "8 or 9"). */
|
|
10692
|
+
lengthSeparator = input(' or ', ...(ngDevMode ? [{ debugName: "lengthSeparator" }] : []));
|
|
9361
10693
|
/**
|
|
9362
10694
|
* Auto-generated example hint (see {@link showExampleHint}). `{number}` is replaced with the
|
|
9363
10695
|
* formatted international example number.
|
|
9364
10696
|
*/
|
|
9365
|
-
exampleHintTemplate = input('
|
|
10697
|
+
exampleHintTemplate = input('e.g. {number}', ...(ngDevMode ? [{ debugName: "exampleHintTemplate" }] : []));
|
|
9366
10698
|
/** Emitted with the parsed parts whenever the number or country changes. */
|
|
9367
10699
|
phoneChange = output();
|
|
10700
|
+
/** `Intl.DisplayNames` for {@link locale}, or null (built-in English names). */
|
|
10701
|
+
regionNames = computed(() => {
|
|
10702
|
+
const locale = this.locale();
|
|
10703
|
+
if (!locale || typeof Intl === 'undefined' || !('DisplayNames' in Intl))
|
|
10704
|
+
return null;
|
|
10705
|
+
try {
|
|
10706
|
+
return new Intl.DisplayNames([locale], { type: 'region' });
|
|
10707
|
+
}
|
|
10708
|
+
catch {
|
|
10709
|
+
return null;
|
|
10710
|
+
}
|
|
10711
|
+
}, ...(ngDevMode ? [{ debugName: "regionNames" }] : []));
|
|
10712
|
+
/** The country's display name in {@link locale}, falling back to the built-in English name. */
|
|
10713
|
+
countryName(c) {
|
|
10714
|
+
try {
|
|
10715
|
+
return this.regionNames()?.of(c.iso2) ?? c.name;
|
|
10716
|
+
}
|
|
10717
|
+
catch {
|
|
10718
|
+
return c.name;
|
|
10719
|
+
}
|
|
10720
|
+
}
|
|
9368
10721
|
national = signal('', ...(ngDevMode ? [{ debugName: "national" }] : []));
|
|
9369
10722
|
countryIso = signal('', ...(ngDevMode ? [{ debugName: "countryIso" }] : []));
|
|
9370
10723
|
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
@@ -9403,7 +10756,8 @@ class SdsPhoneInput {
|
|
|
9403
10756
|
const all = this.availableCountries();
|
|
9404
10757
|
if (!f)
|
|
9405
10758
|
return all;
|
|
9406
|
-
return all.filter((c) => c.
|
|
10759
|
+
return all.filter((c) => this.countryName(c).toLowerCase().includes(f) ||
|
|
10760
|
+
c.name.toLowerCase().includes(f) ||
|
|
9407
10761
|
c.iso2.toLowerCase().includes(f) ||
|
|
9408
10762
|
c.dialCode.includes(f.replace('+', '')));
|
|
9409
10763
|
}, ...(ngDevMode ? [{ debugName: "filteredCountries" }] : []));
|
|
@@ -9416,7 +10770,7 @@ class SdsPhoneInput {
|
|
|
9416
10770
|
const number = `+${c.dialCode} ${sdsFormatNational(c.example, c.format)}`;
|
|
9417
10771
|
return this.exampleHintTemplate().replace('{number}', number);
|
|
9418
10772
|
}, ...(ngDevMode ? [{ debugName: "autoHint" }] : []));
|
|
9419
|
-
countryAriaLabel = computed(() => this.countryLabel().replace('{country}', this.country()
|
|
10773
|
+
countryAriaLabel = computed(() => this.countryLabel().replace('{country}', this.countryName(this.country())), ...(ngDevMode ? [{ debugName: "countryAriaLabel" }] : []));
|
|
9420
10774
|
e164 = computed(() => {
|
|
9421
10775
|
const d = this.national();
|
|
9422
10776
|
return d ? `+${this.country().dialCode}${d}` : '';
|
|
@@ -9732,7 +11086,7 @@ class SdsPhoneInput {
|
|
|
9732
11086
|
this.onValidatorChange = fn;
|
|
9733
11087
|
}
|
|
9734
11088
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsPhoneInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9735
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsPhoneInput, isStandalone: true, selector: "sds-phone-input", inputs: { label: { classPropertyName: "label", publicName: "label", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, defaultCountry: { classPropertyName: "defaultCountry", publicName: "defaultCountry", isSignal: true, isRequired: false, transformFunction: null }, preferredCountries: { classPropertyName: "preferredCountries", publicName: "preferredCountries", isSignal: true, isRequired: false, transformFunction: null }, onlyCountries: { classPropertyName: "onlyCountries", publicName: "onlyCountries", isSignal: true, isRequired: false, transformFunction: null }, showExampleHint: { classPropertyName: "showExampleHint", publicName: "showExampleHint", isSignal: true, isRequired: false, transformFunction: null }, requiredMessage: { classPropertyName: "requiredMessage", publicName: "requiredMessage", isSignal: true, isRequired: false, transformFunction: null }, countryLabel: { classPropertyName: "countryLabel", publicName: "countryLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsLabel: { classPropertyName: "noResultsLabel", publicName: "noResultsLabel", isSignal: true, isRequired: false, transformFunction: null }, incompleteMessage: { classPropertyName: "incompleteMessage", publicName: "incompleteMessage", isSignal: true, isRequired: false, transformFunction: null }, invalidMessage: { classPropertyName: "invalidMessage", publicName: "invalidMessage", isSignal: true, isRequired: false, transformFunction: null }, lengthSeparator: { classPropertyName: "lengthSeparator", publicName: "lengthSeparator", isSignal: true, isRequired: false, transformFunction: null }, exampleHintTemplate: { classPropertyName: "exampleHintTemplate", publicName: "exampleHintTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { phoneChange: "phoneChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
|
|
11089
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsPhoneInput, isStandalone: true, selector: "sds-phone-input", inputs: { label: { classPropertyName: "label", publicName: "label", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, defaultCountry: { classPropertyName: "defaultCountry", publicName: "defaultCountry", isSignal: true, isRequired: false, transformFunction: null }, preferredCountries: { classPropertyName: "preferredCountries", publicName: "preferredCountries", isSignal: true, isRequired: false, transformFunction: null }, onlyCountries: { classPropertyName: "onlyCountries", publicName: "onlyCountries", isSignal: true, isRequired: false, transformFunction: null }, showExampleHint: { classPropertyName: "showExampleHint", publicName: "showExampleHint", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, requiredMessage: { classPropertyName: "requiredMessage", publicName: "requiredMessage", isSignal: true, isRequired: false, transformFunction: null }, countryLabel: { classPropertyName: "countryLabel", publicName: "countryLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsLabel: { classPropertyName: "noResultsLabel", publicName: "noResultsLabel", isSignal: true, isRequired: false, transformFunction: null }, incompleteMessage: { classPropertyName: "incompleteMessage", publicName: "incompleteMessage", isSignal: true, isRequired: false, transformFunction: null }, invalidMessage: { classPropertyName: "invalidMessage", publicName: "invalidMessage", isSignal: true, isRequired: false, transformFunction: null }, lengthSeparator: { classPropertyName: "lengthSeparator", publicName: "lengthSeparator", isSignal: true, isRequired: false, transformFunction: null }, exampleHintTemplate: { classPropertyName: "exampleHintTemplate", publicName: "exampleHintTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { phoneChange: "phoneChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
|
|
9736
11090
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsPhoneInput), multi: true },
|
|
9737
11091
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => SdsPhoneInput), multi: true },
|
|
9738
11092
|
], viewQueries: [{ propertyName: "anchor", first: true, predicate: ["anchor"], descendants: true, isSignal: true }, { propertyName: "field", first: true, predicate: ["field"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
@@ -9841,7 +11195,7 @@ class SdsPhoneInput {
|
|
|
9841
11195
|
<span class="grid h-5 min-w-7 place-items-center rounded bg-muted px-1 text-[11px] font-semibold tracking-wide text-ink-soft">
|
|
9842
11196
|
{{ c.iso2 }}
|
|
9843
11197
|
</span>
|
|
9844
|
-
<span class="flex-1 truncate">{{ c
|
|
11198
|
+
<span class="flex-1 truncate">{{ countryName(c) }}</span>
|
|
9845
11199
|
<span class="text-ink-faint">+{{ c.dialCode }}</span>
|
|
9846
11200
|
</li>
|
|
9847
11201
|
} @empty {
|
|
@@ -9982,7 +11336,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9982
11336
|
<span class="grid h-5 min-w-7 place-items-center rounded bg-muted px-1 text-[11px] font-semibold tracking-wide text-ink-soft">
|
|
9983
11337
|
{{ c.iso2 }}
|
|
9984
11338
|
</span>
|
|
9985
|
-
<span class="flex-1 truncate">{{ c
|
|
11339
|
+
<span class="flex-1 truncate">{{ countryName(c) }}</span>
|
|
9986
11340
|
<span class="text-ink-faint">+{{ c.dialCode }}</span>
|
|
9987
11341
|
</li>
|
|
9988
11342
|
} @empty {
|
|
@@ -10003,7 +11357,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10003
11357
|
}
|
|
10004
11358
|
`,
|
|
10005
11359
|
}]
|
|
10006
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", 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 }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], defaultCountry: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultCountry", required: false }] }], preferredCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredCountries", required: false }] }], onlyCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "onlyCountries", required: false }] }], showExampleHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExampleHint", required: false }] }], requiredMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredMessage", required: false }] }], countryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countryLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], noResultsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsLabel", required: false }] }], incompleteMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "incompleteMessage", required: false }] }], invalidMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidMessage", required: false }] }], lengthSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "lengthSeparator", required: false }] }], exampleHintTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "exampleHintTemplate", required: false }] }], phoneChange: [{ type: i0.Output, args: ["phoneChange"] }], anchor: [{ type: i0.ViewChild, args: ['anchor', { isSignal: true }] }], field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }] } });
|
|
11360
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", 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 }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], defaultCountry: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultCountry", required: false }] }], preferredCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredCountries", required: false }] }], onlyCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "onlyCountries", required: false }] }], showExampleHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExampleHint", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], requiredMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredMessage", required: false }] }], countryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countryLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], noResultsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsLabel", required: false }] }], incompleteMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "incompleteMessage", required: false }] }], invalidMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidMessage", required: false }] }], lengthSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "lengthSeparator", required: false }] }], exampleHintTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "exampleHintTemplate", required: false }] }], phoneChange: [{ type: i0.Output, args: ["phoneChange"] }], anchor: [{ type: i0.ViewChild, args: ['anchor', { isSignal: true }] }], field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }] } });
|
|
10007
11361
|
|
|
10008
11362
|
const SIZES$1 = {
|
|
10009
11363
|
sm: 'h-8 min-w-8 text-xs',
|
|
@@ -10279,7 +11633,7 @@ class SdsPaginator {
|
|
|
10279
11633
|
</label>
|
|
10280
11634
|
}
|
|
10281
11635
|
</div>
|
|
10282
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsSelect, selector: "sds-select", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "dataKey", "placeholder", "label", "ariaLabel", "hint", "error", "size", "appearance", "disabled", "clearable", "filter", "filterPlaceholder", "emptyMessage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11636
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsSelect, selector: "sds-select", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "dataKey", "placeholder", "label", "ariaLabel", "hint", "error", "size", "appearance", "disabled", "clearable", "filter", "filterPlaceholder", "emptyMessage", "clearLabel", "filterLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10283
11637
|
}
|
|
10284
11638
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsPaginator, decorators: [{
|
|
10285
11639
|
type: Component,
|
|
@@ -10405,8 +11759,13 @@ class SdsTabsStore {
|
|
|
10405
11759
|
id = `sds-tabs-${nextId$3++}`;
|
|
10406
11760
|
/** Whether the tab list scrolls horizontally (mirrors [scrollable]). */
|
|
10407
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 = () => { };
|
|
10408
11766
|
value;
|
|
10409
11767
|
registered = signal([], ...(ngDevMode ? [{ debugName: "registered" }] : []));
|
|
11768
|
+
panels = signal([], ...(ngDevMode ? [{ debugName: "panels" }] : []));
|
|
10410
11769
|
/** Called once by <sds-tabs> to share its two-way `value` signal. */
|
|
10411
11770
|
connect(value) {
|
|
10412
11771
|
this.value = value;
|
|
@@ -10417,8 +11776,11 @@ class SdsTabsStore {
|
|
|
10417
11776
|
isActive(value) {
|
|
10418
11777
|
return this.value() === value;
|
|
10419
11778
|
}
|
|
11779
|
+
/** A user pick. Uncontrolled: becomes the active tab. Controlled: only reported to the host. */
|
|
10420
11780
|
select(value) {
|
|
10421
|
-
this.
|
|
11781
|
+
this.onSelect(value);
|
|
11782
|
+
if (!this.controlled())
|
|
11783
|
+
this.value.set(value);
|
|
10422
11784
|
}
|
|
10423
11785
|
registerTab(value) {
|
|
10424
11786
|
this.registered.update((list) => (list.includes(value) ? list : [...list, value]));
|
|
@@ -10429,6 +11791,16 @@ class SdsTabsStore {
|
|
|
10429
11791
|
unregisterTab(value) {
|
|
10430
11792
|
this.registered.update((list) => list.filter((v) => v !== value));
|
|
10431
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
|
+
}
|
|
10432
11804
|
tabId(value) {
|
|
10433
11805
|
return `${this.id}-tab-${value}`;
|
|
10434
11806
|
}
|
|
@@ -10448,10 +11820,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10448
11820
|
* <sds-tab-panel> [value]; it is two-way bindable via [(value)]. When omitted,
|
|
10449
11821
|
* the first registered tab is selected.
|
|
10450
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
|
+
*
|
|
10451
11831
|
* @example
|
|
10452
11832
|
* <sds-tabs [(value)]="active">
|
|
10453
11833
|
* <sds-tab-list>
|
|
10454
|
-
* <sds-tab value="0">
|
|
11834
|
+
* <sds-tab value="0">Details</sds-tab>
|
|
10455
11835
|
* <sds-tab value="1">Historique</sds-tab>
|
|
10456
11836
|
* </sds-tab-list>
|
|
10457
11837
|
* <sds-tab-panels>
|
|
@@ -10459,6 +11839,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10459
11839
|
* <sds-tab-panel value="1">…</sds-tab-panel>
|
|
10460
11840
|
* </sds-tab-panels>
|
|
10461
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>
|
|
10462
11852
|
*/
|
|
10463
11853
|
class SdsTabs {
|
|
10464
11854
|
store = inject(SdsTabsStore);
|
|
@@ -10466,12 +11856,21 @@ class SdsTabs {
|
|
|
10466
11856
|
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
10467
11857
|
/** Let the tab list scroll horizontally instead of overflowing. */
|
|
10468
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();
|
|
10469
11866
|
constructor() {
|
|
10470
11867
|
this.store.connect(this.value);
|
|
11868
|
+
this.store.onSelect = (value) => this.tabSelect.emit(value);
|
|
10471
11869
|
effect(() => this.store.scrollable.set(this.scrollable()));
|
|
11870
|
+
effect(() => this.store.controlled.set(this.controlled()));
|
|
10472
11871
|
}
|
|
10473
11872
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10474
|
-
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 });
|
|
10475
11874
|
}
|
|
10476
11875
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTabs, decorators: [{
|
|
10477
11876
|
type: Component,
|
|
@@ -10482,7 +11881,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10482
11881
|
host: { class: 'block' },
|
|
10483
11882
|
template: `<ng-content />`,
|
|
10484
11883
|
}]
|
|
10485
|
-
}], 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"] }] } });
|
|
10486
11885
|
|
|
10487
11886
|
/**
|
|
10488
11887
|
* Container (role="tablist") for the <sds-tab> headers. Renders the bottom rule
|
|
@@ -10579,7 +11978,7 @@ class SdsTab {
|
|
|
10579
11978
|
role="tab"
|
|
10580
11979
|
[id]="store.tabId(value())"
|
|
10581
11980
|
[attr.aria-selected]="active()"
|
|
10582
|
-
[attr.aria-controls]="store.panelId(value())"
|
|
11981
|
+
[attr.aria-controls]="store.hasPanel(value()) ? store.panelId(value()) : null"
|
|
10583
11982
|
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
10584
11983
|
[attr.tabindex]="active() && !disabled() ? 0 : -1"
|
|
10585
11984
|
[disabled]="disabled()"
|
|
@@ -10602,7 +12001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10602
12001
|
role="tab"
|
|
10603
12002
|
[id]="store.tabId(value())"
|
|
10604
12003
|
[attr.aria-selected]="active()"
|
|
10605
|
-
[attr.aria-controls]="store.panelId(value())"
|
|
12004
|
+
[attr.aria-controls]="store.hasPanel(value()) ? store.panelId(value()) : null"
|
|
10606
12005
|
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
10607
12006
|
[attr.tabindex]="active() && !disabled() ? 0 : -1"
|
|
10608
12007
|
[disabled]="disabled()"
|
|
@@ -10647,6 +12046,12 @@ class SdsTabPanel {
|
|
|
10647
12046
|
store = inject(SdsTabsStore);
|
|
10648
12047
|
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
10649
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
|
+
}
|
|
10650
12055
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTabPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10651
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: `
|
|
10652
12057
|
@if (active()) {
|
|
@@ -10968,8 +12373,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10968
12373
|
*
|
|
10969
12374
|
* @example
|
|
10970
12375
|
* <sds-table [value]="rows" [columns]="cols">
|
|
10971
|
-
* <ng-template sdsCell="
|
|
10972
|
-
* <sds-badge [variant]="row.
|
|
12376
|
+
* <ng-template sdsCell="status" let-value let-row="row">
|
|
12377
|
+
* <sds-badge [variant]="row.active ? 'success' : 'neutral'">{{ value }}</sds-badge>
|
|
10973
12378
|
* </ng-template>
|
|
10974
12379
|
* </sds-table>
|
|
10975
12380
|
*/
|
|
@@ -10993,6 +12398,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10993
12398
|
}]
|
|
10994
12399
|
}], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "sdsCell", required: true }] }] } });
|
|
10995
12400
|
|
|
12401
|
+
/**
|
|
12402
|
+
* Supplies a custom template for a column's header cell, matched by its field key. The template
|
|
12403
|
+
* replaces the header's whole content — label and sort button — so it may hold its own controls
|
|
12404
|
+
* (a column with a header template is not sortable from the header). Typical use: a "select all"
|
|
12405
|
+
* checkbox above a checkbox column rendered with `sdsCell`.
|
|
12406
|
+
*
|
|
12407
|
+
* @example
|
|
12408
|
+
* <sds-table [value]="rows" [columns]="cols" dataKey="id">
|
|
12409
|
+
* <ng-template sdsHeader="select" let-rows="rows">
|
|
12410
|
+
* <sds-checkbox ariaLabel="Select all rows" [ngModel]="allSelected(rows)"
|
|
12411
|
+
* [indeterminate]="someSelected(rows)" (ngModelChange)="selectAll(rows, $event)" />
|
|
12412
|
+
* </ng-template>
|
|
12413
|
+
* <ng-template sdsCell="select" let-row="row">
|
|
12414
|
+
* <sds-checkbox [ariaLabel]="'Select ' + row.name" [ngModel]="isSelected(row)"
|
|
12415
|
+
* (ngModelChange)="toggle(row, $event)" />
|
|
12416
|
+
* </ng-template>
|
|
12417
|
+
* </sds-table>
|
|
12418
|
+
*/
|
|
12419
|
+
class SdsTableHeader {
|
|
12420
|
+
/** The column `field` whose header this template renders. */
|
|
12421
|
+
column = input.required(...(ngDevMode ? [{ debugName: "column", alias: 'sdsHeader' }] : [{ alias: 'sdsHeader' }]));
|
|
12422
|
+
/** The wrapped template, rendered by the host table via ngTemplateOutlet. */
|
|
12423
|
+
template = inject(TemplateRef);
|
|
12424
|
+
/** Lets the compiler type-check `let-*` bindings against SdsTableHeaderContext. */
|
|
12425
|
+
static ngTemplateContextGuard(_dir, _ctx) {
|
|
12426
|
+
return true;
|
|
12427
|
+
}
|
|
12428
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTableHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
12429
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.25", type: SdsTableHeader, isStandalone: true, selector: "ng-template[sdsHeader]", inputs: { column: { classPropertyName: "column", publicName: "sdsHeader", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
12430
|
+
}
|
|
12431
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTableHeader, decorators: [{
|
|
12432
|
+
type: Directive,
|
|
12433
|
+
args: [{
|
|
12434
|
+
selector: 'ng-template[sdsHeader]',
|
|
12435
|
+
standalone: true,
|
|
12436
|
+
}]
|
|
12437
|
+
}], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "sdsHeader", required: true }] }] } });
|
|
12438
|
+
|
|
10996
12439
|
/**
|
|
10997
12440
|
* Supplies the detail template rendered beneath an expanded row when the host
|
|
10998
12441
|
* `<sds-table>` has `expandable`. Use as a structural template inside the table:
|
|
@@ -11000,7 +12443,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
11000
12443
|
* @example
|
|
11001
12444
|
* <sds-table [value]="rows" [columns]="cols" expandable>
|
|
11002
12445
|
* <ng-template sdsRowExpansion let-row>
|
|
11003
|
-
* <div>
|
|
12446
|
+
* <div>Details of {{ row.name }}</div>
|
|
11004
12447
|
* </ng-template>
|
|
11005
12448
|
* </sds-table>
|
|
11006
12449
|
*/
|
|
@@ -11022,6 +12465,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
11022
12465
|
}]
|
|
11023
12466
|
}] });
|
|
11024
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
|
+
|
|
11025
12498
|
const SIZES = {
|
|
11026
12499
|
sm: { cell: 'px-3 py-2 text-sm', head: 'px-3 py-2' },
|
|
11027
12500
|
md: { cell: 'px-4 py-2.5 text-sm', head: 'px-4 py-2.5' },
|
|
@@ -11050,6 +12523,16 @@ let nextId$1 = 0;
|
|
|
11050
12523
|
* across all pages**, not just the current page. Toggling it selects/clears
|
|
11051
12524
|
* every filtered row regardless of pagination (this is an intentional
|
|
11052
12525
|
* deviation from PrimeNG's per-page select-all).
|
|
12526
|
+
* - **Custom headers:** `<ng-template sdsHeader="field">` replaces a column's header content (label and
|
|
12527
|
+
* sort button) — e.g. a "select all" checkbox above your own checkbox column. Its context carries the
|
|
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`.
|
|
12534
|
+
* - **Labels:** every visible and spoken string is an input with an English default (paginator,
|
|
12535
|
+
* filter, selection, expansion, editor). An app serving more than one language passes translations.
|
|
11053
12536
|
*
|
|
11054
12537
|
* **Editable grid (opt-in).** Set `editable` and give columns an `editor` (`text` · `number` ·
|
|
11055
12538
|
* `currency` · `select`). The table becomes an ARIA grid with one tab stop: arrow keys move between
|
|
@@ -11059,14 +12542,16 @@ let nextId$1 = 0;
|
|
|
11059
12542
|
* commits. Each changed commit emits `(cellCommit)` — the host applies it to its data (the table never
|
|
11060
12543
|
* mutates rows) — and marks the cell dirty until {@link clearDirty}. Errors from `[cellErrors]` show
|
|
11061
12544
|
* under the cell with `aria-invalid`. Number/currency cells use sds-input-number (live, locale-aware
|
|
11062
|
-
* formatting: "11,9" → "€11.90"
|
|
12545
|
+
* formatting: "11,9" → "€11.90"; in a comma locale such as fr-BE or nl-BE a typed "." is taken as the
|
|
12546
|
+
* decimal separator, so "12.50" → "12,50 €"). The `select` editor is a styled native select with the
|
|
12547
|
+
* column header as its name. Everything else — sort, paging, selection — is unchanged.
|
|
11063
12548
|
*
|
|
11064
12549
|
* @example
|
|
11065
12550
|
* <sds-table [value]="staff" [columns]="cols" dataKey="id"
|
|
11066
12551
|
* sortable paginator [rows]="10" globalFilter
|
|
11067
12552
|
* selectionMode="multiple" [(selection)]="selected">
|
|
11068
|
-
* <ng-template sdsCell="
|
|
11069
|
-
* <sds-badge [variant]="row.
|
|
12553
|
+
* <ng-template sdsCell="status" let-value let-row="row">
|
|
12554
|
+
* <sds-badge [variant]="row.active ? 'success' : 'neutral'">{{ value }}</sds-badge>
|
|
11070
12555
|
* </ng-template>
|
|
11071
12556
|
* </sds-table>
|
|
11072
12557
|
*
|
|
@@ -11117,6 +12602,14 @@ class SdsTable {
|
|
|
11117
12602
|
selection = model(null, ...(ngDevMode ? [{ debugName: "selection" }] : []));
|
|
11118
12603
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
11119
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" }] : []));
|
|
11120
12613
|
caption = input('', ...(ngDevMode ? [{ debugName: "caption" }] : []));
|
|
11121
12614
|
/** Fallback accessible name for the `<table>` when no `caption` is set. */
|
|
11122
12615
|
ariaLabel = input('Data table', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -11142,6 +12635,20 @@ class SdsTable {
|
|
|
11142
12635
|
locale = input('', ...(ngDevMode ? [{ debugName: "locale" }] : []));
|
|
11143
12636
|
/** Spoken marker of an edited (dirty) cell. */
|
|
11144
12637
|
dirtyLabel = input('edited', ...(ngDevMode ? [{ debugName: "dirtyLabel" }] : []));
|
|
12638
|
+
/** Empty choice of a `select` editor while the cell has no value (a column's `placeholder` wins). */
|
|
12639
|
+
selectPlaceholder = input('Select…', ...(ngDevMode ? [{ debugName: "selectPlaceholder" }] : []));
|
|
12640
|
+
/**
|
|
12641
|
+
* Selection and expansion labels (English defaults; translate them in a multi-language app). The
|
|
12642
|
+
* checkbox/radio and expander buttons are icon-only, so these strings are their only names.
|
|
12643
|
+
*/
|
|
12644
|
+
selectAllLabel = input('Select all rows', ...(ngDevMode ? [{ debugName: "selectAllLabel" }] : []));
|
|
12645
|
+
selectRowLabel = input('Select row', ...(ngDevMode ? [{ debugName: "selectRowLabel" }] : []));
|
|
12646
|
+
/** Screen-reader name of the selection column's header in `single` mode. */
|
|
12647
|
+
selectionColumnLabel = input('Selection', ...(ngDevMode ? [{ debugName: "selectionColumnLabel" }] : []));
|
|
12648
|
+
/** Screen-reader name of the expander column's header (see {@link expandable}). */
|
|
12649
|
+
expandColumnLabel = input('Details', ...(ngDevMode ? [{ debugName: "expandColumnLabel" }] : []));
|
|
12650
|
+
expandRowLabel = input('Expand row', ...(ngDevMode ? [{ debugName: "expandRowLabel" }] : []));
|
|
12651
|
+
collapseRowLabel = input('Collapse row', ...(ngDevMode ? [{ debugName: "collapseRowLabel" }] : []));
|
|
11145
12652
|
// --- outputs --------------------------------------------------------------
|
|
11146
12653
|
sortChange = output();
|
|
11147
12654
|
pageChange = output();
|
|
@@ -11168,11 +12675,36 @@ class SdsTable {
|
|
|
11168
12675
|
templateFor(field) {
|
|
11169
12676
|
return this.templateMap().get(field) ?? null;
|
|
11170
12677
|
}
|
|
12678
|
+
// --- custom header templates ----------------------------------------------
|
|
12679
|
+
headerTemplates = contentChildren(SdsTableHeader, ...(ngDevMode ? [{ debugName: "headerTemplates" }] : []));
|
|
12680
|
+
headerTemplateMap = computed(() => {
|
|
12681
|
+
const map = new Map();
|
|
12682
|
+
for (const h of this.headerTemplates())
|
|
12683
|
+
map.set(h.column(), h.template);
|
|
12684
|
+
return map;
|
|
12685
|
+
}, ...(ngDevMode ? [{ debugName: "headerTemplateMap" }] : []));
|
|
12686
|
+
headerTemplateFor(field) {
|
|
12687
|
+
return this.headerTemplateMap().get(field) ?? null;
|
|
12688
|
+
}
|
|
12689
|
+
headerContext(column, index) {
|
|
12690
|
+
return {
|
|
12691
|
+
$implicit: column,
|
|
12692
|
+
column,
|
|
12693
|
+
index,
|
|
12694
|
+
rows: this.filtered(),
|
|
12695
|
+
pageRows: this.displayRows(),
|
|
12696
|
+
};
|
|
12697
|
+
}
|
|
11171
12698
|
// --- row-expansion template -----------------------------------------------
|
|
11172
12699
|
rowExpansion = contentChild(SdsTableRowExpansion, ...(ngDevMode ? [{ debugName: "rowExpansion" }] : []));
|
|
11173
12700
|
expansionTemplate() {
|
|
11174
12701
|
return this.rowExpansion()?.template ?? null;
|
|
11175
12702
|
}
|
|
12703
|
+
// --- empty-state template -------------------------------------------------
|
|
12704
|
+
emptyTpl = contentChild(SdsTableEmpty, ...(ngDevMode ? [{ debugName: "emptyTpl" }] : []));
|
|
12705
|
+
emptyTemplate() {
|
|
12706
|
+
return this.emptyTpl()?.template ?? null;
|
|
12707
|
+
}
|
|
11176
12708
|
// --- pipeline state -------------------------------------------------------
|
|
11177
12709
|
filterText = signal('', ...(ngDevMode ? [{ debugName: "filterText" }] : []));
|
|
11178
12710
|
sortField = signal(null, ...(ngDevMode ? [{ debugName: "sortField" }] : []));
|
|
@@ -11293,7 +12825,8 @@ class SdsTable {
|
|
|
11293
12825
|
totalColumnCount = computed(() => this.effectiveColumns().length + this.leadingColumnCount(), ...(ngDevMode ? [{ debugName: "totalColumnCount" }] : []));
|
|
11294
12826
|
// --- sorting UI -----------------------------------------------------------
|
|
11295
12827
|
isColumnSortable(col) {
|
|
11296
|
-
|
|
12828
|
+
// A custom header template owns the header content, so it has no sort button.
|
|
12829
|
+
return this.sortable() && !!col.sortable && !this.headerTemplateFor(col.field);
|
|
11297
12830
|
}
|
|
11298
12831
|
sortIcon(col) {
|
|
11299
12832
|
if (this.sortField() !== col.field || this.sortOrder() === 0) {
|
|
@@ -11407,9 +12940,14 @@ class SdsTable {
|
|
|
11407
12940
|
this.toggleRowSelection(row);
|
|
11408
12941
|
}
|
|
11409
12942
|
}
|
|
11410
|
-
/** Enter/Space on a (single
|
|
12943
|
+
/** Enter/Space on a focusable row (single selection or `rowClickable`) acts like a click on it. */
|
|
11411
12944
|
onRowKeydown(event, row) {
|
|
11412
|
-
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)
|
|
11413
12951
|
return;
|
|
11414
12952
|
event.preventDefault();
|
|
11415
12953
|
this.onRowClick(row);
|
|
@@ -11428,9 +12966,11 @@ class SdsTable {
|
|
|
11428
12966
|
this.rowSelect.emit(row);
|
|
11429
12967
|
}
|
|
11430
12968
|
}
|
|
11431
|
-
onRowClick(row) {
|
|
12969
|
+
onRowClick(row, event) {
|
|
11432
12970
|
if (this.loading())
|
|
11433
12971
|
return;
|
|
12972
|
+
if (event && this.fromInnerControl(event))
|
|
12973
|
+
return;
|
|
11434
12974
|
this.rowClick.emit(row);
|
|
11435
12975
|
if (this.selectionMode() === 'single') {
|
|
11436
12976
|
if (this.equals(this.selection(), row)) {
|
|
@@ -11443,6 +12983,16 @@ class SdsTable {
|
|
|
11443
12983
|
}
|
|
11444
12984
|
}
|
|
11445
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
|
+
}
|
|
11446
12996
|
// --- paginator ------------------------------------------------------------
|
|
11447
12997
|
onPageChange(state) {
|
|
11448
12998
|
this.editing.set(null);
|
|
@@ -11653,6 +13203,13 @@ class SdsTable {
|
|
|
11653
13203
|
}
|
|
11654
13204
|
return String(v);
|
|
11655
13205
|
}
|
|
13206
|
+
/** Shared frame of the in-cell editors (text, select): height, radius, focus ring, error state. */
|
|
13207
|
+
editorClass(row, col) {
|
|
13208
|
+
const tone = this.cellErrorFor(row, col.field)
|
|
13209
|
+
? 'border-danger ring-danger/25'
|
|
13210
|
+
: 'border-brand-500 ring-brand-500/25';
|
|
13211
|
+
return `h-9 w-full rounded-control border bg-surface text-sm text-ink outline-none ring-2 ${tone}`;
|
|
13212
|
+
}
|
|
11656
13213
|
gridCellClass(row, col, r, c) {
|
|
11657
13214
|
const align = ALIGN[col.align ?? 'left'];
|
|
11658
13215
|
const editing = this.isEditing(r, c);
|
|
@@ -11969,7 +13526,7 @@ class SdsTable {
|
|
|
11969
13526
|
const align = ALIGN[col?.align ?? 'left'];
|
|
11970
13527
|
return `${SIZES[this.size()].cell} ${align} text-ink align-middle`;
|
|
11971
13528
|
}
|
|
11972
|
-
|
|
13529
|
+
bodyRowClass(row, index) {
|
|
11973
13530
|
const parts = ['transition-colors'];
|
|
11974
13531
|
if (this.gridlines())
|
|
11975
13532
|
parts.push('divide-x divide-border');
|
|
@@ -11981,9 +13538,12 @@ class SdsTable {
|
|
|
11981
13538
|
}
|
|
11982
13539
|
if (this.hoverable() && !this.isRowSelected(row))
|
|
11983
13540
|
parts.push('hover:bg-muted/60');
|
|
11984
|
-
if (this.selectionMode() === 'single') {
|
|
13541
|
+
if (this.selectionMode() === 'single' || (this.rowClickable() && !this.editable())) {
|
|
11985
13542
|
parts.push('cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-brand-500');
|
|
11986
13543
|
}
|
|
13544
|
+
const extra = this.rowClass()?.(row, index);
|
|
13545
|
+
if (extra)
|
|
13546
|
+
parts.push(extra);
|
|
11987
13547
|
return parts.join(' ');
|
|
11988
13548
|
}
|
|
11989
13549
|
checkboxClass(checked, indeterminate) {
|
|
@@ -11992,7 +13552,7 @@ class SdsTable {
|
|
|
11992
13552
|
: 'border-border bg-surface';
|
|
11993
13553
|
}
|
|
11994
13554
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11995
|
-
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 } }, 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: "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: `
|
|
11996
13556
|
<div class="rounded-card border border-border bg-surface overflow-hidden">
|
|
11997
13557
|
<!-- Toolbar: caption + global filter -->
|
|
11998
13558
|
@if (caption() || globalFilter()) {
|
|
@@ -12057,7 +13617,7 @@ class SdsTable {
|
|
|
12057
13617
|
[class.z-10]="scrollHeight()"
|
|
12058
13618
|
[class.bg-muted]="scrollHeight()"
|
|
12059
13619
|
>
|
|
12060
|
-
<span class="sr-only">
|
|
13620
|
+
<span class="sr-only">{{ expandColumnLabel() }}</span>
|
|
12061
13621
|
</th>
|
|
12062
13622
|
}
|
|
12063
13623
|
|
|
@@ -12076,7 +13636,7 @@ class SdsTable {
|
|
|
12076
13636
|
type="button"
|
|
12077
13637
|
role="checkbox"
|
|
12078
13638
|
[attr.aria-checked]="headerChecked() ? 'true' : (headerIndeterminate() ? 'mixed' : 'false')"
|
|
12079
|
-
aria-label="
|
|
13639
|
+
[attr.aria-label]="selectAllLabel()"
|
|
12080
13640
|
[disabled]="loading()"
|
|
12081
13641
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12082
13642
|
[class]="checkboxClass(headerChecked(), headerIndeterminate())"
|
|
@@ -12089,7 +13649,7 @@ class SdsTable {
|
|
|
12089
13649
|
}
|
|
12090
13650
|
</button>
|
|
12091
13651
|
} @else {
|
|
12092
|
-
<span class="sr-only">
|
|
13652
|
+
<span class="sr-only">{{ selectionColumnLabel() }}</span>
|
|
12093
13653
|
}
|
|
12094
13654
|
</th>
|
|
12095
13655
|
}
|
|
@@ -12112,7 +13672,12 @@ class SdsTable {
|
|
|
12112
13672
|
(drop)="onColDrop($event, i)"
|
|
12113
13673
|
(dragend)="onColDragEnd()"
|
|
12114
13674
|
>
|
|
12115
|
-
@if (
|
|
13675
|
+
@if (headerTemplateFor(col.field); as htpl) {
|
|
13676
|
+
<ng-container
|
|
13677
|
+
[ngTemplateOutlet]="htpl"
|
|
13678
|
+
[ngTemplateOutletContext]="headerContext(col, i)"
|
|
13679
|
+
/>
|
|
13680
|
+
} @else if (isColumnSortable(col)) {
|
|
12116
13681
|
<button
|
|
12117
13682
|
type="button"
|
|
12118
13683
|
[disabled]="loading()"
|
|
@@ -12141,10 +13706,10 @@ class SdsTable {
|
|
|
12141
13706
|
<tbody class="divide-y divide-border">
|
|
12142
13707
|
@for (row of displayRows(); track trackRow($index, row); let i = $index) {
|
|
12143
13708
|
<tr
|
|
12144
|
-
[class]="
|
|
12145
|
-
[attr.tabindex]="selectionMode() === 'single' && !loading() && !editable() ? 0 : null"
|
|
13709
|
+
[class]="bodyRowClass(row, i)"
|
|
13710
|
+
[attr.tabindex]="(selectionMode() === 'single' || rowClickable()) && !loading() && !editable() ? 0 : null"
|
|
12146
13711
|
[attr.aria-selected]="selectionMode() === 'single' ? (isRowSelected(row) ? 'true' : 'false') : null"
|
|
12147
|
-
(click)="onRowClick(row)"
|
|
13712
|
+
(click)="onRowClick(row, $event)"
|
|
12148
13713
|
(keydown.enter)="onRowKeydown($event, row)"
|
|
12149
13714
|
(keydown.space)="onRowKeydown($event, row)"
|
|
12150
13715
|
>
|
|
@@ -12154,7 +13719,7 @@ class SdsTable {
|
|
|
12154
13719
|
type="button"
|
|
12155
13720
|
[attr.aria-expanded]="isExpanded(row)"
|
|
12156
13721
|
[attr.aria-controls]="isExpanded(row) ? rowDetailId(row) : null"
|
|
12157
|
-
[attr.aria-label]="isExpanded(row) ?
|
|
13722
|
+
[attr.aria-label]="isExpanded(row) ? collapseRowLabel() : expandRowLabel()"
|
|
12158
13723
|
[disabled]="loading()"
|
|
12159
13724
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded text-ink-soft hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12160
13725
|
(click)="onExpanderClick($event, row)"
|
|
@@ -12179,7 +13744,7 @@ class SdsTable {
|
|
|
12179
13744
|
type="button"
|
|
12180
13745
|
role="checkbox"
|
|
12181
13746
|
[attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
|
|
12182
|
-
aria-label="
|
|
13747
|
+
[attr.aria-label]="selectRowLabel()"
|
|
12183
13748
|
[disabled]="loading()"
|
|
12184
13749
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12185
13750
|
[class]="checkboxClass(isRowSelected(row), false)"
|
|
@@ -12194,7 +13759,7 @@ class SdsTable {
|
|
|
12194
13759
|
type="button"
|
|
12195
13760
|
role="radio"
|
|
12196
13761
|
[attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
|
|
12197
|
-
aria-label="
|
|
13762
|
+
[attr.aria-label]="selectRowLabel()"
|
|
12198
13763
|
[disabled]="loading()"
|
|
12199
13764
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded-full border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12200
13765
|
[class]="checkboxClass(isRowSelected(row), false)"
|
|
@@ -12241,20 +13806,31 @@ class SdsTable {
|
|
|
12241
13806
|
@if (isEditing(i, ci)) {
|
|
12242
13807
|
@switch (col.editor) {
|
|
12243
13808
|
@case ('select') {
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
|
|
13809
|
+
<!-- A native select (dependable inside a grid cell), dressed like the other editors:
|
|
13810
|
+
same height, radius, focus ring and padding, a library chevron, dark-mode popup. -->
|
|
13811
|
+
<div class="relative flex items-center">
|
|
13812
|
+
<select
|
|
13813
|
+
data-sds-cell-editor
|
|
13814
|
+
[class]="editorClass(row, col) + ' cursor-pointer appearance-none pl-2.5 pr-8 dark:scheme-dark'"
|
|
13815
|
+
[attr.aria-label]="col.header"
|
|
13816
|
+
[attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
|
|
13817
|
+
[attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
|
|
13818
|
+
(change)="onSelectEditorChange($event, col)"
|
|
13819
|
+
(blur)="onEditorBlur()"
|
|
13820
|
+
>
|
|
13821
|
+
@if (draft() === null || draft() === undefined) {
|
|
13822
|
+
<option value="" disabled selected>{{ col.placeholder ?? selectPlaceholder() }}</option>
|
|
13823
|
+
}
|
|
13824
|
+
@for (opt of col.options ?? []; track $index; let oi = $index) {
|
|
13825
|
+
<option [value]="oi" [selected]="opt.value === draft()">{{ opt.label }}</option>
|
|
13826
|
+
}
|
|
13827
|
+
</select>
|
|
13828
|
+
<sds-icon
|
|
13829
|
+
name="chevron-down"
|
|
13830
|
+
[size]="16"
|
|
13831
|
+
class="pointer-events-none absolute right-2.5 text-ink-soft"
|
|
13832
|
+
/>
|
|
13833
|
+
</div>
|
|
12258
13834
|
}
|
|
12259
13835
|
@case ('number') {
|
|
12260
13836
|
<sds-input-number
|
|
@@ -12269,6 +13845,8 @@ class SdsTable {
|
|
|
12269
13845
|
[maxFractionDigits]="col.maxFractionDigits ?? null"
|
|
12270
13846
|
[placeholder]="col.placeholder ?? ''"
|
|
12271
13847
|
[ariaLabel]="col.header"
|
|
13848
|
+
[invalid]="!!cellErrorFor(row, col.field)"
|
|
13849
|
+
[ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
|
|
12272
13850
|
(focusout)="onEditorBlur()"
|
|
12273
13851
|
/>
|
|
12274
13852
|
}
|
|
@@ -12286,6 +13864,8 @@ class SdsTable {
|
|
|
12286
13864
|
[maxFractionDigits]="col.maxFractionDigits ?? null"
|
|
12287
13865
|
[placeholder]="col.placeholder ?? ''"
|
|
12288
13866
|
[ariaLabel]="col.header"
|
|
13867
|
+
[invalid]="!!cellErrorFor(row, col.field)"
|
|
13868
|
+
[ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
|
|
12289
13869
|
(focusout)="onEditorBlur()"
|
|
12290
13870
|
/>
|
|
12291
13871
|
}
|
|
@@ -12293,10 +13873,12 @@ class SdsTable {
|
|
|
12293
13873
|
<input
|
|
12294
13874
|
data-sds-cell-editor
|
|
12295
13875
|
type="text"
|
|
12296
|
-
class="
|
|
13876
|
+
[class]="editorClass(row, col) + ' px-2.5 placeholder:text-ink-faint'"
|
|
12297
13877
|
[value]="draftText()"
|
|
12298
13878
|
[placeholder]="col.placeholder ?? ''"
|
|
12299
13879
|
[attr.aria-label]="col.header"
|
|
13880
|
+
[attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
|
|
13881
|
+
[attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
|
|
12300
13882
|
(input)="onTextEditorInput($event)"
|
|
12301
13883
|
(blur)="onEditorBlur()"
|
|
12302
13884
|
/>
|
|
@@ -12352,7 +13934,14 @@ class SdsTable {
|
|
|
12352
13934
|
[attr.colspan]="totalColumnCount()"
|
|
12353
13935
|
class="py-10 text-center text-ink-faint"
|
|
12354
13936
|
>
|
|
12355
|
-
|
|
13937
|
+
@if (emptyTemplate(); as tpl) {
|
|
13938
|
+
<ng-container
|
|
13939
|
+
[ngTemplateOutlet]="tpl"
|
|
13940
|
+
[ngTemplateOutletContext]="{ $implicit: filterText(), filterText: filterText() }"
|
|
13941
|
+
/>
|
|
13942
|
+
} @else {
|
|
13943
|
+
{{ emptyMessage() }}
|
|
13944
|
+
}
|
|
12356
13945
|
</td>
|
|
12357
13946
|
</tr>
|
|
12358
13947
|
}
|
|
@@ -12396,7 +13985,7 @@ class SdsTable {
|
|
|
12396
13985
|
</div>
|
|
12397
13986
|
}
|
|
12398
13987
|
</div>
|
|
12399
|
-
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsPaginator, selector: "sds-paginator", inputs: ["totalRecords", "first", "rows", "rowsPerPageOptions", "pageLinkSize", "showFirstLastIcon", "showPageLinks", "showCurrentPageReport", "currentPageReportTemplate", "showJumpToPageInput", "rowsPerPageLabel", "jumpToPageLabel", "paginationLabel", "firstPageLabel", "previousPageLabel", "nextPageLabel", "lastPageLabel", "pageLinkLabel", "jumpToPageAriaLabel", "size", "disabled"], outputs: ["firstChange", "rowsChange", "pageChange"] }, { kind: "component", type: SdsInputNumber, selector: "sds-input-number", inputs: ["label", "ariaLabel", "placeholder", "hint", "error", "size", "appearance", "disabled", "readonly", "mode", "locale", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "min", "max", "step", "showButtons", "buttonLayout", "incrementIcon", "decrementIcon", "allowEmpty", "clearable", "clearLabel", "incrementLabel", "decrementLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13988
|
+
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsPaginator, selector: "sds-paginator", inputs: ["totalRecords", "first", "rows", "rowsPerPageOptions", "pageLinkSize", "showFirstLastIcon", "showPageLinks", "showCurrentPageReport", "currentPageReportTemplate", "showJumpToPageInput", "rowsPerPageLabel", "jumpToPageLabel", "paginationLabel", "firstPageLabel", "previousPageLabel", "nextPageLabel", "lastPageLabel", "pageLinkLabel", "jumpToPageAriaLabel", "size", "disabled"], outputs: ["firstChange", "rowsChange", "pageChange"] }, { kind: "component", type: SdsInputNumber, selector: "sds-input-number", inputs: ["label", "ariaLabel", "placeholder", "hint", "error", "invalid", "ariaDescribedby", "size", "appearance", "disabled", "readonly", "mode", "locale", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "min", "max", "step", "showButtons", "buttonLayout", "incrementIcon", "decrementIcon", "allowEmpty", "clearable", "clearLabel", "incrementLabel", "decrementLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
12400
13989
|
}
|
|
12401
13990
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTable, decorators: [{
|
|
12402
13991
|
type: Component,
|
|
@@ -12470,7 +14059,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12470
14059
|
[class.z-10]="scrollHeight()"
|
|
12471
14060
|
[class.bg-muted]="scrollHeight()"
|
|
12472
14061
|
>
|
|
12473
|
-
<span class="sr-only">
|
|
14062
|
+
<span class="sr-only">{{ expandColumnLabel() }}</span>
|
|
12474
14063
|
</th>
|
|
12475
14064
|
}
|
|
12476
14065
|
|
|
@@ -12489,7 +14078,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12489
14078
|
type="button"
|
|
12490
14079
|
role="checkbox"
|
|
12491
14080
|
[attr.aria-checked]="headerChecked() ? 'true' : (headerIndeterminate() ? 'mixed' : 'false')"
|
|
12492
|
-
aria-label="
|
|
14081
|
+
[attr.aria-label]="selectAllLabel()"
|
|
12493
14082
|
[disabled]="loading()"
|
|
12494
14083
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12495
14084
|
[class]="checkboxClass(headerChecked(), headerIndeterminate())"
|
|
@@ -12502,7 +14091,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12502
14091
|
}
|
|
12503
14092
|
</button>
|
|
12504
14093
|
} @else {
|
|
12505
|
-
<span class="sr-only">
|
|
14094
|
+
<span class="sr-only">{{ selectionColumnLabel() }}</span>
|
|
12506
14095
|
}
|
|
12507
14096
|
</th>
|
|
12508
14097
|
}
|
|
@@ -12525,7 +14114,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12525
14114
|
(drop)="onColDrop($event, i)"
|
|
12526
14115
|
(dragend)="onColDragEnd()"
|
|
12527
14116
|
>
|
|
12528
|
-
@if (
|
|
14117
|
+
@if (headerTemplateFor(col.field); as htpl) {
|
|
14118
|
+
<ng-container
|
|
14119
|
+
[ngTemplateOutlet]="htpl"
|
|
14120
|
+
[ngTemplateOutletContext]="headerContext(col, i)"
|
|
14121
|
+
/>
|
|
14122
|
+
} @else if (isColumnSortable(col)) {
|
|
12529
14123
|
<button
|
|
12530
14124
|
type="button"
|
|
12531
14125
|
[disabled]="loading()"
|
|
@@ -12554,10 +14148,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12554
14148
|
<tbody class="divide-y divide-border">
|
|
12555
14149
|
@for (row of displayRows(); track trackRow($index, row); let i = $index) {
|
|
12556
14150
|
<tr
|
|
12557
|
-
[class]="
|
|
12558
|
-
[attr.tabindex]="selectionMode() === 'single' && !loading() && !editable() ? 0 : null"
|
|
14151
|
+
[class]="bodyRowClass(row, i)"
|
|
14152
|
+
[attr.tabindex]="(selectionMode() === 'single' || rowClickable()) && !loading() && !editable() ? 0 : null"
|
|
12559
14153
|
[attr.aria-selected]="selectionMode() === 'single' ? (isRowSelected(row) ? 'true' : 'false') : null"
|
|
12560
|
-
(click)="onRowClick(row)"
|
|
14154
|
+
(click)="onRowClick(row, $event)"
|
|
12561
14155
|
(keydown.enter)="onRowKeydown($event, row)"
|
|
12562
14156
|
(keydown.space)="onRowKeydown($event, row)"
|
|
12563
14157
|
>
|
|
@@ -12567,7 +14161,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12567
14161
|
type="button"
|
|
12568
14162
|
[attr.aria-expanded]="isExpanded(row)"
|
|
12569
14163
|
[attr.aria-controls]="isExpanded(row) ? rowDetailId(row) : null"
|
|
12570
|
-
[attr.aria-label]="isExpanded(row) ?
|
|
14164
|
+
[attr.aria-label]="isExpanded(row) ? collapseRowLabel() : expandRowLabel()"
|
|
12571
14165
|
[disabled]="loading()"
|
|
12572
14166
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded text-ink-soft hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12573
14167
|
(click)="onExpanderClick($event, row)"
|
|
@@ -12592,7 +14186,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12592
14186
|
type="button"
|
|
12593
14187
|
role="checkbox"
|
|
12594
14188
|
[attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
|
|
12595
|
-
aria-label="
|
|
14189
|
+
[attr.aria-label]="selectRowLabel()"
|
|
12596
14190
|
[disabled]="loading()"
|
|
12597
14191
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12598
14192
|
[class]="checkboxClass(isRowSelected(row), false)"
|
|
@@ -12607,7 +14201,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12607
14201
|
type="button"
|
|
12608
14202
|
role="radio"
|
|
12609
14203
|
[attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
|
|
12610
|
-
aria-label="
|
|
14204
|
+
[attr.aria-label]="selectRowLabel()"
|
|
12611
14205
|
[disabled]="loading()"
|
|
12612
14206
|
class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded-full border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
|
|
12613
14207
|
[class]="checkboxClass(isRowSelected(row), false)"
|
|
@@ -12654,20 +14248,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12654
14248
|
@if (isEditing(i, ci)) {
|
|
12655
14249
|
@switch (col.editor) {
|
|
12656
14250
|
@case ('select') {
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
14251
|
+
<!-- A native select (dependable inside a grid cell), dressed like the other editors:
|
|
14252
|
+
same height, radius, focus ring and padding, a library chevron, dark-mode popup. -->
|
|
14253
|
+
<div class="relative flex items-center">
|
|
14254
|
+
<select
|
|
14255
|
+
data-sds-cell-editor
|
|
14256
|
+
[class]="editorClass(row, col) + ' cursor-pointer appearance-none pl-2.5 pr-8 dark:scheme-dark'"
|
|
14257
|
+
[attr.aria-label]="col.header"
|
|
14258
|
+
[attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
|
|
14259
|
+
[attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
|
|
14260
|
+
(change)="onSelectEditorChange($event, col)"
|
|
14261
|
+
(blur)="onEditorBlur()"
|
|
14262
|
+
>
|
|
14263
|
+
@if (draft() === null || draft() === undefined) {
|
|
14264
|
+
<option value="" disabled selected>{{ col.placeholder ?? selectPlaceholder() }}</option>
|
|
14265
|
+
}
|
|
14266
|
+
@for (opt of col.options ?? []; track $index; let oi = $index) {
|
|
14267
|
+
<option [value]="oi" [selected]="opt.value === draft()">{{ opt.label }}</option>
|
|
14268
|
+
}
|
|
14269
|
+
</select>
|
|
14270
|
+
<sds-icon
|
|
14271
|
+
name="chevron-down"
|
|
14272
|
+
[size]="16"
|
|
14273
|
+
class="pointer-events-none absolute right-2.5 text-ink-soft"
|
|
14274
|
+
/>
|
|
14275
|
+
</div>
|
|
12671
14276
|
}
|
|
12672
14277
|
@case ('number') {
|
|
12673
14278
|
<sds-input-number
|
|
@@ -12682,6 +14287,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12682
14287
|
[maxFractionDigits]="col.maxFractionDigits ?? null"
|
|
12683
14288
|
[placeholder]="col.placeholder ?? ''"
|
|
12684
14289
|
[ariaLabel]="col.header"
|
|
14290
|
+
[invalid]="!!cellErrorFor(row, col.field)"
|
|
14291
|
+
[ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
|
|
12685
14292
|
(focusout)="onEditorBlur()"
|
|
12686
14293
|
/>
|
|
12687
14294
|
}
|
|
@@ -12699,6 +14306,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12699
14306
|
[maxFractionDigits]="col.maxFractionDigits ?? null"
|
|
12700
14307
|
[placeholder]="col.placeholder ?? ''"
|
|
12701
14308
|
[ariaLabel]="col.header"
|
|
14309
|
+
[invalid]="!!cellErrorFor(row, col.field)"
|
|
14310
|
+
[ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
|
|
12702
14311
|
(focusout)="onEditorBlur()"
|
|
12703
14312
|
/>
|
|
12704
14313
|
}
|
|
@@ -12706,10 +14315,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12706
14315
|
<input
|
|
12707
14316
|
data-sds-cell-editor
|
|
12708
14317
|
type="text"
|
|
12709
|
-
class="
|
|
14318
|
+
[class]="editorClass(row, col) + ' px-2.5 placeholder:text-ink-faint'"
|
|
12710
14319
|
[value]="draftText()"
|
|
12711
14320
|
[placeholder]="col.placeholder ?? ''"
|
|
12712
14321
|
[attr.aria-label]="col.header"
|
|
14322
|
+
[attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
|
|
14323
|
+
[attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
|
|
12713
14324
|
(input)="onTextEditorInput($event)"
|
|
12714
14325
|
(blur)="onEditorBlur()"
|
|
12715
14326
|
/>
|
|
@@ -12765,7 +14376,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12765
14376
|
[attr.colspan]="totalColumnCount()"
|
|
12766
14377
|
class="py-10 text-center text-ink-faint"
|
|
12767
14378
|
>
|
|
12768
|
-
|
|
14379
|
+
@if (emptyTemplate(); as tpl) {
|
|
14380
|
+
<ng-container
|
|
14381
|
+
[ngTemplateOutlet]="tpl"
|
|
14382
|
+
[ngTemplateOutletContext]="{ $implicit: filterText(), filterText: filterText() }"
|
|
14383
|
+
/>
|
|
14384
|
+
} @else {
|
|
14385
|
+
{{ emptyMessage() }}
|
|
14386
|
+
}
|
|
12769
14387
|
</td>
|
|
12770
14388
|
</tr>
|
|
12771
14389
|
}
|
|
@@ -12811,7 +14429,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12811
14429
|
</div>
|
|
12812
14430
|
`,
|
|
12813
14431
|
}]
|
|
12814
|
-
}], 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 }] }], 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 }] }], 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 }] }] } });
|
|
12815
14433
|
|
|
12816
14434
|
/**
|
|
12817
14435
|
* A tiny transient-notification bus. Application code calls {@link success} / {@link error} / {@link info}
|
|
@@ -12823,7 +14441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12823
14441
|
*
|
|
12824
14442
|
* ```ts
|
|
12825
14443
|
* private readonly toasts = inject(SdsToastService);
|
|
12826
|
-
* this.toasts.success('
|
|
14444
|
+
* this.toasts.success('Saved.');
|
|
12827
14445
|
* ```
|
|
12828
14446
|
*
|
|
12829
14447
|
* Mount the host once (e.g. in the shell): `<sds-toast-host />`.
|
|
@@ -12873,10 +14491,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
12873
14491
|
class SdsToastHost {
|
|
12874
14492
|
toasts = inject(SdsToastService);
|
|
12875
14493
|
/**
|
|
12876
|
-
* Accessible name for each toast's close button.
|
|
12877
|
-
*
|
|
14494
|
+
* Accessible name for each toast's close button. English default; the button is icon-only, so an app
|
|
14495
|
+
* serving more than one language MUST translate it.
|
|
12878
14496
|
*/
|
|
12879
|
-
closeLabel = input('
|
|
14497
|
+
closeLabel = input('Close', ...(ngDevMode ? [{ debugName: "closeLabel" }] : []));
|
|
12880
14498
|
errors = computed(() => this.toasts.toasts().filter((t) => t.kind === 'error'), ...(ngDevMode ? [{ debugName: "errors" }] : []));
|
|
12881
14499
|
notices = computed(() => this.toasts.toasts().filter((t) => t.kind !== 'error'), ...(ngDevMode ? [{ debugName: "notices" }] : []));
|
|
12882
14500
|
icon(kind) {
|
|
@@ -13059,11 +14677,11 @@ class SdsThemeToggle {
|
|
|
13059
14677
|
/** `surface` for light/glass bars, `on-brand` for the dark brand bar. */
|
|
13060
14678
|
appearance = input('surface', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
13061
14679
|
/**
|
|
13062
|
-
* Accessible names for the two actions.
|
|
13063
|
-
*
|
|
14680
|
+
* Accessible names for the two actions. English defaults; a multilingual app must pass translated
|
|
14681
|
+
* values.
|
|
13064
14682
|
*/
|
|
13065
|
-
darkLabel = input('
|
|
13066
|
-
lightLabel = input('
|
|
14683
|
+
darkLabel = input('Switch to dark mode', ...(ngDevMode ? [{ debugName: "darkLabel" }] : []));
|
|
14684
|
+
lightLabel = input('Switch to light mode', ...(ngDevMode ? [{ debugName: "lightLabel" }] : []));
|
|
13067
14685
|
iconSize = computed(() => Math.round(this.size() * 0.5), ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
|
|
13068
14686
|
label = computed(() => (this.isDark() ? this.lightLabel() : this.darkLabel()), ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
13069
14687
|
buttonClasses = computed(() => this.appearance() === 'on-brand'
|
|
@@ -13204,11 +14822,10 @@ class SdsTopbar {
|
|
|
13204
14822
|
/** Show the mobile hamburger that toggles the sidebar drawer (< lg). */
|
|
13205
14823
|
menuButton = input(true, ...(ngDevMode ? [{ debugName: "menuButton", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
13206
14824
|
/**
|
|
13207
|
-
* Accessible name for the hamburger.
|
|
13208
|
-
*
|
|
13209
|
-
* aria-label is its only name, and a hardcoded one is simply wrong in every other locale.
|
|
14825
|
+
* Accessible name for the hamburger. English default; any app serving more than one language MUST
|
|
14826
|
+
* pass a translated value — an icon-only control's aria-label is its only name.
|
|
13210
14827
|
*/
|
|
13211
|
-
menuLabel = input('
|
|
14828
|
+
menuLabel = input('Open menu', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
|
|
13212
14829
|
/**
|
|
13213
14830
|
* `brand` (default) paints the gradient and the wave; `surface` is white on a hairline border;
|
|
13214
14831
|
* `glass` is a translucent, brand-tinted bar with a backdrop blur.
|
|
@@ -13549,7 +15166,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
13549
15166
|
* @example
|
|
13550
15167
|
* <sds-sidebar appearance="surface" decorations>
|
|
13551
15168
|
* <sds-nav-group label="Membres">
|
|
13552
|
-
* <sds-nav-item icon="user-plus" label="
|
|
15169
|
+
* <sds-nav-item icon="user-plus" label="Add a member" link="/members/new" />
|
|
13553
15170
|
* </sds-nav-group>
|
|
13554
15171
|
* <div sdsFooter>…</div>
|
|
13555
15172
|
* </sds-sidebar>
|
|
@@ -13589,12 +15206,12 @@ class SdsSidebar {
|
|
|
13589
15206
|
});
|
|
13590
15207
|
}
|
|
13591
15208
|
/**
|
|
13592
|
-
* Accessible names for the rail's three icon-only controls.
|
|
13593
|
-
*
|
|
15209
|
+
* Accessible names for the rail's three icon-only controls. English defaults; a multilingual app
|
|
15210
|
+
* must pass translated values.
|
|
13594
15211
|
*/
|
|
13595
|
-
collapseLabel = input('
|
|
13596
|
-
expandLabel = input('
|
|
13597
|
-
closeLabel = input('
|
|
15212
|
+
collapseLabel = input('Collapse menu', ...(ngDevMode ? [{ debugName: "collapseLabel" }] : []));
|
|
15213
|
+
expandLabel = input('Expand menu', ...(ngDevMode ? [{ debugName: "expandLabel" }] : []));
|
|
15214
|
+
closeLabel = input('Close menu', ...(ngDevMode ? [{ debugName: "closeLabel" }] : []));
|
|
13598
15215
|
/** `brand` (default) is the dark rail; `surface` is a light rail with brand accents. */
|
|
13599
15216
|
appearance = input('brand', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
13600
15217
|
/** Add slow-drifting brand-tinted blobs behind the rail (opt-in). */
|
|
@@ -14246,8 +15863,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
14246
15863
|
* @example
|
|
14247
15864
|
* <sds-user-menu name="Souhail AIT SAID" email="souhail@example.com" status="online" appearance="surface">
|
|
14248
15865
|
* <sds-menu-item icon="user" label="Profil" link="/profile" />
|
|
14249
|
-
* <sds-menu-item icon="settings" label="
|
|
14250
|
-
* <sds-menu-item icon="log-out" label="
|
|
15866
|
+
* <sds-menu-item icon="settings" label="Settings" link="/settings" />
|
|
15867
|
+
* <sds-menu-item icon="log-out" label="Sign out" tone="danger" (select)="signOut()" />
|
|
14251
15868
|
* </sds-user-menu>
|
|
14252
15869
|
*/
|
|
14253
15870
|
class SdsUserMenu {
|
|
@@ -14269,7 +15886,7 @@ class SdsUserMenu {
|
|
|
14269
15886
|
/** Override the trigger avatar's initials background; defaults per appearance. */
|
|
14270
15887
|
avatarBgClass = input(null, ...(ngDevMode ? [{ debugName: "avatarBgClass" }] : []));
|
|
14271
15888
|
/** Accessible name for the trigger (icon/avatar only when details are hidden). */
|
|
14272
|
-
menuLabel = input('
|
|
15889
|
+
menuLabel = input('Account menu', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
|
|
14273
15890
|
openChange = output();
|
|
14274
15891
|
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
14275
15892
|
toggle() {
|
|
@@ -14376,7 +15993,7 @@ class SdsUserMenu {
|
|
|
14376
15993
|
</div>
|
|
14377
15994
|
</div>
|
|
14378
15995
|
}
|
|
14379
|
-
`, 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 });
|
|
14380
15997
|
}
|
|
14381
15998
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsUserMenu, decorators: [{
|
|
14382
15999
|
type: Component,
|
|
@@ -14465,7 +16082,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
14465
16082
|
* @example
|
|
14466
16083
|
* <sds-menu-item icon="user" label="Profil" link="/profile" /> <!-- in-app route -->
|
|
14467
16084
|
* <sds-menu-item icon="external-link" label="Site public" href="https://…" target="_blank" />
|
|
14468
|
-
* <sds-menu-item icon="log-out" label="
|
|
16085
|
+
* <sds-menu-item icon="log-out" label="Sign out" tone="danger" (select)="signOut()" />
|
|
14469
16086
|
*/
|
|
14470
16087
|
class SdsMenuItem {
|
|
14471
16088
|
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
@@ -14593,7 +16210,7 @@ class SdsSearchCommand {
|
|
|
14593
16210
|
/** The searchable entries. Order is preserved; when the field is empty they show as quick navigation. */
|
|
14594
16211
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
14595
16212
|
/** Placeholder on the trigger pill and the search field. */
|
|
14596
|
-
placeholder = input('
|
|
16213
|
+
placeholder = input('Search…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
14597
16214
|
/** Show the built-in trigger pill. Turn off to drive the palette from your own control (`cmd.open()`). */
|
|
14598
16215
|
showTrigger = input(true, ...(ngDevMode ? [{ debugName: "showTrigger", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
14599
16216
|
/** Enable the global ⌘K / Ctrl-K shortcut. */
|
|
@@ -14603,15 +16220,15 @@ class SdsSearchCommand {
|
|
|
14603
16220
|
/** `surface` (default) for a light / glass bar; `on-brand` for the dark brand bar. */
|
|
14604
16221
|
appearance = input('surface', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
14605
16222
|
/**
|
|
14606
|
-
* User-facing copy.
|
|
14607
|
-
* field share `placeholder`, and `searchLabel` is the accessible name for both).
|
|
16223
|
+
* User-facing copy. English defaults; a multilingual app passes translated values (the trigger and
|
|
16224
|
+
* the field share `placeholder`, and `searchLabel` is the accessible name for both).
|
|
14608
16225
|
*/
|
|
14609
|
-
searchLabel = input('
|
|
14610
|
-
clearLabel = input('
|
|
14611
|
-
emptyLabel = input('
|
|
14612
|
-
selectHint = input('
|
|
14613
|
-
navigateHint = input('
|
|
14614
|
-
closeHint = input('
|
|
16226
|
+
searchLabel = input('Search', ...(ngDevMode ? [{ debugName: "searchLabel" }] : []));
|
|
16227
|
+
clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
|
|
16228
|
+
emptyLabel = input('No results', ...(ngDevMode ? [{ debugName: "emptyLabel" }] : []));
|
|
16229
|
+
selectHint = input('Select', ...(ngDevMode ? [{ debugName: "selectHint" }] : []));
|
|
16230
|
+
navigateHint = input('Navigate', ...(ngDevMode ? [{ debugName: "navigateHint" }] : []));
|
|
16231
|
+
closeHint = input('Close', ...(ngDevMode ? [{ debugName: "closeHint" }] : []));
|
|
14615
16232
|
select = output();
|
|
14616
16233
|
openChange = output();
|
|
14617
16234
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
@@ -15085,8 +16702,8 @@ class SdsLanguageSwitcher {
|
|
|
15085
16702
|
/** `up` prefers opening the panel above the trigger — for a switcher near the bottom of the page. */
|
|
15086
16703
|
direction = input('down', ...(ngDevMode ? [{ debugName: "direction" }] : []));
|
|
15087
16704
|
/** Accessible name for the trigger and panel. */
|
|
15088
|
-
menuLabel = input('
|
|
15089
|
-
/** Optional visible header above the list (e.g. "
|
|
16705
|
+
menuLabel = input('Choose language', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
|
|
16706
|
+
/** Optional visible header above the list (e.g. "Language"). Omitted when empty. */
|
|
15090
16707
|
heading = input('', ...(ngDevMode ? [{ debugName: "heading" }] : []));
|
|
15091
16708
|
openChange = output();
|
|
15092
16709
|
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
@@ -15450,5 +17067,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
15450
17067
|
* Generated bundle index. Do not edit.
|
|
15451
17068
|
*/
|
|
15452
17069
|
|
|
15453
|
-
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, 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 };
|
|
15454
17071
|
//# sourceMappingURL=besaitech-ng-design-system.mjs.map
|