Skip to content

Commit

Permalink
feat: add cssStyler option to use typed CSSStyleDeclaration props (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding authored Nov 5, 2023
1 parent c3154f0 commit 8ad2b28
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 4 deletions.
23 changes: 22 additions & 1 deletion demo/src/options/options26.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="row mb-2">
<div class="col-md-12 title-desc">
<h2 class="bd-title">
The Styler
The Styler / CSS Styler
<span class="float-end links">
Code <span class="fa fa-link"></span>
<span class="small">
Expand Down Expand Up @@ -66,4 +66,25 @@ <h2 class="bd-title">
</select>
</div>
</div>

<div class="mb-3 row">
<label class="col-sm-2"> CSS Styler </label>

<div class="col-sm-10">
<select id="select3" multiple="multiple" class="full-width" data-test="select3">
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
</div>
</div>
</div>
15 changes: 15 additions & 0 deletions demo/src/options/options26.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { multipleSelect, OptionRowData, OptGroupRowData, MultipleSelectInstance
export default class Example {
ms1?: MultipleSelectInstance;
ms2?: MultipleSelectInstance;
ms3?: MultipleSelectInstance;

mount() {
this.ms1 = multipleSelect('#basic', {
Expand All @@ -28,13 +29,27 @@ export default class Example {
return null;
},
}) as MultipleSelectInstance;

this.ms3 = multipleSelect('#select3', {
cssStyler: (row: OptionRowData | OptGroupRowData) => {
if (+(row?.value ?? 0) === 2) {
return { backgroundColor: '#6fbeff', color: '#0014ff', fontStyle: 'italic' } as CSSStyleDeclaration;
}
if (+(row?.value ?? 0) === 4) {
return { backgroundColor: '#972727', color: '#fff' } as CSSStyleDeclaration;
}
return null;
},
}) as MultipleSelectInstance;
}

unmount() {
// destroy ms instance(s) to avoid DOM leaks
this.ms1?.destroy();
this.ms2?.destroy();
this.ms3?.destroy();
this.ms1 = undefined;
this.ms2 = undefined;
this.ms3 = undefined;
}
}
8 changes: 7 additions & 1 deletion lib/src/MultipleSelectInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
toggleElement,
} from './utils/domUtils';
import type { HtmlElementPosition } from './utils/domUtils';
import type { MultipleSelectOption } from './interfaces/multipleSelectOption.interface';
import type { CSSStyleDeclarationWritable, MultipleSelectOption } from './interfaces/multipleSelectOption.interface';
import type { MultipleSelectLocales, OptGroupRowData, OptionDataObject, OptionRowData } from './interfaces';
import { BindingEventService, VirtualScroll } from './services';

Expand Down Expand Up @@ -576,6 +576,12 @@ export class MultipleSelectInstance {
}
applyParsedStyleToElement(liElm, style);

const customStyleCss = this.options.cssStyler?.(row);
if (customStyleCss) {
for (const styleProp of Object.keys(customStyleCss)) {
liElm.style[styleProp as CSSStyleDeclarationWritable] = customStyleCss[styleProp as CSSStyleDeclarationWritable];
}
}
const labelClasses = `${row.disabled ? 'disabled' : ''}`;
const labelElm = document.createElement('label');
if (labelClasses) {
Expand Down
15 changes: 14 additions & 1 deletion lib/src/interfaces/multipleSelectOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ export interface MultipleSelectView {
instance: any;
}

export type CSSStyleDeclarationReadonly =
| 'length'
| 'parentRule'
| 'getPropertyPriority'
| 'getPropertyValue'
| 'item'
| 'removeProperty'
| 'setProperty';
export type CSSStyleDeclarationWritable = keyof Omit<CSSStyleDeclaration, CSSStyleDeclarationReadonly>;

export interface MultipleSelectOption extends MultipleSelectLocale {
/** @deprecated @alias `displayTitle` Add a title. By default this option is set to false. */
addTitle?: boolean;
Expand Down Expand Up @@ -176,7 +186,10 @@ export interface MultipleSelectOption extends MultipleSelectLocale {
/** Customize the filter method, for example we use startWith */
customFilter(options: LabelFilter | TextFilter): boolean;

/** The item styler function, return style string to custom the item style such as background: red. The function take one parameter: value. */
/** The item styler function, return style string to customize the item style such as background: red. The function take one parameter: value. */
cssStyler?: (value: OptionRowData | OptGroupRowData) => CSSStyleDeclaration | null;

/** @deprecated @use `cssStyler`. The item styler function, return style string to customize the item style such as background: red. The function take one parameter: value. */
styler: (value: OptionRowData | OptGroupRowData) => string | boolean | null;

/** Returns HTML label attribute of a DOM element */
Expand Down
19 changes: 18 additions & 1 deletion playwright/e2e/options26.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test, expect } from '@playwright/test';

test.describe('Options 26 - The Styler', () => {
test.describe('Options 26 - The Styler / CSS Styler', () => {
test.beforeEach(async ({ page }) => {
await page.goto('#/options26');
});
Expand Down Expand Up @@ -32,4 +32,21 @@ test.describe('Options 26 - The Styler', () => {
const dropLoc2 = await page.locator('[data-test=select2] .ms-choice span', { hasText: '[Group 1: Option 1]' });
await dropLoc2.waitFor();
});

test('third select has February & April with custom CSS styler', async ({ page }) => {
await page.locator('[data-test=select3].ms-parent').click();
const optionLoc2 = await page.locator('[data-test=select3] .ms-drop ul li').nth(1);
optionLoc2.click();
expect(optionLoc2).toHaveText('February');
await expect(optionLoc2).toHaveCSS('color', 'rgb(0, 20, 255)');
await expect(optionLoc2).toHaveCSS('background-color', 'rgb(111, 190, 255)');

const optionLoc4 = await page.locator('[data-test=select3] .ms-drop ul li').nth(3);
optionLoc4.click();
expect(optionLoc4).toHaveText('April');
await expect(optionLoc4).toHaveCSS('color', 'rgb(255, 255, 255)');
await expect(optionLoc4).toHaveCSS('background-color', 'rgb(151, 39, 39)');
const selectedText3 = page.locator('[data-test=select3] .ms-choice span', { hasText: 'February, April' });
await selectedText3.waitFor();
});
});

0 comments on commit 8ad2b28

Please sign in to comment.