UNPKG

17.1 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { forwardRef, Directive, Input, HostBinding, HostListener, Optional, Inject, ContentChildren, NgModule } from '@angular/core';
3import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
5// TODO: config: activeClass - Class to apply to the checked buttons
6const CHECKBOX_CONTROL_VALUE_ACCESSOR = {
7 provide: NG_VALUE_ACCESSOR,
8 useExisting: forwardRef(() => ButtonCheckboxDirective),
9 multi: true
10};
11/**
12 * Add checkbox functionality to any element
13 */
14class ButtonCheckboxDirective {
15 constructor() {
16 /** Truthy value, will be set to ngModel */
17 this.btnCheckboxTrue = true;
18 /** Falsy value, will be set to ngModel */
19 this.btnCheckboxFalse = false;
20 this.state = false;
21 this.isDisabled = false;
22 this.onChange = Function.prototype;
23 this.onTouched = Function.prototype;
24 }
25 // view -> model
26 onClick() {
27 if (this.isDisabled) {
28 return;
29 }
30 this.toggle(!this.state);
31 this.onChange(this.value);
32 }
33 ngOnInit() {
34 this.toggle(this.trueValue === this.value);
35 }
36 get trueValue() {
37 return typeof this.btnCheckboxTrue !== 'undefined'
38 ? this.btnCheckboxTrue
39 : true;
40 }
41 get falseValue() {
42 return typeof this.btnCheckboxFalse !== 'undefined'
43 ? this.btnCheckboxFalse
44 : false;
45 }
46 toggle(state) {
47 this.state = state;
48 this.value = this.state ? this.trueValue : this.falseValue;
49 }
50 // ControlValueAccessor
51 // model -> view
52 writeValue(value) {
53 this.state = this.trueValue === value;
54 this.value = value ? this.trueValue : this.falseValue;
55 }
56 setDisabledState(isDisabled) {
57 this.isDisabled = isDisabled;
58 }
59 registerOnChange(fn) {
60 this.onChange = fn;
61 }
62 registerOnTouched(fn) {
63 this.onTouched = fn;
64 }
65}
66ButtonCheckboxDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonCheckboxDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
67ButtonCheckboxDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.6", type: ButtonCheckboxDirective, selector: "[btnCheckbox]", inputs: { btnCheckboxTrue: "btnCheckboxTrue", btnCheckboxFalse: "btnCheckboxFalse" }, host: { listeners: { "click": "onClick()" }, properties: { "class.active": "this.state", "attr.aria-pressed": "this.state" } }, providers: [CHECKBOX_CONTROL_VALUE_ACCESSOR], ngImport: i0 });
68i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonCheckboxDirective, decorators: [{
69 type: Directive,
70 args: [{
71 selector: '[btnCheckbox]',
72 providers: [CHECKBOX_CONTROL_VALUE_ACCESSOR]
73 }]
74 }], propDecorators: { btnCheckboxTrue: [{
75 type: Input
76 }], btnCheckboxFalse: [{
77 type: Input
78 }], state: [{
79 type: HostBinding,
80 args: ['class.active']
81 }, {
82 type: HostBinding,
83 args: ['attr.aria-pressed']
84 }], onClick: [{
85 type: HostListener,
86 args: ['click']
87 }] } });
88
89const RADIO_CONTROL_VALUE_ACCESSOR$1 = {
90 provide: NG_VALUE_ACCESSOR,
91 useExisting: forwardRef(() => ButtonRadioDirective),
92 multi: true
93};
94/**
95 * Create radio buttons or groups of buttons.
96 * A value of a selected button is bound to a variable specified via ngModel.
97 */
98class ButtonRadioDirective {
99 constructor(el, cdr, renderer, group) {
100 this.el = el;
101 this.cdr = cdr;
102 this.renderer = renderer;
103 this.group = group;
104 this.onChange = Function.prototype;
105 this.onTouched = Function.prototype;
106 /** If `true` — radio button can be unchecked */
107 this.uncheckable = false;
108 this.role = 'radio';
109 this._disabled = false;
110 this._hasFocus = false;
111 }
112 /** Current value of radio component or group */
113 get value() {
114 return this.group ? this.group.value : this._value;
115 }
116 set value(value) {
117 if (this.group) {
118 this.group.value = value;
119 return;
120 }
121 this._value = value;
122 this._onChange(value);
123 }
124 /** If `true` — radio button is disabled */
125 get disabled() {
126 return this._disabled;
127 }
128 set disabled(disabled) {
129 this.setDisabledState(disabled);
130 }
131 get controlOrGroupDisabled() {
132 return this.disabled || (this.group && this.group.disabled) ? true : undefined;
133 }
134 get hasDisabledClass() {
135 // Although the radio is disabled the active radio should still stand out.
136 // The disabled class will prevent this so don't add it on the active radio
137 return this.controlOrGroupDisabled && !this.isActive;
138 }
139 get isActive() {
140 return this.btnRadio === this.value;
141 }
142 get tabindex() {
143 if (this.controlOrGroupDisabled) {
144 // Disabled radio buttons should not receive focus
145 return undefined;
146 }
147 else if (this.isActive || this.group == null) {
148 return 0;
149 }
150 else {
151 return -1;
152 }
153 }
154 get hasFocus() {
155 return this._hasFocus;
156 }
157 toggleIfAllowed() {
158 if (!this.canToggle()) {
159 return;
160 }
161 if (this.uncheckable && this.btnRadio === this.value) {
162 this.value = undefined;
163 }
164 else {
165 this.value = this.btnRadio;
166 }
167 }
168 onSpacePressed(event) {
169 this.toggleIfAllowed();
170 event.preventDefault();
171 }
172 focus() {
173 this.el.nativeElement.focus();
174 }
175 onFocus() {
176 this._hasFocus = true;
177 }
178 onBlur() {
179 this._hasFocus = false;
180 this.onTouched();
181 }
182 canToggle() {
183 return !this.controlOrGroupDisabled && (this.uncheckable || this.btnRadio !== this.value);
184 }
185 ngOnChanges(changes) {
186 if ('uncheckable' in changes) {
187 this.uncheckable = this.uncheckable !== false && typeof this.uncheckable !== 'undefined';
188 }
189 }
190 _onChange(value) {
191 if (this.group) {
192 this.group.value = value;
193 return;
194 }
195 this.onTouched();
196 this.onChange(value);
197 }
198 // ControlValueAccessor
199 // model -> view
200 writeValue(value) {
201 this.value = value;
202 this.cdr.markForCheck();
203 }
204 registerOnChange(fn) {
205 this.onChange = fn;
206 }
207 registerOnTouched(fn) {
208 this.onTouched = fn;
209 }
210 setDisabledState(disabled) {
211 this._disabled = disabled;
212 if (disabled) {
213 this.renderer.setAttribute(this.el.nativeElement, 'disabled', 'disabled');
214 return;
215 }
216 this.renderer.removeAttribute(this.el.nativeElement, 'disabled');
217 }
218}
219ButtonRadioDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonRadioDirective, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: forwardRef(() => ButtonRadioGroupDirective), optional: true }], target: i0.ɵɵFactoryTarget.Directive });
220ButtonRadioDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.6", type: ButtonRadioDirective, selector: "[btnRadio]", inputs: { btnRadio: "btnRadio", uncheckable: "uncheckable", value: "value", disabled: "disabled" }, host: { listeners: { "click": "toggleIfAllowed()", "keydown.space": "onSpacePressed($event)", "focus": "onFocus()", "blur": "onBlur()" }, properties: { "attr.aria-disabled": "this.controlOrGroupDisabled", "class.disabled": "this.hasDisabledClass", "class.active": "this.isActive", "attr.aria-checked": "this.isActive", "attr.role": "this.role", "attr.tabindex": "this.tabindex" } }, providers: [RADIO_CONTROL_VALUE_ACCESSOR$1], usesOnChanges: true, ngImport: i0 });
221i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonRadioDirective, decorators: [{
222 type: Directive,
223 args: [{
224 selector: '[btnRadio]',
225 providers: [RADIO_CONTROL_VALUE_ACCESSOR$1]
226 }]
227 }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: ButtonRadioGroupDirective, decorators: [{
228 type: Optional
229 }, {
230 type: Inject,
231 args: [forwardRef(() => ButtonRadioGroupDirective)]
232 }] }]; }, propDecorators: { btnRadio: [{
233 type: Input
234 }], uncheckable: [{
235 type: Input
236 }], value: [{
237 type: Input
238 }], disabled: [{
239 type: Input
240 }], controlOrGroupDisabled: [{
241 type: HostBinding,
242 args: ['attr.aria-disabled']
243 }], hasDisabledClass: [{
244 type: HostBinding,
245 args: ['class.disabled']
246 }], isActive: [{
247 type: HostBinding,
248 args: ['class.active']
249 }, {
250 type: HostBinding,
251 args: ['attr.aria-checked']
252 }], role: [{
253 type: HostBinding,
254 args: ['attr.role']
255 }], tabindex: [{
256 type: HostBinding,
257 args: ['attr.tabindex']
258 }], toggleIfAllowed: [{
259 type: HostListener,
260 args: ['click']
261 }], onSpacePressed: [{
262 type: HostListener,
263 args: ['keydown.space', ['$event']]
264 }], onFocus: [{
265 type: HostListener,
266 args: ['focus']
267 }], onBlur: [{
268 type: HostListener,
269 args: ['blur']
270 }] } });
271
272const RADIO_CONTROL_VALUE_ACCESSOR = {
273 provide: NG_VALUE_ACCESSOR,
274 useExisting: forwardRef(() => ButtonRadioGroupDirective),
275 multi: true
276};
277/**
278 * A group of radio buttons.
279 * A value of a selected button is bound to a variable specified via ngModel.
280 */
281class ButtonRadioGroupDirective {
282 constructor(cdr) {
283 this.cdr = cdr;
284 this.onChange = Function.prototype;
285 this.onTouched = Function.prototype;
286 this.role = 'radiogroup';
287 this._disabled = false;
288 }
289 get value() {
290 return this._value;
291 }
292 set value(value) {
293 this._value = value;
294 this.onChange(value);
295 }
296 get disabled() {
297 return this._disabled;
298 }
299 get tabindex() {
300 if (this._disabled) {
301 return null;
302 }
303 else {
304 return 0;
305 }
306 }
307 writeValue(value) {
308 this._value = value;
309 this.cdr.markForCheck();
310 }
311 registerOnChange(fn) {
312 this.onChange = fn;
313 }
314 registerOnTouched(fn) {
315 this.onTouched = fn;
316 }
317 setDisabledState(disabled) {
318 if (this.radioButtons) {
319 this._disabled = disabled;
320 this.radioButtons.forEach(buttons => {
321 buttons.setDisabledState(disabled);
322 });
323 this.cdr.markForCheck();
324 }
325 }
326 onFocus() {
327 if (this._disabled) {
328 return;
329 }
330 const activeRadio = this.getActiveOrFocusedRadio();
331 if (activeRadio) {
332 activeRadio.focus();
333 return;
334 }
335 if (this.radioButtons) {
336 const firstEnabled = this.radioButtons.find(r => !r.disabled);
337 if (firstEnabled) {
338 firstEnabled.focus();
339 }
340 }
341 }
342 onBlur() {
343 if (this.onTouched) {
344 this.onTouched();
345 }
346 }
347 selectNext(event) {
348 this.selectInDirection('next');
349 event.preventDefault();
350 }
351 selectPrevious(event) {
352 this.selectInDirection('previous');
353 event.preventDefault();
354 }
355 selectInDirection(direction) {
356 if (this._disabled) {
357 return;
358 }
359 function nextIndex(currentIndex, buttonRadioDirectives) {
360 const step = direction === 'next' ? 1 : -1;
361 let calcIndex = (currentIndex + step) % buttonRadioDirectives.length;
362 if (calcIndex < 0) {
363 calcIndex = buttonRadioDirectives.length - 1;
364 }
365 return calcIndex;
366 }
367 const activeRadio = this.getActiveOrFocusedRadio();
368 if (activeRadio && this.radioButtons) {
369 const buttonRadioDirectives = this.radioButtons.toArray();
370 const currentActiveIndex = buttonRadioDirectives.indexOf(activeRadio);
371 for (let i = nextIndex(currentActiveIndex, buttonRadioDirectives); i !== currentActiveIndex; i = nextIndex(i, buttonRadioDirectives)) {
372 if (buttonRadioDirectives[i].canToggle()) {
373 buttonRadioDirectives[i].toggleIfAllowed();
374 buttonRadioDirectives[i].focus();
375 break;
376 }
377 }
378 }
379 }
380 getActiveOrFocusedRadio() {
381 if (!this.radioButtons) {
382 return void 0;
383 }
384 return this.radioButtons.find(button => button.isActive)
385 || this.radioButtons.find(button => button.hasFocus);
386 }
387}
388ButtonRadioGroupDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonRadioGroupDirective, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
389ButtonRadioGroupDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.6", type: ButtonRadioGroupDirective, selector: "[btnRadioGroup]", host: { listeners: { "focus": "onFocus()", "blur": "onBlur()", "keydown.ArrowRight": "selectNext($event)", "keydown.ArrowDown": "selectNext($event)", "keydown.ArrowLeft": "selectPrevious($event)", "keydown.ArrowUp": "selectPrevious($event)" }, properties: { "attr.role": "this.role", "attr.tabindex": "this.tabindex" } }, providers: [RADIO_CONTROL_VALUE_ACCESSOR], queries: [{ propertyName: "radioButtons", predicate: i0.forwardRef(function () { return ButtonRadioDirective; }) }], ngImport: i0 });
390i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonRadioGroupDirective, decorators: [{
391 type: Directive,
392 args: [{
393 selector: '[btnRadioGroup]',
394 providers: [RADIO_CONTROL_VALUE_ACCESSOR]
395 }]
396 }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { role: [{
397 type: HostBinding,
398 args: ['attr.role']
399 }], radioButtons: [{
400 type: ContentChildren,
401 args: [forwardRef(() => ButtonRadioDirective)]
402 }], tabindex: [{
403 type: HostBinding,
404 args: ['attr.tabindex']
405 }], onFocus: [{
406 type: HostListener,
407 args: ['focus']
408 }], onBlur: [{
409 type: HostListener,
410 args: ['blur']
411 }], selectNext: [{
412 type: HostListener,
413 args: ['keydown.ArrowRight', ['$event']]
414 }, {
415 type: HostListener,
416 args: ['keydown.ArrowDown', ['$event']]
417 }], selectPrevious: [{
418 type: HostListener,
419 args: ['keydown.ArrowLeft', ['$event']]
420 }, {
421 type: HostListener,
422 args: ['keydown.ArrowUp', ['$event']]
423 }] } });
424
425class ButtonsModule {
426 static forRoot() {
427 return { ngModule: ButtonsModule, providers: [] };
428 }
429}
430ButtonsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
431ButtonsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.6", ngImport: i0, type: ButtonsModule, declarations: [ButtonCheckboxDirective, ButtonRadioDirective, ButtonRadioGroupDirective], exports: [ButtonCheckboxDirective, ButtonRadioDirective, ButtonRadioGroupDirective] });
432ButtonsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonsModule });
433i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ButtonsModule, decorators: [{
434 type: NgModule,
435 args: [{
436 declarations: [ButtonCheckboxDirective, ButtonRadioDirective, ButtonRadioGroupDirective],
437 exports: [ButtonCheckboxDirective, ButtonRadioDirective, ButtonRadioGroupDirective]
438 }]
439 }] });
440
441/**
442 * Generated bundle index. Do not edit.
443 */
444
445export { ButtonCheckboxDirective, ButtonRadioDirective, ButtonRadioGroupDirective, ButtonsModule };
446//# sourceMappingURL=ngx-bootstrap-buttons.mjs.map