diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json index e0b5efb..1caa0d7 100644 --- a/packages/angular/package-lock.json +++ b/packages/angular/package-lock.json @@ -1,6 +1,6 @@ { "name": "@anywhere-ui/angular", - "version": "0.2.0+4", + "version": "0.2.0+7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/angular/package.json b/packages/angular/package.json index 4ba0b77..39b3691 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@anywhere-ui/angular", - "version": "0.2.0+7", + "version": "0.2.0", "scripts": { "ng": "ng", "start": "ng serve", @@ -42,5 +42,5 @@ "tslint": "~6.1.0", "typescript": "~4.4.4" }, - "buildnum": "7" + "buildnum": "8" } \ No newline at end of file diff --git a/packages/angular/projects/anywhere-ui/src/lib/anywhere-ui.module.ts b/packages/angular/projects/anywhere-ui/src/lib/anywhere-ui.module.ts index 4fc75ea..202663b 100644 --- a/packages/angular/projects/anywhere-ui/src/lib/anywhere-ui.module.ts +++ b/packages/angular/projects/anywhere-ui/src/lib/anywhere-ui.module.ts @@ -1,9 +1,18 @@ -import { NgModule } from '@angular/core'; -import { defineCustomElements } from '@anywhere-ui/core/loader'; +import { CommonModule, DOCUMENT } from '@angular/common'; +import { + ModuleWithProviders, + APP_INITIALIZER, + NgModule, + NgZone, + InjectionToken, +} from '@angular/core'; +import { AnywhereUIConfig } from '@anywhere-ui/core'; +import { appInitialize } from './app-initialize'; +import { ConfigToken } from './providers/config'; import { BooleanValueAccessor } from './directives/boolean-value-accessor'; // import { NumericValueAccessor } from './directives/number-value-accessor'; -// import { RadioValueAccessor } from './directives/radio-value-accessor'; +import { RadioValueAccessor } from './directives/radio-value-accessor'; import { SelectValueAccessor } from './directives/select-value-accessor'; import { TextValueAccessor } from './directives/text-value-accessor'; @@ -20,9 +29,11 @@ import { AnyBadgeOverlay, AnyRippleEffect, AnyInputSwitch, + AnyRadioButton, + AnyRadioGroup, } from './directives/proxies'; -defineCustomElements(window); +// defineCustomElements(window); const DECLARATIONS = [ // proxies @@ -38,11 +49,13 @@ const DECLARATIONS = [ AnyBadgeOverlay, AnyRippleEffect, AnyInputSwitch, + AnyRadioButton, + AnyRadioGroup, // Value Accessors BooleanValueAccessor, // NumericValueAccessor, - // RadioValueAccessor, + RadioValueAccessor, SelectValueAccessor, TextValueAccessor, ]; @@ -50,6 +63,30 @@ const DECLARATIONS = [ @NgModule({ declarations: DECLARATIONS, exports: DECLARATIONS, - imports: [], + imports: [CommonModule], }) -export class AnywhereUiModule {} +export class AnywhereUiModule { + static forRoot( + config?: AnywhereUIConfig + ): ModuleWithProviders { + return { + ngModule: AnywhereUiModule, + providers: [ + { + provide: ConfigToken, + useValue: config, + }, + // { + // provide: ConfigToken, + // useValue: config, + // }, + { + provide: APP_INITIALIZER, + useFactory: appInitialize, + multi: true, + deps: [ConfigToken, DOCUMENT, NgZone], + }, + ], + }; + } +} diff --git a/packages/angular/projects/anywhere-ui/src/lib/app-initialize.ts b/packages/angular/projects/anywhere-ui/src/lib/app-initialize.ts new file mode 100644 index 0000000..dc9a83e --- /dev/null +++ b/packages/angular/projects/anywhere-ui/src/lib/app-initialize.ts @@ -0,0 +1,40 @@ +import { NgZone } from '@angular/core'; +import { setupConfig } from '@anywhere-ui/core'; +import { applyPolyfills, defineCustomElements } from '@anywhere-ui/core/loader'; + +import { Config } from './providers/config'; +// import { IonicWindow } from './types/interfaces'; +import { raf } from './util/util'; + +export const appInitialize = (config: Config, doc: Document, zone: NgZone) => { + return (): any => { + // const win: IonicWindow | undefined = doc.defaultView as any; + const win = window; + if (win && typeof (window as any) !== 'undefined') { + setupConfig({ + ...config, + _zoneGate: (h: any) => zone.run(h), + }); + + const aelFn = + '__zone_symbol__addEventListener' in (doc.body as any) + ? '__zone_symbol__addEventListener' + : 'addEventListener'; + + return applyPolyfills().then(() => { + return defineCustomElements(win, { + // exclude: ['ion-tabs', 'ion-tab'], + syncQueue: true, + raf, + jmp: (h: any) => zone.runOutsideAngular(h), + ael(elm, eventName, cb, opts) { + (elm as any)[aelFn](eventName, cb, opts); + }, + rel(elm, eventName, cb, opts) { + elm.removeEventListener(eventName, cb, opts); + }, + }); + }); + } + }; +}; diff --git a/packages/angular/projects/anywhere-ui/src/lib/directives/angular-component-lib/utils.ts b/packages/angular/projects/anywhere-ui/src/lib/directives/angular-component-lib/utils.ts index e0c6297..d6cf7bd 100644 --- a/packages/angular/projects/anywhere-ui/src/lib/directives/angular-component-lib/utils.ts +++ b/packages/angular/projects/anywhere-ui/src/lib/directives/angular-component-lib/utils.ts @@ -43,11 +43,13 @@ export const defineCustomElement = (tagName: string, customElement: any) => { } // tslint:disable-next-line: only-arrow-functions -export function ProxyCmp(opts: { tagName: string, customElement?: any, inputs?: any; methods?: any }) { +export function ProxyCmp(opts: { defineCustomElementFn?: () => void, inputs?: any; methods?: any }) { const decorator = function (cls: any) { - const { tagName, customElement, inputs, methods } = opts; + const { defineCustomElementFn, inputs, methods } = opts; - defineCustomElement(tagName, customElement); + if (defineCustomElementFn !== undefined) { + defineCustomElementFn(); + } if (inputs) { proxyInputs(cls, inputs); diff --git a/packages/angular/projects/anywhere-ui/src/lib/directives/proxies.ts b/packages/angular/projects/anywhere-ui/src/lib/directives/proxies.ts index c09bbe3..678011c 100644 --- a/packages/angular/projects/anywhere-ui/src/lib/directives/proxies.ts +++ b/packages/angular/projects/anywhere-ui/src/lib/directives/proxies.ts @@ -11,8 +11,7 @@ import { Components } from '@anywhere-ui/core'; export declare interface AnyBadge extends Components.AnyBadge {} @ProxyCmp({ - tagName: 'any-badge', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['anyStyle', 'severity', 'size', 'styleClass', 'value'] }) @Component({ @@ -33,8 +32,7 @@ export class AnyBadge { export declare interface AnyBadgeOverlay extends Components.AnyBadgeOverlay {} @ProxyCmp({ - tagName: 'any-badge-overlay', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['styleClass'] }) @Component({ @@ -69,8 +67,7 @@ export declare interface AnyButton extends Components.AnyButton { } @ProxyCmp({ - tagName: 'any-button', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['anyStyle', 'badge', 'badgeClass', 'disabled', 'icon', 'iconHeight', 'iconPos', 'iconWidth', 'label', 'loading', 'loadingIcon', 'loadingIconStyleClass', 'styleClass', 'type'] }) @Component({ @@ -106,16 +103,15 @@ export declare interface AnyCheckbox extends Components.AnyCheckbox { } @ProxyCmp({ - tagName: 'any-checkbox', - customElement: undefined, - inputs: ['anyStyle', 'binary', 'checkboxIcon', 'checked', 'disabled', 'inputId', 'label', 'labelStyleClass', 'name', 'readonly', 'styleClass', 'value'], + defineCustomElementFn: undefined, + inputs: ['anyStyle', 'anyTabIndex', 'binary', 'checkboxIcon', 'checked', 'disabled', 'inputId', 'label', 'labelStyleClass', 'name', 'readonly', 'styleClass', 'value'], methods: ['inputFocus'] }) @Component({ selector: 'any-checkbox', changeDetection: ChangeDetectionStrategy.OnPush, template: '', - inputs: ['anyStyle', 'binary', 'checkboxIcon', 'checked', 'disabled', 'inputId', 'label', 'labelStyleClass', 'name', 'readonly', 'styleClass', 'value'] + inputs: ['anyStyle', 'anyTabIndex', 'binary', 'checkboxIcon', 'checked', 'disabled', 'inputId', 'label', 'labelStyleClass', 'name', 'readonly', 'styleClass', 'value'] }) export class AnyCheckbox { protected el: HTMLElement; @@ -164,8 +160,7 @@ export declare interface AnyDropdown extends Components.AnyDropdown { } @ProxyCmp({ - tagName: 'any-dropdown', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['anyStyle', 'anyTabIndex', 'autoZIndex', 'baseZIndex', 'clearIcon', 'disabled', 'dropdownIcon', 'hideAnimation', 'inputId', 'name', 'optionLabel', 'optionValue', 'options', 'panelScrollHeight', 'placeholder', 'readonly', 'showAnimation', 'showClear', 'value', 'virtualScroll'] }) @Component({ @@ -201,8 +196,7 @@ export declare interface AnyInputSwitch extends Components.AnyInputSwitch { } @ProxyCmp({ - tagName: 'any-input-switch', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['anyStyle', 'anyTabIndex', 'ariaLabeledBy', 'checked', 'disabled', 'falseValue', 'inputId', 'name', 'readonly', 'styleClass', 'trueValue'] }) @Component({ @@ -230,8 +224,7 @@ export declare interface AnyInputText extends Components.AnyInputText { } @ProxyCmp({ - tagName: 'any-input-text', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['disabled', 'floatLabel', 'inputId', 'inputWrapperClass', 'label', 'leftIconClass', 'name', 'placeholder', 'readonly', 'rightIconClass', 'value'], methods: ['getInputRef'] }) @@ -260,8 +253,7 @@ export declare interface AnyListbox extends Components.AnyListbox { } @ProxyCmp({ - tagName: 'any-listbox', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['anyStyle', 'disabled', 'inputId', 'listStyle', 'name', 'optionLabel', 'optionValue', 'options', 'readonly', 'scrollerHeight', 'value', 'virtualScroll'] }) @Component({ @@ -280,11 +272,75 @@ export class AnyListbox { } +export declare interface AnyRadioButton extends Components.AnyRadioButton { + /** + * Callback to invoke on radio button select. + */ + aOnSelect: EventEmitter>; + /** + * Callback to invoke when the radio button receives focus. + */ + aOnFocus: EventEmitter>; + /** + * Callback to invoke when the radio button loses focus. + */ + aOnBlur: EventEmitter>; + +} + +@ProxyCmp({ + defineCustomElementFn: undefined, + inputs: ['anyStyle', 'anyTabIndex', 'disabled', 'inputId', 'label', 'labelStyleClass', 'name', 'styleClass', 'value'], + methods: ['setFocus'] +}) +@Component({ + selector: 'any-radio-button', + changeDetection: ChangeDetectionStrategy.OnPush, + template: '', + inputs: ['anyStyle', 'anyTabIndex', 'disabled', 'inputId', 'label', 'labelStyleClass', 'name', 'styleClass', 'value'] +}) +export class AnyRadioButton { + protected el: HTMLElement; + constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + c.detach(); + this.el = r.nativeElement; + proxyOutputs(this, this.el, ['aOnSelect', 'aOnFocus', 'aOnBlur']); + } +} + +import type { RadioGroupChangeEventDetail as IRadioGroupRadioGroupChangeEventDetail } from '@anywhere-ui/core'; +export declare interface AnyRadioGroup extends Components.AnyRadioGroup { + /** + * Emitted when the value has changed. + */ + valueChange: EventEmitter>; + +} + +@ProxyCmp({ + defineCustomElementFn: undefined, + inputs: ['allowEmptySelection', 'name', 'value'] +}) +@Component({ + selector: 'any-radio-group', + changeDetection: ChangeDetectionStrategy.OnPush, + template: '', + inputs: ['allowEmptySelection', 'name', 'value'] +}) +export class AnyRadioGroup { + protected el: HTMLElement; + constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + c.detach(); + this.el = r.nativeElement; + proxyOutputs(this, this.el, ['valueChange']); + } +} + + export declare interface AnyRippleEffect extends Components.AnyRippleEffect {} @ProxyCmp({ - tagName: 'any-ripple-effect', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['type'] }) @Component({ @@ -305,8 +361,7 @@ export class AnyRippleEffect { export declare interface AnyTabPanel extends Components.AnyTabPanel {} @ProxyCmp({ - tagName: 'any-tab-panel', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['disabled', 'header', 'selected'] }) @Component({ @@ -327,8 +382,7 @@ export class AnyTabPanel { export declare interface AnyTabView extends Components.AnyTabView {} @ProxyCmp({ - tagName: 'any-tab-view', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['activeIndex', 'anyStyle', 'styleClass'] }) @Component({ @@ -371,8 +425,7 @@ export declare interface AnyVirtualScroller extends Components.AnyVirtualScrolle } @ProxyCmp({ - tagName: 'any-virtual-scroller', - customElement: undefined, + defineCustomElementFn: undefined, inputs: ['anyStyle', 'contentElemClass', 'contentElemTag', 'delay', 'itemElemClass', 'itemSize', 'itemTag', 'items', 'lazy', 'noDataText', 'rowsPerPage', 'scrollElemClass', 'scrollerHeight', 'styleClass'] }) @Component({ diff --git a/packages/angular/projects/anywhere-ui/src/lib/directives/radio-value-accessor.ts b/packages/angular/projects/anywhere-ui/src/lib/directives/radio-value-accessor.ts new file mode 100644 index 0000000..dec8cd3 --- /dev/null +++ b/packages/angular/projects/anywhere-ui/src/lib/directives/radio-value-accessor.ts @@ -0,0 +1,24 @@ +import { Directive, ElementRef } from '@angular/core'; +import { NG_VALUE_ACCESSOR } from '@angular/forms'; + +import { ValueAccessor } from './value-accessor'; + +@Directive({ + /* tslint:disable-next-line:directive-selector */ + selector: 'any-radio-button', + host: { + '(aOnSelect)': 'handleChangeEvent($event.target.checked)' + }, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: RadioValueAccessor, + multi: true + } + ] +}) +export class RadioValueAccessor extends ValueAccessor { + constructor(el: ElementRef) { + super(el); + } +} diff --git a/packages/angular/projects/anywhere-ui/src/lib/directives/select-value-accessor.ts b/packages/angular/projects/anywhere-ui/src/lib/directives/select-value-accessor.ts index 59eeaf0..448e65d 100644 --- a/packages/angular/projects/anywhere-ui/src/lib/directives/select-value-accessor.ts +++ b/packages/angular/projects/anywhere-ui/src/lib/directives/select-value-accessor.ts @@ -5,7 +5,7 @@ import { ValueAccessor } from './value-accessor'; @Directive({ /* tslint:disable-next-line:directive-selector */ - selector: 'any-dropdown, any-listbox, any-virtual-scroller', + selector: 'any-dropdown, any-listbox, any-virtual-scroller, any-radio-group', host: { '(valueChange)': 'handleChangeEvent($event.target.value)' }, diff --git a/packages/angular/projects/anywhere-ui/src/lib/directives/text-value-accessor.ts b/packages/angular/projects/anywhere-ui/src/lib/directives/text-value-accessor.ts index 2d5ff24..14acee3 100644 --- a/packages/angular/projects/anywhere-ui/src/lib/directives/text-value-accessor.ts +++ b/packages/angular/projects/anywhere-ui/src/lib/directives/text-value-accessor.ts @@ -5,7 +5,7 @@ import { ValueAccessor } from './value-accessor'; @Directive({ /* tslint:disable-next-line:directive-selector */ - selector: 'any-input-text[type=text]', + selector: 'any-input-text:not([type=number])', host: { '(valueChange)': 'handleChangeEvent($event.target.value)' }, diff --git a/packages/angular/projects/anywhere-ui/src/lib/providers/config.ts b/packages/angular/projects/anywhere-ui/src/lib/providers/config.ts new file mode 100644 index 0000000..5138ce9 --- /dev/null +++ b/packages/angular/projects/anywhere-ui/src/lib/providers/config.ts @@ -0,0 +1,45 @@ +import { Injectable, InjectionToken } from '@angular/core'; +import { Config as CoreConfig, AnywhereUIConfig } from '@anywhere-ui/core'; + +// import { IonicWindow } from '../types/interfaces'; + +@Injectable({ + providedIn: 'root', +}) +export class Config { + get(key: keyof AnywhereUIConfig, fallback?: any): any { + const c = getConfig(); + if (c) { + return c.get(key, fallback); + } + return null; + } + + getBoolean(key: keyof AnywhereUIConfig, fallback?: boolean): boolean { + const c = getConfig(); + if (c) { + return c.getBoolean(key, fallback); + } + return false; + } + + getNumber(key: keyof AnywhereUIConfig, fallback?: number): number { + const c = getConfig(); + if (c) { + return c.getNumber(key, fallback); + } + return 0; + } +} + +export const ConfigToken = new InjectionToken('USERCONFIG'); + +const getConfig = (): CoreConfig | null => { + if (typeof (window as any) !== 'undefined') { + const AnywhereUI = (window as any).AnywhereUI; + if (AnywhereUI?.config) { + return AnywhereUI.config; + } + } + return null; +}; diff --git a/packages/angular/projects/anywhere-ui/src/lib/util/util.ts b/packages/angular/projects/anywhere-ui/src/lib/util/util.ts new file mode 100644 index 0000000..6f8b29c --- /dev/null +++ b/packages/angular/projects/anywhere-ui/src/lib/util/util.ts @@ -0,0 +1,12 @@ +declare const __zone_symbol__requestAnimationFrame: any; +declare const requestAnimationFrame: any; + +export const raf = (h: any): any => { + if (typeof __zone_symbol__requestAnimationFrame === 'function') { + return __zone_symbol__requestAnimationFrame(h); + } + if (typeof requestAnimationFrame === 'function') { + return requestAnimationFrame(h); + } + return setTimeout(h); +}; diff --git a/packages/angular/projects/anywhere-ui/src/public-api.ts b/packages/angular/projects/anywhere-ui/src/public-api.ts index 8a7a142..ce2af83 100644 --- a/packages/angular/projects/anywhere-ui/src/public-api.ts +++ b/packages/angular/projects/anywhere-ui/src/public-api.ts @@ -6,3 +6,4 @@ export * from './lib/directives/proxies'; export * from './lib/directives/boolean-value-accessor'; export * from './lib/directives/text-value-accessor'; export * from './lib/directives/select-value-accessor'; +export * from './lib/directives/radio-value-accessor'; diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json index 850c1f8..672a59b 100644 --- a/packages/core/package-lock.json +++ b/packages/core/package-lock.json @@ -1,6 +1,6 @@ { "name": "@anywhere-ui/core", - "version": "0.2.0+5", + "version": "0.2.0+7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -450,12 +450,12 @@ } }, "@iconify/iconify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@iconify/iconify/-/iconify-2.1.0.tgz", - "integrity": "sha512-YXKrDVXIGUeFIRqr6QC/l6MRj9kDOlES4sWx/ty8SXUk0pCZnBwsj0/to9Q3g79TAyh2wG3/yzrkf6fHKichwA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@iconify/iconify/-/iconify-2.1.2.tgz", + "integrity": "sha512-QcUzFeEWkE/mW+BVtEGmcWATClcCOIJFiYUD/PiCWuTcdEA297o8D4oN6Ra44WrNOHu1wqNW4J0ioaDIiqaFOQ==", "dev": true, "requires": { - "cross-fetch": "^3.1.4" + "cross-fetch": "^3.1.5" } }, "@istanbuljs/load-nyc-config": { @@ -687,21 +687,21 @@ } }, "@stencil/angular-output-target": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.3.0.tgz", - "integrity": "sha512-b3+VN9cmQScZqFdK2dlwYTZxwA74Suqf/7Ff05ywUKIAGjic+ZUhJJrdSmsT8bnZGY5hj7OG2CwOB/XeZDlrpg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.4.0.tgz", + "integrity": "sha512-zauaj0za46IWoPgv2IanDp3tiljwDRDNk4jB7WII6KeL66dkk7ffeqYZ0CgySTU5W2FjnKR6JEKbAnwUxjGIsA==", "dev": true }, "@stencil/core": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.10.0.tgz", - "integrity": "sha512-15rWMTPQ/sp0lSV82HVCXkIya3QLN+uBl7pqK4JnTrp4HiLrzLmNbWjbvgCs55gw0lULbCIGbRIEsFz+Pe/Q+A==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.13.0.tgz", + "integrity": "sha512-EEKHOHgYpg3/iFUKMXTZJjUayRul7sXDwNw0OGgkEOe4t7JWiibDkzUHuruvpbqEydX+z1+ez5K2bMMY76c2wA==", "dev": true }, "@stencil/react-output-target": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.1.0.tgz", - "integrity": "sha512-NWeN2S43dwWDIousfojzGXIMkJJhfcdS1JxpwgE7IOqy4tZ+nqlDLPhM6tXvZ3eq4rJm8bkF+3/WbPJNR9xR7Q==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.2.1.tgz", + "integrity": "sha512-A6ut+ua3s9UPVXHmAco8g6phvRsr8Db1wM6Mws2bdSAawzc1n49afS+FbTMUMcjqKAGShMp5lsM0/QA0jx5SdQ==", "dev": true }, "@stencil/sass": { @@ -711,9 +711,9 @@ "dev": true }, "@stencil/vue-output-target": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.5.1.tgz", - "integrity": "sha512-E9HeuUf4DjHO8VFd+faR6T+/JwLtU/2kIA000YTTv0ARPUXuxr/3+U3YMBRPCVFPC5n2jsFxU3E9rTmVH1MGyg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.6.0.tgz", + "integrity": "sha512-UxI0RTgz3AfhOePbgK3CNcX7uLVxDrdkpSCJoIyr8EjSrW5HkfraZ/ukIzuPDJDDxtYRRevY7It+qOhfn0B6aA==", "dev": true }, "@tootallnate/once": { @@ -809,9 +809,9 @@ } }, "@types/lodash": { - "version": "4.14.177", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz", - "integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==", + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", "dev": true }, "@types/node": { @@ -1271,7 +1271,8 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, "caniuse-lite": { "version": "1.0.30001248", @@ -1421,6 +1422,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -1584,12 +1586,45 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cross-fetch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", - "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", "dev": true, "requires": { - "node-fetch": "2.6.1" + "node-fetch": "2.6.7" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } } }, "cross-spawn": { @@ -1675,7 +1710,8 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "decimal.js": { "version": "10.2.1", @@ -1801,7 +1837,8 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "enabled": { "version": "2.0.0", @@ -2161,6 +2198,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -2250,7 +2288,8 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "get-package-type": { "version": "0.1.0", @@ -2720,7 +2759,8 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "is-generator-fn": { "version": "2.1.0", @@ -3450,6 +3490,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "requires": { "p-locate": "^4.1.0" } @@ -3998,6 +4039,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "requires": { "p-try": "^2.0.0" } @@ -4006,6 +4048,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "requires": { "p-limit": "^2.2.0" } @@ -4013,7 +4056,8 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true }, "parse-json": { "version": "5.2.0", @@ -4048,7 +4092,8 @@ "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true }, "path-is-absolute": { "version": "1.0.1", @@ -4122,9 +4167,9 @@ } }, "prismjs": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", - "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.26.0.tgz", + "integrity": "sha512-HUoH9C5Z3jKkl3UunCyiD5jwk0+Hz0fIgQ2nbwU2Oo/ceuTAQAg+pPVnfdt2TJWRVLcxKh9iuoYDUSc8clb5UQ==", "dev": true }, "process-nextick-args": { @@ -4306,6 +4351,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/replace/-/replace-1.2.1.tgz", "integrity": "sha512-KZCBe/tPanwBlbjSMQby4l+zjSiFi3CLEP/6VLClnRYgJ46DZ5u9tmA6ceWeFS8coaUnU4ZdGNb/puUGMHNSRg==", + "dev": true, "requires": { "chalk": "2.4.2", "minimatch": "3.0.4", @@ -4316,6 +4362,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -4324,6 +4371,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4334,6 +4382,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -4341,22 +4390,26 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -4372,12 +4425,14 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "resolve": { "version": "1.20.0", @@ -4746,7 +4801,8 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true }, "set-value": { "version": "2.0.1", @@ -5194,6 +5250,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5219,6 +5276,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -5697,7 +5755,8 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true }, "winston": { "version": "3.3.3", @@ -5758,6 +5817,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5814,7 +5874,8 @@ "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, "yallist": { "version": "4.0.0", @@ -5826,6 +5887,7 @@ "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, "requires": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -5844,6 +5906,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/packages/core/package.json b/packages/core/package.json index 2b10ba3..68f12ac 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@anywhere-ui/core", - "version": "0.2.0+7", + "version": "0.2.0", "description": "AnywhereUI", "main": "dist/index.cjs.js", "module": "dist/index.js", @@ -33,14 +33,14 @@ "deploy-site-to-master": "bash scripts/deploy-site-to-master.sh" }, "devDependencies": { - "@iconify/iconify": "^2.1.0", - "@stencil/angular-output-target": "0.3.0", - "@stencil/core": "^2.10.0", - "@stencil/react-output-target": "^0.1.0", + "@iconify/iconify": "^2.1.2", + "@stencil/angular-output-target": "0.4.0", + "@stencil/core": "^2.13.0", + "@stencil/react-output-target": "^0.2.1", "@stencil/sass": "^1.5.2", - "@stencil/vue-output-target": "^0.5.1", + "@stencil/vue-output-target": "^0.6.0", "@types/clusterize.js": "^0.18.1", - "@types/lodash": "^4.14.177", + "@types/lodash": "^4.14.178", "@types/puppeteer": "^5.4.4", "clusterize.js": "^0.18.1", "clusterize.js-paging": "^1.0.3", @@ -50,7 +50,7 @@ "jest": "26.6.3", "jest-cli": "26.6.3", "lodash": "^4.17.21", - "prismjs": "^1.25.0", + "prismjs": "^1.26.0", "puppeteer": "^9.0.0", "rebase": "^0.3.0", "replace": "^1.2.1", @@ -62,5 +62,5 @@ "build": "^0.1.4", "run": "^1.4.0" }, - "buildnum": "7" + "buildnum": "8" } \ No newline at end of file diff --git a/packages/core/src/app/App.js b/packages/core/src/app/App.js index c1de849..0abe664 100644 --- a/packages/core/src/app/App.js +++ b/packages/core/src/app/App.js @@ -9,6 +9,7 @@ import TabView from "./views/TabView/TabView.js"; import Button from "./views/Button/Button.js"; import Badge from "./views/Badge/Badge.js"; import RippleEffect from "./views/RippleEffect/RippleEffect.js"; +import RadioButton from "./views/RadioButton/RadioButton.js"; const pathToRegex = (path) => new RegExp("^" + path.replace(/\//g, "\\/").replace(/:\w+/g, "(.+)") + "$"); @@ -102,6 +103,10 @@ const router = () => { path: "/ripple-effect", view: RippleEffect, }, + { + path: "/radio-button", + view: RadioButton, + }, ]; // Test each route for potential match @@ -149,6 +154,8 @@ const router = () => { window.addEventListener("popstate", router); document.addEventListener("DOMContentLoaded", () => { + // window.AnywhereUI.config.set('rippleEffect', false); + document.body.addEventListener("click", (e) => { if (e.target.matches("[data-link]")) { e.preventDefault(); diff --git a/packages/core/src/app/css/app.css b/packages/core/src/app/css/app.css index e50b57f..921c195 100644 --- a/packages/core/src/app/css/app.css +++ b/packages/core/src/app/css/app.css @@ -512,6 +512,12 @@ code[class*=language] { user-select: none; } +.any-field-radiobutton { + margin-bottom: 1rem; + display: flex; + align-items: center; +} + .any-link { font-size: 1rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; diff --git a/packages/core/src/app/css/app.css.map b/packages/core/src/app/css/app.css.map index 47d25a8..9a15003 100644 --- a/packages/core/src/app/css/app.css.map +++ b/packages/core/src/app/css/app.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../scss/_core.scss","../scss/_content.scss","../scss/_sidebar.scss","../scss/_topbar.scss","../scss/_footer.scss","../scss/_demo.scss","../scss/_responsive.scss","../scss/_virtual-scroller.scss","../scss/_button.scss","../scss/_ripple.scss"],"names":[],"mappings":"AAAA;EACI;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;AAGJ;EACI;EACA;;AAEA;EACI;;;AAIR;AAAA;AAAA;AAAA;AAAA;AAAA;EAMI;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EACI;;;AAIR;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;EACA;;;AAGJ;EACI;IACI;;EAGJ;IACI;;EAGJ;IACI;;;AAMJ;EAEI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAII;EAEI;;AAGJ;EAEI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EAEI;;;AAMhB;AAAA;EAEI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;;ACjKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;AAEA;EAEI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;;AAIQ;EACI;EACA;;AAIR;EACI;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;;AAKZ;EACI;EACA;;AAEA;EACI;;AAIA;EACI;EACA;;AAEA;EACI;;AAMhB;EACI;;AAIR;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;;AAEA;EACI;;AAGJ;EACI;EAEA;;AAEA;EACI;;AAIR;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIA;EACI;EACA;;AAEA;EACI;EACA;EACA;;AAOJ;EACI;EACA;EACA;;;ACzIxB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGI;EACI;EACA;EACA;EACA;AACA;EACA;AACA;AACA;EACA;EACA;;AAEA;EACI;EACA;;AAIJ;EACI;;AAEA;EACI;;AAQhB;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;;;AAQpB;AAAA;EAEI;EACA;;;ACvGJ;EACI;AACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;;AAGJ;EACI;EACA;EACA;EACA;;;AClFpB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACVJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;;AAIR;AAAA;EAEI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;AAAA;EAEI;;;AAGJ;EACI;;;AAGJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAYI;EACA;;;AAGJ;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AC1IR;EAEQ;IACI;;EAEA;IACI;;;EAKZ;IACI;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAIA;IACI;;EAIR;IACI;IACA;;EAGJ;IACI;IACA;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;;EAGJ;IACI;;;EAMhB;IACI;IACA;;EAEA;IACI;;;EAIR;IACI;;EAGI;IACI;;EAEA;IACI;IACA;;EAKZ;IACI;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;IACA;IACA;;;EAKZ;IACI;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;EAKJ;IACI;;EAGJ;IACI;;EAGJ;IACI;;EAGJ;IACI;;;EAKJ;IACI;IACA;;EAGJ;IACI;;;EAIR;IACI;;;EAGJ;IACI;IACA;;;AAIR;EAKoB;IACI;;;EAUR;IACI;;EAEA;IACI;IACA;IACA;IACA;IACA;;;ACnLxB;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;AAIA;EACI;EACA;EACA;EACA;;AAKA;AAAA;EAEI;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;;;AAMhB;EACI;IACI;;;EAGJ;IACI;;;EAGJ;AAAA;IAEI;;;AChFR;EACI;;;AAGJ;EACI;EACA;;AAGI;EACI;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;;AAMZ;EAEQ;IACI;;;EAKJ;IACI;;EAEA;IACI;IACA;;EAEA;IACI;;EAMZ;IACI;IACA;;EAGJ;IACI;;EAGI;IACI;;EAGJ;IACI;;EAGJ;IACI;IACA;IACA;IACA;;EAGJ;IACI;IACA;IACA;IACA;;;ACzFhB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIA;EACI;;AAKJ;EACI;;AAKJ;EACI;;AAIR;EACI","file":"app.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../scss/_core.scss","../scss/_content.scss","../scss/_sidebar.scss","../scss/_topbar.scss","../scss/_footer.scss","../scss/_demo.scss","../scss/_responsive.scss","../scss/_virtual-scroller.scss","../scss/_button.scss","../scss/_ripple.scss"],"names":[],"mappings":"AAAA;EACI;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;AAGJ;EACI;EACA;;AAEA;EACI;;;AAIR;AAAA;AAAA;AAAA;AAAA;AAAA;EAMI;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EACI;;;AAIR;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;EACA;;;AAGJ;EACI;IACI;;EAGJ;IACI;;EAGJ;IACI;;;AAMJ;EAEI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAII;EAEI;;AAGJ;EAEI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EAEI;;;AAMhB;AAAA;EAEI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;;ACjKJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;AAEA;EAEI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;;AAIQ;EACI;EACA;;AAIR;EACI;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;;AAKZ;EACI;EACA;;AAEA;EACI;;AAIA;EACI;EACA;;AAEA;EACI;;AAMhB;EACI;;AAIR;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;;AAEA;EACI;;AAGJ;EACI;EAEA;;AAEA;EACI;;AAIR;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIA;EACI;EACA;;AAEA;EACI;EACA;EACA;;AAOJ;EACI;EACA;EACA;;;ACzIxB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGI;EACI;EACA;EACA;EACA;AACA;EACA;AACA;AACA;EACA;EACA;;AAEA;EACI;EACA;;AAIJ;EACI;;AAEA;EACI;;AAQhB;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;;;AAQpB;AAAA;EAEI;EACA;;;ACvGJ;EACI;AACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;;AAGJ;EACI;EACA;EACA;EACA;;;AClFpB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACVJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;;AAIR;AAAA;EAEI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;AAAA;EAEI;;;AAGJ;EACI;;;AAGJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAYI;EACA;;;AAGJ;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AChJR;EAEQ;IACI;;EAEA;IACI;;;EAKZ;IACI;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAIA;IACI;;EAIR;IACI;IACA;;EAGJ;IACI;IACA;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;;EAGJ;IACI;;;EAMhB;IACI;IACA;;EAEA;IACI;;;EAIR;IACI;;EAGI;IACI;;EAEA;IACI;IACA;;EAKZ;IACI;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;IACA;IACA;;;EAKZ;IACI;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;EAKJ;IACI;;EAGJ;IACI;;EAGJ;IACI;;EAGJ;IACI;;;EAKJ;IACI;IACA;;EAGJ;IACI;;;EAIR;IACI;;;EAGJ;IACI;IACA;;;AAIR;EAKoB;IACI;;;EAUR;IACI;;EAEA;IACI;IACA;IACA;IACA;IACA;;;ACnLxB;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;AAIA;EACI;EACA;EACA;EACA;;AAKA;AAAA;EAEI;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;;;AAMhB;EACI;IACI;;;EAGJ;IACI;;;EAGJ;AAAA;IAEI;;;AChFR;EACI;;;AAGJ;EACI;EACA;;AAGI;EACI;EACA;;AAEA;EACI;EACA;;AAIR;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;;AAMZ;EAEQ;IACI;;;EAKJ;IACI;;EAEA;IACI;IACA;;EAEA;IACI;;EAMZ;IACI;IACA;;EAGJ;IACI;;EAGI;IACI;;EAGJ;IACI;;EAGJ;IACI;IACA;IACA;IACA;;EAGJ;IACI;IACA;IACA;IACA;;;ACzFhB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIA;EACI;;AAKJ;EACI;;AAKJ;EACI;;AAIR;EACI","file":"app.css"} \ No newline at end of file diff --git a/packages/core/src/app/scss/_demo.scss b/packages/core/src/app/scss/_demo.scss index 1fef53c..dc5e90d 100644 --- a/packages/core/src/app/scss/_demo.scss +++ b/packages/core/src/app/scss/_demo.scss @@ -81,6 +81,12 @@ user-select: none; } +.any-field-radiobutton { + margin-bottom: 1rem; + display: flex; + align-items: center; +} + .any-link { font-size: 1rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; diff --git a/packages/core/src/app/views/RadioButton/RadioButton.html b/packages/core/src/app/views/RadioButton/RadioButton.html new file mode 100644 index 0000000..9e98f61 --- /dev/null +++ b/packages/core/src/app/views/RadioButton/RadioButton.html @@ -0,0 +1,45 @@ +
+
+

