@besaitech/ng-design-system 0.0.68 → 0.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/besaitech-ng-design-system.mjs +831 -281
- package/fesm2022/besaitech-ng-design-system.mjs.map +1 -1
- package/index.d.ts +242 -87
- package/package.json +1 -1
|
@@ -418,7 +418,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
418
418
|
`, 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"] }]
|
|
419
419
|
}], 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 }] }] } });
|
|
420
420
|
|
|
421
|
-
let nextId$
|
|
421
|
+
let nextId$q = 0;
|
|
422
422
|
const SIZES$d = {
|
|
423
423
|
sm: 'h-9 text-sm',
|
|
424
424
|
md: 'h-10 text-sm',
|
|
@@ -431,7 +431,7 @@ const SIZES$d = {
|
|
|
431
431
|
* sidebar search field).
|
|
432
432
|
*/
|
|
433
433
|
class SdsInput {
|
|
434
|
-
autoId = `sds-input-${nextId$
|
|
434
|
+
autoId = `sds-input-${nextId$q++}`;
|
|
435
435
|
/**
|
|
436
436
|
* `id` of the native `<input>` — for a `<label for>` outside the component, or to focus the field with
|
|
437
437
|
* `document.getElementById(id).focus()` (after adding a row, say). Empty (default) generates one. Set it
|
|
@@ -791,7 +791,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
791
791
|
`, 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"] }]
|
|
792
792
|
}], propDecorators: { inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], 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 }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", 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"] }] } });
|
|
793
793
|
|
|
794
|
-
let nextId$
|
|
794
|
+
let nextId$p = 0;
|
|
795
795
|
const HEIGHTS = {
|
|
796
796
|
sm: 'h-9',
|
|
797
797
|
md: 'h-10',
|
|
@@ -819,7 +819,7 @@ const TEXT = {
|
|
|
819
819
|
* with "." ("1.234" in nl-BE) stays a thousands separator.
|
|
820
820
|
*/
|
|
821
821
|
class SdsInputNumber {
|
|
822
|
-
inputId = `sds-input-number-${nextId$
|
|
822
|
+
inputId = `sds-input-number-${nextId$p++}`;
|
|
823
823
|
fieldRef = viewChild('field', ...(ngDevMode ? [{ debugName: "fieldRef" }] : []));
|
|
824
824
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
825
825
|
/** Accessible name used when no visible [label] is provided. */
|
|
@@ -1603,7 +1603,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
1603
1603
|
}]
|
|
1604
1604
|
}], 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 }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", 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 }] }] } });
|
|
1605
1605
|
|
|
1606
|
-
let nextId$
|
|
1606
|
+
let nextId$o = 0;
|
|
1607
1607
|
const SIZES$c = {
|
|
1608
1608
|
sm: 'h-9 text-sm',
|
|
1609
1609
|
md: 'h-10 text-sm',
|
|
@@ -1644,7 +1644,7 @@ function parseTime(value) {
|
|
|
1644
1644
|
* <sds-time-input [ariaLabel]="'Closes at'" [ngModel]="end()" (ngModelChange)="end.set($event)" clearable />
|
|
1645
1645
|
*/
|
|
1646
1646
|
class SdsTimeInput {
|
|
1647
|
-
fieldId = `sds-time-input-${nextId$
|
|
1647
|
+
fieldId = `sds-time-input-${nextId$o++}`;
|
|
1648
1648
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
1649
1649
|
/** Accessible name of the field when there is no visible [label]. */
|
|
1650
1650
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -2173,7 +2173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2173
2173
|
}]
|
|
2174
2174
|
}], 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 }] }] } });
|
|
2175
2175
|
|
|
2176
|
-
let nextId$
|
|
2176
|
+
let nextId$n = 0;
|
|
2177
2177
|
const SIZES$b = {
|
|
2178
2178
|
sm: 'min-h-9 text-sm',
|
|
2179
2179
|
md: 'min-h-10 text-sm',
|
|
@@ -2196,7 +2196,7 @@ const SIZES$b = {
|
|
|
2196
2196
|
* `<sds-localized-input [languages]="['fr','nl','en']" [(ngModel)]="title" />`.
|
|
2197
2197
|
*/
|
|
2198
2198
|
class SdsLocalizedInput {
|
|
2199
|
-
autoId = `sds-localized-input-${nextId$
|
|
2199
|
+
autoId = `sds-localized-input-${nextId$n++}`;
|
|
2200
2200
|
/** The native field's id; a generated one when empty (set it to pair an external `<label for>`). */
|
|
2201
2201
|
inputId = input('', ...(ngDevMode ? [{ debugName: "inputId" }] : []));
|
|
2202
2202
|
/** The native field's id: {@link inputId} or the generated one. */
|
|
@@ -2556,7 +2556,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2556
2556
|
}]
|
|
2557
2557
|
}], propDecorators: { inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", 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 }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], requiredLanguages: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredLanguages", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", 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 }] }], requiredLanguageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredLanguageLabel", required: false }] }] } });
|
|
2558
2558
|
|
|
2559
|
-
let nextId$
|
|
2559
|
+
let nextId$m = 0;
|
|
2560
2560
|
const SIZES$a = {
|
|
2561
2561
|
md: 'h-12 w-11 text-lg',
|
|
2562
2562
|
lg: 'h-14 w-12 text-xl',
|
|
@@ -2573,7 +2573,7 @@ const SIZES$a = {
|
|
|
2573
2573
|
* first box and have it land correctly.
|
|
2574
2574
|
*/
|
|
2575
2575
|
class SdsOtpInput {
|
|
2576
|
-
groupId = `sds-otp-${nextId$
|
|
2576
|
+
groupId = `sds-otp-${nextId$m++}`;
|
|
2577
2577
|
/** How many boxes / characters the code has. */
|
|
2578
2578
|
length = input(6, ...(ngDevMode ? [{ debugName: "length", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
2579
2579
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
@@ -2873,7 +2873,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
2873
2873
|
}]
|
|
2874
2874
|
}], 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 }] }] } });
|
|
2875
2875
|
|
|
2876
|
-
let nextId$
|
|
2876
|
+
let nextId$l = 0;
|
|
2877
2877
|
const SIZES$9 = {
|
|
2878
2878
|
sm: 'text-sm px-3 py-2',
|
|
2879
2879
|
md: 'text-sm px-3.5 py-2.5',
|
|
@@ -2885,7 +2885,7 @@ const SIZES$9 = {
|
|
|
2885
2885
|
* [(ngModel)].
|
|
2886
2886
|
*/
|
|
2887
2887
|
class SdsTextarea {
|
|
2888
|
-
fieldId = `sds-textarea-${nextId$
|
|
2888
|
+
fieldId = `sds-textarea-${nextId$l++}`;
|
|
2889
2889
|
field = viewChild('field', ...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
2890
2890
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2891
2891
|
/** Accessible name used when no visible [label] is provided. */
|
|
@@ -3152,7 +3152,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3152
3152
|
}]
|
|
3153
3153
|
}], 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 }] }] } });
|
|
3154
3154
|
|
|
3155
|
-
let nextId$
|
|
3155
|
+
let nextId$k = 0;
|
|
3156
3156
|
const SIZES$8 = {
|
|
3157
3157
|
sm: { track: 'h-5 w-9', knob: 'h-4 w-4', on: 'translate-x-4', icon: 11 },
|
|
3158
3158
|
md: { track: 'h-6 w-11', knob: 'h-5 w-5', on: 'translate-x-5', icon: 13 },
|
|
@@ -3165,7 +3165,7 @@ const SIZES$8 = {
|
|
|
3165
3165
|
* states.
|
|
3166
3166
|
*/
|
|
3167
3167
|
class SdsToggleSwitch {
|
|
3168
|
-
fieldId = `sds-toggle-switch-${nextId$
|
|
3168
|
+
fieldId = `sds-toggle-switch-${nextId$k++}`;
|
|
3169
3169
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3170
3170
|
/** Accessible name used when no visible [label] is provided. */
|
|
3171
3171
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -3412,7 +3412,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3412
3412
|
}]
|
|
3413
3413
|
}], 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 }] }] } });
|
|
3414
3414
|
|
|
3415
|
-
let nextId$
|
|
3415
|
+
let nextId$j = 0;
|
|
3416
3416
|
/**
|
|
3417
3417
|
* Boolean checkbox. Implements ControlValueAccessor — use with reactive forms
|
|
3418
3418
|
* or `[(ngModel)]`. Renders a styled box (brand-filled with a check when on)
|
|
@@ -3427,7 +3427,7 @@ let nextId$i = 0;
|
|
|
3427
3427
|
* <sds-checkbox label="Auto-merge" [(ngModel)]="autoMerge" />
|
|
3428
3428
|
*/
|
|
3429
3429
|
class SdsCheckbox {
|
|
3430
|
-
id = `sds-checkbox-${nextId$
|
|
3430
|
+
id = `sds-checkbox-${nextId$j++}`;
|
|
3431
3431
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3432
3432
|
/** Accessible name used when no visible [label] is provided. */
|
|
3433
3433
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -3575,7 +3575,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
3575
3575
|
}]
|
|
3576
3576
|
}], 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 }] }] } });
|
|
3577
3577
|
|
|
3578
|
-
let nextId$
|
|
3578
|
+
let nextId$i = 0;
|
|
3579
3579
|
/**
|
|
3580
3580
|
* Mounted radios by group name. A pick updates the rest of its group, because a native radio says
|
|
3581
3581
|
* nothing when the browser unchecks it — without this a reactive form would leave the old choice drawn.
|
|
@@ -3601,7 +3601,7 @@ const groups = new Map();
|
|
|
3601
3601
|
* <sds-radio name="size" value="large" label="Grand" [(ngModel)]="size" />
|
|
3602
3602
|
*/
|
|
3603
3603
|
class SdsRadio {
|
|
3604
|
-
id = `sds-radio-${nextId$
|
|
3604
|
+
id = `sds-radio-${nextId$i++}`;
|
|
3605
3605
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3606
3606
|
/** Accessible name used when no visible [label] is provided. */
|
|
3607
3607
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -4177,7 +4177,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4177
4177
|
|
|
4178
4178
|
/** Activation order: none → contains → may-contain → none. */
|
|
4179
4179
|
const ORDER = ['none', 'contains', 'may-contain'];
|
|
4180
|
-
let nextId$
|
|
4180
|
+
let nextId$h = 0;
|
|
4181
4181
|
/**
|
|
4182
4182
|
* A chip that cycles through three states — `none`, `contains`, `may-contain` — built for the 14-tile
|
|
4183
4183
|
* allergen declaration grid, but generic (any "no / yes / maybe" declaration).
|
|
@@ -4197,7 +4197,7 @@ let nextId$g = 0;
|
|
|
4197
4197
|
* containsLabel="Contains" mayContainLabel="May contain" noneLabel="Not present" />
|
|
4198
4198
|
*/
|
|
4199
4199
|
class SdsTriStateChip {
|
|
4200
|
-
chipId = `sds-tri-state-chip-${nextId$
|
|
4200
|
+
chipId = `sds-tri-state-chip-${nextId$h++}`;
|
|
4201
4201
|
/** Current state. Two-way: `[(value)]`. */
|
|
4202
4202
|
value = model('none', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
4203
4203
|
/** Visible name (e.g. the allergen). Required — the chip has no other accessible name. */
|
|
@@ -4422,7 +4422,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4422
4422
|
}]
|
|
4423
4423
|
}], 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 }] }] } });
|
|
4424
4424
|
|
|
4425
|
-
let nextId$
|
|
4425
|
+
let nextId$g = 0;
|
|
4426
4426
|
/**
|
|
4427
4427
|
* Segmented control: a small set of mutually exclusive options shown side by side (e.g. "Pick exactly /
|
|
4428
4428
|
* at least / up to"). Radio-group semantics: `role="radiogroup"` with `role="radio"` segments, one tab
|
|
@@ -4438,7 +4438,7 @@ let nextId$f = 0;
|
|
|
4438
4438
|
*/
|
|
4439
4439
|
class SdsSegmented {
|
|
4440
4440
|
host = inject(ElementRef);
|
|
4441
|
-
baseId = `sds-segmented-${nextId$
|
|
4441
|
+
baseId = `sds-segmented-${nextId$g++}`;
|
|
4442
4442
|
/** Options: `{ value, label, icon?, disabled? }` objects, or bare strings/numbers. */
|
|
4443
4443
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
4444
4444
|
/** Selected value. Two-way: `[(value)]`. */
|
|
@@ -4716,7 +4716,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
4716
4716
|
`,
|
|
4717
4717
|
}]
|
|
4718
4718
|
}], 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 }] }] } });
|
|
4719
|
-
let nextId$
|
|
4719
|
+
let nextId$f = 0;
|
|
4720
4720
|
/**
|
|
4721
4721
|
* A set of chips: pick ONE (a filter row such as "All · Missing photo · Hidden", VAT presets, a date
|
|
4722
4722
|
* range) or, with `multiple`, SEVERAL (categories of an item, days of the week, dietary tags). Unlike
|
|
@@ -4739,7 +4739,7 @@ let nextId$e = 0;
|
|
|
4739
4739
|
*/
|
|
4740
4740
|
class SdsChipGroup {
|
|
4741
4741
|
host = inject(ElementRef);
|
|
4742
|
-
baseId = `sds-chip-group-${nextId$
|
|
4742
|
+
baseId = `sds-chip-group-${nextId$f++}`;
|
|
4743
4743
|
/** Options: `{ value, label, icon?, count?, disabled? }` objects, or bare strings/numbers. */
|
|
4744
4744
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
4745
4745
|
/** Picked value (single) or values (multiple). Two-way: `[(value)]`. */
|
|
@@ -5641,7 +5641,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
5641
5641
|
}]
|
|
5642
5642
|
}], 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"] }] } });
|
|
5643
5643
|
|
|
5644
|
-
let nextId$
|
|
5644
|
+
let nextId$e = 0;
|
|
5645
5645
|
/**
|
|
5646
5646
|
* Marks the element inside `<sds-menu>` that opens it. It may be a native button or a component that
|
|
5647
5647
|
* renders one (e.g. `<sds-button sdsMenuTrigger>`): the menu wires `aria-haspopup`, `aria-expanded` and
|
|
@@ -5689,7 +5689,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
5689
5689
|
class SdsMenu {
|
|
5690
5690
|
host = inject(ElementRef);
|
|
5691
5691
|
injector = inject(Injector);
|
|
5692
|
-
menuId = `sds-menu-${nextId$
|
|
5692
|
+
menuId = `sds-menu-${nextId$e++}`;
|
|
5693
5693
|
triggerId = `${this.menuId}-trigger`;
|
|
5694
5694
|
/** Actions and separators, in order. */
|
|
5695
5695
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
@@ -6285,7 +6285,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
6285
6285
|
standalone: true,
|
|
6286
6286
|
}]
|
|
6287
6287
|
}] });
|
|
6288
|
-
let nextId$
|
|
6288
|
+
let nextId$d = 0;
|
|
6289
6289
|
/** Fastest auto-scroll step, in px per animation frame (reached at the very edge). */
|
|
6290
6290
|
const AUTO_SCROLL_MAX_STEP = 18;
|
|
6291
6291
|
/** The nearest ancestor that scrolls vertically (below the document, which is handled as the window). */
|
|
@@ -6354,7 +6354,7 @@ function moveItem(list, from, to) {
|
|
|
6354
6354
|
class SdsSortableList {
|
|
6355
6355
|
host = inject(ElementRef);
|
|
6356
6356
|
injector = inject(Injector);
|
|
6357
|
-
instructionsId = `sds-sortable-${nextId$
|
|
6357
|
+
instructionsId = `sds-sortable-${nextId$d++}-help`;
|
|
6358
6358
|
/** The items, in order. Two-way: `[(items)]` receives the new order on drop. */
|
|
6359
6359
|
items = model([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
6360
6360
|
/** Property used as a stable identity for rows (strongly recommended). */
|
|
@@ -6946,7 +6946,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
6946
6946
|
}]
|
|
6947
6947
|
}], 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 }] }] } });
|
|
6948
6948
|
|
|
6949
|
-
let nextId$
|
|
6949
|
+
let nextId$c = 0;
|
|
6950
6950
|
/** "1.5 MB" style size (decimal units, like file managers show them), for messages. */
|
|
6951
6951
|
function sdsFormatBytes(bytes) {
|
|
6952
6952
|
if (!Number.isFinite(bytes) || bytes < 0)
|
|
@@ -7003,7 +7003,7 @@ function sdsFileMatchesAccept(file, accept) {
|
|
|
7003
7003
|
* (files)="upload($event)" (rejected)="onRejected($event)" />
|
|
7004
7004
|
*/
|
|
7005
7005
|
class SdsFileDrop {
|
|
7006
|
-
zoneId = `sds-file-drop-${nextId$
|
|
7006
|
+
zoneId = `sds-file-drop-${nextId$c++}`;
|
|
7007
7007
|
fileInput = viewChild('fileInput', ...(ngDevMode ? [{ debugName: "fileInput" }] : []));
|
|
7008
7008
|
/** Accepted types, native `accept` syntax. Empty = anything. */
|
|
7009
7009
|
accept = input('', ...(ngDevMode ? [{ debugName: "accept" }] : []));
|
|
@@ -7385,7 +7385,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
7385
7385
|
}]
|
|
7386
7386
|
}], propDecorators: { fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], dropLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropLabel", required: false }] }], browseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "browseLabel", required: false }] }], loadingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingLabel", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], wrongTypeMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrongTypeMessage", required: false }] }], tooLargeMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooLargeMessage", required: false }] }], tooManyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooManyMessage", required: false }] }], files: [{ type: i0.Output, args: ["files"] }], rejected: [{ type: i0.Output, args: ["rejected"] }] } });
|
|
7387
7387
|
|
|
7388
|
-
let nextId$
|
|
7388
|
+
let nextId$b = 0;
|
|
7389
7389
|
/**
|
|
7390
7390
|
* Crops an image to a FIXED aspect ratio (e.g. the shop's card ratio): the frame is fixed and the image
|
|
7391
7391
|
* moves and zooms behind it, always covering the frame, so every crop is valid.
|
|
@@ -7403,7 +7403,7 @@ let nextId$a = 0;
|
|
|
7403
7403
|
* <sds-button (click)="upload(await cropper.toBlob({ width: 1600 }))">Save</sds-button>
|
|
7404
7404
|
*/
|
|
7405
7405
|
class SdsImageCropper {
|
|
7406
|
-
helpId = `sds-image-cropper-${nextId$
|
|
7406
|
+
helpId = `sds-image-cropper-${nextId$b++}-help`;
|
|
7407
7407
|
viewport = viewChild('viewport', ...(ngDevMode ? [{ debugName: "viewport" }] : []));
|
|
7408
7408
|
/** Image to crop: a URL, or a Blob/File. */
|
|
7409
7409
|
src = input(null, ...(ngDevMode ? [{ debugName: "src" }] : []));
|
|
@@ -8789,7 +8789,7 @@ const SIZES$7 = {
|
|
|
8789
8789
|
class SdsDatePicker {
|
|
8790
8790
|
host = inject(ElementRef);
|
|
8791
8791
|
injector = inject(Injector);
|
|
8792
|
-
fieldId = `sds-date-${nextId$
|
|
8792
|
+
fieldId = `sds-date-${nextId$a++}`;
|
|
8793
8793
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
8794
8794
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
8795
8795
|
placeholder = input('dd/mm/yyyy', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
@@ -9307,7 +9307,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
9307
9307
|
`,
|
|
9308
9308
|
}]
|
|
9309
9309
|
}], 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 }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTime", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], timeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeLabel", required: false }] }], hoursLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoursLabel", required: false }] }], minutesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "minutesLabel", required: false }] }], doneLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "doneLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], openCalendarLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "openCalendarLabel", required: false }] }], closeCalendarLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeCalendarLabel", required: false }] }], panelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelLabel", required: false }] }], calendarLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarLabel", required: false }] }], previousLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], todayActionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "todayActionLabel", required: false }] }], clearActionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearActionLabel", required: false }] }], calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdsCalendar), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
|
|
9310
|
-
let nextId$
|
|
9310
|
+
let nextId$a = 0;
|
|
9311
9311
|
|
|
9312
9312
|
/** Same first and last day (time-of-day ignored). `null` only equals `null`. */
|
|
9313
9313
|
function isSameRange(a, b) {
|
|
@@ -9912,7 +9912,7 @@ const SIZES$6 = {
|
|
|
9912
9912
|
class SdsDateRangePicker {
|
|
9913
9913
|
host = inject(ElementRef);
|
|
9914
9914
|
injector = inject(Injector);
|
|
9915
|
-
uid = nextId$
|
|
9915
|
+
uid = nextId$9++;
|
|
9916
9916
|
fieldId = `sds-date-range-${this.uid}`;
|
|
9917
9917
|
labelId = `${this.fieldId}-label`;
|
|
9918
9918
|
valueId = `${this.fieldId}-value`;
|
|
@@ -10428,7 +10428,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
10428
10428
|
`,
|
|
10429
10429
|
}]
|
|
10430
10430
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], presets: [{ type: i0.Input, args: [{ isSignal: true, alias: "presets", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], maxDays: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDays", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], months: [{ type: i0.Input, args: [{ isSignal: true, alias: "months", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], 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 }] }], panelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelLabel", required: false }] }], presetsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetsLabel", required: false }] }], startLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "startLabel", required: false }] }], endLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "endLabel", required: false }] }], applyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "applyLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], calendarLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarLabel", required: false }] }], previousLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], presetSelect: [{ type: i0.Output, args: ["presetSelect"] }], calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdsRangeCalendar), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
|
|
10431
|
-
let nextId$
|
|
10431
|
+
let nextId$9 = 0;
|
|
10432
10432
|
|
|
10433
10433
|
/**
|
|
10434
10434
|
* Supplies a custom template for each option row (and the selected value shown
|
|
@@ -10512,7 +10512,7 @@ const SIZES$5 = {
|
|
|
10512
10512
|
md: 'h-10 text-sm',
|
|
10513
10513
|
lg: 'h-12 text-base',
|
|
10514
10514
|
};
|
|
10515
|
-
let nextId$
|
|
10515
|
+
let nextId$8 = 0;
|
|
10516
10516
|
/**
|
|
10517
10517
|
* Single-select dropdown. Options may be primitives or objects (configure via
|
|
10518
10518
|
* [optionLabel]/[optionValue]/[optionDisabled]). The overlay is appended to
|
|
@@ -10546,7 +10546,7 @@ let nextId$7 = 0;
|
|
|
10546
10546
|
class SdsSelect {
|
|
10547
10547
|
host = inject(ElementRef);
|
|
10548
10548
|
injector = inject(Injector);
|
|
10549
|
-
selectId = `sds-select-${nextId$
|
|
10549
|
+
selectId = `sds-select-${nextId$8++}`;
|
|
10550
10550
|
listId = `${this.selectId}-list`;
|
|
10551
10551
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
10552
10552
|
optionLabel = input('label', ...(ngDevMode ? [{ debugName: "optionLabel" }] : []));
|
|
@@ -11256,7 +11256,7 @@ const SIZES$4 = {
|
|
|
11256
11256
|
md: 'min-h-10 text-sm',
|
|
11257
11257
|
lg: 'min-h-12 text-base',
|
|
11258
11258
|
};
|
|
11259
|
-
let nextId$
|
|
11259
|
+
let nextId$7 = 0;
|
|
11260
11260
|
/**
|
|
11261
11261
|
* Multi-select dropdown (value is an array). Options may be primitives or
|
|
11262
11262
|
* objects (configure via [optionLabel]/[optionValue]/[optionDisabled]). The
|
|
@@ -11289,7 +11289,7 @@ let nextId$6 = 0;
|
|
|
11289
11289
|
class SdsMultiSelect {
|
|
11290
11290
|
host = inject(ElementRef);
|
|
11291
11291
|
injector = inject(Injector);
|
|
11292
|
-
selectId = `sds-multiselect-${nextId$
|
|
11292
|
+
selectId = `sds-multiselect-${nextId$7++}`;
|
|
11293
11293
|
listId = `${this.selectId}-list`;
|
|
11294
11294
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
11295
11295
|
optionLabel = input('label', ...(ngDevMode ? [{ debugName: "optionLabel" }] : []));
|
|
@@ -12172,7 +12172,7 @@ const SIZES$3 = {
|
|
|
12172
12172
|
md: 'h-10 text-sm',
|
|
12173
12173
|
lg: 'h-12 text-base',
|
|
12174
12174
|
};
|
|
12175
|
-
let nextId$
|
|
12175
|
+
let nextId$6 = 0;
|
|
12176
12176
|
/**
|
|
12177
12177
|
* International phone number input: a country selector (ISO chip + dial code)
|
|
12178
12178
|
* with a searchable, body-appended dropdown, plus a formatted national-number
|
|
@@ -12187,7 +12187,7 @@ let nextId$5 = 0;
|
|
|
12187
12187
|
class SdsPhoneInput {
|
|
12188
12188
|
host = inject(ElementRef);
|
|
12189
12189
|
injector = inject(Injector);
|
|
12190
|
-
fieldId = `sds-phone-${nextId$
|
|
12190
|
+
fieldId = `sds-phone-${nextId$6++}`;
|
|
12191
12191
|
listId = `${this.fieldId}-list`;
|
|
12192
12192
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
12193
12193
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
@@ -12945,7 +12945,7 @@ const SIZES$2 = {
|
|
|
12945
12945
|
md: 'h-10 text-sm',
|
|
12946
12946
|
lg: 'h-12 text-base',
|
|
12947
12947
|
};
|
|
12948
|
-
let nextId$
|
|
12948
|
+
let nextId$5 = 0;
|
|
12949
12949
|
/**
|
|
12950
12950
|
* Address search field — a combobox over an app-supplied geocoder. Typing (at least `minChars`
|
|
12951
12951
|
* characters) runs the `search` provider, debounced by `debounceMs`; only the latest query's response is
|
|
@@ -12980,7 +12980,7 @@ let nextId$4 = 0;
|
|
|
12980
12980
|
*/
|
|
12981
12981
|
class SdsAddressAutocomplete {
|
|
12982
12982
|
host = inject(ElementRef);
|
|
12983
|
-
autoId = `sds-address-${nextId$
|
|
12983
|
+
autoId = `sds-address-${nextId$5++}`;
|
|
12984
12984
|
locateListId = `${this.autoId}-here`;
|
|
12985
12985
|
listId = `${this.autoId}-list`;
|
|
12986
12986
|
// --- providers ------------------------------------------------------------
|
|
@@ -14251,7 +14251,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
14251
14251
|
}]
|
|
14252
14252
|
}], propDecorators: { totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], first: [{ type: i0.Input, args: [{ isSignal: true, alias: "first", required: false }] }, { type: i0.Output, args: ["firstChange"] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }, { type: i0.Output, args: ["rowsChange"] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], pageLinkSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLinkSize", required: false }] }], showFirstLastIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFirstLastIcon", required: false }] }], showPageLinks: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageLinks", required: false }] }], showCurrentPageReport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCurrentPageReport", required: false }] }], currentPageReportTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPageReportTemplate", required: false }] }], showJumpToPageInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showJumpToPageInput", required: false }] }], rowsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageLabel", required: false }] }], jumpToPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "jumpToPageLabel", 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 }] }], jumpToPageAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "jumpToPageAriaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }] } });
|
|
14253
14253
|
|
|
14254
|
-
let nextId$
|
|
14254
|
+
let nextId$4 = 0;
|
|
14255
14255
|
/**
|
|
14256
14256
|
* Coordinates a single <sds-tabs> instance: holds the active value (shared from
|
|
14257
14257
|
* the host's two-way model), tracks registered tabs for default selection and
|
|
@@ -14261,7 +14261,7 @@ let nextId$3 = 0;
|
|
|
14261
14261
|
*/
|
|
14262
14262
|
class SdsTabsStore {
|
|
14263
14263
|
/** Unique base id used to link tabs and panels via ARIA. */
|
|
14264
|
-
id = `sds-tabs-${nextId$
|
|
14264
|
+
id = `sds-tabs-${nextId$4++}`;
|
|
14265
14265
|
/** Whether the tab list scrolls horizontally (mirrors [scrollable]). */
|
|
14266
14266
|
scrollable = signal(false, ...(ngDevMode ? [{ debugName: "scrollable" }] : []));
|
|
14267
14267
|
/** Header style (mirrors [variant]). */
|
|
@@ -14877,7 +14877,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
14877
14877
|
}]
|
|
14878
14878
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }] } });
|
|
14879
14879
|
|
|
14880
|
-
let nextId$
|
|
14880
|
+
let nextId$3 = 0;
|
|
14881
14881
|
/**
|
|
14882
14882
|
* Coordinates a single <sds-accordion>: holds the open value(s) (shared from the
|
|
14883
14883
|
* host's two-way model), the multiple-open flag, and generates the ARIA ids that
|
|
@@ -14887,7 +14887,7 @@ let nextId$2 = 0;
|
|
|
14887
14887
|
*/
|
|
14888
14888
|
class SdsAccordionStore {
|
|
14889
14889
|
/** Unique base id used to link headers and content regions via ARIA. */
|
|
14890
|
-
id = `sds-accordion-${nextId$
|
|
14890
|
+
id = `sds-accordion-${nextId$3++}`;
|
|
14891
14891
|
/** Whether more than one panel may be open at a time (mirrors [multiple]). */
|
|
14892
14892
|
multiple = signal(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
14893
14893
|
value;
|
|
@@ -15293,7 +15293,7 @@ const ALIGN = {
|
|
|
15293
15293
|
center: 'text-center',
|
|
15294
15294
|
right: 'text-right',
|
|
15295
15295
|
};
|
|
15296
|
-
let nextId$
|
|
15296
|
+
let nextId$2 = 0;
|
|
15297
15297
|
/**
|
|
15298
15298
|
* Client-side data table mirroring PrimeNG's table, scoped to a strong local
|
|
15299
15299
|
* feature set: sorting, pagination (reuses {@link SdsPaginator}), global filter,
|
|
@@ -15349,7 +15349,7 @@ let nextId$1 = 0;
|
|
|
15349
15349
|
* dataKey="id" editable [cellErrors]="errors()" (cellCommit)="apply($event)" />
|
|
15350
15350
|
*/
|
|
15351
15351
|
class SdsTable {
|
|
15352
|
-
tableId = `sds-table-${nextId$
|
|
15352
|
+
tableId = `sds-table-${nextId$2++}`;
|
|
15353
15353
|
// --- inputs ---------------------------------------------------------------
|
|
15354
15354
|
value = input([], ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
15355
15355
|
columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
@@ -17612,6 +17612,8 @@ function stripUiPrefs(url) {
|
|
|
17612
17612
|
return absolute ? parsed.toString() : parsed.pathname + parsed.search + parsed.hash;
|
|
17613
17613
|
}
|
|
17614
17614
|
|
|
17615
|
+
/** The breakpoint below which the rail is the off-canvas drawer (Tailwind's `lg`). */
|
|
17616
|
+
const DRAWER_QUERY = '(max-width: 1023.98px)';
|
|
17615
17617
|
/**
|
|
17616
17618
|
* Shared collapse state for the sidebar and its nav items.
|
|
17617
17619
|
*
|
|
@@ -17620,16 +17622,45 @@ function stripUiPrefs(url) {
|
|
|
17620
17622
|
* multiple independent sidebars, provide it at a component level instead.
|
|
17621
17623
|
*/
|
|
17622
17624
|
class SidebarStore {
|
|
17623
|
-
|
|
17625
|
+
document = inject(DOCUMENT);
|
|
17626
|
+
/**
|
|
17627
|
+
* The person's desktop preference: icon-only rail. It is a PREFERENCE, not the rendered state — use
|
|
17628
|
+
* {@link railCollapsed} to know whether the rail is actually icon-only right now.
|
|
17629
|
+
*/
|
|
17624
17630
|
collapsed = signal(false, ...(ngDevMode ? [{ debugName: "collapsed" }] : []));
|
|
17631
|
+
/** True below `lg`, where the rail is the off-canvas drawer. */
|
|
17632
|
+
belowLg = signal(false, ...(ngDevMode ? [{ debugName: "belowLg" }] : []));
|
|
17633
|
+
/**
|
|
17634
|
+
* Whether the rail is icon-only RIGHT NOW: the desktop collapse applies at ≥ lg only. The mobile drawer
|
|
17635
|
+
* is always full width — reading `collapsed` there hid every collapsible group's pages behind a header
|
|
17636
|
+
* that could no longer open them (collapse on desktop, then open the drawer on a narrow screen).
|
|
17637
|
+
*/
|
|
17638
|
+
railCollapsed = computed(() => this.collapsed() && !this.belowLg(), ...(ngDevMode ? [{ debugName: "railCollapsed" }] : []));
|
|
17625
17639
|
/**
|
|
17626
17640
|
* The rail's paint, published by <sds-sidebar> so projected <sds-nav-item>/<sds-nav-group> pick the
|
|
17627
17641
|
* matching state and hover colours (white-on-dark for `brand`, ink-and-brand for `surface`) without
|
|
17628
17642
|
* every item taking an input. One rail, one appearance — set by the sidebar, read by its children.
|
|
17629
17643
|
*/
|
|
17630
17644
|
appearance = signal('brand', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
17645
|
+
/** Accordion mode, published by <sds-sidebar [accordion]>: opening one group closes the others. */
|
|
17646
|
+
accordion = signal(false, ...(ngDevMode ? [{ debugName: "accordion" }] : []));
|
|
17647
|
+
/** The collapsible group most recently opened by hand (accordion mode closes the rest). */
|
|
17648
|
+
openedGroup = signal(null, ...(ngDevMode ? [{ debugName: "openedGroup" }] : []));
|
|
17631
17649
|
/** Mobile drawer state: whether the off-canvas sidebar is slid in (< lg). */
|
|
17632
17650
|
mobileOpen = signal(false, ...(ngDevMode ? [{ debugName: "mobileOpen" }] : []));
|
|
17651
|
+
constructor() {
|
|
17652
|
+
const mql = this.document.defaultView?.matchMedia?.(DRAWER_QUERY);
|
|
17653
|
+
if (mql) {
|
|
17654
|
+
this.belowLg.set(mql.matches);
|
|
17655
|
+
mql.addEventListener('change', (e) => {
|
|
17656
|
+
this.belowLg.set(e.matches);
|
|
17657
|
+
// Growing past lg turns the drawer into the in-flow rail: a drawer left "open" would otherwise
|
|
17658
|
+
// come back, scrim and all, the next time the window narrows.
|
|
17659
|
+
if (!e.matches)
|
|
17660
|
+
this.mobileOpen.set(false);
|
|
17661
|
+
});
|
|
17662
|
+
}
|
|
17663
|
+
}
|
|
17633
17664
|
/** Toggle the desktop icon-rail. */
|
|
17634
17665
|
toggle() {
|
|
17635
17666
|
this.collapsed.update((v) => !v);
|
|
@@ -17655,7 +17686,7 @@ class SidebarStore {
|
|
|
17655
17686
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SidebarStore, decorators: [{
|
|
17656
17687
|
type: Injectable,
|
|
17657
17688
|
args: [{ providedIn: 'root' }]
|
|
17658
|
-
}] });
|
|
17689
|
+
}], ctorParameters: () => [] });
|
|
17659
17690
|
|
|
17660
17691
|
/**
|
|
17661
17692
|
* Application top bar: a logo slot, the app name, and three slots the app fills.
|
|
@@ -18031,6 +18062,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18031
18062
|
}]
|
|
18032
18063
|
}], propDecorators: { background: [{ type: i0.Input, args: [{ isSignal: true, alias: "background", required: false }] }], decorations: [{ type: i0.Input, args: [{ isSignal: true, alias: "decorations", required: false }] }] } });
|
|
18033
18064
|
|
|
18065
|
+
const SDS_NAV_GROUP = new InjectionToken('SDS_NAV_GROUP');
|
|
18066
|
+
const SDS_SIDEBAR = new InjectionToken('SDS_SIDEBAR');
|
|
18067
|
+
|
|
18034
18068
|
/**
|
|
18035
18069
|
* Collapsible navigation rail. Project <sds-nav-group>/<sds-nav-item> as the
|
|
18036
18070
|
* default content, and pin a footer (e.g. search + version badge) via the
|
|
@@ -18043,11 +18077,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18043
18077
|
*
|
|
18044
18078
|
* Responsive: below `lg` it is a fixed off-canvas drawer opened by the top bar's hamburger; it is a
|
|
18045
18079
|
* modal (scrim + trap), so while open Escape closes it, focus moves into it and is restored on close,
|
|
18046
|
-
*
|
|
18047
|
-
*
|
|
18080
|
+
* Tab is kept inside, the page behind stops scrolling, and a swipe to the left closes it. While closed
|
|
18081
|
+
* it is `inert`, so its off-screen items are out of the tab order. The drawer is always full width —
|
|
18082
|
+
* the desktop collapse preference never applies to it. At `lg` and up it is the in-flow, collapsible
|
|
18083
|
+
* rail; collapsed to icons, its collapsible groups open as flyout panels and its items show tooltips.
|
|
18084
|
+
*
|
|
18085
|
+
* Project an `[sdsHeader]` element (typically the logo + app name) to brand the drawer's header row,
|
|
18086
|
+
* and set `[accordion]` to keep a single collapsible group open at a time.
|
|
18048
18087
|
*
|
|
18049
18088
|
* @example
|
|
18050
18089
|
* <sds-sidebar appearance="surface" decorations>
|
|
18090
|
+
* <img sdsHeader class="h-7 lg:hidden" src="/logo.svg" alt="Saitech" />
|
|
18051
18091
|
* <sds-nav-group label="Membres">
|
|
18052
18092
|
* <sds-nav-item icon="user-plus" label="Add a member" link="/members/new" />
|
|
18053
18093
|
* </sds-nav-group>
|
|
@@ -18060,18 +18100,27 @@ class SdsSidebar {
|
|
|
18060
18100
|
drawer = viewChild('drawer', ...(ngDevMode ? [{ debugName: "drawer" }] : []));
|
|
18061
18101
|
closeBtn = viewChild('closeBtn', ...(ngDevMode ? [{ debugName: "closeBtn" }] : []));
|
|
18062
18102
|
/** True below the `lg` breakpoint — where the rail is the off-canvas modal drawer. */
|
|
18063
|
-
belowLg =
|
|
18103
|
+
belowLg = this.store.belowLg;
|
|
18064
18104
|
/** The element focused before the drawer opened, restored to it on close. */
|
|
18065
18105
|
restoreFocusTo = null;
|
|
18106
|
+
/** Live horizontal offset while a swipe drags the drawer closed (≤ 0). */
|
|
18107
|
+
dragX = signal(0, ...(ngDevMode ? [{ debugName: "dragX" }] : []));
|
|
18108
|
+
touch = null;
|
|
18066
18109
|
constructor() {
|
|
18067
|
-
// Publish the rail's paint so projected nav items match it.
|
|
18110
|
+
// Publish the rail's paint (and accordion mode) so projected nav groups/items match it.
|
|
18068
18111
|
effect(() => this.store.appearance.set(this.appearance()));
|
|
18069
|
-
|
|
18070
|
-
|
|
18071
|
-
|
|
18072
|
-
|
|
18073
|
-
|
|
18074
|
-
|
|
18112
|
+
effect(() => this.store.accordion.set(this.accordion()));
|
|
18113
|
+
// The page behind an open drawer must not scroll under the person's thumb.
|
|
18114
|
+
const body = this.document.body;
|
|
18115
|
+
effect(() => {
|
|
18116
|
+
const lock = this.belowLg() && this.mobileOpen();
|
|
18117
|
+
if (body)
|
|
18118
|
+
body.style.overflow = lock ? 'hidden' : '';
|
|
18119
|
+
});
|
|
18120
|
+
inject(DestroyRef).onDestroy(() => {
|
|
18121
|
+
if (body)
|
|
18122
|
+
body.style.overflow = '';
|
|
18123
|
+
});
|
|
18075
18124
|
// Modal focus handling for the mobile drawer: on open, remember what was focused (the hamburger) and
|
|
18076
18125
|
// move focus to the close button; on close, restore it. A no-op at ≥ lg, where the rail is not modal.
|
|
18077
18126
|
effect(() => {
|
|
@@ -18095,11 +18144,16 @@ class SdsSidebar {
|
|
|
18095
18144
|
collapseLabel = input('Collapse menu', ...(ngDevMode ? [{ debugName: "collapseLabel" }] : []));
|
|
18096
18145
|
expandLabel = input('Expand menu', ...(ngDevMode ? [{ debugName: "expandLabel" }] : []));
|
|
18097
18146
|
closeLabel = input('Close menu', ...(ngDevMode ? [{ debugName: "closeLabel" }] : []));
|
|
18147
|
+
/** Accessible name of the navigation landmark (e.g. "Main navigation"). */
|
|
18148
|
+
navLabel = input('', ...(ngDevMode ? [{ debugName: "navLabel" }] : []));
|
|
18098
18149
|
/** `brand` (default) is the dark rail; `surface` is a light rail with brand accents. */
|
|
18099
18150
|
appearance = input('brand', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
|
|
18151
|
+
/** Keep a single collapsible group open: opening one folds the others. */
|
|
18152
|
+
accordion = input(false, ...(ngDevMode ? [{ debugName: "accordion", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
18100
18153
|
/** Add slow-drifting brand-tinted blobs behind the rail (opt-in). */
|
|
18101
18154
|
decorations = input(false, ...(ngDevMode ? [{ debugName: "decorations", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
18102
|
-
|
|
18155
|
+
/** Icon-only right now (desktop preference, never in the mobile drawer). */
|
|
18156
|
+
railCollapsed = this.store.railCollapsed;
|
|
18103
18157
|
mobileOpen = this.store.mobileOpen;
|
|
18104
18158
|
asideClass = computed(() => {
|
|
18105
18159
|
// The rail must stay OPAQUE: as a mobile drawer it slides over page content, so a translucent stop
|
|
@@ -18116,9 +18170,45 @@ class SdsSidebar {
|
|
|
18116
18170
|
? 'text-ink-soft hover:bg-muted hover:text-ink focus-visible:ring-brand-500/40'
|
|
18117
18171
|
: 'text-white/70 hover:bg-white/10 hover:text-white focus-visible:ring-white/40', ...(ngDevMode ? [{ debugName: "railBtnClass" }] : []));
|
|
18118
18172
|
/** Desktop rail width (full vs. collapsed); mobile always uses full width. */
|
|
18119
|
-
railWidth = computed(() => this.
|
|
18173
|
+
railWidth = computed(() => this.railCollapsed()
|
|
18120
18174
|
? 'var(--sds-sidebar-w-collapsed)'
|
|
18121
18175
|
: 'var(--sds-sidebar-w)', ...(ngDevMode ? [{ debugName: "railWidth" }] : []));
|
|
18176
|
+
// --- Swipe to close (mobile drawer) ------------------------------------------------------------
|
|
18177
|
+
// The drawer follows the thumb once the gesture is clearly horizontal and leftward; released past a
|
|
18178
|
+
// fifth of its width (or 72 px) it closes, otherwise it springs back. Vertical swipes scroll the nav.
|
|
18179
|
+
onTouchStart(event) {
|
|
18180
|
+
if (!this.belowLg() || !this.mobileOpen() || event.touches.length !== 1)
|
|
18181
|
+
return;
|
|
18182
|
+
const t = event.touches[0];
|
|
18183
|
+
this.touch = { x: t.clientX, y: t.clientY, dragging: false };
|
|
18184
|
+
}
|
|
18185
|
+
onTouchMove(event) {
|
|
18186
|
+
if (!this.touch)
|
|
18187
|
+
return;
|
|
18188
|
+
const t = event.touches[0];
|
|
18189
|
+
const dx = t.clientX - this.touch.x;
|
|
18190
|
+
const dy = t.clientY - this.touch.y;
|
|
18191
|
+
if (!this.touch.dragging) {
|
|
18192
|
+
if (Math.abs(dx) < 10 && Math.abs(dy) < 10)
|
|
18193
|
+
return;
|
|
18194
|
+
if (dx >= 0 || Math.abs(dy) > Math.abs(dx)) {
|
|
18195
|
+
this.touch = null; // a scroll, or a swipe the wrong way
|
|
18196
|
+
return;
|
|
18197
|
+
}
|
|
18198
|
+
this.touch.dragging = true;
|
|
18199
|
+
}
|
|
18200
|
+
this.dragX.set(Math.min(0, dx));
|
|
18201
|
+
}
|
|
18202
|
+
onTouchEnd() {
|
|
18203
|
+
if (!this.touch)
|
|
18204
|
+
return;
|
|
18205
|
+
const width = this.drawer()?.nativeElement.offsetWidth ?? 280;
|
|
18206
|
+
const dx = this.dragX();
|
|
18207
|
+
this.touch = null;
|
|
18208
|
+
this.dragX.set(0);
|
|
18209
|
+
if (dx < -Math.min(72, width / 5))
|
|
18210
|
+
this.store.closeMobile();
|
|
18211
|
+
}
|
|
18122
18212
|
onEscape() {
|
|
18123
18213
|
if (this.mobileOpen())
|
|
18124
18214
|
this.store.closeMobile();
|
|
@@ -18150,11 +18240,11 @@ class SdsSidebar {
|
|
|
18150
18240
|
return Array.from(root.querySelectorAll(sel)).filter((el) => el.offsetParent !== null || el === this.document.activeElement);
|
|
18151
18241
|
}
|
|
18152
18242
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18153
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSidebar, isStandalone: true, selector: "sds-sidebar", inputs: { collapseLabel: { classPropertyName: "collapseLabel", publicName: "collapseLabel", isSignal: true, isRequired: false, transformFunction: null }, expandLabel: { classPropertyName: "expandLabel", publicName: "expandLabel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, decorations: { classPropertyName: "decorations", publicName: "decorations", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "block h-full" }, viewQueries: [{ propertyName: "drawer", first: true, predicate: ["drawer"], descendants: true, isSignal: true }, { propertyName: "closeBtn", first: true, predicate: ["closeBtn"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
18243
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSidebar, isStandalone: true, selector: "sds-sidebar", inputs: { collapseLabel: { classPropertyName: "collapseLabel", publicName: "collapseLabel", isSignal: true, isRequired: false, transformFunction: null }, expandLabel: { classPropertyName: "expandLabel", publicName: "expandLabel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, navLabel: { classPropertyName: "navLabel", publicName: "navLabel", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, accordion: { classPropertyName: "accordion", publicName: "accordion", isSignal: true, isRequired: false, transformFunction: null }, decorations: { classPropertyName: "decorations", publicName: "decorations", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "block h-full" }, providers: [{ provide: SDS_SIDEBAR, useExisting: forwardRef(() => SdsSidebar) }], viewQueries: [{ propertyName: "drawer", first: true, predicate: ["drawer"], descendants: true, isSignal: true }, { propertyName: "closeBtn", first: true, predicate: ["closeBtn"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
18154
18244
|
<!-- Mobile backdrop (only when the drawer is open, < lg) -->
|
|
18155
18245
|
@if (mobileOpen()) {
|
|
18156
18246
|
<div
|
|
18157
|
-
class="fixed inset-0 z-40 bg-black/
|
|
18247
|
+
class="sds-scrim fixed inset-0 z-40 bg-black/45 backdrop-blur-[2px] lg:hidden"
|
|
18158
18248
|
(click)="store.closeMobile()"
|
|
18159
18249
|
aria-hidden="true"
|
|
18160
18250
|
></div>
|
|
@@ -18167,13 +18257,19 @@ class SdsSidebar {
|
|
|
18167
18257
|
-->
|
|
18168
18258
|
<aside
|
|
18169
18259
|
#drawer
|
|
18170
|
-
class="fixed inset-y-0 left-0 z-50 flex h-full w-[var(--sds-sidebar-w)] flex-col transition-transform duration-200 ease-out lg:relative lg:z-auto lg:w-[var(--sds-rail)] lg:translate-
|
|
18260
|
+
class="fixed inset-y-0 left-0 z-50 flex h-full w-[min(var(--sds-sidebar-w),86vw)] flex-col transition-transform duration-200 ease-out motion-reduce:transition-none lg:relative lg:z-auto lg:w-[var(--sds-rail)] lg:translate-none lg:transition-[width]"
|
|
18171
18261
|
[class]="asideClass()"
|
|
18172
18262
|
[style.--sds-rail]="railWidth()"
|
|
18263
|
+
[style.transform]="dragX() ? 'translateX(' + dragX() + 'px)' : null"
|
|
18264
|
+
[style.transition]="dragX() ? 'none' : null"
|
|
18173
18265
|
[inert]="belowLg() && !mobileOpen()"
|
|
18174
18266
|
[attr.role]="belowLg() && mobileOpen() ? 'dialog' : null"
|
|
18175
18267
|
[attr.aria-modal]="belowLg() && mobileOpen() ? 'true' : null"
|
|
18176
18268
|
(keydown)="onDrawerKeydown($event)"
|
|
18269
|
+
(touchstart)="onTouchStart($event)"
|
|
18270
|
+
(touchmove)="onTouchMove($event)"
|
|
18271
|
+
(touchend)="onTouchEnd()"
|
|
18272
|
+
(touchcancel)="onTouchEnd()"
|
|
18177
18273
|
>
|
|
18178
18274
|
@if (decorations()) {
|
|
18179
18275
|
<span class="pointer-events-none absolute inset-0 overflow-hidden" aria-hidden="true">
|
|
@@ -18182,29 +18278,32 @@ class SdsSidebar {
|
|
|
18182
18278
|
</span>
|
|
18183
18279
|
}
|
|
18184
18280
|
|
|
18185
|
-
<!-- Header: collapse toggle (desktop) / close (mobile) -->
|
|
18281
|
+
<!-- Header: optional [sdsHeader] (logo) + collapse toggle (desktop) / close (mobile) -->
|
|
18186
18282
|
<div
|
|
18187
|
-
class="relative flex items-center px-3"
|
|
18188
|
-
style="height:
|
|
18189
|
-
[class]="
|
|
18283
|
+
class="relative flex shrink-0 items-center gap-2 px-3"
|
|
18284
|
+
style="height: 56px"
|
|
18285
|
+
[class]="railCollapsed() ? 'justify-center' : 'justify-between'"
|
|
18190
18286
|
>
|
|
18287
|
+
<div class="flex min-w-0 flex-1 items-center pl-1" [class.hidden]="railCollapsed()">
|
|
18288
|
+
<ng-content select="[sdsHeader]" />
|
|
18289
|
+
</div>
|
|
18191
18290
|
<button
|
|
18192
18291
|
type="button"
|
|
18193
|
-
class="hidden h-9 w-9 items-center justify-center rounded-control transition-colors focus-visible:outline-none focus-visible:ring-2 lg:inline-flex"
|
|
18292
|
+
class="hidden h-9 w-9 shrink-0 items-center justify-center rounded-control transition-colors focus-visible:outline-none focus-visible:ring-2 lg:inline-flex"
|
|
18194
18293
|
[class]="railBtnClass()"
|
|
18195
|
-
[attr.aria-label]="
|
|
18196
|
-
[attr.aria-expanded]="!
|
|
18294
|
+
[attr.aria-label]="railCollapsed() ? expandLabel() : collapseLabel()"
|
|
18295
|
+
[attr.aria-expanded]="!railCollapsed()"
|
|
18197
18296
|
(click)="store.toggle()"
|
|
18198
18297
|
>
|
|
18199
18298
|
<sds-icon
|
|
18200
|
-
[name]="
|
|
18299
|
+
[name]="railCollapsed() ? 'panel-left-open' : 'panel-left-close'"
|
|
18201
18300
|
[size]="20"
|
|
18202
18301
|
/>
|
|
18203
18302
|
</button>
|
|
18204
18303
|
<button
|
|
18205
18304
|
#closeBtn
|
|
18206
18305
|
type="button"
|
|
18207
|
-
class="inline-flex h-
|
|
18306
|
+
class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-control transition-colors focus-visible:outline-none focus-visible:ring-2 lg:hidden"
|
|
18208
18307
|
[class]="railBtnClass()"
|
|
18209
18308
|
[attr.aria-label]="closeLabel()"
|
|
18210
18309
|
(click)="store.closeMobile()"
|
|
@@ -18214,32 +18313,27 @@ class SdsSidebar {
|
|
|
18214
18313
|
</div>
|
|
18215
18314
|
|
|
18216
18315
|
<!-- Navigation -->
|
|
18217
|
-
<nav class="relative flex-1 overflow-y-auto overflow-x-hidden px-3 pb-4">
|
|
18316
|
+
<nav class="relative flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-3 pb-4" [attr.aria-label]="navLabel() || null">
|
|
18218
18317
|
<ng-content />
|
|
18219
18318
|
</nav>
|
|
18220
18319
|
|
|
18221
18320
|
<!-- Footer (search, version, …) -->
|
|
18222
|
-
<div class="relative px-3
|
|
18321
|
+
<div class="relative px-3 pt-2 pb-[max(1rem,env(safe-area-inset-bottom))]">
|
|
18223
18322
|
<ng-content select="[sdsFooter]" />
|
|
18224
18323
|
</div>
|
|
18225
18324
|
</aside>
|
|
18226
|
-
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth", "filled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18325
|
+
`, isInline: true, styles: ["@keyframes sds-scrim-in{0%{opacity:0}}.sds-scrim{animation:sds-scrim-in .18s ease-out}@media(prefers-reduced-motion:reduce){.sds-scrim{animation:none}}\n"], dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth", "filled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18227
18326
|
}
|
|
18228
18327
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSidebar, decorators: [{
|
|
18229
18328
|
type: Component,
|
|
18230
|
-
args: [{
|
|
18231
|
-
selector: 'sds-sidebar',
|
|
18232
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
18233
|
-
imports: [SdsIcon],
|
|
18234
|
-
host: {
|
|
18329
|
+
args: [{ selector: 'sds-sidebar', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdsIcon], providers: [{ provide: SDS_SIDEBAR, useExisting: forwardRef(() => SdsSidebar) }], host: {
|
|
18235
18330
|
class: 'block h-full',
|
|
18236
18331
|
'(document:keydown.escape)': 'onEscape()',
|
|
18237
|
-
},
|
|
18238
|
-
template: `
|
|
18332
|
+
}, template: `
|
|
18239
18333
|
<!-- Mobile backdrop (only when the drawer is open, < lg) -->
|
|
18240
18334
|
@if (mobileOpen()) {
|
|
18241
18335
|
<div
|
|
18242
|
-
class="fixed inset-0 z-40 bg-black/
|
|
18336
|
+
class="sds-scrim fixed inset-0 z-40 bg-black/45 backdrop-blur-[2px] lg:hidden"
|
|
18243
18337
|
(click)="store.closeMobile()"
|
|
18244
18338
|
aria-hidden="true"
|
|
18245
18339
|
></div>
|
|
@@ -18252,13 +18346,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18252
18346
|
-->
|
|
18253
18347
|
<aside
|
|
18254
18348
|
#drawer
|
|
18255
|
-
class="fixed inset-y-0 left-0 z-50 flex h-full w-[var(--sds-sidebar-w)] flex-col transition-transform duration-200 ease-out lg:relative lg:z-auto lg:w-[var(--sds-rail)] lg:translate-
|
|
18349
|
+
class="fixed inset-y-0 left-0 z-50 flex h-full w-[min(var(--sds-sidebar-w),86vw)] flex-col transition-transform duration-200 ease-out motion-reduce:transition-none lg:relative lg:z-auto lg:w-[var(--sds-rail)] lg:translate-none lg:transition-[width]"
|
|
18256
18350
|
[class]="asideClass()"
|
|
18257
18351
|
[style.--sds-rail]="railWidth()"
|
|
18352
|
+
[style.transform]="dragX() ? 'translateX(' + dragX() + 'px)' : null"
|
|
18353
|
+
[style.transition]="dragX() ? 'none' : null"
|
|
18258
18354
|
[inert]="belowLg() && !mobileOpen()"
|
|
18259
18355
|
[attr.role]="belowLg() && mobileOpen() ? 'dialog' : null"
|
|
18260
18356
|
[attr.aria-modal]="belowLg() && mobileOpen() ? 'true' : null"
|
|
18261
18357
|
(keydown)="onDrawerKeydown($event)"
|
|
18358
|
+
(touchstart)="onTouchStart($event)"
|
|
18359
|
+
(touchmove)="onTouchMove($event)"
|
|
18360
|
+
(touchend)="onTouchEnd()"
|
|
18361
|
+
(touchcancel)="onTouchEnd()"
|
|
18262
18362
|
>
|
|
18263
18363
|
@if (decorations()) {
|
|
18264
18364
|
<span class="pointer-events-none absolute inset-0 overflow-hidden" aria-hidden="true">
|
|
@@ -18267,29 +18367,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18267
18367
|
</span>
|
|
18268
18368
|
}
|
|
18269
18369
|
|
|
18270
|
-
<!-- Header: collapse toggle (desktop) / close (mobile) -->
|
|
18370
|
+
<!-- Header: optional [sdsHeader] (logo) + collapse toggle (desktop) / close (mobile) -->
|
|
18271
18371
|
<div
|
|
18272
|
-
class="relative flex items-center px-3"
|
|
18273
|
-
style="height:
|
|
18274
|
-
[class]="
|
|
18372
|
+
class="relative flex shrink-0 items-center gap-2 px-3"
|
|
18373
|
+
style="height: 56px"
|
|
18374
|
+
[class]="railCollapsed() ? 'justify-center' : 'justify-between'"
|
|
18275
18375
|
>
|
|
18376
|
+
<div class="flex min-w-0 flex-1 items-center pl-1" [class.hidden]="railCollapsed()">
|
|
18377
|
+
<ng-content select="[sdsHeader]" />
|
|
18378
|
+
</div>
|
|
18276
18379
|
<button
|
|
18277
18380
|
type="button"
|
|
18278
|
-
class="hidden h-9 w-9 items-center justify-center rounded-control transition-colors focus-visible:outline-none focus-visible:ring-2 lg:inline-flex"
|
|
18381
|
+
class="hidden h-9 w-9 shrink-0 items-center justify-center rounded-control transition-colors focus-visible:outline-none focus-visible:ring-2 lg:inline-flex"
|
|
18279
18382
|
[class]="railBtnClass()"
|
|
18280
|
-
[attr.aria-label]="
|
|
18281
|
-
[attr.aria-expanded]="!
|
|
18383
|
+
[attr.aria-label]="railCollapsed() ? expandLabel() : collapseLabel()"
|
|
18384
|
+
[attr.aria-expanded]="!railCollapsed()"
|
|
18282
18385
|
(click)="store.toggle()"
|
|
18283
18386
|
>
|
|
18284
18387
|
<sds-icon
|
|
18285
|
-
[name]="
|
|
18388
|
+
[name]="railCollapsed() ? 'panel-left-open' : 'panel-left-close'"
|
|
18286
18389
|
[size]="20"
|
|
18287
18390
|
/>
|
|
18288
18391
|
</button>
|
|
18289
18392
|
<button
|
|
18290
18393
|
#closeBtn
|
|
18291
18394
|
type="button"
|
|
18292
|
-
class="inline-flex h-
|
|
18395
|
+
class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-control transition-colors focus-visible:outline-none focus-visible:ring-2 lg:hidden"
|
|
18293
18396
|
[class]="railBtnClass()"
|
|
18294
18397
|
[attr.aria-label]="closeLabel()"
|
|
18295
18398
|
(click)="store.closeMobile()"
|
|
@@ -18299,51 +18402,87 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18299
18402
|
</div>
|
|
18300
18403
|
|
|
18301
18404
|
<!-- Navigation -->
|
|
18302
|
-
<nav class="relative flex-1 overflow-y-auto overflow-x-hidden px-3 pb-4">
|
|
18405
|
+
<nav class="relative flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-3 pb-4" [attr.aria-label]="navLabel() || null">
|
|
18303
18406
|
<ng-content />
|
|
18304
18407
|
</nav>
|
|
18305
18408
|
|
|
18306
18409
|
<!-- Footer (search, version, …) -->
|
|
18307
|
-
<div class="relative px-3
|
|
18410
|
+
<div class="relative px-3 pt-2 pb-[max(1rem,env(safe-area-inset-bottom))]">
|
|
18308
18411
|
<ng-content select="[sdsFooter]" />
|
|
18309
18412
|
</div>
|
|
18310
18413
|
</aside>
|
|
18311
|
-
`,
|
|
18312
|
-
|
|
18313
|
-
}], ctorParameters: () => [], propDecorators: { drawer: [{ type: i0.ViewChild, args: ['drawer', { isSignal: true }] }], closeBtn: [{ type: i0.ViewChild, args: ['closeBtn', { isSignal: true }] }], collapseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseLabel", required: false }] }], expandLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], decorations: [{ type: i0.Input, args: [{ isSignal: true, alias: "decorations", required: false }] }] } });
|
|
18414
|
+
`, styles: ["@keyframes sds-scrim-in{0%{opacity:0}}.sds-scrim{animation:sds-scrim-in .18s ease-out}@media(prefers-reduced-motion:reduce){.sds-scrim{animation:none}}\n"] }]
|
|
18415
|
+
}], ctorParameters: () => [], propDecorators: { drawer: [{ type: i0.ViewChild, args: ['drawer', { isSignal: true }] }], closeBtn: [{ type: i0.ViewChild, args: ['closeBtn', { isSignal: true }] }], collapseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseLabel", required: false }] }], expandLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], navLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "navLabel", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], accordion: [{ type: i0.Input, args: [{ isSignal: true, alias: "accordion", required: false }] }], decorations: [{ type: i0.Input, args: [{ isSignal: true, alias: "decorations", required: false }] }] } });
|
|
18314
18416
|
|
|
18417
|
+
let nextId$1 = 0;
|
|
18315
18418
|
/**
|
|
18316
|
-
* Groups nav items under an optional
|
|
18419
|
+
* Groups nav items under an optional section label.
|
|
18317
18420
|
*
|
|
18318
18421
|
* Two modes:
|
|
18319
|
-
* - **Section** (default) — a static
|
|
18320
|
-
* the
|
|
18321
|
-
* - **Collapsible** (`[collapsible]`) — the label becomes a
|
|
18322
|
-
* group
|
|
18323
|
-
*
|
|
18324
|
-
*
|
|
18422
|
+
* - **Section** (default) — a static uppercase caption over its items. On the collapsed rail the caption
|
|
18423
|
+
* becomes a divider and the items (which carry their own icons) stay visible.
|
|
18424
|
+
* - **Collapsible** (`[collapsible]`) — the label becomes a row-height header that opens and closes the
|
|
18425
|
+
* group with a short height animation. Its items render as nested sub-destinations on a tree guide
|
|
18426
|
+
* line, the active one marked on the line itself. Set `[basePath]` (or several `[basePaths]`) and the
|
|
18427
|
+
* group opens itself whenever the active route is inside it, so a deep link or a browser Back lands
|
|
18428
|
+
* with the right section already open; while closed it still shows that it holds the current page
|
|
18429
|
+
* (a highlighted header with a dot).
|
|
18325
18430
|
*
|
|
18326
|
-
*
|
|
18327
|
-
*
|
|
18431
|
+
* On the collapsed desktop rail a collapsible group is its icon alone, and its pages open in a FLYOUT
|
|
18432
|
+
* panel beside the rail — on hover, on click/tap (which pins it), or from the keyboard (Enter, Space or
|
|
18433
|
+
* → opens it and focuses the first page; ↑/↓ move, Esc or ← closes back to the header). So every
|
|
18434
|
+
* destination stays reachable on the icon rail, without navigating anywhere just to see what a section
|
|
18435
|
+
* holds.
|
|
18328
18436
|
*
|
|
18329
|
-
*
|
|
18330
|
-
*
|
|
18331
|
-
*
|
|
18437
|
+
* A collapsible group can carry a `[badge]` of its own — typically the sum of its children's. It is
|
|
18438
|
+
* drawn on the header only while the children are hidden, so a closed section still says that
|
|
18439
|
+
* something inside it is waiting, and an open one does not show the same count twice.
|
|
18440
|
+
*
|
|
18441
|
+
* Inside the mobile drawer the rail is always full width, whatever the desktop collapse preference.
|
|
18332
18442
|
*/
|
|
18333
18443
|
class SdsNavGroup {
|
|
18334
18444
|
store = inject(SidebarStore);
|
|
18335
18445
|
router = inject(Router);
|
|
18446
|
+
document = inject(DOCUMENT);
|
|
18447
|
+
host = inject(ElementRef);
|
|
18448
|
+
injector = inject(Injector);
|
|
18449
|
+
id = ++nextId$1;
|
|
18450
|
+
headerId = `sds-nav-group-${this.id}-header`;
|
|
18451
|
+
panelId = `sds-nav-group-${this.id}-panel`;
|
|
18452
|
+
header = viewChild('header', ...(ngDevMode ? [{ debugName: "header" }] : []));
|
|
18453
|
+
panel = viewChild('panel', ...(ngDevMode ? [{ debugName: "panel" }] : []));
|
|
18336
18454
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
18337
18455
|
/** Turn the label into an expand/collapse control. */
|
|
18338
18456
|
collapsible = input(false, ...(ngDevMode ? [{ debugName: "collapsible", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
18339
|
-
/**
|
|
18457
|
+
/** Start open (until the person toggles it), even when the route is not inside the group. */
|
|
18458
|
+
defaultOpen = input(false, ...(ngDevMode ? [{ debugName: "defaultOpen", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
18459
|
+
/** Icon for a collapsible header — and the group's only representation on the collapsed rail. */
|
|
18340
18460
|
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
18341
18461
|
/**
|
|
18342
18462
|
* URL prefix owned by this group, e.g. `/payments`. While the active route starts with it the
|
|
18343
18463
|
* group counts as active and opens itself — unless the person has explicitly toggled it since.
|
|
18344
18464
|
*/
|
|
18345
18465
|
basePath = input(null, ...(ngDevMode ? [{ debugName: "basePath" }] : []));
|
|
18346
|
-
/**
|
|
18466
|
+
/**
|
|
18467
|
+
* More URL prefixes owned by this group, for an area whose pages don't share one root
|
|
18468
|
+
* (`['/people', '/customers', '/drivers']`). Matched exactly like {@link basePath}, alongside it.
|
|
18469
|
+
*/
|
|
18470
|
+
basePaths = input(null, ...(ngDevMode ? [{ debugName: "basePaths" }] : []));
|
|
18471
|
+
/**
|
|
18472
|
+
* A count for the header, e.g. the items waiting across the group's children. Drawn only while the
|
|
18473
|
+
* children are hidden; null or 0 shows nothing.
|
|
18474
|
+
*/
|
|
18475
|
+
badge = input(null, ...(ngDevMode ? [{ debugName: "badge" }] : []));
|
|
18476
|
+
/** Spoken text for the badge; `{count}` is replaced. Pass a translated string. */
|
|
18477
|
+
badgeLabel = input('{count} pending', ...(ngDevMode ? [{ debugName: "badgeLabel" }] : []));
|
|
18478
|
+
/** Counts above this read as "max+" (e.g. 99+). */
|
|
18479
|
+
badgeMax = input(99, ...(ngDevMode ? [{ debugName: "badgeMax" }] : []));
|
|
18480
|
+
/** Badge colour, as on {@link SdsNavItem}. */
|
|
18481
|
+
badgeTone = input('brand', ...(ngDevMode ? [{ debugName: "badgeTone" }] : []));
|
|
18482
|
+
/**
|
|
18483
|
+
* Emits the new state on every manual inline toggle. Not emitted for route-driven auto-expansion, nor
|
|
18484
|
+
* for the collapsed rail's flyout (which shows the pages instead — no need to navigate to see them).
|
|
18485
|
+
*/
|
|
18347
18486
|
expandedChange = output();
|
|
18348
18487
|
/** Explicit user choice; null means "follow the route". */
|
|
18349
18488
|
manual = signal(null, ...(ngDevMode ? [{ debugName: "manual" }] : []));
|
|
@@ -18354,106 +18493,361 @@ class SdsNavGroup {
|
|
|
18354
18493
|
* first).
|
|
18355
18494
|
*/
|
|
18356
18495
|
routeActive = computed(() => {
|
|
18357
|
-
const
|
|
18358
|
-
if (!
|
|
18496
|
+
const bases = [this.basePath(), ...(this.basePaths() ?? [])].filter((b) => !!b);
|
|
18497
|
+
if (!bases.length)
|
|
18359
18498
|
return false;
|
|
18360
18499
|
const path = this.url().split(/[?#]/)[0];
|
|
18361
|
-
return path === base || path.startsWith(base + '/');
|
|
18500
|
+
return bases.some((base) => path === base || path.startsWith(base + '/'));
|
|
18362
18501
|
}, ...(ngDevMode ? [{ debugName: "routeActive" }] : []));
|
|
18363
|
-
expanded = computed(() => this.manual() ?? this.routeActive(), ...(ngDevMode ? [{ debugName: "expanded" }] : []));
|
|
18364
|
-
|
|
18502
|
+
expanded = computed(() => this.manual() ?? (this.routeActive() || this.defaultOpen()), ...(ngDevMode ? [{ debugName: "expanded" }] : []));
|
|
18503
|
+
/** Icon-only desktop rail right now (never inside the mobile drawer). */
|
|
18504
|
+
railCollapsed = this.store.railCollapsed;
|
|
18505
|
+
// --- Flyout (collapsed rail) ------------------------------------------------------------------
|
|
18506
|
+
flyoutOpen = signal(false, ...(ngDevMode ? [{ debugName: "flyoutOpen" }] : []));
|
|
18507
|
+
/** Opened by click / keyboard: stays open when the pointer leaves, until a choice, Esc or outside click. */
|
|
18508
|
+
pinned = false;
|
|
18509
|
+
pos = signal({ top: 0, left: 0, maxHeight: 480 }, ...(ngDevMode ? [{ debugName: "pos" }] : []));
|
|
18510
|
+
openTimer;
|
|
18511
|
+
closeTimer;
|
|
18512
|
+
flyoutShown = computed(() => this.collapsible() && this.railCollapsed() && this.flyoutOpen(), ...(ngDevMode ? [{ debugName: "flyoutShown" }] : []));
|
|
18513
|
+
// --- Context for projected items -------------------------------------------------------------
|
|
18514
|
+
nested = computed(() => this.collapsible(), ...(ngDevMode ? [{ debugName: "nested" }] : []));
|
|
18515
|
+
inFlyout = computed(() => this.collapsible() && this.railCollapsed(), ...(ngDevMode ? [{ debugName: "inFlyout" }] : []));
|
|
18516
|
+
constructor() {
|
|
18517
|
+
// Accordion: another group was opened by hand — fold this one.
|
|
18518
|
+
effect(() => {
|
|
18519
|
+
const opened = this.store.openedGroup();
|
|
18520
|
+
if (!this.store.accordion() || opened === null || opened === this.id)
|
|
18521
|
+
return;
|
|
18522
|
+
untracked(() => {
|
|
18523
|
+
if (this.expanded())
|
|
18524
|
+
this.manual.set(false);
|
|
18525
|
+
});
|
|
18526
|
+
});
|
|
18527
|
+
// The flyout belongs to the collapsed rail only.
|
|
18528
|
+
effect(() => {
|
|
18529
|
+
if (!this.railCollapsed())
|
|
18530
|
+
untracked(() => this.closeFlyout());
|
|
18531
|
+
});
|
|
18532
|
+
// While the flyout is open: an outside press, a resize or a scroll of anything but the panel closes
|
|
18533
|
+
// it (a fixed panel would otherwise float away from its header).
|
|
18534
|
+
effect((onCleanup) => {
|
|
18535
|
+
if (!this.flyoutOpen())
|
|
18536
|
+
return;
|
|
18537
|
+
const win = this.document.defaultView;
|
|
18538
|
+
if (!win)
|
|
18539
|
+
return;
|
|
18540
|
+
const inside = (t) => t instanceof Node && this.host.nativeElement.contains(t);
|
|
18541
|
+
const onDown = (e) => {
|
|
18542
|
+
if (!inside(e.target))
|
|
18543
|
+
this.closeFlyout();
|
|
18544
|
+
};
|
|
18545
|
+
const onScroll = (e) => {
|
|
18546
|
+
if (!inside(e.target))
|
|
18547
|
+
this.closeFlyout();
|
|
18548
|
+
};
|
|
18549
|
+
const onResize = () => this.closeFlyout();
|
|
18550
|
+
this.document.addEventListener('pointerdown', onDown, true);
|
|
18551
|
+
win.addEventListener('scroll', onScroll, true);
|
|
18552
|
+
win.addEventListener('resize', onResize);
|
|
18553
|
+
onCleanup(() => {
|
|
18554
|
+
this.document.removeEventListener('pointerdown', onDown, true);
|
|
18555
|
+
win.removeEventListener('scroll', onScroll, true);
|
|
18556
|
+
win.removeEventListener('resize', onResize);
|
|
18557
|
+
});
|
|
18558
|
+
});
|
|
18559
|
+
inject(DestroyRef).onDestroy(() => this.clearTimers());
|
|
18560
|
+
}
|
|
18561
|
+
/** The header badge's spoken text — only while the children (which show their own) are hidden. */
|
|
18562
|
+
headerBadgeText = computed(() => {
|
|
18563
|
+
const n = this.badge();
|
|
18564
|
+
if (n === null || n === undefined || !Number.isFinite(n) || n <= 0)
|
|
18565
|
+
return null;
|
|
18566
|
+
if (this.collapsible() && this.childrenVisible())
|
|
18567
|
+
return null;
|
|
18568
|
+
return this.badgeLabel().replace('{count}', String(n));
|
|
18569
|
+
}, ...(ngDevMode ? [{ debugName: "headerBadgeText" }] : []));
|
|
18570
|
+
badgeDisplay = computed(() => {
|
|
18571
|
+
const n = this.badge() ?? 0;
|
|
18572
|
+
return n > this.badgeMax() ? `${this.badgeMax()}+` : String(n);
|
|
18573
|
+
}, ...(ngDevMode ? [{ debugName: "badgeDisplay" }] : []));
|
|
18574
|
+
/** Accessible name of the icon-only header: "Money, 3 pending". */
|
|
18575
|
+
collapsedName = computed(() => {
|
|
18576
|
+
const text = this.headerBadgeText();
|
|
18577
|
+
return text ? `${this.label()}, ${text}` : this.label();
|
|
18578
|
+
}, ...(ngDevMode ? [{ debugName: "collapsedName" }] : []));
|
|
18365
18579
|
/** Rail paint, shared via the store — see SidebarStore.appearance. Drives the header/caption tones. */
|
|
18366
|
-
|
|
18580
|
+
rail = inject(SDS_SIDEBAR, { optional: true });
|
|
18581
|
+
surface = computed(() => (this.rail?.appearance() ?? this.store.appearance()) === 'surface', ...(ngDevMode ? [{ debugName: "surface" }] : []));
|
|
18582
|
+
badgeTone$() {
|
|
18583
|
+
return this.badgeTone() === 'danger'
|
|
18584
|
+
? 'bg-danger text-white'
|
|
18585
|
+
: this.badgeTone() === 'neutral'
|
|
18586
|
+
? 'bg-muted text-ink-soft border border-border'
|
|
18587
|
+
: this.surface()
|
|
18588
|
+
? `bg-brand-600 text-white ${DARK_PRIMARY_BG} ${DARK_ON_PRIMARY}`
|
|
18589
|
+
: 'bg-white text-brand-800';
|
|
18590
|
+
}
|
|
18591
|
+
badgeClass = computed(() => 'inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 ' +
|
|
18592
|
+
'text-[11px] font-bold tabular-nums leading-none ' +
|
|
18593
|
+
this.badgeTone$(), ...(ngDevMode ? [{ debugName: "badgeClass" }] : []));
|
|
18594
|
+
/** The badge as a small pill on the icon's corner (collapsed rail). */
|
|
18595
|
+
pipClass = computed(() => 'absolute right-1 top-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full px-1 ' +
|
|
18596
|
+
'text-[10px] font-bold tabular-nums leading-none ' +
|
|
18597
|
+
this.badgeTone$() +
|
|
18598
|
+
(this.surface() ? ' ring-2 ring-surface' : ' ring-2 ring-brand-900'), ...(ngDevMode ? [{ debugName: "pipClass" }] : []));
|
|
18599
|
+
activeDotClass = computed(() => 'size-1.5 shrink-0 rounded-full ' + (this.surface() ? 'bg-brand-500' : 'bg-white'), ...(ngDevMode ? [{ debugName: "activeDotClass" }] : []));
|
|
18600
|
+
wrapClass = computed(() => (this.collapsible() ? 'mt-1 first:mt-2' : 'mt-5 first:mt-3'), ...(ngDevMode ? [{ debugName: "wrapClass" }] : []));
|
|
18367
18601
|
/** Collapsible header, painted for the active rail (ink+brand on `surface`, white on `brand`). */
|
|
18368
18602
|
headerClass = computed(() => {
|
|
18369
18603
|
const s = this.surface();
|
|
18370
|
-
const
|
|
18371
|
-
|
|
18372
|
-
|
|
18373
|
-
(
|
|
18374
|
-
|
|
18375
|
-
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
|
|
18604
|
+
const rail = this.railCollapsed();
|
|
18605
|
+
const base = 'group/header relative flex w-full items-center gap-3 rounded-control text-left text-sm font-medium ' +
|
|
18606
|
+
'transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 ' +
|
|
18607
|
+
(rail ? 'h-10 justify-center ' : 'h-11 px-3 lg:h-10 ') +
|
|
18608
|
+
(s ? 'focus-visible:ring-brand-500 ' : 'focus-visible:ring-white/50 ');
|
|
18609
|
+
let state;
|
|
18610
|
+
if (rail && this.routeActive()) {
|
|
18611
|
+
// The icon IS the group here: wear the active item's pill when the current page is inside.
|
|
18612
|
+
state = s
|
|
18613
|
+
? 'bg-linear-to-r from-brand-500/15 to-brand-500/5 text-ink shadow-sm'
|
|
18614
|
+
: 'bg-brand-500 text-white shadow-sm';
|
|
18615
|
+
}
|
|
18616
|
+
else if (rail && this.flyoutOpen()) {
|
|
18617
|
+
state = s ? 'bg-muted text-ink' : 'bg-white/10 text-white';
|
|
18618
|
+
}
|
|
18619
|
+
else if (this.routeActive() && !this.expanded()) {
|
|
18620
|
+
state = s ? 'bg-brand-500/8 text-ink hover:bg-brand-500/12' : 'bg-white/8 text-white hover:bg-white/12';
|
|
18621
|
+
}
|
|
18622
|
+
else if (this.expanded()) {
|
|
18623
|
+
state = s ? 'text-ink hover:bg-brand-500/8' : 'text-white hover:bg-white/8';
|
|
18624
|
+
}
|
|
18625
|
+
else {
|
|
18626
|
+
state = s ? 'text-ink-soft hover:bg-brand-500/8 hover:text-ink' : 'text-white/75 hover:bg-white/8 hover:text-white';
|
|
18627
|
+
}
|
|
18628
|
+
return base + state;
|
|
18379
18629
|
}, ...(ngDevMode ? [{ debugName: "headerClass" }] : []));
|
|
18380
|
-
chevronClass = computed(() => 'shrink-0 transition-transform
|
|
18630
|
+
chevronClass = computed(() => 'shrink-0 transition-transform duration-200 ease-out motion-reduce:transition-none ' +
|
|
18631
|
+
(this.expanded() ? 'rotate-90 ' : '') +
|
|
18632
|
+
(this.surface() ? 'text-ink-faint group-hover/header:text-ink-soft' : 'text-white/45 group-hover/header:text-white/80'), ...(ngDevMode ? [{ debugName: "chevronClass" }] : []));
|
|
18381
18633
|
dividerClass = computed(() => 'mx-3 mb-2 mt-2 h-px ' + (this.surface() ? 'bg-border' : 'bg-white/10'), ...(ngDevMode ? [{ debugName: "dividerClass" }] : []));
|
|
18382
18634
|
captionClass = computed(() => 'mb-1.5 px-3 text-[11px] font-semibold uppercase tracking-wider ' +
|
|
18383
|
-
(this.surface() ? 'text-ink-faint' : 'text-white/
|
|
18635
|
+
(this.surface() ? 'text-ink-faint' : 'text-white/55'), ...(ngDevMode ? [{ debugName: "captionClass" }] : []));
|
|
18636
|
+
flyoutTitleClass = computed(() => 'px-3 pb-1.5 pt-1 text-[11px] font-semibold uppercase tracking-wider ' +
|
|
18637
|
+
(this.surface() ? 'text-ink-faint' : 'text-white/55'), ...(ngDevMode ? [{ debugName: "flyoutTitleClass" }] : []));
|
|
18384
18638
|
/**
|
|
18385
|
-
*
|
|
18386
|
-
* rail
|
|
18387
|
-
* typically have no icon, which on an icon-only rail is a row with nothing in it.
|
|
18639
|
+
* Whether the items are on screen: a plain section always; a collapsible group when open on the full
|
|
18640
|
+
* rail (its items have no icon of their own, so on the icon rail they live in the flyout instead).
|
|
18388
18641
|
*/
|
|
18389
|
-
childrenVisible = computed(() => !this.collapsible() || (!this.
|
|
18390
|
-
/**
|
|
18391
|
-
|
|
18392
|
-
|
|
18393
|
-
|
|
18394
|
-
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
18399
|
-
|
|
18400
|
-
|
|
18401
|
-
|
|
18402
|
-
|
|
18403
|
-
|
|
18404
|
-
|
|
18405
|
-
|
|
18406
|
-
|
|
18407
|
-
|
|
18642
|
+
childrenVisible = computed(() => !this.collapsible() || (!this.railCollapsed() && this.expanded()), ...(ngDevMode ? [{ debugName: "childrenVisible" }] : []));
|
|
18643
|
+
/** Closed panels are `inert`, so their (visually hidden) links leave the tab order. */
|
|
18644
|
+
childrenInteractive = computed(() => this.childrenVisible() || this.flyoutShown(), ...(ngDevMode ? [{ debugName: "childrenInteractive" }] : []));
|
|
18645
|
+
panelClass = computed(() => {
|
|
18646
|
+
if (!this.collapsible())
|
|
18647
|
+
return 'block';
|
|
18648
|
+
if (this.railCollapsed()) {
|
|
18649
|
+
if (!this.flyoutOpen())
|
|
18650
|
+
return 'hidden';
|
|
18651
|
+
return ('sds-flyout fixed z-[70] flex w-60 flex-col rounded-card border p-1.5 shadow-xl ' +
|
|
18652
|
+
(this.surface() ? 'border-border bg-surface text-ink' : 'border-white/10 bg-brand-900 text-white ring-1 ring-black/10'));
|
|
18653
|
+
}
|
|
18654
|
+
// grid-rows 0fr → 1fr animates to the content's real height with no measuring.
|
|
18655
|
+
return ('grid transition-[grid-template-rows,opacity] duration-200 ease-out motion-reduce:transition-none ' +
|
|
18656
|
+
(this.expanded() ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'));
|
|
18657
|
+
}, ...(ngDevMode ? [{ debugName: "panelClass" }] : []));
|
|
18658
|
+
innerClass = computed(() => {
|
|
18659
|
+
if (!this.collapsible())
|
|
18660
|
+
return '';
|
|
18661
|
+
return this.railCollapsed() ? 'min-h-0 overflow-y-auto overscroll-contain' : 'min-h-0 overflow-hidden';
|
|
18662
|
+
}, ...(ngDevMode ? [{ debugName: "innerClass" }] : []));
|
|
18408
18663
|
/**
|
|
18409
|
-
*
|
|
18410
|
-
*
|
|
18411
|
-
* meaning the control can have there.
|
|
18664
|
+
* The tree guide: a hairline under the header's icon (22 px = the header's 12 px padding + half its
|
|
18665
|
+
* 20 px icon), with the items indented beside it. The active item marks its own stretch of the line.
|
|
18412
18666
|
*/
|
|
18667
|
+
listClass = computed(() => {
|
|
18668
|
+
if (!this.collapsible())
|
|
18669
|
+
return 'flex flex-col gap-1';
|
|
18670
|
+
if (this.railCollapsed())
|
|
18671
|
+
return 'flex flex-col gap-0.5';
|
|
18672
|
+
return ('relative ml-[1.375rem] mt-0.5 flex flex-col gap-0.5 pb-1.5 pl-3 ' +
|
|
18673
|
+
'before:pointer-events-none before:absolute before:inset-y-1 before:left-0 before:w-px ' +
|
|
18674
|
+
(this.surface() ? 'before:bg-border' : 'before:bg-white/12'));
|
|
18675
|
+
}, ...(ngDevMode ? [{ debugName: "listClass" }] : []));
|
|
18676
|
+
/** Header click: toggle inline; on the collapsed rail, open (and pin) or close the flyout. */
|
|
18413
18677
|
toggle() {
|
|
18414
|
-
|
|
18678
|
+
if (this.railCollapsed()) {
|
|
18679
|
+
if (this.flyoutOpen() && this.pinned)
|
|
18680
|
+
this.closeFlyout();
|
|
18681
|
+
else
|
|
18682
|
+
this.openFlyout(false);
|
|
18683
|
+
return;
|
|
18684
|
+
}
|
|
18685
|
+
const next = !this.expanded();
|
|
18415
18686
|
this.manual.set(next);
|
|
18687
|
+
if (next)
|
|
18688
|
+
this.store.openedGroup.set(this.id);
|
|
18416
18689
|
this.expandedChange.emit(next);
|
|
18417
18690
|
}
|
|
18691
|
+
onHeaderKeydown(event) {
|
|
18692
|
+
if (!this.railCollapsed())
|
|
18693
|
+
return;
|
|
18694
|
+
if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowRight' || event.key === 'ArrowDown') {
|
|
18695
|
+
event.preventDefault();
|
|
18696
|
+
this.openFlyout(true);
|
|
18697
|
+
}
|
|
18698
|
+
}
|
|
18699
|
+
onHeaderEnter() {
|
|
18700
|
+
if (!this.railCollapsed())
|
|
18701
|
+
return;
|
|
18702
|
+
this.cancelClose();
|
|
18703
|
+
if (this.flyoutOpen())
|
|
18704
|
+
return;
|
|
18705
|
+
clearTimeout(this.openTimer);
|
|
18706
|
+
// A short intent delay, so sweeping the pointer down the rail doesn't flash every panel.
|
|
18707
|
+
this.openTimer = setTimeout(() => this.openFlyout(false, false), 90);
|
|
18708
|
+
}
|
|
18709
|
+
scheduleClose() {
|
|
18710
|
+
clearTimeout(this.openTimer);
|
|
18711
|
+
if (!this.railCollapsed() || !this.flyoutOpen() || this.pinned)
|
|
18712
|
+
return;
|
|
18713
|
+
clearTimeout(this.closeTimer);
|
|
18714
|
+
this.closeTimer = setTimeout(() => this.closeFlyout(), 220);
|
|
18715
|
+
}
|
|
18716
|
+
cancelClose() {
|
|
18717
|
+
clearTimeout(this.closeTimer);
|
|
18718
|
+
}
|
|
18719
|
+
openFlyout(focusFirst, pin = true) {
|
|
18720
|
+
const btn = this.header()?.nativeElement;
|
|
18721
|
+
const win = this.document.defaultView;
|
|
18722
|
+
if (!btn || !win)
|
|
18723
|
+
return;
|
|
18724
|
+
this.clearTimers();
|
|
18725
|
+
const r = btn.getBoundingClientRect();
|
|
18726
|
+
const margin = 8;
|
|
18727
|
+
this.pinned = this.pinned || pin;
|
|
18728
|
+
// Beside the RAIL, not the button: the panel must clear the rail's edge, not overlap its padding.
|
|
18729
|
+
const railRight = btn.closest('aside')?.getBoundingClientRect().right ?? r.right;
|
|
18730
|
+
this.pos.set({ top: Math.max(margin, r.top - 6), left: railRight + 8, maxHeight: win.innerHeight - margin * 2 });
|
|
18731
|
+
this.flyoutOpen.set(true);
|
|
18732
|
+
afterNextRender(() => {
|
|
18733
|
+
const el = this.panel()?.nativeElement;
|
|
18734
|
+
if (!el)
|
|
18735
|
+
return;
|
|
18736
|
+
// Keep the whole panel on screen: lift it when it would run past the bottom edge.
|
|
18737
|
+
const h = el.offsetHeight;
|
|
18738
|
+
const top = this.pos().top;
|
|
18739
|
+
if (top + h > win.innerHeight - margin)
|
|
18740
|
+
this.pos.update((p) => ({ ...p, top: Math.max(margin, win.innerHeight - margin - h) }));
|
|
18741
|
+
if (focusFirst)
|
|
18742
|
+
this.items()[0]?.focus();
|
|
18743
|
+
}, { injector: this.injector });
|
|
18744
|
+
}
|
|
18745
|
+
/** {@link SdsNavGroupContext} — also called by an item chosen inside the flyout. */
|
|
18746
|
+
closeFlyout(restoreFocus = false) {
|
|
18747
|
+
this.clearTimers();
|
|
18748
|
+
this.pinned = false;
|
|
18749
|
+
if (!this.flyoutOpen())
|
|
18750
|
+
return;
|
|
18751
|
+
this.flyoutOpen.set(false);
|
|
18752
|
+
if (restoreFocus)
|
|
18753
|
+
this.header()?.nativeElement.focus();
|
|
18754
|
+
}
|
|
18755
|
+
onEscape() {
|
|
18756
|
+
if (this.flyoutOpen()) {
|
|
18757
|
+
const within = this.host.nativeElement.contains(this.document.activeElement);
|
|
18758
|
+
this.closeFlyout(within);
|
|
18759
|
+
}
|
|
18760
|
+
}
|
|
18761
|
+
/** Focus leaving the header + flyout altogether closes the flyout (Tab past the last page). */
|
|
18762
|
+
onFocusOut(event) {
|
|
18763
|
+
if (!this.flyoutOpen())
|
|
18764
|
+
return;
|
|
18765
|
+
const next = event.relatedTarget;
|
|
18766
|
+
if (next instanceof Node && this.host.nativeElement.contains(next))
|
|
18767
|
+
return;
|
|
18768
|
+
if (next === null)
|
|
18769
|
+
return; // focus went nowhere in particular (e.g. a click on the page) — the pointerdown handler decides
|
|
18770
|
+
this.closeFlyout();
|
|
18771
|
+
}
|
|
18772
|
+
/** ↑/↓ (and Home/End) move between the flyout's pages; ← closes back to the header. */
|
|
18773
|
+
onPanelKeydown(event) {
|
|
18774
|
+
if (!this.flyoutShown())
|
|
18775
|
+
return;
|
|
18776
|
+
const items = this.items();
|
|
18777
|
+
const i = items.indexOf(this.document.activeElement);
|
|
18778
|
+
let next = -1;
|
|
18779
|
+
switch (event.key) {
|
|
18780
|
+
case 'ArrowDown':
|
|
18781
|
+
next = i < 0 ? 0 : (i + 1) % items.length;
|
|
18782
|
+
break;
|
|
18783
|
+
case 'ArrowUp':
|
|
18784
|
+
next = i < 0 ? items.length - 1 : (i - 1 + items.length) % items.length;
|
|
18785
|
+
break;
|
|
18786
|
+
case 'Home':
|
|
18787
|
+
next = 0;
|
|
18788
|
+
break;
|
|
18789
|
+
case 'End':
|
|
18790
|
+
next = items.length - 1;
|
|
18791
|
+
break;
|
|
18792
|
+
case 'ArrowLeft':
|
|
18793
|
+
event.preventDefault();
|
|
18794
|
+
this.closeFlyout(true);
|
|
18795
|
+
return;
|
|
18796
|
+
default:
|
|
18797
|
+
return;
|
|
18798
|
+
}
|
|
18799
|
+
event.preventDefault();
|
|
18800
|
+
items[next]?.focus();
|
|
18801
|
+
}
|
|
18802
|
+
items() {
|
|
18803
|
+
const el = this.panel()?.nativeElement;
|
|
18804
|
+
return el ? Array.from(el.querySelectorAll('a[href],button:not([disabled])')) : [];
|
|
18805
|
+
}
|
|
18806
|
+
clearTimers() {
|
|
18807
|
+
clearTimeout(this.openTimer);
|
|
18808
|
+
clearTimeout(this.closeTimer);
|
|
18809
|
+
}
|
|
18418
18810
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsNavGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18419
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsNavGroup, isStandalone: true, selector: "sds-nav-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandedChange: "expandedChange" }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
18420
|
-
<div class="
|
|
18811
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsNavGroup, isStandalone: true, selector: "sds-nav-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null }, basePaths: { classPropertyName: "basePaths", publicName: "basePaths", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, badgeLabel: { classPropertyName: "badgeLabel", publicName: "badgeLabel", isSignal: true, isRequired: false, transformFunction: null }, badgeMax: { classPropertyName: "badgeMax", publicName: "badgeMax", isSignal: true, isRequired: false, transformFunction: null }, badgeTone: { classPropertyName: "badgeTone", publicName: "badgeTone", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandedChange: "expandedChange" }, host: { listeners: { "document:keydown.escape": "onEscape()", "focusout": "onFocusOut($event)" }, classAttribute: "block" }, providers: [{ provide: SDS_NAV_GROUP, useExisting: forwardRef(() => SdsNavGroup) }], viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true, isSignal: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
18812
|
+
<div [class]="wrapClass()">
|
|
18421
18813
|
@if (label()) {
|
|
18422
18814
|
@if (collapsible()) {
|
|
18423
|
-
<!--
|
|
18424
|
-
A collapsible header is styled as a NAV ROW, not as a section caption. A small uppercase
|
|
18425
|
-
caption says "everything under me belongs to me" — which is a lie the moment the group is
|
|
18426
|
-
collapsed and the next section's items sit directly beneath it. At row scale, with an icon
|
|
18427
|
-
and a chevron, it reads as the control it is.
|
|
18428
|
-
|
|
18429
|
-
It renders on the collapsed rail too, as an icon alone, because there it is the group's
|
|
18430
|
-
ONLY representation: the children are hidden (a child with no icon of its own would be a
|
|
18431
|
-
blank row), so the app is expected to treat the toggle as "take me into this section" —
|
|
18432
|
-
which is what expandedChange already means.
|
|
18433
|
-
-->
|
|
18434
18815
|
<button
|
|
18816
|
+
#header
|
|
18435
18817
|
type="button"
|
|
18818
|
+
[id]="headerId"
|
|
18436
18819
|
[class]="headerClass()"
|
|
18437
|
-
[attr.aria-expanded]="
|
|
18438
|
-
[attr.
|
|
18439
|
-
[attr.aria-
|
|
18820
|
+
[attr.aria-expanded]="railCollapsed() ? flyoutOpen() : expanded()"
|
|
18821
|
+
[attr.aria-controls]="panelId"
|
|
18822
|
+
[attr.aria-haspopup]="railCollapsed() ? 'true' : null"
|
|
18823
|
+
[attr.aria-label]="railCollapsed() ? collapsedName() : null"
|
|
18440
18824
|
(click)="toggle()"
|
|
18825
|
+
(keydown)="onHeaderKeydown($event)"
|
|
18826
|
+
(pointerenter)="onHeaderEnter()"
|
|
18827
|
+
(pointerleave)="scheduleClose()"
|
|
18441
18828
|
>
|
|
18442
18829
|
@if (icon()) {
|
|
18443
18830
|
<sds-icon [name]="icon()!" [size]="20" class="shrink-0" />
|
|
18444
18831
|
}
|
|
18445
|
-
|
|
18446
|
-
|
|
18447
|
-
|
|
18448
|
-
|
|
18449
|
-
|
|
18450
|
-
|
|
18451
|
-
|
|
18452
|
-
|
|
18453
|
-
|
|
18454
|
-
|
|
18832
|
+
@if (railCollapsed()) {
|
|
18833
|
+
@if (headerBadgeText()) {
|
|
18834
|
+
<span [class]="pipClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
|
|
18835
|
+
} @else if (routeActive()) {
|
|
18836
|
+
<span [class]="activeDotClass() + ' absolute right-2 top-2'" aria-hidden="true"></span>
|
|
18837
|
+
}
|
|
18838
|
+
} @else {
|
|
18839
|
+
<span class="min-w-0 flex-1 truncate text-left">{{ label() }}</span>
|
|
18840
|
+
@if (headerBadgeText(); as text) {
|
|
18841
|
+
<span [class]="badgeClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
|
|
18842
|
+
<span class="sr-only">, {{ text }}</span>
|
|
18843
|
+
} @else if (routeActive() && !expanded()) {
|
|
18844
|
+
<!-- Closed, but the current page lives in here: say so without opening it. -->
|
|
18845
|
+
<span [class]="activeDotClass()" aria-hidden="true"></span>
|
|
18846
|
+
}
|
|
18847
|
+
<sds-icon name="chevron-right" [size]="16" [class]="chevronClass()" />
|
|
18848
|
+
}
|
|
18455
18849
|
</button>
|
|
18456
|
-
} @else if (
|
|
18850
|
+
} @else if (railCollapsed()) {
|
|
18457
18851
|
<div [class]="dividerClass()"></div>
|
|
18458
18852
|
} @else {
|
|
18459
18853
|
<p [class]="captionClass()">
|
|
@@ -18462,57 +18856,83 @@ class SdsNavGroup {
|
|
|
18462
18856
|
}
|
|
18463
18857
|
}
|
|
18464
18858
|
|
|
18465
|
-
|
|
18466
|
-
|
|
18859
|
+
<!--
|
|
18860
|
+
One panel, three shapes: the always-visible list of a plain section; the height-animated, inert-
|
|
18861
|
+
when-closed list of an open/closed collapsible group; or, on the collapsed rail, the fixed flyout
|
|
18862
|
+
beside it. The projected items are the same DOM nodes in all three — only the classes change.
|
|
18863
|
+
-->
|
|
18864
|
+
<div
|
|
18865
|
+
#panel
|
|
18866
|
+
[id]="panelId"
|
|
18867
|
+
[class]="panelClass()"
|
|
18868
|
+
[style.top.px]="flyoutShown() ? pos().top : null"
|
|
18869
|
+
[style.left.px]="flyoutShown() ? pos().left : null"
|
|
18870
|
+
[style.max-height.px]="flyoutShown() ? pos().maxHeight : null"
|
|
18871
|
+
[attr.role]="collapsible() && railCollapsed() ? 'group' : null"
|
|
18872
|
+
[attr.aria-labelledby]="collapsible() && railCollapsed() ? panelId + '-title' : null"
|
|
18873
|
+
[inert]="!childrenInteractive()"
|
|
18874
|
+
(pointerenter)="cancelClose()"
|
|
18875
|
+
(pointerleave)="scheduleClose()"
|
|
18876
|
+
(keydown)="onPanelKeydown($event)"
|
|
18877
|
+
>
|
|
18878
|
+
@if (collapsible() && railCollapsed()) {
|
|
18879
|
+
<p [id]="panelId + '-title'" [class]="flyoutTitleClass()">{{ label() }}</p>
|
|
18880
|
+
}
|
|
18881
|
+
<div [class]="innerClass()">
|
|
18882
|
+
<div [class]="listClass()">
|
|
18883
|
+
<ng-content />
|
|
18884
|
+
</div>
|
|
18885
|
+
</div>
|
|
18467
18886
|
</div>
|
|
18468
18887
|
</div>
|
|
18469
|
-
`, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth", "filled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18888
|
+
`, isInline: true, styles: ["@keyframes sds-flyout-in{0%{opacity:0;transform:translate(-4px) scale(.98)}to{opacity:1;transform:none}}.sds-flyout{animation:sds-flyout-in .14s ease-out;transform-origin:left top}@media(prefers-reduced-motion:reduce){.sds-flyout{animation:none}}\n"], dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth", "filled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18470
18889
|
}
|
|
18471
18890
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsNavGroup, decorators: [{
|
|
18472
18891
|
type: Component,
|
|
18473
|
-
args: [{
|
|
18474
|
-
|
|
18475
|
-
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
|
|
18479
|
-
<div class="mt-5 first:mt-3">
|
|
18892
|
+
args: [{ selector: 'sds-nav-group', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdsIcon], providers: [{ provide: SDS_NAV_GROUP, useExisting: forwardRef(() => SdsNavGroup) }], host: {
|
|
18893
|
+
class: 'block',
|
|
18894
|
+
'(document:keydown.escape)': 'onEscape()',
|
|
18895
|
+
'(focusout)': 'onFocusOut($event)',
|
|
18896
|
+
}, template: `
|
|
18897
|
+
<div [class]="wrapClass()">
|
|
18480
18898
|
@if (label()) {
|
|
18481
18899
|
@if (collapsible()) {
|
|
18482
|
-
<!--
|
|
18483
|
-
A collapsible header is styled as a NAV ROW, not as a section caption. A small uppercase
|
|
18484
|
-
caption says "everything under me belongs to me" — which is a lie the moment the group is
|
|
18485
|
-
collapsed and the next section's items sit directly beneath it. At row scale, with an icon
|
|
18486
|
-
and a chevron, it reads as the control it is.
|
|
18487
|
-
|
|
18488
|
-
It renders on the collapsed rail too, as an icon alone, because there it is the group's
|
|
18489
|
-
ONLY representation: the children are hidden (a child with no icon of its own would be a
|
|
18490
|
-
blank row), so the app is expected to treat the toggle as "take me into this section" —
|
|
18491
|
-
which is what expandedChange already means.
|
|
18492
|
-
-->
|
|
18493
18900
|
<button
|
|
18901
|
+
#header
|
|
18494
18902
|
type="button"
|
|
18903
|
+
[id]="headerId"
|
|
18495
18904
|
[class]="headerClass()"
|
|
18496
|
-
[attr.aria-expanded]="
|
|
18497
|
-
[attr.
|
|
18498
|
-
[attr.aria-
|
|
18905
|
+
[attr.aria-expanded]="railCollapsed() ? flyoutOpen() : expanded()"
|
|
18906
|
+
[attr.aria-controls]="panelId"
|
|
18907
|
+
[attr.aria-haspopup]="railCollapsed() ? 'true' : null"
|
|
18908
|
+
[attr.aria-label]="railCollapsed() ? collapsedName() : null"
|
|
18499
18909
|
(click)="toggle()"
|
|
18910
|
+
(keydown)="onHeaderKeydown($event)"
|
|
18911
|
+
(pointerenter)="onHeaderEnter()"
|
|
18912
|
+
(pointerleave)="scheduleClose()"
|
|
18500
18913
|
>
|
|
18501
18914
|
@if (icon()) {
|
|
18502
18915
|
<sds-icon [name]="icon()!" [size]="20" class="shrink-0" />
|
|
18503
18916
|
}
|
|
18504
|
-
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18917
|
+
@if (railCollapsed()) {
|
|
18918
|
+
@if (headerBadgeText()) {
|
|
18919
|
+
<span [class]="pipClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
|
|
18920
|
+
} @else if (routeActive()) {
|
|
18921
|
+
<span [class]="activeDotClass() + ' absolute right-2 top-2'" aria-hidden="true"></span>
|
|
18922
|
+
}
|
|
18923
|
+
} @else {
|
|
18924
|
+
<span class="min-w-0 flex-1 truncate text-left">{{ label() }}</span>
|
|
18925
|
+
@if (headerBadgeText(); as text) {
|
|
18926
|
+
<span [class]="badgeClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
|
|
18927
|
+
<span class="sr-only">, {{ text }}</span>
|
|
18928
|
+
} @else if (routeActive() && !expanded()) {
|
|
18929
|
+
<!-- Closed, but the current page lives in here: say so without opening it. -->
|
|
18930
|
+
<span [class]="activeDotClass()" aria-hidden="true"></span>
|
|
18931
|
+
}
|
|
18932
|
+
<sds-icon name="chevron-right" [size]="16" [class]="chevronClass()" />
|
|
18933
|
+
}
|
|
18514
18934
|
</button>
|
|
18515
|
-
} @else if (
|
|
18935
|
+
} @else if (railCollapsed()) {
|
|
18516
18936
|
<div [class]="dividerClass()"></div>
|
|
18517
18937
|
} @else {
|
|
18518
18938
|
<p [class]="captionClass()">
|
|
@@ -18521,18 +18941,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18521
18941
|
}
|
|
18522
18942
|
}
|
|
18523
18943
|
|
|
18524
|
-
|
|
18525
|
-
|
|
18944
|
+
<!--
|
|
18945
|
+
One panel, three shapes: the always-visible list of a plain section; the height-animated, inert-
|
|
18946
|
+
when-closed list of an open/closed collapsible group; or, on the collapsed rail, the fixed flyout
|
|
18947
|
+
beside it. The projected items are the same DOM nodes in all three — only the classes change.
|
|
18948
|
+
-->
|
|
18949
|
+
<div
|
|
18950
|
+
#panel
|
|
18951
|
+
[id]="panelId"
|
|
18952
|
+
[class]="panelClass()"
|
|
18953
|
+
[style.top.px]="flyoutShown() ? pos().top : null"
|
|
18954
|
+
[style.left.px]="flyoutShown() ? pos().left : null"
|
|
18955
|
+
[style.max-height.px]="flyoutShown() ? pos().maxHeight : null"
|
|
18956
|
+
[attr.role]="collapsible() && railCollapsed() ? 'group' : null"
|
|
18957
|
+
[attr.aria-labelledby]="collapsible() && railCollapsed() ? panelId + '-title' : null"
|
|
18958
|
+
[inert]="!childrenInteractive()"
|
|
18959
|
+
(pointerenter)="cancelClose()"
|
|
18960
|
+
(pointerleave)="scheduleClose()"
|
|
18961
|
+
(keydown)="onPanelKeydown($event)"
|
|
18962
|
+
>
|
|
18963
|
+
@if (collapsible() && railCollapsed()) {
|
|
18964
|
+
<p [id]="panelId + '-title'" [class]="flyoutTitleClass()">{{ label() }}</p>
|
|
18965
|
+
}
|
|
18966
|
+
<div [class]="innerClass()">
|
|
18967
|
+
<div [class]="listClass()">
|
|
18968
|
+
<ng-content />
|
|
18969
|
+
</div>
|
|
18970
|
+
</div>
|
|
18526
18971
|
</div>
|
|
18527
18972
|
</div>
|
|
18528
|
-
`,
|
|
18529
|
-
|
|
18530
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], basePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "basePath", required: false }] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }] } });
|
|
18973
|
+
`, styles: ["@keyframes sds-flyout-in{0%{opacity:0;transform:translate(-4px) scale(.98)}to{opacity:1;transform:none}}.sds-flyout{animation:sds-flyout-in .14s ease-out;transform-origin:left top}@media(prefers-reduced-motion:reduce){.sds-flyout{animation:none}}\n"] }]
|
|
18974
|
+
}], ctorParameters: () => [], propDecorators: { header: [{ type: i0.ViewChild, args: ['header', { isSignal: true }] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], defaultOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultOpen", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], basePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "basePath", required: false }] }], basePaths: [{ type: i0.Input, args: [{ isSignal: true, alias: "basePaths", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], badgeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeLabel", required: false }] }], badgeMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeMax", required: false }] }], badgeTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeTone", required: false }] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }] } });
|
|
18531
18975
|
|
|
18532
18976
|
/**
|
|
18533
18977
|
* A single sidebar navigation entry. Renders an anchor when [link] is set
|
|
18534
18978
|
* (with automatic active state via routerLinkActive) or a button otherwise.
|
|
18535
18979
|
*
|
|
18980
|
+
* It adapts to where it sits, with no input from the app:
|
|
18981
|
+
* - at the top level, an icon + label row with a pill and accent bar when active;
|
|
18982
|
+
* - inside a collapsible <sds-nav-group>, a nested sub-destination on the group's tree guide (no icon
|
|
18983
|
+
* needed), the active one marked on the guide line;
|
|
18984
|
+
* - inside the collapsed rail's flyout panel, a full row with its label;
|
|
18985
|
+
* - on the collapsed rail itself, its icon alone, with a tooltip naming it on hover and focus.
|
|
18986
|
+
*
|
|
18987
|
+
* Choosing an item closes the mobile drawer and any open flyout.
|
|
18988
|
+
*
|
|
18536
18989
|
* Requires the host application to provide the Angular Router (`provideRouter`),
|
|
18537
18990
|
* as it depends on RouterLink/RouterLinkActive even when used as a button.
|
|
18538
18991
|
*
|
|
@@ -18542,6 +18995,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18542
18995
|
*/
|
|
18543
18996
|
class SdsNavItem {
|
|
18544
18997
|
store = inject(SidebarStore);
|
|
18998
|
+
group = inject(SDS_NAV_GROUP, { optional: true });
|
|
18545
18999
|
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
18546
19000
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
18547
19001
|
/** Router link target; when null, the item behaves as a button. */
|
|
@@ -18561,7 +19015,17 @@ class SdsNavItem {
|
|
|
18561
19015
|
/** Badge colour. `danger` for things that block, `brand` (default) for a neutral count. */
|
|
18562
19016
|
badgeTone = input('brand', ...(ngDevMode ? [{ debugName: "badgeTone" }] : []));
|
|
18563
19017
|
select = output();
|
|
18564
|
-
|
|
19018
|
+
/** Inside a collapsible group: a nested sub-destination. */
|
|
19019
|
+
nested = computed(() => this.group?.nested() ?? false, ...(ngDevMode ? [{ debugName: "nested" }] : []));
|
|
19020
|
+
/** A row of the collapsed rail's flyout panel. */
|
|
19021
|
+
inFlyout = computed(() => this.group?.inFlyout() ?? false, ...(ngDevMode ? [{ debugName: "inFlyout" }] : []));
|
|
19022
|
+
/** Icon alone: on the collapsed desktop rail, unless it is listed in a flyout. */
|
|
19023
|
+
iconOnly = computed(() => this.store.railCollapsed() && !this.inFlyout(), ...(ngDevMode ? [{ debugName: "iconOnly" }] : []));
|
|
19024
|
+
/** Tooltip anchor (viewport coordinates) while hovered/focused on the icon rail. */
|
|
19025
|
+
tip = signal(null, ...(ngDevMode ? [{ debugName: "tip" }] : []));
|
|
19026
|
+
rail = inject(SDS_SIDEBAR, { optional: true });
|
|
19027
|
+
/** Paint of the rail this item sits in (its own sidebar's, else the store's for a free-standing item). */
|
|
19028
|
+
surface = computed(() => (this.rail?.appearance() ?? this.store.appearance()) === 'surface', ...(ngDevMode ? [{ debugName: "surface" }] : []));
|
|
18565
19029
|
/** The badge's spoken text, or null when there is nothing to show. */
|
|
18566
19030
|
badgeText = computed(() => {
|
|
18567
19031
|
const n = this.badge();
|
|
@@ -18583,44 +19047,84 @@ class SdsNavItem {
|
|
|
18583
19047
|
? 'bg-danger text-white'
|
|
18584
19048
|
: this.badgeTone() === 'neutral'
|
|
18585
19049
|
? 'bg-muted text-ink-soft border border-border'
|
|
18586
|
-
: this.
|
|
19050
|
+
: this.surface()
|
|
18587
19051
|
? `bg-brand-600 text-white ${DARK_PRIMARY_BG} ${DARK_ON_PRIMARY}`
|
|
18588
19052
|
: 'bg-white text-brand-800';
|
|
18589
|
-
|
|
18590
|
-
|
|
18591
|
-
|
|
18592
|
-
|
|
18593
|
-
|
|
18594
|
-
|
|
18595
|
-
|
|
18596
|
-
|
|
19053
|
+
if (this.iconOnly()) {
|
|
19054
|
+
// A small pill pinned to the top-right of the centred icon.
|
|
19055
|
+
return ('absolute right-1 top-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full px-1 ' +
|
|
19056
|
+
`text-[10px] font-bold tabular-nums leading-none ${tone} ` +
|
|
19057
|
+
(this.surface() ? 'ring-2 ring-surface' : 'ring-2 ring-brand-900'));
|
|
19058
|
+
}
|
|
19059
|
+
return ('ml-auto inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 ' +
|
|
19060
|
+
`text-[11px] font-bold tabular-nums leading-none ${tone}`);
|
|
18597
19061
|
}, ...(ngDevMode ? [{ debugName: "badgeClass" }] : []));
|
|
18598
19062
|
itemClass(isActive) {
|
|
18599
|
-
//
|
|
18600
|
-
//
|
|
18601
|
-
//
|
|
18602
|
-
//
|
|
18603
|
-
const
|
|
18604
|
-
const
|
|
19063
|
+
// `surface` (light rail): an active item is a brand-tinted pill with an accent bar; inactive is muted
|
|
19064
|
+
// ink that lifts on hover. `brand` (dark rail): an active top-level item is a solid brand-500 pill;
|
|
19065
|
+
// a nested one is a quieter white wash, its accent riding the tree guide. One input on <sds-sidebar>
|
|
19066
|
+
// switches the whole rail via the shared store.
|
|
19067
|
+
const s = this.surface();
|
|
19068
|
+
const nested = this.nested() && !this.iconOnly();
|
|
19069
|
+
const size = this.iconOnly()
|
|
19070
|
+
? 'h-10 justify-center'
|
|
19071
|
+
: nested
|
|
19072
|
+
? 'h-10 px-3 lg:h-9'
|
|
19073
|
+
: 'h-11 px-3 lg:h-10';
|
|
19074
|
+
const base = 'group relative flex w-full items-center gap-3 rounded-control text-left text-sm font-medium ' +
|
|
18605
19075
|
'transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 ' +
|
|
18606
|
-
(
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
|
|
18612
|
-
|
|
18613
|
-
|
|
18614
|
-
|
|
18615
|
-
|
|
19076
|
+
(s ? 'focus-visible:ring-brand-500 ' : 'focus-visible:ring-white/50 ') +
|
|
19077
|
+
size +
|
|
19078
|
+
' ';
|
|
19079
|
+
let state;
|
|
19080
|
+
if (nested) {
|
|
19081
|
+
// A brand-tinted wash (green on emerald, grey on a monochrome brand) — quieter than the top-level
|
|
19082
|
+
// pill, so the parent header stays the stronger landmark.
|
|
19083
|
+
state = isActive
|
|
19084
|
+
? s
|
|
19085
|
+
? 'bg-brand-500/10 text-ink'
|
|
19086
|
+
: 'bg-brand-500/35 text-white'
|
|
19087
|
+
: s
|
|
19088
|
+
? 'text-ink-soft hover:bg-brand-500/6 hover:text-ink'
|
|
19089
|
+
: 'text-white/65 hover:bg-white/6 hover:text-white';
|
|
19090
|
+
}
|
|
19091
|
+
else {
|
|
19092
|
+
state = isActive
|
|
19093
|
+
? s
|
|
19094
|
+
? 'bg-linear-to-r from-brand-500/15 to-brand-500/5 text-ink shadow-sm'
|
|
19095
|
+
: 'bg-brand-500 text-white shadow-sm'
|
|
19096
|
+
: s
|
|
19097
|
+
? 'text-ink-soft hover:bg-brand-500/8 hover:text-ink'
|
|
19098
|
+
: 'text-white/75 hover:bg-white/8 hover:text-white';
|
|
19099
|
+
}
|
|
19100
|
+
return base + state;
|
|
18616
19101
|
}
|
|
18617
19102
|
/**
|
|
18618
|
-
* The
|
|
18619
|
-
*
|
|
18620
|
-
*
|
|
19103
|
+
* The active marker — the strongest "selected" cue, and the one that survives a grayscale brand where a
|
|
19104
|
+
* tinted pill alone is nearly invisible. A top-level (or flyout) item carries it inside its pill; a
|
|
19105
|
+
* nested item draws it ON the group's tree guide (12 px to its left), so the line itself points at the
|
|
19106
|
+
* current page.
|
|
18621
19107
|
*/
|
|
18622
|
-
accentBarClass = computed(() =>
|
|
18623
|
-
|
|
19108
|
+
accentBarClass = computed(() => {
|
|
19109
|
+
const color = this.surface() ? 'bg-brand-500' : 'bg-white';
|
|
19110
|
+
const nestedInline = this.nested() && !this.inFlyout() && !this.iconOnly();
|
|
19111
|
+
return nestedInline
|
|
19112
|
+
? `pointer-events-none absolute -left-3 top-1/2 h-5 w-0.5 -translate-x-1/2 -translate-y-1/2 rounded-full ${color}`
|
|
19113
|
+
: `pointer-events-none absolute left-1 top-1/2 h-5 w-1 -translate-y-1/2 rounded-full ${color}`;
|
|
19114
|
+
}, ...(ngDevMode ? [{ debugName: "accentBarClass" }] : []));
|
|
19115
|
+
showTip(event) {
|
|
19116
|
+
if (!this.iconOnly())
|
|
19117
|
+
return;
|
|
19118
|
+
const el = event.currentTarget;
|
|
19119
|
+
const r = el.getBoundingClientRect();
|
|
19120
|
+
const railRight = el.closest('aside')?.getBoundingClientRect().right ?? r.right;
|
|
19121
|
+
this.tip.set({ top: r.top + r.height / 2, left: railRight + 8 });
|
|
19122
|
+
}
|
|
19123
|
+
chosen() {
|
|
19124
|
+
this.tip.set(null);
|
|
19125
|
+
this.store.closeMobile();
|
|
19126
|
+
this.group?.closeFlyout();
|
|
19127
|
+
}
|
|
18624
19128
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsNavItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18625
19129
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsNavItem, isStandalone: true, selector: "sds-nav-item", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null }, exact: { classPropertyName: "exact", publicName: "exact", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, badgeLabel: { classPropertyName: "badgeLabel", publicName: "badgeLabel", isSignal: true, isRequired: false, transformFunction: null }, badgeMax: { classPropertyName: "badgeMax", publicName: "badgeMax", isSignal: true, isRequired: false, transformFunction: null }, badgeTone: { classPropertyName: "badgeTone", publicName: "badgeTone", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select" }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
18626
19130
|
@if (link() !== null) {
|
|
@@ -18630,10 +19134,13 @@ class SdsNavItem {
|
|
|
18630
19134
|
#rla="routerLinkActive"
|
|
18631
19135
|
[routerLinkActiveOptions]="{ exact: exact() }"
|
|
18632
19136
|
[class]="itemClass(rla.isActive || active())"
|
|
18633
|
-
[attr.
|
|
18634
|
-
[attr.aria-label]="collapsed() ? collapsedName() : null"
|
|
19137
|
+
[attr.aria-label]="iconOnly() ? collapsedName() : null"
|
|
18635
19138
|
[attr.aria-current]="rla.isActive || active() ? 'page' : null"
|
|
18636
|
-
(click)="
|
|
19139
|
+
(click)="chosen()"
|
|
19140
|
+
(pointerenter)="showTip($event)"
|
|
19141
|
+
(pointerleave)="tip.set(null)"
|
|
19142
|
+
(focus)="showTip($event)"
|
|
19143
|
+
(blur)="tip.set(null)"
|
|
18637
19144
|
>
|
|
18638
19145
|
@if (rla.isActive || active()) {
|
|
18639
19146
|
<span [class]="accentBarClass()" aria-hidden="true"></span>
|
|
@@ -18644,10 +19151,13 @@ class SdsNavItem {
|
|
|
18644
19151
|
<button
|
|
18645
19152
|
type="button"
|
|
18646
19153
|
[class]="itemClass(active())"
|
|
18647
|
-
[attr.
|
|
18648
|
-
[attr.aria-label]="collapsed() ? collapsedName() : null"
|
|
19154
|
+
[attr.aria-label]="iconOnly() ? collapsedName() : null"
|
|
18649
19155
|
[attr.aria-current]="active() ? 'page' : null"
|
|
18650
|
-
(click)="select.emit();
|
|
19156
|
+
(click)="select.emit(); chosen()"
|
|
19157
|
+
(pointerenter)="showTip($event)"
|
|
19158
|
+
(pointerleave)="tip.set(null)"
|
|
19159
|
+
(focus)="showTip($event)"
|
|
19160
|
+
(blur)="tip.set(null)"
|
|
18651
19161
|
>
|
|
18652
19162
|
@if (active()) {
|
|
18653
19163
|
<span [class]="accentBarClass()" aria-hidden="true"></span>
|
|
@@ -18658,15 +19168,32 @@ class SdsNavItem {
|
|
|
18658
19168
|
|
|
18659
19169
|
<ng-template #content>
|
|
18660
19170
|
@if (icon()) {
|
|
18661
|
-
<sds-icon [name]="icon()!" [size]="20" class="shrink-0" />
|
|
19171
|
+
<sds-icon [name]="icon()!" [size]="nested() && !iconOnly() ? 18 : 20" class="shrink-0" />
|
|
19172
|
+
}
|
|
19173
|
+
@if (!iconOnly()) {
|
|
19174
|
+
<span class="min-w-0 flex-1 truncate">{{ label() }}</span>
|
|
18662
19175
|
}
|
|
18663
|
-
<!-- Label is hidden only on the collapsed desktop rail; always shown in the mobile drawer. -->
|
|
18664
|
-
<span class="truncate" [class]="collapsed() ? 'lg:hidden' : ''">{{ label() }}</span>
|
|
18665
19176
|
@if (badgeText(); as text) {
|
|
18666
|
-
<!-- The number is drawn; the words are what is spoken ("Menu, 3 pending"). On the
|
|
18667
|
-
|
|
19177
|
+
<!-- The number is drawn; the words are what is spoken ("Menu, 3 pending"). On the icon rail it
|
|
19178
|
+
becomes a small pill on the icon's corner. -->
|
|
18668
19179
|
<span [class]="badgeClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
|
|
18669
|
-
|
|
19180
|
+
@if (!iconOnly()) {
|
|
19181
|
+
<span class="sr-only">, {{ text }}</span>
|
|
19182
|
+
}
|
|
19183
|
+
}
|
|
19184
|
+
@if (tip(); as t) {
|
|
19185
|
+
<!-- Icon-rail tooltip: fixed, so the rail's scroll container never clips it. -->
|
|
19186
|
+
<span
|
|
19187
|
+
aria-hidden="true"
|
|
19188
|
+
class="pointer-events-none fixed z-[70] -translate-y-1/2 whitespace-nowrap rounded-control bg-ink px-2.5 py-1.5 text-xs font-medium text-surface shadow-lg"
|
|
19189
|
+
[style.top.px]="t.top"
|
|
19190
|
+
[style.left.px]="t.left"
|
|
19191
|
+
>
|
|
19192
|
+
{{ label() }}
|
|
19193
|
+
@if (badgeText()) {
|
|
19194
|
+
<span class="ml-1 opacity-70">· {{ badgeDisplay() }}</span>
|
|
19195
|
+
}
|
|
19196
|
+
</span>
|
|
18670
19197
|
}
|
|
18671
19198
|
</ng-template>
|
|
18672
19199
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth", "filled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -18686,10 +19213,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18686
19213
|
#rla="routerLinkActive"
|
|
18687
19214
|
[routerLinkActiveOptions]="{ exact: exact() }"
|
|
18688
19215
|
[class]="itemClass(rla.isActive || active())"
|
|
18689
|
-
[attr.
|
|
18690
|
-
[attr.aria-label]="collapsed() ? collapsedName() : null"
|
|
19216
|
+
[attr.aria-label]="iconOnly() ? collapsedName() : null"
|
|
18691
19217
|
[attr.aria-current]="rla.isActive || active() ? 'page' : null"
|
|
18692
|
-
(click)="
|
|
19218
|
+
(click)="chosen()"
|
|
19219
|
+
(pointerenter)="showTip($event)"
|
|
19220
|
+
(pointerleave)="tip.set(null)"
|
|
19221
|
+
(focus)="showTip($event)"
|
|
19222
|
+
(blur)="tip.set(null)"
|
|
18693
19223
|
>
|
|
18694
19224
|
@if (rla.isActive || active()) {
|
|
18695
19225
|
<span [class]="accentBarClass()" aria-hidden="true"></span>
|
|
@@ -18700,10 +19230,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18700
19230
|
<button
|
|
18701
19231
|
type="button"
|
|
18702
19232
|
[class]="itemClass(active())"
|
|
18703
|
-
[attr.
|
|
18704
|
-
[attr.aria-label]="collapsed() ? collapsedName() : null"
|
|
19233
|
+
[attr.aria-label]="iconOnly() ? collapsedName() : null"
|
|
18705
19234
|
[attr.aria-current]="active() ? 'page' : null"
|
|
18706
|
-
(click)="select.emit();
|
|
19235
|
+
(click)="select.emit(); chosen()"
|
|
19236
|
+
(pointerenter)="showTip($event)"
|
|
19237
|
+
(pointerleave)="tip.set(null)"
|
|
19238
|
+
(focus)="showTip($event)"
|
|
19239
|
+
(blur)="tip.set(null)"
|
|
18707
19240
|
>
|
|
18708
19241
|
@if (active()) {
|
|
18709
19242
|
<span [class]="accentBarClass()" aria-hidden="true"></span>
|
|
@@ -18714,15 +19247,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
18714
19247
|
|
|
18715
19248
|
<ng-template #content>
|
|
18716
19249
|
@if (icon()) {
|
|
18717
|
-
<sds-icon [name]="icon()!" [size]="20" class="shrink-0" />
|
|
19250
|
+
<sds-icon [name]="icon()!" [size]="nested() && !iconOnly() ? 18 : 20" class="shrink-0" />
|
|
19251
|
+
}
|
|
19252
|
+
@if (!iconOnly()) {
|
|
19253
|
+
<span class="min-w-0 flex-1 truncate">{{ label() }}</span>
|
|
18718
19254
|
}
|
|
18719
|
-
<!-- Label is hidden only on the collapsed desktop rail; always shown in the mobile drawer. -->
|
|
18720
|
-
<span class="truncate" [class]="collapsed() ? 'lg:hidden' : ''">{{ label() }}</span>
|
|
18721
19255
|
@if (badgeText(); as text) {
|
|
18722
|
-
<!-- The number is drawn; the words are what is spoken ("Menu, 3 pending"). On the
|
|
18723
|
-
|
|
19256
|
+
<!-- The number is drawn; the words are what is spoken ("Menu, 3 pending"). On the icon rail it
|
|
19257
|
+
becomes a small pill on the icon's corner. -->
|
|
18724
19258
|
<span [class]="badgeClass()" aria-hidden="true">{{ badgeDisplay() }}</span>
|
|
18725
|
-
|
|
19259
|
+
@if (!iconOnly()) {
|
|
19260
|
+
<span class="sr-only">, {{ text }}</span>
|
|
19261
|
+
}
|
|
19262
|
+
}
|
|
19263
|
+
@if (tip(); as t) {
|
|
19264
|
+
<!-- Icon-rail tooltip: fixed, so the rail's scroll container never clips it. -->
|
|
19265
|
+
<span
|
|
19266
|
+
aria-hidden="true"
|
|
19267
|
+
class="pointer-events-none fixed z-[70] -translate-y-1/2 whitespace-nowrap rounded-control bg-ink px-2.5 py-1.5 text-xs font-medium text-surface shadow-lg"
|
|
19268
|
+
[style.top.px]="t.top"
|
|
19269
|
+
[style.left.px]="t.left"
|
|
19270
|
+
>
|
|
19271
|
+
{{ label() }}
|
|
19272
|
+
@if (badgeText()) {
|
|
19273
|
+
<span class="ml-1 opacity-70">· {{ badgeDisplay() }}</span>
|
|
19274
|
+
}
|
|
19275
|
+
</span>
|
|
18726
19276
|
}
|
|
18727
19277
|
</ng-template>
|
|
18728
19278
|
`,
|