@cute-widgets/base 20.0.1
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/CHANGELOG.md +1 -0
- package/LICENSE.md +191 -0
- package/README.md +190 -0
- package/abstract/index.d.ts +327 -0
- package/alert/index.d.ts +68 -0
- package/autocomplete/index.d.ts +442 -0
- package/badge/index.d.ts +26 -0
- package/bottom-sheet/index.d.ts +231 -0
- package/button/index.d.ts +182 -0
- package/button-toggle/index.d.ts +225 -0
- package/card/index.d.ts +163 -0
- package/checkbox/index.d.ts +174 -0
- package/chips/index.d.ts +963 -0
- package/collapse/index.d.ts +97 -0
- package/core/animation/index.d.ts +43 -0
- package/core/datetime/index.d.ts +404 -0
- package/core/directives/index.d.ts +168 -0
- package/core/error/index.d.ts +74 -0
- package/core/index.d.ts +1039 -0
- package/core/interfaces/index.d.ts +114 -0
- package/core/layout/index.d.ts +53 -0
- package/core/line/index.d.ts +37 -0
- package/core/nav/index.d.ts +321 -0
- package/core/observers/index.d.ts +124 -0
- package/core/option/index.d.ts +185 -0
- package/core/pipes/index.d.ts +53 -0
- package/core/ripple/index.d.ts +66 -0
- package/core/testing/index.d.ts +154 -0
- package/core/theming/index.d.ts +118 -0
- package/core/types/index.d.ts +53 -0
- package/core/utils/index.d.ts +129 -0
- package/cute-widgets-base-20.0.1.tgz +0 -0
- package/datepicker/index.d.ts +1817 -0
- package/dialog/index.d.ts +484 -0
- package/divider/index.d.ts +24 -0
- package/expansion/README.md +8 -0
- package/expansion/index.d.ts +308 -0
- package/fesm2022/cute-widgets-base-abstract.mjs +547 -0
- package/fesm2022/cute-widgets-base-abstract.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-alert.mjs +198 -0
- package/fesm2022/cute-widgets-base-alert.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-autocomplete.mjs +1217 -0
- package/fesm2022/cute-widgets-base-autocomplete.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-badge.mjs +75 -0
- package/fesm2022/cute-widgets-base-badge.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-bottom-sheet.mjs +416 -0
- package/fesm2022/cute-widgets-base-bottom-sheet.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-button-toggle.mjs +640 -0
- package/fesm2022/cute-widgets-base-button-toggle.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-button.mjs +546 -0
- package/fesm2022/cute-widgets-base-button.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-card.mjs +471 -0
- package/fesm2022/cute-widgets-base-card.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-checkbox.mjs +390 -0
- package/fesm2022/cute-widgets-base-checkbox.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-chips.mjs +2360 -0
- package/fesm2022/cute-widgets-base-chips.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-collapse.mjs +259 -0
- package/fesm2022/cute-widgets-base-collapse.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-animation.mjs +53 -0
- package/fesm2022/cute-widgets-base-core-animation.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-datetime.mjs +568 -0
- package/fesm2022/cute-widgets-base-core-datetime.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-directives.mjs +404 -0
- package/fesm2022/cute-widgets-base-core-directives.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-error.mjs +105 -0
- package/fesm2022/cute-widgets-base-core-error.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-interfaces.mjs +22 -0
- package/fesm2022/cute-widgets-base-core-interfaces.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-layout.mjs +74 -0
- package/fesm2022/cute-widgets-base-core-layout.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-line.mjs +87 -0
- package/fesm2022/cute-widgets-base-core-line.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-nav.mjs +863 -0
- package/fesm2022/cute-widgets-base-core-nav.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-observers.mjs +304 -0
- package/fesm2022/cute-widgets-base-core-observers.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-option.mjs +373 -0
- package/fesm2022/cute-widgets-base-core-option.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-pipes.mjs +97 -0
- package/fesm2022/cute-widgets-base-core-pipes.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-ripple.mjs +172 -0
- package/fesm2022/cute-widgets-base-core-ripple.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-testing.mjs +210 -0
- package/fesm2022/cute-widgets-base-core-testing.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-theming.mjs +314 -0
- package/fesm2022/cute-widgets-base-core-theming.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-types.mjs +22 -0
- package/fesm2022/cute-widgets-base-core-types.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core-utils.mjs +257 -0
- package/fesm2022/cute-widgets-base-core-utils.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-core.mjs +1600 -0
- package/fesm2022/cute-widgets-base-core.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-datepicker.mjs +4827 -0
- package/fesm2022/cute-widgets-base-datepicker.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-dialog.mjs +1046 -0
- package/fesm2022/cute-widgets-base-dialog.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-divider.mjs +86 -0
- package/fesm2022/cute-widgets-base-divider.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-expansion.mjs +623 -0
- package/fesm2022/cute-widgets-base-expansion.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-form-field.mjs +969 -0
- package/fesm2022/cute-widgets-base-form-field.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-grid-list.mjs +715 -0
- package/fesm2022/cute-widgets-base-grid-list.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-icon.mjs +1105 -0
- package/fesm2022/cute-widgets-base-icon.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-input.mjs +726 -0
- package/fesm2022/cute-widgets-base-input.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-layout-container.mjs +95 -0
- package/fesm2022/cute-widgets-base-layout-container.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-layout-stack.mjs +166 -0
- package/fesm2022/cute-widgets-base-layout-stack.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-layout.mjs +250 -0
- package/fesm2022/cute-widgets-base-layout.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-list.mjs +1557 -0
- package/fesm2022/cute-widgets-base-list.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-menu.mjs +1283 -0
- package/fesm2022/cute-widgets-base-menu.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-navbar.mjs +359 -0
- package/fesm2022/cute-widgets-base-navbar.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-paginator.mjs +485 -0
- package/fesm2022/cute-widgets-base-paginator.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-progress.mjs +321 -0
- package/fesm2022/cute-widgets-base-progress.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-radio.mjs +637 -0
- package/fesm2022/cute-widgets-base-radio.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-select.mjs +1208 -0
- package/fesm2022/cute-widgets-base-select.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-sidenav.mjs +1095 -0
- package/fesm2022/cute-widgets-base-sidenav.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-slider.mjs +99 -0
- package/fesm2022/cute-widgets-base-slider.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-snack-bar.mjs +897 -0
- package/fesm2022/cute-widgets-base-snack-bar.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-sort.mjs +639 -0
- package/fesm2022/cute-widgets-base-sort.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-spinner.mjs +154 -0
- package/fesm2022/cute-widgets-base-spinner.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-stepper.mjs +673 -0
- package/fesm2022/cute-widgets-base-stepper.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-table.mjs +1023 -0
- package/fesm2022/cute-widgets-base-table.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-tabs.mjs +729 -0
- package/fesm2022/cute-widgets-base-tabs.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-timepicker.mjs +965 -0
- package/fesm2022/cute-widgets-base-timepicker.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-toolbar.mjs +120 -0
- package/fesm2022/cute-widgets-base-toolbar.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-tooltip.mjs +947 -0
- package/fesm2022/cute-widgets-base-tooltip.mjs.map +1 -0
- package/fesm2022/cute-widgets-base-tree.mjs +598 -0
- package/fesm2022/cute-widgets-base-tree.mjs.map +1 -0
- package/fesm2022/cute-widgets-base.mjs +68 -0
- package/fesm2022/cute-widgets-base.mjs.map +1 -0
- package/form-field/index.d.ts +401 -0
- package/grid-list/index.d.ts +361 -0
- package/icon/index.d.ts +477 -0
- package/index.d.ts +3 -0
- package/input/index.d.ts +256 -0
- package/layout/container/index.d.ts +31 -0
- package/layout/index.d.ts +78 -0
- package/layout/stack/index.d.ts +52 -0
- package/list/index.d.ts +659 -0
- package/menu/index.d.ts +497 -0
- package/navbar/index.d.ts +91 -0
- package/package.json +279 -0
- package/paginator/index.d.ts +216 -0
- package/progress/index.d.ts +130 -0
- package/radio/index.d.ts +259 -0
- package/select/index.d.ts +426 -0
- package/sidenav/index.d.ts +369 -0
- package/slider/index.d.ts +48 -0
- package/snack-bar/index.d.ts +374 -0
- package/sort/index.d.ts +334 -0
- package/spinner/index.d.ts +70 -0
- package/stepper/index.d.ts +295 -0
- package/table/index.d.ts +395 -0
- package/tabs/index.d.ts +307 -0
- package/timepicker/index.d.ts +350 -0
- package/toolbar/index.d.ts +36 -0
- package/tooltip/index.d.ts +299 -0
- package/tree/index.d.ts +314 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, booleanAttribute, Input, ChangeDetectionStrategy, ViewEncapsulation, Component, EventEmitter, ViewChild, Output, NgModule } from '@angular/core';
|
|
3
|
+
import { ENTER, SPACE, hasModifierKey } from '@angular/cdk/keycodes';
|
|
4
|
+
import { Subject } from 'rxjs';
|
|
5
|
+
import { CuteFocusableControl } from '@cute-widgets/base/abstract';
|
|
6
|
+
import { toTextBgCssClass } from '@cute-widgets/base/core/theming';
|
|
7
|
+
import { CommonModule } from '@angular/common';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @license Apache-2.0
|
|
11
|
+
*
|
|
12
|
+
* Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
|
|
13
|
+
*
|
|
14
|
+
* You may not use this file except in compliance with the License
|
|
15
|
+
* that can be found at http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* This code is a modification of the `@angular/material` original
|
|
18
|
+
* code licensed under MIT-style License (https://angular.dev/license).
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Injection token used to provide the parent component to options.
|
|
22
|
+
*/
|
|
23
|
+
const CUTE_OPTION_PARENT_COMPONENT = new InjectionToken('CUTE_OPTION_PARENT_COMPONENT');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @license Apache-2.0
|
|
27
|
+
*
|
|
28
|
+
* Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
|
|
29
|
+
*
|
|
30
|
+
* You may not use this file except in compliance with the License
|
|
31
|
+
* that can be found at http://www.apache.org/licenses/LICENSE-2.0
|
|
32
|
+
*
|
|
33
|
+
* This code is a modification of the `@angular/material` original
|
|
34
|
+
* code licensed under MIT-style License (https://angular.dev/license).
|
|
35
|
+
*/
|
|
36
|
+
// Notes on the accessibility pattern used for `cute-optgroup`.
|
|
37
|
+
// The option group has two different "modes": regular and inert. The regular mode uses the
|
|
38
|
+
// recommended a11y pattern which has `role="group"` on the group element with `aria-labelledby`
|
|
39
|
+
// pointing to the label. This works for `cute-select`, but it seems to hit a bug for autocomplete
|
|
40
|
+
// under VoiceOver where the group doesn't get read out at all. The bug appears to be that if
|
|
41
|
+
// there's __any__ a11y-related attribute on the group (e.g. `role` or `aria-labelledby`),
|
|
42
|
+
// VoiceOver on Safari won't read it out.
|
|
43
|
+
// We've introduced the `inert` mode as a workaround. Under this mode, all a11y attributes are
|
|
44
|
+
// removed from the group, and we get the screen reader to read out the group label by mirroring it
|
|
45
|
+
// inside an invisible element in the option. This is suboptimal, because the screen reader will
|
|
46
|
+
// repeat the group label on each navigation, whereas the default pattern only reads the group when
|
|
47
|
+
// the user enters a new group. The following alternate approaches were considered:
|
|
48
|
+
// 1. Reading out the group label using the `LiveAnnouncer` solves the problem, but we can't control
|
|
49
|
+
// when the text will be read out, so sometimes it comes in too late or never if the user
|
|
50
|
+
// navigates quickly.
|
|
51
|
+
// 2. `<cute-option aria-describedby="groupLabel"` - This works on Safari, but VoiceOver in Chrome
|
|
52
|
+
// won't read out the description at all.
|
|
53
|
+
// 3. `<cute-option aria-labelledby="optionLabel groupLabel"` - This works on Chrome, but Safari
|
|
54
|
+
// doesn't read out the text at all. Furthermore, on
|
|
55
|
+
// Counter for unique group ids.
|
|
56
|
+
let _uniqueOptgroupIdCounter = 0;
|
|
57
|
+
/**
|
|
58
|
+
* Injection token that can be used to reference instances of `CuteOptgroup`. It serves as
|
|
59
|
+
* an alternative token to the actual `CuteOptgroup` class which could cause unnecessary
|
|
60
|
+
* retention of the class and its component metadata.
|
|
61
|
+
*/
|
|
62
|
+
const CUTE_OPTGROUP = new InjectionToken('CuteOptgroup');
|
|
63
|
+
/**
|
|
64
|
+
* Component that is used to group instances of `mat-option`.
|
|
65
|
+
*/
|
|
66
|
+
class CuteOptgroup {
|
|
67
|
+
constructor() {
|
|
68
|
+
/** whether the option group is disabled. */
|
|
69
|
+
this.disabled = false;
|
|
70
|
+
/** Unique id for the underlying label. */
|
|
71
|
+
this._labelId = `cute-optgroup-label-${_uniqueOptgroupIdCounter++}`;
|
|
72
|
+
const parent = inject(CUTE_OPTION_PARENT_COMPONENT, { optional: true });
|
|
73
|
+
this._inert = parent?.inertGroups ?? false;
|
|
74
|
+
}
|
|
75
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteOptgroup, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
76
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.3.15", type: CuteOptgroup, isStandalone: true, selector: "cute-optgroup", inputs: { label: "label", disabled: ["disabled", "disabled", booleanAttribute] }, host: { properties: { "attr.role": "_inert ? null : \"group\"", "attr.aria-disabled": "_inert ? null : disabled", "attr.aria-labelledby": "_inert ? null : _labelId" }, classAttribute: "cute-optgroup" }, providers: [{ provide: CUTE_OPTGROUP, useExisting: CuteOptgroup }], exportAs: ["cuteOptgroup"], ngImport: i0, template: "<span\r\n class=\"cute-optgroup-label\"\r\n role=\"presentation\"\r\n [class.disabled]=\"disabled\"\r\n [id]=\"_labelId\">\r\n <span class=\"cute-list-item__primary-text\">{{ label }} <ng-content></ng-content></span>\r\n</span>\r\n\r\n<ng-content select=\"cute-option, ng-container\"></ng-content>\r\n", styles: [".cute-optgroup .cute-optgroup-label{display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;outline:none}.cute-optgroup .cute-optgroup-label.disabled{opacity:.38}.cute-optgroup .cute-optgroup-label .cute-list-item__primary-text{font-size:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;font-family:inherit;text-decoration:inherit;text-transform:inherit;white-space:normal;color:inherit}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
77
|
+
}
|
|
78
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteOptgroup, decorators: [{
|
|
79
|
+
type: Component,
|
|
80
|
+
args: [{ selector: 'cute-optgroup', exportAs: 'cuteOptgroup', host: {
|
|
81
|
+
'class': 'cute-optgroup',
|
|
82
|
+
'[attr.role]': '_inert ? null : "group"',
|
|
83
|
+
'[attr.aria-disabled]': '_inert ? null : disabled',
|
|
84
|
+
'[attr.aria-labelledby]': '_inert ? null : _labelId',
|
|
85
|
+
}, providers: [{ provide: CUTE_OPTGROUP, useExisting: CuteOptgroup }], standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<span\r\n class=\"cute-optgroup-label\"\r\n role=\"presentation\"\r\n [class.disabled]=\"disabled\"\r\n [id]=\"_labelId\">\r\n <span class=\"cute-list-item__primary-text\">{{ label }} <ng-content></ng-content></span>\r\n</span>\r\n\r\n<ng-content select=\"cute-option, ng-container\"></ng-content>\r\n", styles: [".cute-optgroup .cute-optgroup-label{display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;outline:none}.cute-optgroup .cute-optgroup-label.disabled{opacity:.38}.cute-optgroup .cute-optgroup-label .cute-list-item__primary-text{font-size:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;font-family:inherit;text-decoration:inherit;text-transform:inherit;white-space:normal;color:inherit}\n"] }]
|
|
86
|
+
}], ctorParameters: () => [], propDecorators: { label: [{
|
|
87
|
+
type: Input
|
|
88
|
+
}], disabled: [{
|
|
89
|
+
type: Input,
|
|
90
|
+
args: [{ transform: booleanAttribute }]
|
|
91
|
+
}] } });
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @license Apache-2.0
|
|
95
|
+
*
|
|
96
|
+
* Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
|
|
97
|
+
*
|
|
98
|
+
* You may not use this file except in compliance with the License
|
|
99
|
+
* that can be found at http://www.apache.org/licenses/LICENSE-2.0
|
|
100
|
+
*
|
|
101
|
+
* This code is a modification of the `@angular/material` original
|
|
102
|
+
* code licensed under MIT-style License (https://angular.dev/license).
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* Option IDs need to be unique across components, so this counter exists outside
|
|
106
|
+
* the component definition.
|
|
107
|
+
*/
|
|
108
|
+
let _uniqueIdCounter = 0;
|
|
109
|
+
/** Event object emitted by CuteOption when selected or deselected. */
|
|
110
|
+
class CuteOptionSelectionChange {
|
|
111
|
+
constructor(
|
|
112
|
+
/** Reference to the option that emitted the event. */
|
|
113
|
+
source,
|
|
114
|
+
/** Whether the change in the option's value was a result of a user action. */
|
|
115
|
+
isUserInput = false) {
|
|
116
|
+
this.source = source;
|
|
117
|
+
this.isUserInput = isUserInput;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Single option inside a `<cute-select>` element.
|
|
122
|
+
*/
|
|
123
|
+
class CuteOption extends CuteFocusableControl {
|
|
124
|
+
/** Whether the wrapping component is in multiple selection mode. */
|
|
125
|
+
get multiple() {
|
|
126
|
+
return this._parent && this._parent.multiple;
|
|
127
|
+
}
|
|
128
|
+
/** Whether the option is currently selected. */
|
|
129
|
+
get selected() {
|
|
130
|
+
return this._selected;
|
|
131
|
+
}
|
|
132
|
+
/** Whether ripples for the option are disabled. */
|
|
133
|
+
get disableRipple() {
|
|
134
|
+
return !!(this._parent && this._parent.disableRipple);
|
|
135
|
+
}
|
|
136
|
+
/** Whether to display checkmark for single-selection. */
|
|
137
|
+
get hideSingleSelectionIndicator() {
|
|
138
|
+
return !!(this._parent && this._parent.hideSingleSelectionIndicator);
|
|
139
|
+
}
|
|
140
|
+
getDisabledState() {
|
|
141
|
+
return (this.group && this.group.disabled) || super.getDisabledState();
|
|
142
|
+
}
|
|
143
|
+
generateId() {
|
|
144
|
+
return `cute-option-${_uniqueIdCounter++}`;
|
|
145
|
+
;
|
|
146
|
+
}
|
|
147
|
+
constructor() {
|
|
148
|
+
super();
|
|
149
|
+
this._parent = inject(CUTE_OPTION_PARENT_COMPONENT, { optional: true });
|
|
150
|
+
this.group = inject(CUTE_OPTGROUP, { optional: true });
|
|
151
|
+
this._selected = false;
|
|
152
|
+
this._active = false;
|
|
153
|
+
this._mostRecentViewValue = '';
|
|
154
|
+
/** Event emitted when the option is selected or deselected. */
|
|
155
|
+
this.onSelectionChange = new EventEmitter();
|
|
156
|
+
/** Emits when the state of the option changes and any parents have to be notified. */
|
|
157
|
+
this._stateChanges = new Subject();
|
|
158
|
+
this.toTextBgCssClass = toTextBgCssClass;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Whether the option is currently active and ready to be selected.
|
|
162
|
+
* An active option displays styles, as if it is focused, but the
|
|
163
|
+
* focus is actually retained somewhere else. This comes in handy
|
|
164
|
+
* for components like autocomplete where focus must remain on the input.
|
|
165
|
+
*/
|
|
166
|
+
get active() {
|
|
167
|
+
return this._active;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The displayed value of the option. It is necessary to show the selected option in the
|
|
171
|
+
* select's trigger.
|
|
172
|
+
*/
|
|
173
|
+
get viewValue() {
|
|
174
|
+
// TODO(kara): Add input property alternative for node envs.
|
|
175
|
+
return (this._text?.nativeElement.textContent || '').trim();
|
|
176
|
+
}
|
|
177
|
+
/** Selects the option. */
|
|
178
|
+
select(emitEvent = true) {
|
|
179
|
+
if (!this._selected) {
|
|
180
|
+
this._selected = true;
|
|
181
|
+
this.markForCheck();
|
|
182
|
+
if (emitEvent) {
|
|
183
|
+
this._emitSelectionChangeEvent();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** Deselects the option. */
|
|
188
|
+
deselect(emitEvent = true) {
|
|
189
|
+
if (this._selected) {
|
|
190
|
+
this._selected = false;
|
|
191
|
+
this.markForCheck();
|
|
192
|
+
if (emitEvent) {
|
|
193
|
+
this._emitSelectionChangeEvent();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* This method sets display styles on the option to make it appear
|
|
199
|
+
* active. This is used by the ActiveDescendantKeyManager so key
|
|
200
|
+
* events will display the proper options as active on arrow key events.
|
|
201
|
+
*/
|
|
202
|
+
setActiveStyles() {
|
|
203
|
+
if (!this._active) {
|
|
204
|
+
this._active = true;
|
|
205
|
+
this.markForCheck();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* This method removes display styles on the option that made it appear
|
|
210
|
+
* active. This is used by the ActiveDescendantKeyManager so key
|
|
211
|
+
* events will display the proper options as active on arrow key events.
|
|
212
|
+
*/
|
|
213
|
+
setInactiveStyles() {
|
|
214
|
+
if (this._active) {
|
|
215
|
+
this._active = false;
|
|
216
|
+
this.markForCheck();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/** Gets the label to be used when determining whether the option should be focused. */
|
|
220
|
+
getLabel() {
|
|
221
|
+
return this.viewValue;
|
|
222
|
+
}
|
|
223
|
+
/** Ensures the option is selected when activated from the keyboard. */
|
|
224
|
+
_handleKeydown(event) {
|
|
225
|
+
if ((event.keyCode === ENTER || event.keyCode === SPACE) && !hasModifierKey(event)) {
|
|
226
|
+
this._selectViaInteraction();
|
|
227
|
+
// Prevent the page from scrolling down and form submits.
|
|
228
|
+
event.preventDefault();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Selects the option while indicating the selection came from the user. Used to
|
|
233
|
+
* determine if the select's view -> model callback should be invoked.
|
|
234
|
+
* Used by `CuteSelect` component.
|
|
235
|
+
*/
|
|
236
|
+
_selectViaInteraction() {
|
|
237
|
+
if (!this.disabled) {
|
|
238
|
+
this._selected = this.multiple ? !this._selected : true;
|
|
239
|
+
this.markForCheck();
|
|
240
|
+
this._emitSelectionChangeEvent(true);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** Gets the host DOM element. */
|
|
244
|
+
_getHostElement() {
|
|
245
|
+
return this._elementRef.nativeElement;
|
|
246
|
+
}
|
|
247
|
+
ngAfterViewChecked() {
|
|
248
|
+
// Since parent components could be using the option's label to display the selected values
|
|
249
|
+
// (e.g. `mat-select`) and they don't have a way of knowing if the option's label has changed,
|
|
250
|
+
// we have to check for changes in the DOM ourselves and dispatch an event. These checks are
|
|
251
|
+
// relatively cheap, however; we still limit them only to selected options in order to avoid
|
|
252
|
+
// hitting the DOM too often.
|
|
253
|
+
if (this._selected) {
|
|
254
|
+
const viewValue = this.viewValue;
|
|
255
|
+
if (viewValue !== this._mostRecentViewValue) {
|
|
256
|
+
if (this._mostRecentViewValue) {
|
|
257
|
+
this._stateChanges.next();
|
|
258
|
+
}
|
|
259
|
+
this._mostRecentViewValue = viewValue;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
ngOnDestroy() {
|
|
264
|
+
super.ngOnDestroy();
|
|
265
|
+
this._stateChanges.complete();
|
|
266
|
+
}
|
|
267
|
+
/** Emits the selection change event. */
|
|
268
|
+
_emitSelectionChangeEvent(isUserInput = false) {
|
|
269
|
+
this.onSelectionChange.emit(new CuteOptionSelectionChange(this, isUserInput));
|
|
270
|
+
}
|
|
271
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteOption, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
272
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: CuteOption, isStandalone: true, selector: "cute-option", inputs: { value: "value" }, outputs: { onSelectionChange: "onSelectionChange" }, host: { attributes: { "role": "option" }, listeners: { "click": "_selectViaInteraction()", "keydown": "_handleKeydown($event)" }, properties: { "class": "selected ? toTextBgCssClass(color??\"primary\") : undefined", "class.selected": "selected", "class.multiple": "multiple", "class.active": "active", "class.disabled": "disabled", "id": "id", "tabindex": "disabled ? -1 : 0", "attr.aria-selected": "selected", "attr.aria-disabled": "disabled" }, classAttribute: "cute-option " }, viewQueries: [{ propertyName: "_text", first: true, predicate: ["text"], descendants: true, static: true }], exportAs: ["cuteOption"], usesInheritance: true, ngImport: i0, template: "\r\n<ng-content select=\"cute-icon, i, img, [role=img]\"></ng-content>\r\n\r\n<span class=\"cute-list-item__primary-text\" #text><ng-content></ng-content></span>\r\n", styles: [".cute-option{display:flex;gap:.25em;position:relative;align-items:center;justify-content:flex-start;-webkit-user-select:none;user-select:none;padding:var(--cute-option-padding-y, .25rem) 1rem;cursor:pointer;background-color:transparent}.cute-option .cute-list-item__primary-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cute-option:hover,.cute-option:active,.cute-option.active{outline:none;background-color:var(--bs-secondary-bg)}.cute-option.disabled{opacity:.5;cursor:auto}.cute-option.disabled:hover,.cute-option.disabled:focus{outline:none;background-color:#0000000f}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
273
|
+
}
|
|
274
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteOption, decorators: [{
|
|
275
|
+
type: Component,
|
|
276
|
+
args: [{ selector: 'cute-option', exportAs: 'cuteOption', host: {
|
|
277
|
+
'role': 'option',
|
|
278
|
+
'class': 'cute-option ',
|
|
279
|
+
//'[class]': 'selected ? "text-bg-"+(color ? color : "primary") : "" ',
|
|
280
|
+
'[class]': 'selected ? toTextBgCssClass(color??"primary") : undefined',
|
|
281
|
+
'[class.selected]': 'selected',
|
|
282
|
+
'[class.multiple]': 'multiple',
|
|
283
|
+
'[class.active]': 'active',
|
|
284
|
+
'[class.disabled]': 'disabled',
|
|
285
|
+
'[id]': 'id',
|
|
286
|
+
'[tabindex]': 'disabled ? -1 : 0',
|
|
287
|
+
// Set aria-selected to false for non-selected items and true for selected items. Conform to
|
|
288
|
+
// [WAI ARIA Listbox authoring practices guide](
|
|
289
|
+
// https://www.w3.org/WAI/ARIA/apg/patterns/listbox/), "If any options are selected, each
|
|
290
|
+
// selected option has either aria-selected or aria-checked set to true. All options that are
|
|
291
|
+
// selectable but not selected have either aria-selected or aria-checked set to false." Align
|
|
292
|
+
// aria-selected implementation of Chips and List components.
|
|
293
|
+
//
|
|
294
|
+
// Set `aria-selected="false"` on not-selected listbox options to fix VoiceOver announcing
|
|
295
|
+
// every option as "selected" (#21491).
|
|
296
|
+
'[attr.aria-selected]': 'selected',
|
|
297
|
+
'[attr.aria-disabled]': 'disabled',
|
|
298
|
+
'(click)': '_selectViaInteraction()',
|
|
299
|
+
'(keydown)': '_handleKeydown($event)',
|
|
300
|
+
}, standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "\r\n<ng-content select=\"cute-icon, i, img, [role=img]\"></ng-content>\r\n\r\n<span class=\"cute-list-item__primary-text\" #text><ng-content></ng-content></span>\r\n", styles: [".cute-option{display:flex;gap:.25em;position:relative;align-items:center;justify-content:flex-start;-webkit-user-select:none;user-select:none;padding:var(--cute-option-padding-y, .25rem) 1rem;cursor:pointer;background-color:transparent}.cute-option .cute-list-item__primary-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cute-option:hover,.cute-option:active,.cute-option.active{outline:none;background-color:var(--bs-secondary-bg)}.cute-option.disabled{opacity:.5;cursor:auto}.cute-option.disabled:hover,.cute-option.disabled:focus{outline:none;background-color:#0000000f}\n"] }]
|
|
301
|
+
}], ctorParameters: () => [], propDecorators: { value: [{
|
|
302
|
+
type: Input
|
|
303
|
+
}], onSelectionChange: [{
|
|
304
|
+
type: Output
|
|
305
|
+
}], _text: [{
|
|
306
|
+
type: ViewChild,
|
|
307
|
+
args: ['text', { static: true }]
|
|
308
|
+
}] } });
|
|
309
|
+
/**
|
|
310
|
+
* Counts the number of option group labels that precede the specified option.
|
|
311
|
+
* @param optionIndex Index of the option at which to start counting.
|
|
312
|
+
* @param options Flat list of all the options.
|
|
313
|
+
* @param optionGroups Flat list of all the option groups.
|
|
314
|
+
* @docs-private
|
|
315
|
+
*/
|
|
316
|
+
function _countGroupLabelsBeforeOption(optionIndex, options, optionGroups) {
|
|
317
|
+
if (optionGroups.length) {
|
|
318
|
+
let optionsArray = options.toArray();
|
|
319
|
+
let groups = optionGroups.toArray();
|
|
320
|
+
let groupCounter = 0;
|
|
321
|
+
for (let i = 0; i < optionIndex + 1; i++) {
|
|
322
|
+
if (optionsArray[i].group && optionsArray[i].group === groups[groupCounter]) {
|
|
323
|
+
groupCounter++;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return groupCounter;
|
|
327
|
+
}
|
|
328
|
+
return 0;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Determines the position to which to scroll a panel in order for an option to be into view.
|
|
332
|
+
* @param optionOffset Offset of the option from the top of the panel.
|
|
333
|
+
* @param optionHeight Height of the options.
|
|
334
|
+
* @param currentScrollPosition Current scroll position of the panel.
|
|
335
|
+
* @param panelHeight Height of the panel.
|
|
336
|
+
* @docs-private
|
|
337
|
+
*/
|
|
338
|
+
function _getOptionScrollPosition(optionOffset, optionHeight, currentScrollPosition, panelHeight) {
|
|
339
|
+
if (optionOffset < currentScrollPosition) {
|
|
340
|
+
return optionOffset;
|
|
341
|
+
}
|
|
342
|
+
if (optionOffset + optionHeight > currentScrollPosition + panelHeight) {
|
|
343
|
+
return Math.max(0, optionOffset - panelHeight + optionHeight);
|
|
344
|
+
}
|
|
345
|
+
return currentScrollPosition;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const TYPES = [
|
|
349
|
+
CuteOption,
|
|
350
|
+
CuteOptgroup,
|
|
351
|
+
];
|
|
352
|
+
class CuteOptionModule {
|
|
353
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteOptionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
354
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: CuteOptionModule, imports: [CommonModule, CuteOption,
|
|
355
|
+
CuteOptgroup], exports: [CuteOption,
|
|
356
|
+
CuteOptgroup] }); }
|
|
357
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteOptionModule, imports: [CommonModule] }); }
|
|
358
|
+
}
|
|
359
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteOptionModule, decorators: [{
|
|
360
|
+
type: NgModule,
|
|
361
|
+
args: [{
|
|
362
|
+
imports: [CommonModule, ...TYPES],
|
|
363
|
+
exports: TYPES,
|
|
364
|
+
declarations: [],
|
|
365
|
+
}]
|
|
366
|
+
}] });
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Generated bundle index. Do not edit.
|
|
370
|
+
*/
|
|
371
|
+
|
|
372
|
+
export { CUTE_OPTGROUP, CUTE_OPTION_PARENT_COMPONENT, CuteOptgroup, CuteOption, CuteOptionModule, CuteOptionSelectionChange, _countGroupLabelsBeforeOption, _getOptionScrollPosition };
|
|
373
|
+
//# sourceMappingURL=cute-widgets-base-core-option.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cute-widgets-base-core-option.mjs","sources":["../../../../projects/cute-widgets/base/core/option/src/option-parent.interface.ts","../../../../projects/cute-widgets/base/core/option/src/optgroup.component.ts","../../../../projects/cute-widgets/base/core/option/src/optgroup.component.html","../../../../projects/cute-widgets/base/core/option/src/option.component.ts","../../../../projects/cute-widgets/base/core/option/src/option.component.html","../../../../projects/cute-widgets/base/core/option/src/option.module.ts","../../../../projects/cute-widgets/base/core/option/cute-widgets-base-core-option.ts"],"sourcesContent":["/**\r\n * @license Apache-2.0\r\n *\r\n * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.\r\n *\r\n * You may not use this file except in compliance with the License\r\n * that can be found at http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * This code is a modification of the `@angular/material` original\r\n * code licensed under MIT-style License (https://angular.dev/license).\r\n */\r\nimport {InjectionToken, Signal} from '@angular/core';\r\n\r\n/**\r\n * Describes a parent component that manages a list of options.\r\n * Contains properties that the options can inherit.\r\n */\r\nexport interface CuteOptionParentComponent {\r\n disableRipple?: boolean| Signal<boolean>;\r\n multiple?: boolean;\r\n inertGroups?: boolean;\r\n hideSingleSelectionIndicator?: boolean;\r\n}\r\n\r\n/**\r\n * Injection token used to provide the parent component to options.\r\n */\r\nexport const CUTE_OPTION_PARENT_COMPONENT = new InjectionToken<CuteOptionParentComponent>(\r\n 'CUTE_OPTION_PARENT_COMPONENT',\r\n);\r\n","/**\r\n * @license Apache-2.0\r\n *\r\n * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.\r\n *\r\n * You may not use this file except in compliance with the License\r\n * that can be found at http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * This code is a modification of the `@angular/material` original\r\n * code licensed under MIT-style License (https://angular.dev/license).\r\n */\r\nimport {\r\n Component,\r\n ViewEncapsulation,\r\n ChangeDetectionStrategy,\r\n Input,\r\n InjectionToken,\r\n booleanAttribute, inject,\r\n} from '@angular/core';\r\nimport {CuteOptionParentComponent, CUTE_OPTION_PARENT_COMPONENT} from './option-parent.interface';\r\n\r\n// Notes on the accessibility pattern used for `cute-optgroup`.\r\n// The option group has two different \"modes\": regular and inert. The regular mode uses the\r\n// recommended a11y pattern which has `role=\"group\"` on the group element with `aria-labelledby`\r\n// pointing to the label. This works for `cute-select`, but it seems to hit a bug for autocomplete\r\n// under VoiceOver where the group doesn't get read out at all. The bug appears to be that if\r\n// there's __any__ a11y-related attribute on the group (e.g. `role` or `aria-labelledby`),\r\n// VoiceOver on Safari won't read it out.\r\n// We've introduced the `inert` mode as a workaround. Under this mode, all a11y attributes are\r\n// removed from the group, and we get the screen reader to read out the group label by mirroring it\r\n// inside an invisible element in the option. This is suboptimal, because the screen reader will\r\n// repeat the group label on each navigation, whereas the default pattern only reads the group when\r\n// the user enters a new group. The following alternate approaches were considered:\r\n// 1. Reading out the group label using the `LiveAnnouncer` solves the problem, but we can't control\r\n// when the text will be read out, so sometimes it comes in too late or never if the user\r\n// navigates quickly.\r\n// 2. `<cute-option aria-describedby=\"groupLabel\"` - This works on Safari, but VoiceOver in Chrome\r\n// won't read out the description at all.\r\n// 3. `<cute-option aria-labelledby=\"optionLabel groupLabel\"` - This works on Chrome, but Safari\r\n// doesn't read out the text at all. Furthermore, on\r\n\r\n// Counter for unique group ids.\r\nlet _uniqueOptgroupIdCounter = 0;\r\n\r\n/**\r\n * Injection token that can be used to reference instances of `CuteOptgroup`. It serves as\r\n * an alternative token to the actual `CuteOptgroup` class which could cause unnecessary\r\n * retention of the class and its component metadata.\r\n */\r\nexport const CUTE_OPTGROUP = new InjectionToken<CuteOptgroup>('CuteOptgroup');\r\n\r\n/**\r\n * Component that is used to group instances of `mat-option`.\r\n */\r\n@Component({\r\n selector: 'cute-optgroup',\r\n exportAs: 'cuteOptgroup',\r\n templateUrl: './optgroup.component.html',\r\n styleUrls: ['./optgroup.component.scss'],\r\n host: {\r\n 'class': 'cute-optgroup',\r\n '[attr.role]': '_inert ? null : \"group\"',\r\n '[attr.aria-disabled]': '_inert ? null : disabled',\r\n '[attr.aria-labelledby]': '_inert ? null : _labelId',\r\n },\r\n providers: [{provide: CUTE_OPTGROUP, useExisting: CuteOptgroup}],\r\n standalone: true,\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class CuteOptgroup {\r\n /** Label for the option group. */\r\n @Input() label: string | undefined;\r\n\r\n /** whether the option group is disabled. */\r\n @Input({transform: booleanAttribute}) disabled: boolean = false;\r\n\r\n /** Unique id for the underlying label. */\r\n _labelId: string = `cute-optgroup-label-${_uniqueOptgroupIdCounter++}`;\r\n\r\n /** Whether the group is in inert a11y mode. */\r\n _inert: boolean;\r\n\r\n constructor(...args: unknown[]);\r\n constructor() {\r\n const parent = inject<CuteOptionParentComponent>(CUTE_OPTION_PARENT_COMPONENT, {optional: true});\r\n this._inert = parent?.inertGroups ?? false;\r\n }\r\n}\r\n","<span\r\n class=\"cute-optgroup-label\"\r\n role=\"presentation\"\r\n [class.disabled]=\"disabled\"\r\n [id]=\"_labelId\">\r\n <span class=\"cute-list-item__primary-text\">{{ label }} <ng-content></ng-content></span>\r\n</span>\r\n\r\n<ng-content select=\"cute-option, ng-container\"></ng-content>\r\n","/**\r\n * @license Apache-2.0\r\n *\r\n * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.\r\n *\r\n * You may not use this file except in compliance with the License\r\n * that can be found at http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * This code is a modification of the `@angular/material` original\r\n * code licensed under MIT-style License (https://angular.dev/license).\r\n */\r\nimport {ENTER, hasModifierKey, SPACE} from '@angular/cdk/keycodes';\r\nimport {\r\n Component,\r\n ViewEncapsulation,\r\n ChangeDetectionStrategy,\r\n ElementRef,\r\n AfterViewChecked,\r\n Input,\r\n Output,\r\n EventEmitter,\r\n QueryList,\r\n ViewChild,\r\n inject,\r\n} from '@angular/core';\r\nimport {Subject} from 'rxjs';\r\nimport {CUTE_OPTGROUP, CuteOptgroup} from './optgroup.component';\r\nimport {CuteOptionParentComponent, CUTE_OPTION_PARENT_COMPONENT} from './option-parent.interface';\r\nimport {CuteFocusableControl} from \"@cute-widgets/base/abstract\";\r\nimport {Highlightable} from \"@angular/cdk/a11y\";\r\nimport {toTextBgCssClass} from \"@cute-widgets/base/core/theming\";\r\n\r\n\r\n/**\r\n * Option IDs need to be unique across components, so this counter exists outside\r\n * the component definition.\r\n */\r\nlet _uniqueIdCounter = 0;\r\n\r\n/** Event object emitted by CuteOption when selected or deselected. */\r\nexport class CuteOptionSelectionChange<T = any> {\r\n constructor(\r\n /** Reference to the option that emitted the event. */\r\n public source: CuteOption<T>,\r\n /** Whether the change in the option's value was a result of a user action. */\r\n public isUserInput = false,\r\n ) {}\r\n}\r\n\r\n/**\r\n * Single option inside a `<cute-select>` element.\r\n */\r\n@Component({\r\n selector: 'cute-option',\r\n templateUrl: './option.component.html',\r\n styleUrls: ['./option.component.scss'],\r\n exportAs: 'cuteOption',\r\n host: {\r\n 'role': 'option',\r\n 'class': 'cute-option ',\r\n //'[class]': 'selected ? \"text-bg-\"+(color ? color : \"primary\") : \"\" ',\r\n '[class]': 'selected ? toTextBgCssClass(color??\"primary\") : undefined',\r\n '[class.selected]': 'selected',\r\n '[class.multiple]': 'multiple',\r\n '[class.active]': 'active',\r\n '[class.disabled]': 'disabled',\r\n '[id]': 'id',\r\n '[tabindex]': 'disabled ? -1 : 0',\r\n // Set aria-selected to false for non-selected items and true for selected items. Conform to\r\n // [WAI ARIA Listbox authoring practices guide](\r\n // https://www.w3.org/WAI/ARIA/apg/patterns/listbox/), \"If any options are selected, each\r\n // selected option has either aria-selected or aria-checked set to true. All options that are\r\n // selectable but not selected have either aria-selected or aria-checked set to false.\" Align\r\n // aria-selected implementation of Chips and List components.\r\n //\r\n // Set `aria-selected=\"false\"` on not-selected listbox options to fix VoiceOver announcing\r\n // every option as \"selected\" (#21491).\r\n '[attr.aria-selected]': 'selected',\r\n '[attr.aria-disabled]': 'disabled',\r\n '(click)': '_selectViaInteraction()',\r\n '(keydown)': '_handleKeydown($event)',\r\n },\r\n standalone: true,\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class CuteOption<T = any> extends CuteFocusableControl implements Highlightable, AfterViewChecked {\r\n private _parent = inject<CuteOptionParentComponent>(CUTE_OPTION_PARENT_COMPONENT, {optional: true});\r\n public readonly group = inject<CuteOptgroup>(CUTE_OPTGROUP, {optional: true});\r\n\r\n private _selected = false;\r\n private _active = false;\r\n private _mostRecentViewValue = '';\r\n\r\n /** Whether the wrapping component is in multiple selection mode. */\r\n get multiple() {\r\n return this._parent && this._parent.multiple;\r\n }\r\n\r\n /** Whether the option is currently selected. */\r\n get selected(): boolean {\r\n return this._selected;\r\n }\r\n\r\n /** Whether ripples for the option are disabled. */\r\n get disableRipple(): boolean {\r\n return !!(this._parent && this._parent.disableRipple);\r\n }\r\n\r\n /** Whether to display checkmark for single-selection. */\r\n get hideSingleSelectionIndicator(): boolean {\r\n return !!(this._parent && this._parent.hideSingleSelectionIndicator);\r\n }\r\n\r\n protected override getDisabledState(): boolean {\r\n return (this.group && this.group.disabled) || super.getDisabledState();\r\n }\r\n\r\n protected override generateId(): string {\r\n return `cute-option-${_uniqueIdCounter++}`;;\r\n }\r\n\r\n /** The form value of the option. */\r\n @Input() value: T | undefined;\r\n\r\n /** Event emitted when the option is selected or deselected. */\r\n @Output() readonly onSelectionChange = new EventEmitter<CuteOptionSelectionChange<T>>();\r\n\r\n /** Element containing the option's text. */\r\n @ViewChild('text', {static: true}) _text: ElementRef<HTMLElement> | undefined;\r\n\r\n /** Emits when the state of the option changes and any parents have to be notified. */\r\n readonly _stateChanges = new Subject<void>();\r\n\r\n constructor(...args: unknown[]);\r\n constructor() {\r\n super();\r\n }\r\n\r\n /**\r\n * Whether the option is currently active and ready to be selected.\r\n * An active option displays styles, as if it is focused, but the\r\n * focus is actually retained somewhere else. This comes in handy\r\n * for components like autocomplete where focus must remain on the input.\r\n */\r\n get active(): boolean {\r\n return this._active;\r\n }\r\n\r\n /**\r\n * The displayed value of the option. It is necessary to show the selected option in the\r\n * select's trigger.\r\n */\r\n get viewValue(): string {\r\n // TODO(kara): Add input property alternative for node envs.\r\n return (this._text?.nativeElement.textContent || '').trim();\r\n }\r\n\r\n /** Selects the option. */\r\n select(emitEvent = true): void {\r\n if (!this._selected) {\r\n this._selected = true;\r\n this.markForCheck();\r\n\r\n if (emitEvent) {\r\n this._emitSelectionChangeEvent();\r\n }\r\n }\r\n }\r\n\r\n /** Deselects the option. */\r\n deselect(emitEvent = true): void {\r\n if (this._selected) {\r\n this._selected = false;\r\n this.markForCheck();\r\n\r\n if (emitEvent) {\r\n this._emitSelectionChangeEvent();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * This method sets display styles on the option to make it appear\r\n * active. This is used by the ActiveDescendantKeyManager so key\r\n * events will display the proper options as active on arrow key events.\r\n */\r\n setActiveStyles(): void {\r\n if (!this._active) {\r\n this._active = true;\r\n this.markForCheck();\r\n }\r\n }\r\n\r\n /**\r\n * This method removes display styles on the option that made it appear\r\n * active. This is used by the ActiveDescendantKeyManager so key\r\n * events will display the proper options as active on arrow key events.\r\n */\r\n setInactiveStyles(): void {\r\n if (this._active) {\r\n this._active = false;\r\n this.markForCheck();\r\n }\r\n }\r\n\r\n /** Gets the label to be used when determining whether the option should be focused. */\r\n override getLabel(): string {\r\n return this.viewValue;\r\n }\r\n\r\n /** Ensures the option is selected when activated from the keyboard. */\r\n protected _handleKeydown(event: KeyboardEvent): void {\r\n if ((event.keyCode === ENTER || event.keyCode === SPACE) && !hasModifierKey(event)) {\r\n this._selectViaInteraction();\r\n\r\n // Prevent the page from scrolling down and form submits.\r\n event.preventDefault();\r\n }\r\n }\r\n\r\n /**\r\n * Selects the option while indicating the selection came from the user. Used to\r\n * determine if the select's view -> model callback should be invoked.\r\n * Used by `CuteSelect` component.\r\n */\r\n public _selectViaInteraction(): void {\r\n if (!this.disabled) {\r\n this._selected = this.multiple ? !this._selected : true;\r\n this.markForCheck();\r\n this._emitSelectionChangeEvent(true);\r\n }\r\n }\r\n\r\n /** Gets the host DOM element. */\r\n _getHostElement(): HTMLElement {\r\n return this._elementRef.nativeElement;\r\n }\r\n\r\n ngAfterViewChecked() {\r\n // Since parent components could be using the option's label to display the selected values\r\n // (e.g. `mat-select`) and they don't have a way of knowing if the option's label has changed,\r\n // we have to check for changes in the DOM ourselves and dispatch an event. These checks are\r\n // relatively cheap, however; we still limit them only to selected options in order to avoid\r\n // hitting the DOM too often.\r\n if (this._selected) {\r\n const viewValue = this.viewValue;\r\n\r\n if (viewValue !== this._mostRecentViewValue) {\r\n if (this._mostRecentViewValue) {\r\n this._stateChanges.next();\r\n }\r\n this._mostRecentViewValue = viewValue;\r\n }\r\n }\r\n }\r\n\r\n override ngOnDestroy() {\r\n super.ngOnDestroy();\r\n this._stateChanges.complete();\r\n }\r\n\r\n /** Emits the selection change event. */\r\n private _emitSelectionChangeEvent(isUserInput = false): void {\r\n this.onSelectionChange.emit(new CuteOptionSelectionChange<T>(this, isUserInput));\r\n }\r\n\r\n protected readonly toTextBgCssClass = toTextBgCssClass;\r\n}\r\n\r\n/**\r\n * Counts the number of option group labels that precede the specified option.\r\n * @param optionIndex Index of the option at which to start counting.\r\n * @param options Flat list of all the options.\r\n * @param optionGroups Flat list of all the option groups.\r\n * @docs-private\r\n */\r\nexport function _countGroupLabelsBeforeOption(\r\n optionIndex: number,\r\n options: QueryList<CuteOption>,\r\n optionGroups: QueryList<CuteOptgroup>,\r\n): number {\r\n if (optionGroups.length) {\r\n let optionsArray = options.toArray();\r\n let groups = optionGroups.toArray();\r\n let groupCounter = 0;\r\n\r\n for (let i = 0; i < optionIndex + 1; i++) {\r\n if (optionsArray[i].group && optionsArray[i].group === groups[groupCounter]) {\r\n groupCounter++;\r\n }\r\n }\r\n\r\n return groupCounter;\r\n }\r\n\r\n return 0;\r\n}\r\n\r\n/**\r\n * Determines the position to which to scroll a panel in order for an option to be into view.\r\n * @param optionOffset Offset of the option from the top of the panel.\r\n * @param optionHeight Height of the options.\r\n * @param currentScrollPosition Current scroll position of the panel.\r\n * @param panelHeight Height of the panel.\r\n * @docs-private\r\n */\r\nexport function _getOptionScrollPosition(\r\n optionOffset: number,\r\n optionHeight: number,\r\n currentScrollPosition: number,\r\n panelHeight: number,\r\n): number {\r\n if (optionOffset < currentScrollPosition) {\r\n return optionOffset;\r\n }\r\n\r\n if (optionOffset + optionHeight > currentScrollPosition + panelHeight) {\r\n return Math.max(0, optionOffset - panelHeight + optionHeight);\r\n }\r\n\r\n return currentScrollPosition;\r\n}\r\n","\r\n<ng-content select=\"cute-icon, i, img, [role=img]\"></ng-content>\r\n\r\n<span class=\"cute-list-item__primary-text\" #text><ng-content></ng-content></span>\r\n","import {NgModule, Type} from '@angular/core';\r\nimport {CommonModule} from '@angular/common';\r\nimport {CuteOption} from './option.component';\r\nimport {CuteOptgroup} from './optgroup.component';\r\n\r\nconst TYPES: (any | Type<any>)[] = [\r\n CuteOption,\r\n CuteOptgroup,\r\n];\r\n\r\n@NgModule({\r\n imports: [CommonModule, ...TYPES],\r\n exports: TYPES,\r\n declarations: [],\r\n})\r\nexport class CuteOptionModule {\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, Pipe, SecurityContext } from '@angular/core';
|
|
3
|
+
import { DomSanitizer } from '@angular/platform-browser';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @license Apache-2.0
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
|
|
9
|
+
*
|
|
10
|
+
* You may not use this file except in compliance with the License
|
|
11
|
+
* that can be found at http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Bypass security and trust the given value to be a safe resource.
|
|
15
|
+
* > WARNING: calling this method with untrusted user data exposes your application to XSS security risks!
|
|
16
|
+
* @example
|
|
17
|
+
* ```html
|
|
18
|
+
* <img [src]="item.source | safe:'url'" alt="Item image"/>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
class CuteSafePipe {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.sanitizer = inject(DomSanitizer);
|
|
24
|
+
}
|
|
25
|
+
transform(value, type = "html") {
|
|
26
|
+
if (typeof value === "string") {
|
|
27
|
+
switch (type.toLowerCase()) {
|
|
28
|
+
case 'html': return this.sanitizer.bypassSecurityTrustHtml(value);
|
|
29
|
+
case 'style': return this.sanitizer.bypassSecurityTrustStyle(value);
|
|
30
|
+
case 'script': return this.sanitizer.bypassSecurityTrustScript(value);
|
|
31
|
+
case 'url': return this.sanitizer.bypassSecurityTrustUrl(value);
|
|
32
|
+
case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(value);
|
|
33
|
+
default: throw new Error(`Invalid safe type specified: ${type}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteSafePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
39
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: CuteSafePipe, isStandalone: true, name: "safe" }); }
|
|
40
|
+
}
|
|
41
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteSafePipe, decorators: [{
|
|
42
|
+
type: Pipe,
|
|
43
|
+
args: [{
|
|
44
|
+
name: 'safe'
|
|
45
|
+
}]
|
|
46
|
+
}] });
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @license Apache-2.0
|
|
50
|
+
*
|
|
51
|
+
* Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
|
|
52
|
+
*
|
|
53
|
+
* You may not use this file except in compliance with the License
|
|
54
|
+
* that can be found at http://www.apache.org/licenses/LICENSE-2.0
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* Gets a safe value from either a known safe value or a value with unknown safety.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```html
|
|
61
|
+
* <div [innerHTML]="item.htmlContent | sanitize:'html'"></div>
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
class CuteSanitizePipe {
|
|
65
|
+
constructor() {
|
|
66
|
+
this.sanitizer = inject(DomSanitizer);
|
|
67
|
+
}
|
|
68
|
+
transform(value, context = 'html') {
|
|
69
|
+
if (typeof value === "string") {
|
|
70
|
+
switch (context.toLowerCase()) {
|
|
71
|
+
case 'html': return this.sanitizer.sanitize(SecurityContext.HTML, value);
|
|
72
|
+
case 'style': return this.sanitizer.sanitize(SecurityContext.STYLE, value);
|
|
73
|
+
case 'script': return this.sanitizer.sanitize(SecurityContext.SCRIPT, value);
|
|
74
|
+
case 'url': return this.sanitizer.sanitize(SecurityContext.URL, value);
|
|
75
|
+
case 'resourceUrl': return this.sanitizer.sanitize(SecurityContext.RESOURCE_URL, value);
|
|
76
|
+
case 'none': return this.sanitizer.sanitize(SecurityContext.NONE, value);
|
|
77
|
+
default: throw new Error(`Invalid security context specified: ${context}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return "";
|
|
81
|
+
}
|
|
82
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteSanitizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
83
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: CuteSanitizePipe, isStandalone: true, name: "sanitize" }); }
|
|
84
|
+
}
|
|
85
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteSanitizePipe, decorators: [{
|
|
86
|
+
type: Pipe,
|
|
87
|
+
args: [{
|
|
88
|
+
name: 'sanitize'
|
|
89
|
+
}]
|
|
90
|
+
}] });
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Generated bundle index. Do not edit.
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
export { CuteSafePipe, CuteSanitizePipe };
|
|
97
|
+
//# sourceMappingURL=cute-widgets-base-core-pipes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cute-widgets-base-core-pipes.mjs","sources":["../../../../projects/cute-widgets/base/core/pipes/src/safe.pipe.ts","../../../../projects/cute-widgets/base/core/pipes/src/sanitize.pipe.ts","../../../../projects/cute-widgets/base/core/pipes/cute-widgets-base-core-pipes.ts"],"sourcesContent":["/**\r\n * @license Apache-2.0\r\n *\r\n * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.\r\n *\r\n * You may not use this file except in compliance with the License\r\n * that can be found at http://www.apache.org/licenses/LICENSE-2.0\r\n */\r\nimport {inject, Pipe, PipeTransform} from '@angular/core';\r\nimport { DomSanitizer, SafeValue } from \"@angular/platform-browser\";\r\n\r\n/**\r\n * Bypass security and trust the given value to be a safe resource.\r\n * > WARNING: calling this method with untrusted user data exposes your application to XSS security risks!\r\n * @example\r\n * ```html\r\n * <img [src]=\"item.source | safe:'url'\" alt=\"Item image\"/>\r\n * ```\r\n */\r\n@Pipe({\r\n name: 'safe'\r\n})\r\nexport class CuteSafePipe implements PipeTransform {\r\n protected sanitizer: DomSanitizer = inject(DomSanitizer);\r\n\r\n transform(value: any, type: 'html'|'style'|'script'|'url'|'resourceUrl' = \"html\"): SafeValue {\r\n if (typeof value===\"string\") {\r\n switch (type.toLowerCase()) {\r\n case 'html': return this.sanitizer.bypassSecurityTrustHtml(value);\r\n case 'style': return this.sanitizer.bypassSecurityTrustStyle(value);\r\n case 'script': return this.sanitizer.bypassSecurityTrustScript(value);\r\n case 'url': return this.sanitizer.bypassSecurityTrustUrl(value);\r\n case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(value);\r\n default: throw new Error(`Invalid safe type specified: ${type}`);\r\n }\r\n }\r\n return \"\";\r\n }\r\n}\r\n","/**\r\n * @license Apache-2.0\r\n *\r\n * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.\r\n *\r\n * You may not use this file except in compliance with the License\r\n * that can be found at http://www.apache.org/licenses/LICENSE-2.0\r\n */\r\nimport {inject, Pipe, PipeTransform, SecurityContext} from '@angular/core';\r\nimport {DomSanitizer, SafeValue} from \"@angular/platform-browser\";\r\n\r\n/**\r\n * Gets a safe value from either a known safe value or a value with unknown safety.\r\n *\r\n * @example\r\n * ```html\r\n * <div [innerHTML]=\"item.htmlContent | sanitize:'html'\"></div>\r\n * ```\r\n */\r\n@Pipe({\r\n name: 'sanitize'\r\n})\r\nexport class CuteSanitizePipe implements PipeTransform {\r\n protected sanitizer: DomSanitizer = inject(DomSanitizer);\r\n\r\n transform(value: any, context: 'html'|'style'|'script'|'url'|'resourceUrl'|'none' = 'html'): SafeValue|null {\r\n if (typeof value===\"string\") {\r\n switch (context.toLowerCase()) {\r\n case 'html': return this.sanitizer.sanitize(SecurityContext.HTML, value);\r\n case 'style': return this.sanitizer.sanitize(SecurityContext.STYLE, value);\r\n case 'script': return this.sanitizer.sanitize(SecurityContext.SCRIPT, value);\r\n case 'url': return this.sanitizer.sanitize(SecurityContext.URL, value);\r\n case 'resourceUrl': return this.sanitizer.sanitize(SecurityContext.RESOURCE_URL, value);\r\n case 'none': return this.sanitizer.sanitize(SecurityContext.NONE, value);\r\n default: throw new Error(`Invalid security context specified: ${context}`);\r\n }\r\n }\r\n return \"\";\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|