RadioButton

+

RadioButton is an extension to standard radio button element with theming.

+
+ +
+ +
+
+
+
+
+
Basic
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+
Preselection, Value Binding and Disabled Option
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+
diff --git a/packages/core/src/app/views/RadioButton/RadioButton.js b/packages/core/src/app/views/RadioButton/RadioButton.js new file mode 100644 index 0000000..1b03a99 --- /dev/null +++ b/packages/core/src/app/views/RadioButton/RadioButton.js @@ -0,0 +1,22 @@ +import AbstractView from "../AbstractView.js"; + +export default class extends AbstractView { + constructor(params) { + super(params); + this.setTitle("RadioButton"); + } + + executeScript() { + this.viewOnGithubBtn = document.querySelector("#view_on_github"); + this.viewOnGithubBtn.addEventListener("aOnClick", (event) => { + window.open('https://github.com/adaleks/anywhere-ui/tree/main/packages/core/src/components/radio-button', '_blank'); + }); + } + + async getHtml() { + return fetch('app/views/RadioButton/RadioButton.html') + .then(data => { + return data.text(); + }); + } +} diff --git a/packages/core/src/assets/favicon/android-icon-144x144.png b/packages/core/src/assets/favicon/android-icon-144x144.png index 583b787..6f2498a 100644 Binary files a/packages/core/src/assets/favicon/android-icon-144x144.png and b/packages/core/src/assets/favicon/android-icon-144x144.png differ diff --git a/packages/core/src/assets/favicon/android-icon-192x192.png b/packages/core/src/assets/favicon/android-icon-192x192.png index c943e99..9cc31f0 100644 Binary files a/packages/core/src/assets/favicon/android-icon-192x192.png and b/packages/core/src/assets/favicon/android-icon-192x192.png differ diff --git a/packages/core/src/assets/favicon/android-icon-36x36.png b/packages/core/src/assets/favicon/android-icon-36x36.png index af662e0..6b482c9 100644 Binary files a/packages/core/src/assets/favicon/android-icon-36x36.png and b/packages/core/src/assets/favicon/android-icon-36x36.png differ diff --git a/packages/core/src/assets/favicon/android-icon-48x48.png b/packages/core/src/assets/favicon/android-icon-48x48.png index c473169..7cb1047 100644 Binary files a/packages/core/src/assets/favicon/android-icon-48x48.png and b/packages/core/src/assets/favicon/android-icon-48x48.png differ diff --git a/packages/core/src/assets/favicon/android-icon-72x72.png b/packages/core/src/assets/favicon/android-icon-72x72.png index e09b8e4..4ba93a7 100644 Binary files a/packages/core/src/assets/favicon/android-icon-72x72.png and b/packages/core/src/assets/favicon/android-icon-72x72.png differ diff --git a/packages/core/src/assets/favicon/android-icon-96x96.png b/packages/core/src/assets/favicon/android-icon-96x96.png index 3c529a8..48d5581 100644 Binary files a/packages/core/src/assets/favicon/android-icon-96x96.png and b/packages/core/src/assets/favicon/android-icon-96x96.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-114x114.png b/packages/core/src/assets/favicon/apple-icon-114x114.png index c06996a..4d21025 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-114x114.png and b/packages/core/src/assets/favicon/apple-icon-114x114.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-120x120.png b/packages/core/src/assets/favicon/apple-icon-120x120.png index 6fddc3b..15d89d0 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-120x120.png and b/packages/core/src/assets/favicon/apple-icon-120x120.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-144x144.png b/packages/core/src/assets/favicon/apple-icon-144x144.png index 583b787..6f2498a 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-144x144.png and b/packages/core/src/assets/favicon/apple-icon-144x144.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-152x152.png b/packages/core/src/assets/favicon/apple-icon-152x152.png index fc30a33..3c92162 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-152x152.png and b/packages/core/src/assets/favicon/apple-icon-152x152.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-180x180.png b/packages/core/src/assets/favicon/apple-icon-180x180.png index 3681409..116353d 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-180x180.png and b/packages/core/src/assets/favicon/apple-icon-180x180.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-57x57.png b/packages/core/src/assets/favicon/apple-icon-57x57.png index 71823fa..1c54448 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-57x57.png and b/packages/core/src/assets/favicon/apple-icon-57x57.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-60x60.png b/packages/core/src/assets/favicon/apple-icon-60x60.png index 43a8f69..9666d1d 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-60x60.png and b/packages/core/src/assets/favicon/apple-icon-60x60.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-72x72.png b/packages/core/src/assets/favicon/apple-icon-72x72.png index e09b8e4..4ba93a7 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-72x72.png and b/packages/core/src/assets/favicon/apple-icon-72x72.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-76x76.png b/packages/core/src/assets/favicon/apple-icon-76x76.png index 83c00ce..88dd961 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-76x76.png and b/packages/core/src/assets/favicon/apple-icon-76x76.png differ diff --git a/packages/core/src/assets/favicon/apple-icon-precomposed.png b/packages/core/src/assets/favicon/apple-icon-precomposed.png index f9324d4..f47cea9 100644 Binary files a/packages/core/src/assets/favicon/apple-icon-precomposed.png and b/packages/core/src/assets/favicon/apple-icon-precomposed.png differ diff --git a/packages/core/src/assets/favicon/apple-icon.png b/packages/core/src/assets/favicon/apple-icon.png index f9324d4..f47cea9 100644 Binary files a/packages/core/src/assets/favicon/apple-icon.png and b/packages/core/src/assets/favicon/apple-icon.png differ diff --git a/packages/core/src/assets/favicon/favicon-16x16.png b/packages/core/src/assets/favicon/favicon-16x16.png index 3061dbf..6bdf74e 100644 Binary files a/packages/core/src/assets/favicon/favicon-16x16.png and b/packages/core/src/assets/favicon/favicon-16x16.png differ diff --git a/packages/core/src/assets/favicon/favicon-32x32.png b/packages/core/src/assets/favicon/favicon-32x32.png index a13b10a..9c3ea17 100644 Binary files a/packages/core/src/assets/favicon/favicon-32x32.png and b/packages/core/src/assets/favicon/favicon-32x32.png differ diff --git a/packages/core/src/assets/favicon/favicon-96x96.png b/packages/core/src/assets/favicon/favicon-96x96.png index 3c529a8..48d5581 100644 Binary files a/packages/core/src/assets/favicon/favicon-96x96.png and b/packages/core/src/assets/favicon/favicon-96x96.png differ diff --git a/packages/core/src/assets/favicon/favicon.ico b/packages/core/src/assets/favicon/favicon.ico index cc088e9..a98ce0e 100644 Binary files a/packages/core/src/assets/favicon/favicon.ico and b/packages/core/src/assets/favicon/favicon.ico differ diff --git a/packages/core/src/assets/favicon/ms-icon-144x144.png b/packages/core/src/assets/favicon/ms-icon-144x144.png index 583b787..6f2498a 100644 Binary files a/packages/core/src/assets/favicon/ms-icon-144x144.png and b/packages/core/src/assets/favicon/ms-icon-144x144.png differ diff --git a/packages/core/src/assets/favicon/ms-icon-150x150.png b/packages/core/src/assets/favicon/ms-icon-150x150.png index 1fc865b..5f99b6f 100644 Binary files a/packages/core/src/assets/favicon/ms-icon-150x150.png and b/packages/core/src/assets/favicon/ms-icon-150x150.png differ diff --git a/packages/core/src/assets/favicon/ms-icon-310x310.png b/packages/core/src/assets/favicon/ms-icon-310x310.png index 9aede79..731214c 100644 Binary files a/packages/core/src/assets/favicon/ms-icon-310x310.png and b/packages/core/src/assets/favicon/ms-icon-310x310.png differ diff --git a/packages/core/src/assets/favicon/ms-icon-70x70.png b/packages/core/src/assets/favicon/ms-icon-70x70.png index ceacad9..656f45b 100644 Binary files a/packages/core/src/assets/favicon/ms-icon-70x70.png and b/packages/core/src/assets/favicon/ms-icon-70x70.png differ diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index f98450b..600df73 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -5,7 +5,7 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; -import { SelectChangeEventDetail } from "./interfaces"; +import { RadioGroupChangeEventDetail, SelectChangeEventDetail } from "./interfaces"; export namespace Components { interface AnyBadge { /** @@ -98,6 +98,10 @@ export namespace Components { * Inline style of the component. */ "anyStyle": any; + /** + * Index of the element in tabbing order + */ + "anyTabIndex"?: number; /** * Allows to select a boolean value instead of multiple values. */ @@ -369,6 +373,62 @@ export namespace Components { */ "virtualScroll": boolean; } + interface AnyRadioButton { + /** + * Inline style of the component. + */ + "anyStyle": any; + /** + * Index of the element in tabbing order + */ + "anyTabIndex"?: number; + /** + * When present, it specifies that the element should be disabled. + */ + "disabled": boolean; + /** + * Identifier of the focus input to match a label defined for the component. + */ + "inputId": string; + /** + * Label of the radiobutton. + */ + "label": string; + /** + * Style class of the label. + */ + "labelStyleClass": string; + /** + * The name of the control, which is submitted with the form data. + */ + "name": string; + /** + * Applies focus. + */ + "setFocus": (ev: any) => Promise; + /** + * Style class of the component. + */ + "styleClass": any; + /** + * the value of the radio. + */ + "value"?: any | null; + } + interface AnyRadioGroup { + /** + * If `true`, the radios can be deselected. + */ + "allowEmptySelection": boolean; + /** + * The name of the control, which is submitted with the form data. + */ + "name": string; + /** + * the value of the radio group. + */ + "value"?: any | null; + } interface AnyRippleEffect { /** * Sets the type of ripple-effect: @@ -511,6 +571,18 @@ declare global { prototype: HTMLAnyListboxElement; new (): HTMLAnyListboxElement; }; + interface HTMLAnyRadioButtonElement extends Components.AnyRadioButton, HTMLStencilElement { + } + var HTMLAnyRadioButtonElement: { + prototype: HTMLAnyRadioButtonElement; + new (): HTMLAnyRadioButtonElement; + }; + interface HTMLAnyRadioGroupElement extends Components.AnyRadioGroup, HTMLStencilElement { + } + var HTMLAnyRadioGroupElement: { + prototype: HTMLAnyRadioGroupElement; + new (): HTMLAnyRadioGroupElement; + }; interface HTMLAnyRippleEffectElement extends Components.AnyRippleEffect, HTMLStencilElement { } var HTMLAnyRippleEffectElement: { @@ -544,6 +616,8 @@ declare global { "any-input-switch": HTMLAnyInputSwitchElement; "any-input-text": HTMLAnyInputTextElement; "any-listbox": HTMLAnyListboxElement; + "any-radio-button": HTMLAnyRadioButtonElement; + "any-radio-group": HTMLAnyRadioGroupElement; "any-ripple-effect": HTMLAnyRippleEffectElement; "any-tab-panel": HTMLAnyTabPanelElement; "any-tab-view": HTMLAnyTabViewElement; @@ -654,6 +728,10 @@ declare namespace LocalJSX { * Inline style of the component. */ "anyStyle"?: any; + /** + * Index of the element in tabbing order + */ + "anyTabIndex"?: number; /** * Allows to select a boolean value instead of multiple values. */ @@ -987,6 +1065,74 @@ declare namespace LocalJSX { */ "virtualScroll"?: boolean; } + interface AnyRadioButton { + /** + * Inline style of the component. + */ + "anyStyle"?: any; + /** + * Index of the element in tabbing order + */ + "anyTabIndex"?: number; + /** + * When present, it specifies that the element should be disabled. + */ + "disabled"?: boolean; + /** + * Identifier of the focus input to match a label defined for the component. + */ + "inputId"?: string; + /** + * Label of the radiobutton. + */ + "label"?: string; + /** + * Style class of the label. + */ + "labelStyleClass"?: string; + /** + * The name of the control, which is submitted with the form data. + */ + "name"?: string; + /** + * Callback to invoke when the radio button loses focus. + */ + "onAOnBlur"?: (event: CustomEvent) => void; + /** + * Callback to invoke when the radio button receives focus. + */ + "onAOnFocus"?: (event: CustomEvent) => void; + /** + * Callback to invoke on radio button select. + */ + "onAOnSelect"?: (event: CustomEvent) => void; + /** + * Style class of the component. + */ + "styleClass"?: any; + /** + * the value of the radio. + */ + "value"?: any | null; + } + interface AnyRadioGroup { + /** + * If `true`, the radios can be deselected. + */ + "allowEmptySelection"?: boolean; + /** + * The name of the control, which is submitted with the form data. + */ + "name"?: string; + /** + * Emitted when the value has changed. + */ + "onValueChange"?: (event: CustomEvent) => void; + /** + * the value of the radio group. + */ + "value"?: any | null; + } interface AnyRippleEffect { /** * Sets the type of ripple-effect: @@ -1108,6 +1254,8 @@ declare namespace LocalJSX { "any-input-switch": AnyInputSwitch; "any-input-text": AnyInputText; "any-listbox": AnyListbox; + "any-radio-button": AnyRadioButton; + "any-radio-group": AnyRadioGroup; "any-ripple-effect": AnyRippleEffect; "any-tab-panel": AnyTabPanel; "any-tab-view": AnyTabView; @@ -1126,6 +1274,8 @@ declare module "@stencil/core" { "any-input-switch": LocalJSX.AnyInputSwitch & JSXBase.HTMLAttributes; "any-input-text": LocalJSX.AnyInputText & JSXBase.HTMLAttributes; "any-listbox": LocalJSX.AnyListbox & JSXBase.HTMLAttributes; + "any-radio-button": LocalJSX.AnyRadioButton & JSXBase.HTMLAttributes; + "any-radio-group": LocalJSX.AnyRadioGroup & JSXBase.HTMLAttributes; "any-ripple-effect": LocalJSX.AnyRippleEffect & JSXBase.HTMLAttributes; "any-tab-panel": LocalJSX.AnyTabPanel & JSXBase.HTMLAttributes; "any-tab-view": LocalJSX.AnyTabView & JSXBase.HTMLAttributes; diff --git a/packages/core/src/components/checkbox/checkbox.tsx b/packages/core/src/components/checkbox/checkbox.tsx index df10ad8..becd2ce 100644 --- a/packages/core/src/components/checkbox/checkbox.tsx +++ b/packages/core/src/components/checkbox/checkbox.tsx @@ -47,6 +47,11 @@ export class AnyCheckbox { */ @Prop() name: string = this.inputId; + /** + * Index of the element in tabbing order + */ + @Prop() anyTabIndex?: number = 0; + /** * The value of the checkbox does not mean if it's checked or not, use the `checked` * property for that. @@ -186,6 +191,7 @@ export class AnyCheckbox {
{ this.onFocus(); }} diff --git a/packages/core/src/components/checkbox/readme.md b/packages/core/src/components/checkbox/readme.md index 8851898..99a1fa6 100644 --- a/packages/core/src/components/checkbox/readme.md +++ b/packages/core/src/components/checkbox/readme.md @@ -10,6 +10,7 @@ | Property | Attribute | Description | Type | Default | | ----------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | --------------------------- | | `anyStyle` | `any-style` | Inline style of the component. | `any` | `null` | +| `anyTabIndex` | `any-tab-index` | Index of the element in tabbing order | `number` | `0` | | `binary` | `binary` | Allows to select a boolean value instead of multiple values. | `boolean` | `false` | | `checkboxIcon` | `checkbox-icon` | Icon class of the checkbox icon. | `string` | `"fa-solid:check"` | | `checked` | `checked` | If `true`, the checkbox is selected. | `boolean` | `false` | diff --git a/packages/core/src/components/radio-button/radio-button.scss b/packages/core/src/components/radio-button/radio-button.scss new file mode 100644 index 0000000..00b49d3 --- /dev/null +++ b/packages/core/src/components/radio-button/radio-button.scss @@ -0,0 +1,91 @@ +@import "../../themes/anywhere.globals.scss"; + +:host { + display: block; + + .any-radiobutton { + display: inline-flex; + cursor: pointer; + user-select: none; + vertical-align: bottom; + position: relative; + } + + .any-radiobutton-box { + display: flex; + justify-content: center; + align-items: center; + } + + .any-radiobutton-icon { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transform: translateZ(0) scale(0.1); + border-radius: 50%; + visibility: hidden; + } + + .any-radiobutton-box.any-highlight .any-radiobutton-icon { + transform: translateZ(0) scale(1, 1); + visibility: visible; + } + + p-radiobutton { + display: inline-flex; + vertical-align: bottom; + align-items: center; + } + + .any-radiobutton-label { + line-height: 1; + } + + .any-radiobutton { + width: var(--radiobuttonWidth); + height: var(--radiobuttonHeight); + } + + .any-radiobutton .any-radiobutton-box { + border: var(--radiobuttonBorder); + background: var(--inputBgColor); + width: var(--radiobuttonWidth); + height: var(--radiobuttonHeight); + color: var(--textColor); + border-radius: 50%; + transition: var(--formElementTransition); + } + + .any-radiobutton + .any-radiobutton-box:not(.any-disabled):not(.any-highlight):hover { + border-color: var(--primaryColor); + } + + .any-radiobutton .any-radiobutton-box:not(.any-disabled).any-focus { + outline: var(--focusOutline); + outline-offset: var(--focusOutlineOffset); + box-shadow: var(--focusShadow); + border-color: var(--primaryColor); + } + + .any-radiobutton .any-radiobutton-box .any-radiobutton-icon { + width: var(--radiobuttonIconSize); + height: var(--radiobuttonIconSize); + transition-duration: var(--transitionDuration); + background-color: var(--inputBgColor); + } + + .any-radiobutton .any-radiobutton-box.any-highlight { + border-color: var(--primaryColor); + background: var(--primaryColor); + } + + .any-radiobutton .any-radiobutton-box.any-highlight:not(.any-disabled):hover { + border-color: var(--radiobuttonActiveHoverBorderColor); + background: var(--radiobuttonActiveHoverBg); + color: var(--radiobuttonIconActiveHoverColor); + } + + .any-radiobutton-label { + margin-left: 0.5rem; + } +} diff --git a/packages/core/src/components/radio-button/radio-button.tsx b/packages/core/src/components/radio-button/radio-button.tsx new file mode 100644 index 0000000..3cdc8c3 --- /dev/null +++ b/packages/core/src/components/radio-button/radio-button.tsx @@ -0,0 +1,246 @@ +import { + Component, + Host, + h, + Prop, + Element, + State, + EventEmitter, + Event, + Method, +} from "@stencil/core"; + +import { + addEventListener, + // getAriaLabel, + removeEventListener, +} from "../../utils/helpers"; + +@Component({ + tag: "any-radio-button", + styleUrl: "radio-button.scss", + shadow: true, +}) +export class RadioButton { + @Element() private element: HTMLElement; + + private radiobutton: HTMLElement | null = null; + private nativeInput!: HTMLInputElement; + private radioGroup: HTMLAnyRadioGroupElement | null = null; + + /** + * If `true`, the radio is focused. + */ + @State() focused: boolean = false; + + /** + * If `true`, the radio is selected. + */ + @State() checked: boolean = false; + + /** + * the value of the radio. + */ + @Prop() value?: any | null; + + /** + * Identifier of the focus input to match a label defined for the component. + */ + @Prop() inputId: string = `any-rb-${radiobuttonIds++}`; + + /** + * Label of the radiobutton. + */ + @Prop() label: string = null; + + /** + * Inline style of the component. + */ + @Prop() anyStyle: any = null; + + /** + * Style class of the component. + */ + @Prop() styleClass: any = null; + + /** + * Style class of the label. + */ + @Prop() labelStyleClass: string = null; + + /** + * When present, it specifies that the element should be disabled. + */ + @Prop() disabled: boolean = false; + + /** + * The name of the control, which is submitted with the form data. + */ + @Prop() name: string = this.inputId; + + /** + * Index of the element in tabbing order + */ + @Prop() anyTabIndex?: number = 0; + + /** + * Callback to invoke on radio button select. + */ + @Event() aOnSelect?: EventEmitter; + + /** + * Callback to invoke when the radio button receives focus. + */ + @Event() aOnFocus?: EventEmitter; + + /** + * Callback to invoke when the radio button loses focus. + */ + @Event() aOnBlur?: EventEmitter; + + /** + * Applies focus. + */ + @Method() + async setFocus(ev: any) { + ev.stopPropagation(); + ev.preventDefault(); + + this.radiobutton.focus(); + } + + connectedCallback() { + if (this.value === undefined) { + this.value = this.inputId; + } + const radioGroup = (this.radioGroup = + this.element.closest("any-radio-group")); + if (radioGroup) { + this.updateState(); + addEventListener(radioGroup, "valueChange", this.updateState); + } + } + + disconnectedCallback() { + const radioGroup = this.radioGroup; + if (radioGroup) { + removeEventListener(radioGroup, "valueChange", this.updateState); + this.radioGroup = null; + } + } + + private updateState = () => { + if (this.radioGroup) { + console.log("UPDATE STATE", this.radioGroup.value, this.value); + this.checked = this.radioGroup.value === this.value; + } + }; + + componentWillLoad() {} + + componentDidLoad() { + this.radiobutton = this.element.shadowRoot.querySelector( + "input[type='radio']" + ) as HTMLElement; + } + + onClick(event, focus: boolean) { + event.preventDefault(); + + if (this.disabled) { + return; + } + + this.checked = this.nativeInput.checked; + console.log("NATIVE", this.nativeInput); + + this.aOnSelect.emit(event); + + if (focus) { + this.radiobutton.focus(); + } + } + + onFocus(e) { + this.focused = true; + this.aOnFocus.emit(e); + } + + onBlur(e) { + this.focused = false; + this.aOnBlur.emit(e); + } + + render() { + const { checked, focused, disabled } = this; + + return ( + +
+ + +
+
+ ); + } +} + +let radiobuttonIds = 0; diff --git a/packages/core/src/components/radio-button/readme.md b/packages/core/src/components/radio-button/readme.md new file mode 100644 index 0000000..d9d4f28 --- /dev/null +++ b/packages/core/src/components/radio-button/readme.md @@ -0,0 +1,47 @@ +# any-radio-button + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| ----------------- | ------------------- | ------------------------------------------------------------------------- | --------- | ------------------------------ | +| `anyStyle` | `any-style` | Inline style of the component. | `any` | `null` | +| `anyTabIndex` | `any-tab-index` | Index of the element in tabbing order | `number` | `0` | +| `disabled` | `disabled` | When present, it specifies that the element should be disabled. | `boolean` | `false` | +| `inputId` | `input-id` | Identifier of the focus input to match a label defined for the component. | `string` | ``any-rb-${radiobuttonIds++}`` | +| `label` | `label` | Label of the radiobutton. | `string` | `null` | +| `labelStyleClass` | `label-style-class` | Style class of the label. | `string` | `null` | +| `name` | `name` | The name of the control, which is submitted with the form data. | `string` | `this.inputId` | +| `styleClass` | `style-class` | Style class of the component. | `any` | `null` | +| `value` | `value` | the value of the radio. | `any` | `undefined` | + + +## Events + +| Event | Description | Type | +| ----------- | -------------------------------------------------------- | ------------------ | +| `aOnBlur` | Callback to invoke when the radio button loses focus. | `CustomEvent` | +| `aOnFocus` | Callback to invoke when the radio button receives focus. | `CustomEvent` | +| `aOnSelect` | Callback to invoke on radio button select. | `CustomEvent` | + + +## Methods + +### `setFocus(ev: any) => Promise` + +Applies focus. + +#### Returns + +Type: `Promise` + + + + +---------------------------------------------- + +*Built with love by **AdaleksTech!*** diff --git a/packages/core/src/components/radio-button/test/radio-button.e2e.ts b/packages/core/src/components/radio-button/test/radio-button.e2e.ts new file mode 100644 index 0000000..eeb970c --- /dev/null +++ b/packages/core/src/components/radio-button/test/radio-button.e2e.ts @@ -0,0 +1,11 @@ +import { newE2EPage } from '@stencil/core/testing'; + +describe('any-radio-button', () => { + it('renders', async () => { + const page = await newE2EPage(); + await page.setContent(''); + + const element = await page.find('any-radio-button'); + expect(element).toHaveClass('hydrated'); + }); +}); diff --git a/packages/core/src/components/radio-button/test/radio-button.spec.tsx b/packages/core/src/components/radio-button/test/radio-button.spec.tsx new file mode 100644 index 0000000..e7f616b --- /dev/null +++ b/packages/core/src/components/radio-button/test/radio-button.spec.tsx @@ -0,0 +1,18 @@ +import { newSpecPage } from '@stencil/core/testing'; +import { RadioButton } from '../radio-button'; + +describe('any-radio-button', () => { + it('renders', async () => { + const page = await newSpecPage({ + components: [RadioButton], + html: ``, + }); + expect(page.root).toEqualHtml(` + + + + + + `); + }); +}); diff --git a/packages/core/src/components/radio-group/radio-group-inteface.ts b/packages/core/src/components/radio-group/radio-group-inteface.ts new file mode 100644 index 0000000..cf7309b --- /dev/null +++ b/packages/core/src/components/radio-group/radio-group-inteface.ts @@ -0,0 +1,8 @@ +export interface RadioGroupChangeEventDetail { + value: T; +} + +export interface RadioGroupCustomEvent extends CustomEvent { + detail: RadioGroupChangeEventDetail; + target: HTMLAnyRadioGroupElement; +} diff --git a/packages/core/src/components/radio-group/radio-group.scss b/packages/core/src/components/radio-group/radio-group.scss new file mode 100644 index 0000000..5d4e87f --- /dev/null +++ b/packages/core/src/components/radio-group/radio-group.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/packages/core/src/components/radio-group/radio-group.tsx b/packages/core/src/components/radio-group/radio-group.tsx new file mode 100644 index 0000000..be028a1 --- /dev/null +++ b/packages/core/src/components/radio-group/radio-group.tsx @@ -0,0 +1,119 @@ +import { + Component, + ComponentInterface, + Element, + Event, + EventEmitter, + Host, + /*Listen,*/ + Prop, + Watch, + h, +} from "@stencil/core"; + +import { RadioGroupChangeEventDetail } from "../../interfaces"; +// import { renderHiddenInput } from "../../utils/helpers"; + +@Component({ + tag: "any-radio-group", + styleUrl: "radio-group.scss", + // shadow: true, +}) +export class RadioGroup implements ComponentInterface { + private inputId = `any-rg-${radioGroupIds++}`; + private labelId = `${this.inputId}-lbl`; + private label?: HTMLElement | null; + + @Element() element!: HTMLElement; + + /** + * If `true`, the radios can be deselected. + */ + @Prop() allowEmptySelection = false; + + /** + * The name of the control, which is submitted with the form data. + */ + @Prop() name: string = this.inputId; + + /** + * the value of the radio group. + */ + @Prop({ mutable: true }) value?: any | null; + + @Watch("value") + valueChanged(value: any | undefined) { + this.setRadioTabindex(value); + + this.valueChange.emit({ value }); + } + + /** + * Emitted when the value has changed. + */ + @Event() valueChange!: EventEmitter; + + componentDidLoad() { + this.setRadioTabindex(this.value); + } + + private setRadioTabindex = (value: any | undefined) => { + const radios = this.getRadios(); + + // Get the first radio that is not disabled and the checked one + const first = radios.find((radio) => !radio.disabled); + const checked = radios.find( + (radio) => radio.value === value && !radio.disabled + ); + + if (!first && !checked) { + return; + } + + // If an enabled checked radio exists, set it to be the focusable radio + // otherwise we default to focus the first radio + // const focusable = checked || first; + + // for (const radio of radios) { + // const tabindex = radio === focusable ? 0 : -1; + // radio.setButtonTabindex(tabindex); + // } + }; + + private getRadios(): HTMLAnyRadioButtonElement[] { + return Array.from(this.element.querySelectorAll("any-radio-button")); + } + + private onClick = (ev: Event) => { + ev.preventDefault(); + + const selectedRadio = + ev.target && (ev.target as HTMLElement).closest("any-radio-button"); + + if (selectedRadio) { + const currentValue = this.value; + const newValue = selectedRadio.value; + if (newValue !== currentValue && !selectedRadio.disabled) { + this.value = newValue; + } else if (this.allowEmptySelection) { + this.value = undefined; + } + selectedRadio.setFocus(ev); + } + }; + + render() { + const { name, labelId, label } = this; + + return ( + + ); + } +} + +let radioGroupIds = 0; diff --git a/packages/core/src/components/radio-group/readme.md b/packages/core/src/components/radio-group/readme.md new file mode 100644 index 0000000..f1509b4 --- /dev/null +++ b/packages/core/src/components/radio-group/readme.md @@ -0,0 +1,26 @@ +# any-radio-group + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| --------------------- | ----------------------- | --------------------------------------------------------------- | --------- | -------------- | +| `allowEmptySelection` | `allow-empty-selection` | If `true`, the radios can be deselected. | `boolean` | `false` | +| `name` | `name` | The name of the control, which is submitted with the form data. | `string` | `this.inputId` | +| `value` | `value` | the value of the radio group. | `any` | `undefined` | + + +## Events + +| Event | Description | Type | +| ------------- | ----------------------------------- | ----------------------------------------------- | +| `valueChange` | Emitted when the value has changed. | `CustomEvent>` | + + +---------------------------------------------- + +*Built with love by **AdaleksTech!*** diff --git a/packages/core/src/components/radio-group/test/radio-group.e2e.ts b/packages/core/src/components/radio-group/test/radio-group.e2e.ts new file mode 100644 index 0000000..fa9f227 --- /dev/null +++ b/packages/core/src/components/radio-group/test/radio-group.e2e.ts @@ -0,0 +1,11 @@ +import { newE2EPage } from '@stencil/core/testing'; + +describe('any-radio-group', () => { + it('renders', async () => { + const page = await newE2EPage(); + await page.setContent(''); + + const element = await page.find('any-radio-group'); + expect(element).toHaveClass('hydrated'); + }); +}); diff --git a/packages/core/src/components/radio-group/test/radio-group.spec.tsx b/packages/core/src/components/radio-group/test/radio-group.spec.tsx new file mode 100644 index 0000000..20e9d71 --- /dev/null +++ b/packages/core/src/components/radio-group/test/radio-group.spec.tsx @@ -0,0 +1,18 @@ +import { newSpecPage } from '@stencil/core/testing'; +import { RadioGroup } from '../radio-group'; + +describe('any-radio-group', () => { + it('renders', async () => { + const page = await newSpecPage({ + components: [RadioGroup], + html: ``, + }); + expect(page.root).toEqualHtml(` + + + + + + `); + }); +}); diff --git a/packages/core/src/components/ripple-effect/ripple-effect.tsx b/packages/core/src/components/ripple-effect/ripple-effect.tsx index 19fa23a..46ad775 100644 --- a/packages/core/src/components/ripple-effect/ripple-effect.tsx +++ b/packages/core/src/components/ripple-effect/ripple-effect.tsx @@ -1,5 +1,6 @@ import { Component, Host, h, Element, Prop } from "@stencil/core"; import { DomHandler } from "../../utils/dom"; +import { config } from "../../global/config"; @Component({ tag: "any-ripple-effect", @@ -11,6 +12,8 @@ export class RippleEffect { private mouseDownListener: any; + private useRippleEffect: boolean = true; + @Element() element: HTMLElement; /** @@ -18,13 +21,19 @@ export class RippleEffect { */ @Prop() type: "bounded" | "unbounded" = "bounded"; + connectedCallback() { + this.useRippleEffect = config.getBoolean("rippleEffect", true); + } + componentDidLoad() { - this.create(); - this.mouseDownListener = this.onMouseDown.bind(this); - this.element.parentNode.addEventListener( - "mousedown", - this.mouseDownListener - ); + if (this.useRippleEffect) { + this.create(); + this.mouseDownListener = this.onMouseDown.bind(this); + this.element.parentNode.addEventListener( + "mousedown", + this.mouseDownListener + ); + } } onMouseDown(event: MouseEvent) { diff --git a/packages/core/src/global/anywhere-global.ts b/packages/core/src/global/anywhere-global.ts index e69de29..286a041 100644 --- a/packages/core/src/global/anywhere-global.ts +++ b/packages/core/src/global/anywhere-global.ts @@ -0,0 +1,48 @@ +import { /*getMode, setMode,*/ setPlatformHelpers } from "@stencil/core"; + +import { AnywhereUIConfig /*, Mode, setupConfig*/ } from "../interfaces"; +// import { isPlatform, setupPlatforms } from "../utils/platform"; + +import { config, saveConfig, configFromSession, configFromURL } from "./config"; + +declare const Context: any; + +export const initialize = (userConfig: AnywhereUIConfig = {}) => { + if (typeof (window as any) === "undefined") { + return; + } + + // const doc = window.document; + const win = window; + Context.config = config; + const AnywhereUI = ((win as any).AnywhereUI = (win as any).AnywhereUI || {}); + + const platformHelpers: any = {}; + if (userConfig._ael) { + platformHelpers.ael = userConfig._ael; + } + if (userConfig._rel) { + platformHelpers.rel = userConfig._rel; + } + if (userConfig._ce) { + platformHelpers.ce = userConfig._ce; + } + setPlatformHelpers(platformHelpers); + + const configObj = { + ...configFromSession(win), + persistConfig: false, + ...AnywhereUI.config, + ...configFromURL(win), + ...userConfig, + }; + + config.reset(configObj); + if (config.getBoolean("persistConfig")) { + saveConfig(win, configObj); + } + + AnywhereUI.config = config; +}; + +export default initialize; diff --git a/packages/core/src/global/config.ts b/packages/core/src/global/config.ts new file mode 100644 index 0000000..02ffe73 --- /dev/null +++ b/packages/core/src/global/config.ts @@ -0,0 +1,78 @@ +import { AnywhereUIConfig } from "../interfaces"; + +export class Config { + private m = new Map(); + + reset(configObj: AnywhereUIConfig) { + this.m = new Map( + Object.entries(configObj) as any + ); + } + + get(key: keyof AnywhereUIConfig, fallback?: any): any { + const value = this.m.get(key); + return value !== undefined ? value : fallback; + } + + getBoolean(key: keyof AnywhereUIConfig, fallback = false): boolean { + const val = this.m.get(key); + if (val === undefined) { + return fallback; + } + if (typeof val === "string") { + return val === "true"; + } + return !!val; + } + + getNumber(key: keyof AnywhereUIConfig, fallback?: number): number { + const val = parseFloat(this.m.get(key)); + return isNaN(val) ? (fallback !== undefined ? fallback : NaN) : val; + } + + set(key: keyof AnywhereUIConfig, value: any) { + this.m.set(key, value); + } +} +export const config = /*@__PURE__*/ new Config(); + +export const configFromSession = (win: Window): any => { + try { + const configStr = win.sessionStorage.getItem(ANYWHERE_UI_SESSION_KEY); + return configStr !== null ? JSON.parse(configStr) : {}; + } catch (e) { + return {}; + } +}; + +export const saveConfig = (win: Window, c: any) => { + try { + win.sessionStorage.setItem(ANYWHERE_UI_SESSION_KEY, JSON.stringify(c)); + } catch (e) { + return; + } +}; + +export const configFromURL = (win: Window) => { + const configObj: any = {}; + win.location.search + .slice(1) + .split("&") + .map((entry) => entry.split("=")) + .map(([key, value]) => [decodeURIComponent(key), decodeURIComponent(value)]) + .filter(([key]) => startsWith(key, ANYWHERE_UI_PREFIX)) + .map(([key, value]) => [key.slice(ANYWHERE_UI_PREFIX.length), value]) + .forEach(([key, value]) => { + configObj[key] = value; + }); + + return configObj; +}; + +const startsWith = (input: string, search: string): boolean => { + return input.substr(0, search.length) === search; +}; + +const ANYWHERE_UI_PREFIX = "anywhere-ui:"; + +const ANYWHERE_UI_SESSION_KEY = "anywhere-ui-persist-config"; diff --git a/packages/core/src/index.html b/packages/core/src/index.html index a5be22c..c9da5f1 100644 --- a/packages/core/src/index.html +++ b/packages/core/src/index.html @@ -70,6 +70,7 @@ InputSwitch InputText Listbox + RadioButton