Skip to content

Commit b85b54d

Browse files
authored
feat: update to UI5 Web Components 2.10.0 (#7308)
1 parent 5b75245 commit b85b54d

File tree

53 files changed

+1627
-451
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1627
-451
lines changed

.storybook/custom-element-manifests/fiori.json

Lines changed: 584 additions & 67 deletions
Large diffs are not rendered by default.

.storybook/custom-element-manifests/main.json

Lines changed: 346 additions & 53 deletions
Large diffs are not rendered by default.

config/version-info.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@
5151
"2.6.0": "2.6.2",
5252
"2.7.0": "2.7.0",
5353
"2.8.0": "2.8.0",
54-
"2.9.0": "2.9.0"
54+
"2.9.0": "2.9.0",
55+
"2.10.0": "2.10.0"
5556
}

docs/knowledge-base/ChangeEvents.mdx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,9 @@ const onSelectionChange = (event) => {
4646
};
4747

4848
<List mode={ListSelectionMode.MultiSelect} onSelectionChange={onSelectionChange}>
49-
<ListItemStandard additionalText="3" data-custom="custom value of list item 1">
50-
List Item 1
51-
</ListItemStandard>
52-
<ListItemStandard additionalText="2" data-custom="custom value of list item 2">
53-
List Item 2
54-
</ListItemStandard>
55-
<ListItemStandard additionalText="1" data-custom="custom value of list item 3">
56-
List Item 3
57-
</ListItemStandard>
49+
<ListItemStandard additionalText="3" data-custom="custom value of list item 1" text="List Item 1" />
50+
<ListItemStandard additionalText="2" data-custom="custom value of list item 2" text="List Item 2" />
51+
<ListItemStandard additionalText="1" data-custom="custom value of list item 3" text="List Item 3" />
5852
</List>;
5953
```
6054

docs/knowledge-base/Styling.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ function MyComponent() {
163163
className="card"
164164
>
165165
<List>
166-
<ListItemStandard description="Software Architect">Richard Wilson</ListItemStandard>
167-
<ListItemStandard description="Visual Designer">Elena Petrova</ListItemStandard>
168-
<ListItemStandard description="Quality Specialist">John Miller</ListItemStandard>
166+
<ListItemStandard description="Software Architect" text="Richard Wilson" />
167+
<ListItemStandard description="Visual Designer" text="Elena Petrova" />
168+
<ListItemStandard description="Quality Specialist" text="John Miller" />
169169
</List>
170170
</Card>
171171
);

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@
4343
"@storybook/react": "8.6.12",
4444
"@storybook/react-vite": "8.6.12",
4545
"@storybook/theming": "8.6.12",
46-
"@ui5/webcomponents": "2.9.0",
47-
"@ui5/webcomponents-ai": "2.9.0",
48-
"@ui5/webcomponents-compat": "2.9.0",
49-
"@ui5/webcomponents-fiori": "2.9.0",
50-
"@ui5/webcomponents-icons": "2.9.0",
46+
"@ui5/webcomponents": "2.10.0",
47+
"@ui5/webcomponents-ai": "2.10.0",
48+
"@ui5/webcomponents-compat": "2.10.0",
49+
"@ui5/webcomponents-fiori": "2.10.0",
50+
"@ui5/webcomponents-icons": "2.10.0",
5151
"react": "^19.0.0",
5252
"react-dom": "^19.0.0",
5353
"remark-gfm": "^4.0.0",
@@ -69,7 +69,7 @@
6969
"@types/node": "^22.0.0",
7070
"@types/react": "^19.0.1",
7171
"@types/react-dom": "^19.0.1",
72-
"@ui5/webcomponents-tools": "2.9.0",
72+
"@ui5/webcomponents-tools": "2.10.0",
7373
"@vitejs/plugin-react": "^4.2.0",
7474
"chromatic": "^11.0.0",
7575
"cssnano": "^7.0.0",

packages/ai/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"@ui5/webcomponents-react-base": "workspace:~"
3434
},
3535
"peerDependencies": {
36-
"@ui5/webcomponents-ai": "~2.9.0",
36+
"@ui5/webcomponents-ai": "~2.10.0",
3737
"react": "^18 || ^19"
3838
},
3939
"publishConfig": {

packages/base/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
},
3333
"peerDependencies": {
3434
"@types/react": "*",
35-
"@ui5/webcomponents-base": "~2.9.0",
35+
"@ui5/webcomponents-base": "~2.10.0",
3636
"react": "^18 || ^19"
3737
},
3838
"peerDependenciesMeta": {

packages/charts/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
"recharts": "2.15.3"
4040
},
4141
"peerDependencies": {
42-
"@ui5/webcomponents-react": "~2.9.0",
43-
"@ui5/webcomponents-react-base": "~2.9.0",
42+
"@ui5/webcomponents-react": "~2.10.0",
43+
"@ui5/webcomponents-react-base": "~2.10.0",
4444
"react": "^18 || ^19"
4545
},
4646
"publishConfig": {

packages/compat/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
"peerDependencies": {
4242
"@types/react": "*",
4343
"@types/react-dom": "*",
44-
"@ui5/webcomponents-compat": "~2.9.0",
45-
"@ui5/webcomponents-react": "~2.9.0",
44+
"@ui5/webcomponents-compat": "~2.10.0",
45+
"@ui5/webcomponents-react": "~2.10.0",
4646
"react": "^18 || ^19",
4747
"react-dom": "^18 || ^19"
4848
},

packages/cypress-commands/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
"clean": "rimraf dist api-commands.json api-queries.json"
2424
},
2525
"peerDependencies": {
26-
"@ui5/webcomponents": "~2.9.0",
27-
"@ui5/webcomponents-base": "~2.9.0",
26+
"@ui5/webcomponents": "~2.10.0",
27+
"@ui5/webcomponents-base": "~2.10.0",
2828
"cypress": "^12 || ^13 || ^14"
2929
},
3030
"peerDependenciesMeta": {

packages/cypress-commands/test/UI5WebComponentsChild.cy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ describe('UI5 Web Components - Child Commands', () => {
125125
it('click list item', () => {
126126
cy.mount(
127127
<List selectionMode="Multiple">
128-
<ListItemStandard data-testid="s">ListItemStandard</ListItemStandard>
128+
<ListItemStandard data-testid="s" text="ListItemStandard" />
129129
<ListItemCustom data-testid="c">ListItemCustom</ListItemCustom>
130130
</List>
131131
);

packages/main/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@
5757
"peerDependencies": {
5858
"@types/react": "*",
5959
"@types/react-dom": "*",
60-
"@ui5/webcomponents": "~2.9.0",
61-
"@ui5/webcomponents-base": "~2.9.0",
62-
"@ui5/webcomponents-fiori": "~2.9.0",
63-
"@ui5/webcomponents-icons": "~2.9.0",
60+
"@ui5/webcomponents": "~2.10.0",
61+
"@ui5/webcomponents-base": "~2.10.0",
62+
"@ui5/webcomponents-fiori": "~2.10.0",
63+
"@ui5/webcomponents-icons": "~2.10.0",
6464
"react": "^18 || ^19",
6565
"react-dom": "^18 || ^19"
6666
},

packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -111,21 +111,21 @@ describe('AnalyticalTable', () => {
111111

112112
cy.findByText('Name').click();
113113
cy.get('[ui5-popover]').should('be.visible');
114-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
114+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
115115
cy.get('@onSortSpy').should('have.been.calledWithMatch', {
116116
detail: { column: { id: 'name' }, sortDirection: 'asc' }
117117
});
118118
cy.get('[aria-rowindex="3"] > [aria-colindex="1"]').should('text', 'C');
119119

120120
cy.findByText('Name').click();
121-
cy.findByText('Clear Sorting').shadow().findByRole('listitem').click({ force: true });
121+
cy.get('[ui5-list]').clickUi5ListItemByText('Clear Sorting');
122122
cy.get('@onSortSpy').should('have.been.calledWithMatch', {
123123
detail: { column: { id: 'name' }, sortDirection: 'clear' }
124124
});
125125
cy.get('[aria-rowindex="3"] > [aria-colindex="1"]').should('text', 'X');
126126

127127
cy.findByText('Name').click();
128-
cy.findByText('Sort Descending').shadow().findByRole('listitem').click({ force: true });
128+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Descending');
129129
cy.get('@onSortSpy').should('have.been.calledWithMatch', {
130130
detail: { column: { id: 'name' }, sortDirection: 'desc' }
131131
});
@@ -873,7 +873,7 @@ describe('AnalyticalTable', () => {
873873
cy.findByTestId('isSelected').should('have.text', 'true');
874874

875875
cy.findByText('Friend Name').click();
876-
cy.findByText('Group').realClick();
876+
cy.get('[ui5-list]').clickUi5ListItemByText('Group');
877877
cy.focused()
878878
.should('have.attr', 'data-row-index', '0')
879879
.and('have.attr', 'data-column-index', '2')
@@ -894,7 +894,7 @@ describe('AnalyticalTable', () => {
894894
cy.findByTestId('isSelected').should('have.text', 'false');
895895

896896
cy.findByText('Friend Name').click();
897-
cy.findByText('Ungroup').realClick();
897+
cy.get('[ui5-list]').clickUi5ListItemByText('Ungroup');
898898
cy.focused()
899899
.should('have.attr', 'data-row-index', '0')
900900
.and('have.attr', 'data-column-index', '3')
@@ -1560,7 +1560,7 @@ describe('AnalyticalTable', () => {
15601560

15611561
testAlternateRowColor();
15621562
cy.findByText('Name').click();
1563-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
1563+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
15641564
testAlternateRowColor();
15651565
});
15661566

@@ -2336,22 +2336,22 @@ describe('AnalyticalTable', () => {
23362336
cy.get('[data-visible-row-index="1"][data-visible-column-index="1"]').should('have.attr', 'aria-label', 'Age 40 ');
23372337

23382338
cy.findByText('Name').click();
2339-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2339+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
23402340
cy.get('[data-column-id="name"]').should('have.attr', 'aria-sort', 'ascending');
23412341
cy.findByText('Name').click();
2342-
cy.findByText('Clear Sorting').shadow().findByRole('listitem').click({ force: true });
2342+
cy.get('[ui5-list]').clickUi5ListItemByText('Clear Sorting');
23432343
cy.get('[data-column-id="name"]').should('not.have.attr', 'aria-sort');
23442344
cy.findByText('Name').click();
2345-
cy.findByText('Sort Descending').shadow().findByRole('listitem').click({ force: true });
2345+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Descending');
23462346
cy.get('[data-column-id="name"]').should('have.attr', 'aria-sort', 'descending');
23472347
cy.findByText('Name').click();
2348-
cy.findByText('Sort Ascending').shadow().get('[ui5-input]').typeIntoUi5Input('A{enter}');
2348+
cy.get('[text="Sort Ascending"]').shadow().get('[ui5-input]').typeIntoUi5Input('A{enter}');
23492349
cy.get('[data-column-id="name"]')
23502350
.should('have.attr', 'aria-sort', 'descending')
23512351
.and('have.attr', 'aria-label', 'Filtered');
23522352

23532353
cy.findByText('Name').click();
2354-
cy.findByText('Group').shadow().findByRole('listitem').click({ force: true });
2354+
cy.get('[ui5-list]').clickUi5ListItemByText('Group');
23552355
cy.get('[data-column-id="name"]')
23562356
.should('have.attr', 'aria-sort', 'descending')
23572357
.and('have.attr', 'aria-label', 'Filtered Grouped');
@@ -2367,14 +2367,14 @@ describe('AnalyticalTable', () => {
23672367
'Name A Grouped, To collapse the row, press the spacebar.'
23682368
);
23692369
cy.findByText('Name').click();
2370-
cy.findByText('Ungroup').shadow().findByRole('listitem').click({ force: true });
2370+
cy.get('[ui5-list]').clickUi5ListItemByText('Ungroup');
23712371
cy.get('[data-visible-row-index="1"][data-visible-column-index="0"]').should('have.attr', 'aria-label', 'Name A ');
23722372
cy.get('[data-column-id="name"]')
23732373
.should('have.attr', 'aria-sort', 'descending')
23742374
.and('have.attr', 'aria-label', 'Filtered');
23752375

23762376
cy.findByText('Name').click();
2377-
cy.findByText('Sort Ascending').shadow().get('[ui5-input]').typeIntoUi5Input('{selectall}{backspace}{enter}');
2377+
cy.get('[text="Sort Ascending"]').shadow().get('[ui5-input]').typeIntoUi5Input('{selectall}{backspace}{enter}');
23782378
cy.get('[data-column-id="name"]').should('have.attr', 'aria-sort', 'descending').and('have.attr', 'aria-label', '');
23792379

23802380
cy.get('[data-column-id="friend.age"]').should('have.attr', 'aria-label', 'Custom Label ');
@@ -2436,7 +2436,7 @@ describe('AnalyticalTable', () => {
24362436

24372437
cy.mount(<AnalyticalTable data={[...data, ...data]} columns={columns} visibleRows={5} groupable />);
24382438
cy.findByText('Name').click();
2439-
cy.findByText('Group').realClick();
2439+
cy.get('[ui5-list]').clickUi5ListItemByText('Group');
24402440
cy.findByText('A (2)').trigger('keydown', {
24412441
key: 'Enter'
24422442
});
@@ -2522,9 +2522,9 @@ describe('AnalyticalTable', () => {
25222522

25232523
//sort both Name and Age (multi-sort enabled)
25242524
cy.findByText('Name').click();
2525-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2525+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
25262526
cy.findByText('Age').click();
2527-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2527+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
25282528

25292529
cy.get('[data-column-index="0"][data-row-index="1"]').children().should('have.text', 'A');
25302530
cy.get('[data-column-index="1"][data-row-index="1"]').children().should('have.text', '30');
@@ -2545,7 +2545,7 @@ describe('AnalyticalTable', () => {
25452545

25462546
//only sort Name2
25472547
cy.findByText('Name 2').click();
2548-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2548+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
25492549

25502550
cy.get('[data-column-index="0"][data-row-index="1"]').children().should('have.text', 'B');
25512551
cy.get('[data-column-index="1"][data-row-index="1"]').children().should('have.text', '60');
@@ -2753,7 +2753,7 @@ describe('AnalyticalTable', () => {
27532753
cy.findByText('Aggregated').should('not.exist');
27542754

27552755
cy.findByText('Name').click();
2756-
cy.findByText('Group').realClick();
2756+
cy.get('[ui5-list]').clickUi5ListItemByText('Group');
27572757
cy.findByText('Simon').should('be.visible').should('have.length', 1);
27582758
cy.findAllByText('Aggregated').should('be.visible').should('have.length', 2);
27592759
cy.get('[ui5-icon][name="navigation-right-arrow"]').should('be.visible').should('have.length', 2);
@@ -2815,17 +2815,17 @@ describe('AnalyticalTable', () => {
28152815

28162816
cy.mount(<TestComponent orderedIds={['name', 'name2', 'age', 'age2']} />);
28172817
cy.findByText('Age').click();
2818-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2818+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
28192819
cy.findByText('Name').click();
2820-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2820+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
28212821

28222822
cy.get('[data-visible-row-index="1"][data-visible-column-index="0"]').should('have.text', 'Graham');
28232823
cy.get('[data-visible-row-index="1"][data-visible-column-index="1"]').should('have.text', '40');
28242824
cy.get('[data-visible-row-index="5"][data-visible-column-index="0"]').should('have.text', 'Kristen');
28252825
cy.get('[data-visible-row-index="5"][data-visible-column-index="1"]').should('have.text', '20');
28262826

28272827
cy.findByText('Name 2').click();
2828-
cy.findByText('Sort Descending').shadow().findByRole('listitem').click({ force: true });
2828+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Descending');
28292829

28302830
cy.get('[data-visible-row-index="1"][data-visible-column-index="0"]').should('have.text', 'Graham');
28312831
cy.get('[data-visible-row-index="1"][data-visible-column-index="1"]').should('have.text', '62');
@@ -2835,7 +2835,7 @@ describe('AnalyticalTable', () => {
28352835
cy.get('[data-visible-row-index="5"][data-visible-column-index="2"]').should('have.text', 'Willis');
28362836

28372837
cy.findByText('Name 2').click();
2838-
cy.findByText('Clear Sorting').shadow().findByRole('listitem').click({ force: true });
2838+
cy.get('[ui5-list]').clickUi5ListItemByText('Clear Sorting');
28392839

28402840
cy.get('[data-visible-row-index="1"][data-visible-column-index="0"]').should('have.text', 'Graham');
28412841
cy.get('[data-visible-row-index="1"][data-visible-column-index="1"]').should('have.text', '40');
@@ -2844,17 +2844,17 @@ describe('AnalyticalTable', () => {
28442844

28452845
cy.mount(<TestComponent orderedIds={['name2']} />);
28462846
cy.findByText('Age').click();
2847-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2847+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
28482848
cy.findByText('Name').click();
2849-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2849+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
28502850

28512851
cy.get('[data-visible-row-index="1"][data-visible-column-index="0"]').should('have.text', 'Kristen');
28522852
cy.get('[data-visible-row-index="1"][data-visible-column-index="1"]').should('have.text', '20');
28532853
cy.get('[data-visible-row-index="5"][data-visible-column-index="0"]').should('have.text', 'Peter');
28542854
cy.get('[data-visible-row-index="5"][data-visible-column-index="1"]').should('have.text', '40');
28552855

28562856
cy.findByText('Age 2').click();
2857-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2857+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
28582858

28592859
cy.get('[data-visible-row-index="1"][data-visible-column-index="0"]').should('have.text', 'Kristen');
28602860
cy.get('[data-visible-row-index="1"][data-visible-column-index="1"]').should('have.text', '20');
@@ -2864,7 +2864,7 @@ describe('AnalyticalTable', () => {
28642864
cy.get('[data-visible-row-index="5"][data-visible-column-index="3"]').should('have.text', '18');
28652865

28662866
cy.findByText('Name 2').click();
2867-
cy.findByText('Sort Ascending').shadow().findByRole('listitem').click({ force: true });
2867+
cy.get('[ui5-list]').clickUi5ListItemByText('Sort Ascending');
28682868
cy.get('[data-visible-row-index="1"][data-visible-column-index="0"]').should('have.text', 'Kristen');
28692869
cy.get('[data-visible-row-index="1"][data-visible-column-index="1"]').should('have.text', '20');
28702870
cy.get('[data-visible-row-index="1"][data-visible-column-index="2"]').should('have.text', 'Alissa');

packages/main/src/components/AnalyticalTable/defaults/Column/ColumnHeaderModal.tsx

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -195,24 +195,26 @@ export const ColumnHeaderModal = (instance: TableInstanceWithPopoverProps) => {
195195
data-component-name="ATHeaderPopoverList"
196196
>
197197
{isSortedAscending && (
198-
<ListItemStandard type={ListItemType.Active} icon={iconDecline} data-sort="clear">
199-
{clearSortingText}
200-
</ListItemStandard>
198+
<ListItemStandard type={ListItemType.Active} icon={iconDecline} data-sort="clear" text={clearSortingText} />
201199
)}
202200
{showSort && !isSortedAscending && (
203-
<ListItemStandard type={ListItemType.Active} icon={iconSortAscending} data-sort="asc">
204-
{sortAscendingText}
205-
</ListItemStandard>
201+
<ListItemStandard
202+
type={ListItemType.Active}
203+
icon={iconSortAscending}
204+
data-sort="asc"
205+
text={sortAscendingText}
206+
/>
206207
)}
207208
{showSort && !isSortedDescending && (
208-
<ListItemStandard type={ListItemType.Active} icon={iconSortDescending} data-sort="desc">
209-
{sortDescendingText}
210-
</ListItemStandard>
209+
<ListItemStandard
210+
type={ListItemType.Active}
211+
icon={iconSortDescending}
212+
data-sort="desc"
213+
text={sortDescendingText}
214+
/>
211215
)}
212216
{isSortedDescending && (
213-
<ListItemStandard type={ListItemType.Active} icon={iconDecline} data-sort="clear">
214-
{clearSortingText}
215-
</ListItemStandard>
217+
<ListItemStandard type={ListItemType.Active} icon={iconDecline} data-sort="clear" text={clearSortingText} />
216218
)}
217219
{showFilter && (
218220
<ListItemCustom type={ListItemType.Inactive} onKeyDown={handleCustomLiKeyDown} accessibleName={filterText}>
@@ -244,9 +246,12 @@ export const ColumnHeaderModal = (instance: TableInstanceWithPopoverProps) => {
244246
</ListItemCustom>
245247
)}
246248
{showGroup && (
247-
<ListItemStandard type={ListItemType.Active} icon={iconGroup} data-sort={'group'}>
248-
{column.isGrouped ? ungroupText : groupText}
249-
</ListItemStandard>
249+
<ListItemStandard
250+
type={ListItemType.Active}
251+
icon={iconGroup}
252+
data-sort={'group'}
253+
text={column.isGrouped ? ungroupText : groupText}
254+
/>
250255
)}
251256
</List>
252257
</Popover>

0 commit comments

Comments
 (0)