Skip to content

Commit 6829d5b

Browse files
authored
Merge branch 'master' into rkaraivanov/combo-navigation-refactor
2 parents 77d9171 + 2d23e42 commit 6829d5b

File tree

8 files changed

+140
-23
lines changed

8 files changed

+140
-23
lines changed

CHANGELOG.md

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,57 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7-
## [Unreleased]
7+
## [5.2.0] - 2025-01-09
88
### Added
99
- Form-associated elements now have a `defaultValue` property (`defaultChecked` for radio buttons, checkboxes, and switches). When a form is reset, components will use this property’s value as their new value or checked state.
1010

1111
### Changed
12-
- Calendar - allow passing a string value to the backing `value`, `values` and `activeDate` properties [#1467](https://github.com/IgniteUI/igniteui-webcomponents/issues/1467)
13-
- Date-time input - allow passing a string value to the backing `value`, `min` and `max` properties [#1467](https://github.com/IgniteUI/igniteui-webcomponents/issues/1467)
14-
- Date picker - allow passing a string value to the backing `value`, `min`, `max` and `activeDate` properties [#1467](https://github.com/IgniteUI/igniteui-webcomponents/issues/1467)
15-
- Component validation - aligned validation constraints to follow the behavior of their native HTML counterparts.
16-
For example, `minlength` will no longer trigger a `tooShort` validity state, unless there is text present in the component.
12+
- #### Calendar
13+
- enabled passing string values to the **value**, **values**, and **activeDate** properties [#1467](https://github.com/IgniteUI/igniteui-webcomponents/issues/1467)
14+
- #### Checkbox
15+
- updated style implementation and improved slotted checkbox styles [#1489](https://github.com/IgniteUI/igniteui-webcomponents/pull/1489)
16+
- #### Date-time input
17+
- enabled passing string values to the **value**, **min**, and **max** properties [#1467](https://github.com/IgniteUI/igniteui-webcomponents/issues/1467)
18+
- #### Date picker
19+
- enabled passing string values to the **value**, **min**, **max** and **activeDate** properties [#1467](https://github.com/IgniteUI/igniteui-webcomponents/issues/1467)
20+
- #### List
21+
- updated list item internal slots gaps and sizing [#1480](https://github.com/IgniteUI/igniteui-webcomponents/pull/1480)
22+
- #### Progressbar
23+
- the default value label animation now uses CSS counters and animations [#1492](https://github.com/IgniteUI/igniteui-webcomponents/pull/1492)
24+
- #### Validation
25+
- Updated validation constraints to align with the behavior of native HTML elements. For instance, the minlength attribute will now only trigger a tooShort validity state if the component contains a value.
1726

1827
### Fixed
19-
- Combo - Rendering issue after Edge browser autofill behavior [#1497](https://github.com/IgniteUI/igniteui-webcomponents/issues/1497)
28+
- #### Avatar
29+
- slotted icon size [#1504](https://github.com/IgniteUI/igniteui-webcomponents/pull/1504)
30+
- #### Badge
31+
- aligned colors with UI kits [#1466](https://github.com/IgniteUI/igniteui-webcomponents/pull/1466)
32+
- #### Card
33+
- actions content alignment in vertical orientation [#1472](https://github.com/IgniteUI/igniteui-webcomponents/pull/1472)
34+
- #### Combo
35+
- rendering issue after Edge browser autofill behavior [#1497](https://github.com/IgniteUI/igniteui-webcomponents/issues/1497)
36+
- #### Checkbox
37+
- removed extra gap between the checkbox and the label [#1479](https://github.com/IgniteUI/igniteui-webcomponents/pull/1479)
38+
- tick color in disabled state [#1528](https://github.com/IgniteUI/igniteui-webcomponents/pull/1528)
39+
- #### Dialog
40+
- removed vertical padding in Bootstrap theme [#1471](https://github.com/IgniteUI/igniteui-webcomponents/pull/1471)
41+
- Fluent theme typography [#1475](https://github.com/IgniteUI/igniteui-webcomponents/pull/1475)
42+
- #### Dropdown
43+
- remove vertical padding in Bootstrap theme [#1471](https://github.com/IgniteUI/igniteui-webcomponents/pull/1471)
44+
- #### Input
45+
- input type search does not interfere with the outline variant in Material theme [#1520](https://github.com/IgniteUI/igniteui-webcomponents/pull/1520)
46+
- step validation for numeric input [#1522](https://github.com/IgniteUI/igniteui-webcomponents/pull/1522)
47+
- helper-text color in invalid state [#1525](https://github.com/IgniteUI/igniteui-webcomponents/pull/1525)
48+
- #### List
49+
- discrepancies between the list and the UI kits [#1488](https://github.com/IgniteUI/igniteui-webcomponents/pull/1488)
50+
- #### Radio
51+
- remove label part when there is not slotted content [#1482](https://github.com/IgniteUI/igniteui-webcomponents/pull/1482)
52+
- #### Textarea
53+
- label position in Material theme [#1518](https://github.com/IgniteUI/igniteui-webcomponents/pull/1518)
54+
- helper-text color in disabled state [#1519](https://github.com/IgniteUI/igniteui-webcomponents/pull/1519)
55+
- remove layout space for hidden content in prefix/suffix slots [#1526](https://github.com/IgniteUI/igniteui-webcomponents/pull/1526)
56+
- #### Icon service
57+
- reduce sync events between copies of the service in different tabs [#1532](https://github.com/IgniteUI/igniteui-webcomponents/pull/1532)
2058

2159
## [5.1.2] - 2024-11-04
2260
### Added
@@ -623,6 +661,7 @@ Initial release of Ignite UI Web Components
623661
- Ripple component
624662
- Switch component
625663

664+
[5.2.0]: https://github.com/IgniteUI/igniteui-webcomponents/compare/5.1.2...5.2.0
626665
[5.1.2]: https://github.com/IgniteUI/igniteui-webcomponents/compare/5.1.1...5.1.2
627666
[5.1.1]: https://github.com/IgniteUI/igniteui-webcomponents/compare/5.1.0...5.1.1
628667
[5.1.0]: https://github.com/IgniteUI/igniteui-webcomponents/compare/5.0.2...5.1.0

src/components/common/util.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ export const asPercent = (part: number, whole: number) => (part / whole) * 100;
1515
export const clamp = (number: number, min: number, max: number) =>
1616
Math.max(min, Math.min(number, max));
1717

18+
export function numberOfDecimals(number: number): number {
19+
const decimals = last(number.toString().split('.'));
20+
return decimals ? decimals.length : 0;
21+
}
22+
23+
export function roundPrecise(number: number, magnitude = 1): number {
24+
const factor = 10 ** magnitude;
25+
return Math.round(number * factor) / factor;
26+
}
27+
1828
export function numberInRangeInclusive(
1929
value: number,
2030
min: number,

src/components/common/validators.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { DateTimeUtil } from '../date-time-input/date-util.js';
22
import validatorMessages from './localization/validation-en.js';
3-
import { asNumber, formatString, isDefined } from './util.js';
3+
import {
4+
asNumber,
5+
formatString,
6+
isDefined,
7+
numberOfDecimals,
8+
roundPrecise,
9+
} from './util.js';
410

511
type ValidatorHandler<T> = (host: T) => boolean;
612
type ValidatorMessageFormat<T> = (host: T) => string;
@@ -93,10 +99,20 @@ export const stepValidator: Validator<{
9399
}> = {
94100
key: 'stepMismatch',
95101
message: 'Value does not conform to step constraint',
96-
isValid: ({ min, step, value }) =>
97-
isDefined(value) && value !== '' && isDefined(step)
98-
? (asNumber(value) - asNumber(min)) % asNumber(step, 1) === 0
99-
: true,
102+
isValid: ({ min, step, value }) => {
103+
if (isDefined(value) && value !== '' && isDefined(step)) {
104+
const _value = asNumber(value) - asNumber(min);
105+
const _step = asNumber(step);
106+
const magnitude = numberOfDecimals(_step) + 1;
107+
const rem = roundPrecise(
108+
Math.abs(_value - _step * Math.round(_value / _step)),
109+
magnitude
110+
);
111+
112+
return !rem;
113+
}
114+
return true;
115+
},
100116
};
101117

102118
export const emailValidator: Validator<{ value: string }> = {

src/components/icon/icon-state.broadcast.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export class IconsStateBroadcast {
1111
private channel!: BroadcastChannel | null;
1212
private collections: IconsCollection<SvgIcon>;
1313
private refsCollection: IconsCollection<IconMeta>;
14+
private static readonly origin = 'igniteui-webcomponents';
1415

1516
constructor(
1617
collections: IconsCollection<SvgIcon>,
@@ -31,14 +32,19 @@ export class IconsStateBroadcast {
3132
}
3233

3334
public handleEvent({ data }: MessageEvent<BroadcastIconsChangeMessage>) {
34-
if (data.actionType !== ActionType.SyncState) {
35+
// no need to sync with other wc icon services, just with angular elements
36+
if (
37+
data.actionType !== ActionType.SyncState ||
38+
data.origin === IconsStateBroadcast.origin
39+
) {
3540
return;
3641
}
3742

3843
this.send({
3944
actionType: ActionType.SyncState,
4045
collections: this.getUserSetCollection(this.collections).toMap(),
4146
references: this.getUserRefsCollection(this.refsCollection).toMap(),
47+
origin: IconsStateBroadcast.origin,
4248
});
4349
}
4450

src/components/icon/icon.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
aTimeout,
23
elementUpdated,
34
expect,
45
fixture,
@@ -9,13 +10,15 @@ import { stub } from 'sinon';
910

1011
import { defineComponents } from '../common/definitions/defineComponents.js';
1112
import { first, last } from '../common/util.js';
13+
import { IconsStateBroadcast } from './icon-state.broadcast.js';
1214
import IgcIconComponent from './icon.js';
1315
import {
1416
getIconRegistry,
1517
registerIcon,
1618
registerIconFromText,
1719
setIconRef,
1820
} from './icon.registry.js';
21+
import { createIconDefaultMap } from './registry/default-map.js';
1922
import {
2023
ActionType,
2124
type BroadcastIconsChangeMessage,
@@ -251,6 +254,31 @@ describe('Icon broadcast service', () => {
251254

252255
expect(events.length).to.equal(0);
253256
});
257+
258+
it('when multiple broadcast services are initialized they should not send sync events to each other.', async () => {
259+
const collections = createIconDefaultMap<string, SvgIcon>();
260+
const references = createIconDefaultMap<string, IconMeta>();
261+
// 2 new broadcasts
262+
const broadcast1 = new IconsStateBroadcast(collections, references);
263+
const broadcast2 = new IconsStateBroadcast(collections, references);
264+
// 1 global one, initialized when you get the icon registry first time.
265+
const iconReg = getIconRegistry();
266+
// total - 3 services now.
267+
268+
// a peer is requesting a state sync
269+
channel.postMessage({ actionType: ActionType.SyncState });
270+
await aTimeout(20);
271+
272+
// all icon broadcasts must respond with their state
273+
// 2 from broadcast service + 1 from global.
274+
expect(events.length).to.equal(3);
275+
276+
// dispose of mock services.
277+
// biome-ignore lint/complexity/useLiteralKeys: private access escape
278+
broadcast1['dispose']();
279+
// biome-ignore lint/complexity/useLiteralKeys: private access escape
280+
broadcast2['dispose']();
281+
});
254282
});
255283

256284
describe('Peer registry', () => {

src/components/icon/registry/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export interface BroadcastIconsChangeMessage {
3535
actionType: ActionType;
3636
collections?: Map<string, Map<string, SvgIcon>>;
3737
references?: Map<string, Map<string, IconMeta>>;
38+
origin?: string;
3839
}
3940

4041
// Exported public types

src/components/input/input.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,30 @@ describe('Input component', () => {
356356
});
357357
});
358358

359+
describe('issue-1521', () => {
360+
let input: IgcInputComponent;
361+
362+
beforeEach(async () => {
363+
input = await fixture<IgcInputComponent>(html`
364+
<igc-input type="number" step="0.1"></igc-input>
365+
`);
366+
});
367+
368+
it('', () => {
369+
input.value = '1';
370+
expect(input.checkValidity()).to.be.true;
371+
372+
input.value = '1.1';
373+
expect(input.checkValidity()).to.be.true;
374+
375+
input.value = '1.11';
376+
expect(input.checkValidity()).to.be.false;
377+
378+
input.step = 0.01;
379+
expect(input.checkValidity()).to.be.true;
380+
});
381+
});
382+
359383
describe('Form integration', () => {
360384
const spec = createFormAssociatedTestBed<IgcInputComponent>(
361385
html`<igc-input name="input"></igc-input>`

src/components/rating/rating.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import {
3535
formatString,
3636
isEmpty,
3737
isLTR,
38+
numberOfDecimals,
39+
roundPrecise,
3840
} from '../common/util.js';
3941
import IgcIconComponent from '../icon/icon.js';
4042
import IgcRatingSymbolComponent from './rating-symbol.js';
@@ -328,17 +330,8 @@ export default class IgcRatingComponent extends FormAssociatedMixin(
328330
return clamp(value, this.step, this.max);
329331
}
330332

331-
protected getPrecision(num: number) {
332-
const [_, decimal] = num.toString().split('.');
333-
return decimal ? decimal.length : 0;
334-
}
335-
336333
protected round(value: number) {
337-
return Number(
338-
(Math.round(value / this.step) * this.step).toFixed(
339-
this.getPrecision(this.step)
340-
)
341-
);
334+
return roundPrecise(value, numberOfDecimals(this.step));
342335
}
343336

344337
protected clipSymbol(index: number, isLTR = true) {

0 commit comments

Comments
 (0)