UNPKG

@alyle/ui

Version:

Minimal Design, a set of components for Angular

376 lines (372 loc) 18.7 kB
import * as i0 from '@angular/core'; import { forwardRef, EventEmitter, ContentChildren, Input, Output, ChangeDetectionStrategy, Component, ViewChild, Optional, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import * as i1 from '@alyle/ui'; import { st2c, LY_COMMON_STYLES, StyleCollection, mixinDisableRipple, StyleRenderer, LyCommonModule } from '@alyle/ui'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import * as i2 from '@angular/cdk/platform'; const STYLE_PRIORITY = -2; const DEFAULT_DISABLE_RIPPLE = false; const DEFAULT_COLOR = 'accent'; const LY_RADIO_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => LyRadioGroup), multi: true }; let idx = 0; class UndefinedValue { constructor() { } } const STYLES = (theme, ref) => { const radio = ref.selectorsOf(STYLES); const { after, before } = theme; return { $priority: STYLE_PRIORITY, /** ly-radio-group */ root: () => (_className) => `${_className}{display:inline-block;}${st2c(((theme.radio && theme.radio.root && (theme.radio.root instanceof StyleCollection ? theme.radio.root.setTransformer(fn => fn(radio)) : theme.radio.root(radio)))), `${_className}`)}`, radio: () => (_className) => `${_className}{display:inline-block;-webkit-tap-highlight-color:transparent;}${_className}${radio.checked} ${radio.container} div:nth-child(1){transform:scale(1.25);}${_className}${radio.checked} ${radio.container} div:nth-child(2){transform:scale(0.8);}${_className}${radio.onFocusByKeyboard} ${radio.container}::after{box-shadow:0 0 0 12px;background:currentColor;opacity:.13;border-radius:50%;}`, label: (_className) => `${_className}{user-select:none;cursor:pointer;white-space:nowrap;position:relative;display:flex;align-items:baseline;}`, labelContent: null, container: (_className) => `${_className}{position:relative;margin-${before}:.125em;margin-${after}:.5em;margin-top:auto;margin-bottom:auto;width:16px;height:16px;}${_className} div{margin:auto;border-radius:50%;width:1em;height:1em;box-sizing:border-box;}${_className}::after{content:'';}${st2c((LY_COMMON_STYLES.fill), `${_className}::after`)}${_className}::after{width:16px;height:16px;margin:auto;}${_className} div:nth-child(2){background:currentColor;transform:scale(0);}${_className} div:nth-child(1){transform:scale(1);border:solid .08em currentColor;color:${theme.text.disabled};}`, checked: null, _animations: () => (_className) => `${_className} ${radio.container} div{transition:transform cubic-bezier(.1,1,0.5,1);transition-duration:250ms;}`, onFocusByKeyboard: null, disabled: () => (_className) => `${_className}{color:${theme.disabled.contrast};}${_className} ${radio.container} div{color:${theme.disabled.contrast}!important;}` }; }; class LyRadioGroup { /** @docs-private */ static { this.и = 'LyRadioGroup'; } set value(val) { if (this._value !== val) { if (this._radios) { this._updateCheckFromValue(val); } } } get value() { return this._value; } /** * Mark this group as being "touched" (for ngModel). Meant to be called by the contained * radio buttons upon their blur. */ _touch() { if (this.onTouched) { this.onTouched(); } } /** @docs-private */ writeValue(value) { if (!!this._radios) { this.value = value; this._markForCheck(); } } /** * Registers a callback to be triggered when the model value changes. * Implemented as part of ControlValueAccessor. * @param fn Callback to be registered. * @docs-private */ registerOnChange(fn) { this._controlValueAccessorChangeFn = fn; } /** * Registers a callback to be triggered when the control is touched. * Implemented as part of ControlValueAccessor. * @param fn Callback to be registered. * @docs-private */ registerOnTouched(fn) { this.onTouched = fn; } /** * Sets the disabled state of the control. Implemented as a part of ControlValueAccessor. * @param _isDisabled Whether the control should be disabled. * @docs-private */ setDisabledState(_isDisabled) { // this.disabled = isDisabled; this._markForCheck(); } constructor(elementRef, renderer, _theme, _cd) { this._theme = _theme; this._cd = _cd; /** @docs-private */ this.classes = this._theme.renderStyleSheet(STYLES); /** @docs-private */ this.name = `ly-radio-name-${idx++}`; this.change = new EventEmitter(); this.color = 'accent'; /** The method to be called in order to update ngModel */ this._controlValueAccessorChangeFn = () => { }; /** * onTouch function registered via registerOnTouch (ControlValueAccessor). * @docs-private */ this.onTouched = () => { }; renderer.addClass(elementRef.nativeElement, this.classes.root); } _updateCheckFromValue(val) { let newChecked; this._radios.forEach(radioButton => { if (val === radioButton.value) { this.updatevalue(val); newChecked = true; radioButton.checked = true; } else if (radioButton.checked) { radioButton.checked = false; } }); if (!newChecked) { /** when val not exist in radio button !== */ this._controlValueAccessorChangeFn(null); if (this._value != null) { this._value = null; } } } /** @docs-private */ updatevalue(value) { this._value = value; this._controlValueAccessorChangeFn(value); this.change.emit(); this._markForCheck(); } _markForCheck() { this._cd.markForCheck(); } _radioResetChecked() { this._radios.forEach(_ => _._setCheckedToFalsy()); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyRadioGroup, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.LyTheme2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyRadioGroup, isStandalone: false, selector: "ly-radio-group", inputs: { value: "value", color: "color" }, outputs: { change: "change" }, providers: [LY_RADIO_CONTROL_VALUE_ACCESSOR], queries: [{ propertyName: "_radios", predicate: i0.forwardRef(() => LyRadio) }], exportAs: ["lyRadioGroup"], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyRadioGroup, decorators: [{ type: Component, args: [{ selector: 'ly-radio-group', template: `<ng-content></ng-content>`, providers: [LY_RADIO_CONTROL_VALUE_ACCESSOR], changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, exportAs: 'lyRadioGroup', standalone: false }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.LyTheme2 }, { type: i0.ChangeDetectorRef }], propDecorators: { value: [{ type: Input }], change: [{ type: Output }], color: [{ type: Input }], _radios: [{ type: ContentChildren, args: [forwardRef(() => LyRadio)] }] } }); /** @docs-private */ class LyRadioBase { constructor(_theme, _ngZone, _platform) { this._theme = _theme; this._ngZone = _ngZone; this._platform = _platform; } } /** @docs-private */ const LyRadioMixinBase = mixinDisableRipple(LyRadioBase); class LyRadio extends LyRadioMixinBase { /** @docs-private */ static { this.и = 'LyRadio'; } set value(val) { if (this._value !== val) { this._value = val; } } get value() { return this._value; } set color(val) { if (this._color !== val) { this._color = val; this[0x1] = this._styleRenderer.add(`${LyRadio.и}--color-${val}`, (theme, ref) => { const { checked, container } = ref.selectorsOf(STYLES); return (_className) => `${_className}${checked} ${container},${_className}${checked} ${container} div:nth-child(1),${_className} ${container} div:nth-child(2){color:${theme.colorOf(val)};}`; }, STYLE_PRIORITY, this[0x1]); } } get color() { return this._color; } set checked(val) { const newCheckedState = coerceBooleanProperty(val); const before = this._checked; if (before !== newCheckedState) { this._checked = newCheckedState; if (!before && newCheckedState) { /** Add class checked */ this._renderer.addClass(this._elementRef.nativeElement, this.classes.checked); if (this.value !== this.radioGroup.value) { /** update Value */ this.radioGroup.updatevalue(this.value); } } else { /** Remove class checked */ this._renderer.removeClass(this._elementRef.nativeElement, this.classes.checked); } this._markForCheck(); } } get checked() { return this._checked; } /** @docs-private */ get inputId() { return `${this.id}-input`; } get disabled() { return this._disabled; } set disabled(value) { const newVal = coerceBooleanProperty(value); if (newVal) { this._renderer.addClass(this._elementRef.nativeElement, this.classes.disabled); this._disabledClass = this.classes.disabled; } else if (this._disabledClass) { this._renderer.removeClass(this._elementRef.nativeElement, this.classes.disabled); this._disabledClass = undefined; } this._disabled = coerceBooleanProperty(value); this._markForCheck(); } constructor( /** @docs-private */ radioGroup, _elementRef, _renderer, theme, changeDetectorRef, ngZone, _coreStyles, _focusState, _styleRenderer, platform) { super(theme, ngZone, platform); this.radioGroup = radioGroup; this._elementRef = _elementRef; this._renderer = _renderer; this.changeDetectorRef = changeDetectorRef; this._coreStyles = _coreStyles; this._focusState = _focusState; this._styleRenderer = _styleRenderer; /** @docs-private */ this.classes = this.radioGroup.classes; /** @docs-private */ this.id = `ly-radio-id-${idx++}`; /** @docs-private */ this.name = ''; this._value = null; this._checked = false; this.change = new EventEmitter(); this._triggerElement = this._elementRef; this._rippleConfig = { centered: true, radius: 'containerSize', percentageToIncrease: 150 }; _renderer.addClass(_elementRef.nativeElement, radioGroup.classes.radio); } ngOnInit() { if (this.radioGroup) { // Copy name from parent radio group this.name = this.radioGroup.name; } if (!this.color) { this.color = this.radioGroup.color || DEFAULT_COLOR; } } ngAfterViewInit() { this._rippleContainer = this._radioContainer; // set default disable ripple if (this.disableRipple == null) { this.disableRipple = DEFAULT_DISABLE_RIPPLE; } const focusState = this._focusState.listen(this._input, this._elementRef); if (focusState) { focusState.subscribe((event) => { if (event === 'keyboard') { this._renderer.addClass(this._elementRef.nativeElement, this.classes.onFocusByKeyboard); } else if (event == null) { this._renderer.removeClass(this._elementRef.nativeElement, this.classes.onFocusByKeyboard); } }); } } _markForCheck() { this.changeDetectorRef.markForCheck(); } ngOnDestroy() { this._focusState.unlisten(this._elementRef); this._removeRippleEvents(); } _onInputChange(event) { event.stopPropagation(); this.radioGroup._updateCheckFromValue(this.value); this.radioGroup._touch(); this._addAnim(); } _addAnim() { if (!this._animClass) { this._renderer.addClass(this._elementRef.nativeElement, this.classes._animations); this._animClass = this.classes._animations; } } _onInputClick(event) { event.stopPropagation(); } _setCheckedToFalsy() { this.checked = false; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyRadio, deps: [{ token: LyRadioGroup, optional: true }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.LyTheme2 }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i1.LyCoreStyles }, { token: i1.LyFocusState }, { token: i1.StyleRenderer }, { token: i2.Platform }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyRadio, isStandalone: false, selector: "ly-radio", inputs: { disableRipple: "disableRipple", value: "value", color: "color", checked: "checked", disabled: "disabled" }, outputs: { change: "change" }, providers: [ StyleRenderer ], viewQueries: [{ propertyName: "_input", first: true, predicate: ["_input"], descendants: true }, { propertyName: "_radioContainer", first: true, predicate: ["_radioContainer"], descendants: true }, { propertyName: "_labelContainer", first: true, predicate: ["_labelContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<label #_labelContainer [attr.for]=\"inputId\" [className]=\"classes.label\">\n <input #_input\n [className]=\"_coreStyles.classes.visuallyHidden\"\n [id]=\"inputId\"\n [checked]=\"checked\"\n [name]=\"name\"\n (change)=\"_onInputChange($event)\"\n (click)=\"_onInputClick($event)\"\n [disabled]=\"disabled\"\n type=\"radio\"\n >\n <div #_radioContainer [className]=\"classes.container\">\n <div [className]=\"_coreStyles.classes.fill\"></div>\n <div [className]=\"_coreStyles.classes.fill\"></div>\n </div>\n <div\n [className]=\"classes.labelContent\">\n <ng-content></ng-content>\n </div>\n</label>", changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyRadio, decorators: [{ type: Component, args: [{ selector: 'ly-radio', changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, inputs: [ 'disableRipple' ], providers: [ StyleRenderer ], standalone: false, template: "<label #_labelContainer [attr.for]=\"inputId\" [className]=\"classes.label\">\n <input #_input\n [className]=\"_coreStyles.classes.visuallyHidden\"\n [id]=\"inputId\"\n [checked]=\"checked\"\n [name]=\"name\"\n (change)=\"_onInputChange($event)\"\n (click)=\"_onInputClick($event)\"\n [disabled]=\"disabled\"\n type=\"radio\"\n >\n <div #_radioContainer [className]=\"classes.container\">\n <div [className]=\"_coreStyles.classes.fill\"></div>\n <div [className]=\"_coreStyles.classes.fill\"></div>\n </div>\n <div\n [className]=\"classes.labelContent\">\n <ng-content></ng-content>\n </div>\n</label>" }] }], ctorParameters: () => [{ type: LyRadioGroup, decorators: [{ type: Optional }] }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.LyTheme2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i1.LyCoreStyles }, { type: i1.LyFocusState }, { type: i1.StyleRenderer }, { type: i2.Platform }], propDecorators: { _input: [{ type: ViewChild, args: ['_input'] }], _radioContainer: [{ type: ViewChild, args: ['_radioContainer'] }], _labelContainer: [{ type: ViewChild, args: ['_labelContainer'] }], change: [{ type: Output }], value: [{ type: Input }], color: [{ type: Input }], checked: [{ type: Input }], disabled: [{ type: Input }] } }); class LyRadioModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyRadioModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: LyRadioModule, declarations: [LyRadioGroup, LyRadio], imports: [CommonModule, FormsModule, LyCommonModule], exports: [LyRadioGroup, LyRadio] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyRadioModule, imports: [CommonModule, FormsModule, LyCommonModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyRadioModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, FormsModule, LyCommonModule], exports: [LyRadioGroup, LyRadio], declarations: [LyRadioGroup, LyRadio], }] }] }); /** * Generated bundle index. Do not edit. */ export { LY_RADIO_CONTROL_VALUE_ACCESSOR, LyRadio, LyRadioBase, LyRadioGroup, LyRadioMixinBase, LyRadioModule, STYLES, UndefinedValue }; //# sourceMappingURL=alyle-ui-radio.mjs.map