diff --git a/packages/ui-library/src/components/button-group/index.ts b/packages/ui-library/src/components/button-group/index.ts index 13a5f0012..ceba822ec 100644 --- a/packages/ui-library/src/components/button-group/index.ts +++ b/packages/ui-library/src/components/button-group/index.ts @@ -5,8 +5,9 @@ import { styleCustom } from './index.css'; import { ButtonGroupAlignmentType, ButtonGroupSizesType } from '../../globals/types'; import { TAG_NAME } from './renderFunction'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; -export class BlrButtonGroup extends LitElement { +export class BlrButtonGroup extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() sizeVariant: ButtonGroupSizesType = 'md'; diff --git a/packages/ui-library/src/components/button-icon/index.ts b/packages/ui-library/src/components/button-icon/index.ts index 2d0ffd6cc..dc0c4584f 100644 --- a/packages/ui-library/src/components/button-icon/index.ts +++ b/packages/ui-library/src/components/button-icon/index.ts @@ -21,6 +21,7 @@ import { createBlrClickEvent, createBlrFocusEvent, } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrButtonIconEventHandlers = { blrFocus?: (event: BlrFocusEvent) => void; @@ -33,7 +34,7 @@ export type BlrButtonIconEventHandlers = { * @fires blrBlur Button lost focus * @fires blrClick Button was clicked */ -export class BlrButtonIcon extends LitElement { +export class BlrButtonIcon extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() arialabel!: string; diff --git a/packages/ui-library/src/components/button-text/index.ts b/packages/ui-library/src/components/button-text/index.ts index 6b5d59f55..9934eeb93 100644 --- a/packages/ui-library/src/components/button-text/index.ts +++ b/packages/ui-library/src/components/button-text/index.ts @@ -27,6 +27,7 @@ import { createBlrClickEvent, createBlrFocusEvent, } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrButtonTextEventHandlers = { blrFocus?: (event: BlrFocusEvent) => void; @@ -39,7 +40,7 @@ export type BlrButtonTextEventHandlers = { * @fires blrBlur Button lost focus * @fires blrClick Button was clicked */ -export class BlrButtonText extends LitElement { +export class BlrButtonText extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() label = 'Button Label'; diff --git a/packages/ui-library/src/components/checkbox/index.ts b/packages/ui-library/src/components/checkbox/index.ts index d09e39be1..ca89b16f0 100644 --- a/packages/ui-library/src/components/checkbox/index.ts +++ b/packages/ui-library/src/components/checkbox/index.ts @@ -21,6 +21,7 @@ import { createBlrBlurEvent, createBlrFocusEvent, } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrCheckboxEventHandlers = { blrFocus?: (event: BlrFocusEvent) => void; @@ -33,7 +34,7 @@ export type BlrCheckboxEventHandlers = { * @fires blrBlur Checkbox lost focus * @fires blrCheckedChange Checkbox state changed (event.checkState) */ -export class BlrCheckbox extends LitElement { +export class BlrCheckbox extends kebabCaseAttributes(LitElement) { static styles = []; @query('input') @@ -265,7 +266,8 @@ export class BlrCheckbox extends LitElement { ?checked=${this.currentCheckedState} ?indeterminate=${this.currentIndeterminateState} ?readonly=${this.readonly} - ?hasError=${this.hasError} + ?has-Error=${this.hasError} + ?has-Label=${this.hasLabel} @change=${this.handleChange} aria-hidden="true" /> diff --git a/packages/ui-library/src/components/form-label/index.ts b/packages/ui-library/src/components/form-label/index.ts index 2da49f01c..d5f4b8ca7 100644 --- a/packages/ui-library/src/components/form-label/index.ts +++ b/packages/ui-library/src/components/form-label/index.ts @@ -5,8 +5,9 @@ import { property } from 'lit/decorators.js'; import { ThemeType } from '../../foundation/_tokens-generated/index.themes'; import { formLight, formDark } from '../../foundation/semantic-tokens/form.css'; import { InputSizesType } from '../../globals/types'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; -export class BlrFormLabel extends LitElement { +export class BlrFormLabel extends kebabCaseAttributes(LitElement) { static styles = []; @property() label = ''; diff --git a/packages/ui-library/src/components/icon/index.ts b/packages/ui-library/src/components/icon/index.ts index 801bf2702..c55b451ca 100644 --- a/packages/ui-library/src/components/icon/index.ts +++ b/packages/ui-library/src/components/icon/index.ts @@ -10,6 +10,7 @@ import { unsafeSVG } from 'lit-html/directives/unsafe-svg.js'; import { TAG_NAME } from './renderFunction'; import { ThemeType } from '../../foundation/_tokens-generated/index.themes'; import { BlrClickEvent, createBlrClickEvent } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrIconEventHandlers = { blrClick?: (event: BlrClickEvent) => void; @@ -18,7 +19,7 @@ export type BlrIconEventHandlers = { /** * @fires blrClick Icon was clicked */ -export class BlrIcon extends LitElement { +export class BlrIcon extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() icon: IconType = 'blr360Xs'; diff --git a/packages/ui-library/src/components/input-field-number/index.ts b/packages/ui-library/src/components/input-field-number/index.ts index 8b4343482..850a3ab8d 100644 --- a/packages/ui-library/src/components/input-field-number/index.ts +++ b/packages/ui-library/src/components/input-field-number/index.ts @@ -26,6 +26,7 @@ import { createBlrNumberValueChangeEvent, createBlrSelectEvent, } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrNumberInputEventListeners = { blrFocus?: (event: BlrFocusEvent) => void; @@ -42,7 +43,7 @@ export type BlrNumberInputEventListeners = { * @fires blrSelect Text in NumberInput was selected * @fires blrNumberStepperClick Step button was clicked */ -export class BlrInputFieldNumber extends LitElement { +export class BlrInputFieldNumber extends kebabCaseAttributes(LitElement) { static styles = [baseStyle]; @query('input') diff --git a/packages/ui-library/src/components/input-field-text/index.ts b/packages/ui-library/src/components/input-field-text/index.ts index b3ba2a230..a6dba935a 100644 --- a/packages/ui-library/src/components/input-field-text/index.ts +++ b/packages/ui-library/src/components/input-field-text/index.ts @@ -24,6 +24,7 @@ import { createBlrSelectEvent, createBlrTextValueChangeEvent, } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrInputFieldTextEventHandlers = { blrFocus?: (event: BlrFocusEvent) => void; @@ -38,7 +39,7 @@ export type BlrInputFieldTextEventHandlers = { * @fires blrTextValueChange InputFieldText value changed * @fires blrSelect Text in InputFieldText got selected */ -export class BlrInputFieldText extends LitElement { +export class BlrInputFieldText extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() inputFieldTextId!: string; @@ -197,7 +198,7 @@ export class BlrInputFieldText extends LitElement { @focus=${this.handleFocus} maxlength="${this.maxLength}" pattern="${this.pattern}" - hasError="${this.hasError}" + has-Error="${this.hasError}" @select=${this.handleSelect} /> diff --git a/packages/ui-library/src/components/loader/index.ts b/packages/ui-library/src/components/loader/index.ts index 904b01fd0..b170028a7 100644 --- a/packages/ui-library/src/components/loader/index.ts +++ b/packages/ui-library/src/components/loader/index.ts @@ -6,8 +6,9 @@ import { styleCustomLight, styleCustomDark } from './index.css'; import { TAG_NAME } from './renderFunction'; import { ThemeType } from '../../foundation/_tokens-generated/index.themes'; import { ActionSizesType, FeedbackVariantType } from '../../globals/types'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; -export class BlrLoader extends LitElement { +export class BlrLoader extends kebabCaseAttributes(LitElement) { static styles = []; @property() sizeVariant?: ActionSizesType = 'md'; diff --git a/packages/ui-library/src/components/radio-group/index.ts b/packages/ui-library/src/components/radio-group/index.ts index cca3a477c..eb63bffbd 100644 --- a/packages/ui-library/src/components/radio-group/index.ts +++ b/packages/ui-library/src/components/radio-group/index.ts @@ -11,8 +11,9 @@ import { BlrFormCaptionGroupRenderFunction } from '../form-caption-group/renderF import { BlrFormCaptionRenderFunction } from '../form-caption/renderFunction'; import { BlrFormLabelInlineRenderFunction } from '../form-label/form-label-inline/renderFunction'; import { TAG_NAME } from './renderFunction'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; -export class BlrRadioGroup extends LitElement { +export class BlrRadioGroup extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() disabled?: boolean; diff --git a/packages/ui-library/src/components/radio/index.ts b/packages/ui-library/src/components/radio/index.ts index da788a7cf..a14e6f4e9 100644 --- a/packages/ui-library/src/components/radio/index.ts +++ b/packages/ui-library/src/components/radio/index.ts @@ -11,8 +11,9 @@ import { ThemeType } from '../../foundation/_tokens-generated/index.themes'; import { BlrFormCaptionGroupRenderFunction } from '../form-caption-group/renderFunction'; import { BlrFormCaptionRenderFunction } from '../form-caption/renderFunction'; import { BlrFormLabelInlineRenderFunction } from '../form-label/form-label-inline/renderFunction'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; -export class BlrRadio extends LitElement { +export class BlrRadio extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() optionId!: string; diff --git a/packages/ui-library/src/components/select/index.ts b/packages/ui-library/src/components/select/index.ts index 54f732f3f..749a9339e 100644 --- a/packages/ui-library/src/components/select/index.ts +++ b/packages/ui-library/src/components/select/index.ts @@ -16,6 +16,7 @@ import { BlrFormCaptionGroupRenderFunction } from '../form-caption-group/renderF import { BlrFormCaptionRenderFunction } from '../form-caption/renderFunction'; import { BlrFormLabelRenderFunction } from '../form-label/renderFunction'; import { BlrSelectedValueChangeEvent, createBlrSelectedValueChangeEvent } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrSelectEventHandlers = { blrSelectedValueChange?: (event: BlrSelectedValueChangeEvent) => void; @@ -24,7 +25,7 @@ export type BlrSelectEventHandlers = { /** * @fires blrSelectedValueChange Selected value changed */ -export class BlrSelect extends LitElement { +export class BlrSelect extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() arialabel?: string; diff --git a/packages/ui-library/src/components/slider-single-value/range-legend-slider/index.ts b/packages/ui-library/src/components/slider-single-value/range-legend-slider/index.ts index 3096965a5..2df4a5c21 100644 --- a/packages/ui-library/src/components/slider-single-value/range-legend-slider/index.ts +++ b/packages/ui-library/src/components/slider-single-value/range-legend-slider/index.ts @@ -12,8 +12,9 @@ import { sliderLight, sliderDark } from '../../../foundation/component-tokens/sl import { FormSizesType, ActionVariantType, RenderBtnProps } from '../../../globals/types'; import { setOnclickValue, findToolTipPosition } from '../../../utils/range-slider-utils'; import { BlrButtonIconRenderFunction } from '../../button-icon/renderFunction'; +import { kebabCaseAttributes } from '../../../mixins/kebab-case-attributes'; -export class BlrRangeLegendSlider extends LitElement { +export class BlrRangeLegendSlider extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() onClickMinMax?: (param: number) => void; diff --git a/packages/ui-library/src/components/slider-single-value/range-slider/index.ts b/packages/ui-library/src/components/slider-single-value/range-slider/index.ts index 18bb6bee1..d7d7656a9 100644 --- a/packages/ui-library/src/components/slider-single-value/range-slider/index.ts +++ b/packages/ui-library/src/components/slider-single-value/range-slider/index.ts @@ -10,8 +10,9 @@ import { SizelessIconType } from '@boiler/icons'; import { ThemeType } from '../../../foundation/_tokens-generated/index.themes'; import { findPercentage, generateRangeBar, setOnclickValue, findNearestValue } from '../../../utils/range-slider-utils'; import { BlrButtonIconRenderFunction } from '../../button-icon/renderFunction'; +import { kebabCaseAttributes } from '../../../mixins/kebab-case-attributes'; -export class BlrRangeSlider extends LitElement { +export class BlrRangeSlider extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() onClickMinMax?: (param: number) => void; diff --git a/packages/ui-library/src/components/slider-two-values/range-legend-min-max-slider/index.ts b/packages/ui-library/src/components/slider-two-values/range-legend-min-max-slider/index.ts index 7191e093d..004aa4c89 100644 --- a/packages/ui-library/src/components/slider-two-values/range-legend-min-max-slider/index.ts +++ b/packages/ui-library/src/components/slider-two-values/range-legend-min-max-slider/index.ts @@ -11,8 +11,9 @@ import { sliderLight, sliderDark } from '../../../foundation/component-tokens/sl import { FormSizesType, ActionVariantType, RenderBtnProps } from '../../../globals/types'; import { setOnclickValue, findToolTipPosition } from '../../../utils/range-slider-utils'; import { BlrButtonIconRenderFunction } from '../../button-icon/renderFunction'; +import { kebabCaseAttributes } from '../../../mixins/kebab-case-attributes'; -export class BlrRangeLegendMinMaxSlider extends LitElement { +export class BlrRangeLegendMinMaxSlider extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() onBtnClick?: (min: number, max: number) => void; diff --git a/packages/ui-library/src/components/slider-two-values/range-min-max-slider/index.ts b/packages/ui-library/src/components/slider-two-values/range-min-max-slider/index.ts index c5e5508a5..9ee4bd7af 100644 --- a/packages/ui-library/src/components/slider-two-values/range-min-max-slider/index.ts +++ b/packages/ui-library/src/components/slider-two-values/range-min-max-slider/index.ts @@ -9,8 +9,9 @@ import { sliderLight, sliderDark } from '../../../foundation/component-tokens/sl import { FormSizesType, ActionVariantType, RenderBtnProps } from '../../../globals/types'; import { findPercentage, generateRangeBar, findNearestValue, setOnclickValue } from '../../../utils/range-slider-utils'; import { BlrButtonIconRenderFunction } from '../../button-icon/renderFunction'; +import { kebabCaseAttributes } from '../../../mixins/kebab-case-attributes'; -export class BlrRangeMinMaxSlider extends LitElement { +export class BlrRangeMinMaxSlider extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() onBtnClick?: (min: number, max: number) => void; diff --git a/packages/ui-library/src/components/tab-bar/index.ts b/packages/ui-library/src/components/tab-bar/index.ts index 230527b09..570baecff 100644 --- a/packages/ui-library/src/components/tab-bar/index.ts +++ b/packages/ui-library/src/components/tab-bar/index.ts @@ -22,8 +22,9 @@ import { getComponentConfigToken } from '../../utils/get-component-config-token' import { BlrDividerRenderFunction } from '../divider/renderFunction'; import { BlrIconRenderFunction } from '../icon/renderFunction'; import { formLight, formDark } from '../../foundation/semantic-tokens/form.css'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; -export class BlrTabBar extends LitElement { +export class BlrTabBar extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @query('.blr-tab-bar') diff --git a/packages/ui-library/src/components/textarea/index.ts b/packages/ui-library/src/components/textarea/index.ts index 17cbf61ea..07714360d 100644 --- a/packages/ui-library/src/components/textarea/index.ts +++ b/packages/ui-library/src/components/textarea/index.ts @@ -22,6 +22,7 @@ import { createBlrSelectEvent, createBlrTextValueChangeEvent, } from '../../globals/events'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; export type BlrTextareaEventHandlers = { blrFocus?: (event: BlrFocusEvent) => void; @@ -36,7 +37,7 @@ export type BlrTextareaEventHandlers = { * @fires blrTextValueChange Textarea value changed * @fires blrSelect Text in Textarea got selected */ -export class BlrTextarea extends LitElement { +export class BlrTextarea extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @property() textAreaId!: string; diff --git a/packages/ui-library/src/components/toggle-switch/index.ts b/packages/ui-library/src/components/toggle-switch/index.ts index 2cde4d6b1..c6313d862 100644 --- a/packages/ui-library/src/components/toggle-switch/index.ts +++ b/packages/ui-library/src/components/toggle-switch/index.ts @@ -12,8 +12,9 @@ import { FormSizesType, IconPositionVariant } from '../../globals/types'; import { BlrFormCaptionRenderFunction } from '../form-caption/renderFunction'; import { BlrFormLabelInlineRenderFunction } from '../form-label/form-label-inline/renderFunction'; import { styleCustom, toggleSwitchLight, toggleSwitchDark } from './index.css'; +import { kebabCaseAttributes } from '../../mixins/kebab-case-attributes'; -export class BlrToggleSwitch extends LitElement { +export class BlrToggleSwitch extends kebabCaseAttributes(LitElement) { static styles = [styleCustom]; @query('input') diff --git a/packages/ui-library/src/mixins/kebab-case-attributes.ts b/packages/ui-library/src/mixins/kebab-case-attributes.ts new file mode 100644 index 000000000..0b636bffc --- /dev/null +++ b/packages/ui-library/src/mixins/kebab-case-attributes.ts @@ -0,0 +1,25 @@ +import type { PropertyDeclaration } from 'lit-element'; + +export const camelCaseToKebabCase = (str: string) => str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase(); + +export function kebabCaseAttributes< + T extends { + createProperty(name: PropertyKey, customOptions: PropertyDeclaration): unknown; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + new (...args: any[]): object; + } +>(constructor: T) { + return class extends constructor { + static createProperty(name: PropertyKey, options: PropertyDeclaration) { + let customOptions = options; + + // generate the attribute name if it hasn't been defined or if it's disabled. + if (typeof options?.attribute === 'undefined' || options?.attribute === true) { + const attributeName = camelCaseToKebabCase(name.toString()); + customOptions = { ...options, attribute: attributeName }; + } + + return super.createProperty(name, customOptions); + } + }; +} diff --git a/packages/ui-library/src/utils/typesafe-generic-component-renderer.ts b/packages/ui-library/src/utils/typesafe-generic-component-renderer.ts index b6d96bdb4..43a2ee61b 100644 --- a/packages/ui-library/src/utils/typesafe-generic-component-renderer.ts +++ b/packages/ui-library/src/utils/typesafe-generic-component-renderer.ts @@ -1,4 +1,5 @@ import { TemplateResult, html } from 'lit'; +import { camelCaseToKebabCase } from '../mixins/kebab-case-attributes'; export const genericBlrComponentRenderer = >( tagName: string, @@ -25,14 +26,14 @@ export const genericBlrComponentRenderer =