Skip to content

Commit 8cfb531

Browse files
authored
fix(accordion): toggle api (#1286)
1 parent f966268 commit 8cfb531

File tree

4 files changed

+80
-65
lines changed

4 files changed

+80
-65
lines changed

core/src/components/accordion/accordion.spec.ts

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ function createItems(accordion: AccordionWidget, n = 3): AccordionItemWidget[] {
1818
for (let i = 0; i < n; i++) {
1919
items.push(accordion.api.registerItem());
2020
}
21-
items.forEach((i) => i.directives.itemDirective(el));
21+
items.forEach((i) => {
22+
i.directives.itemDirective(el);
23+
i.directives.bodyContainerDirective(el);
24+
});
2225
return items;
2326
}
2427

@@ -125,38 +128,44 @@ describe(`Accordion`, () => {
125128
button.click();
126129
});
127130

128-
test(`should expand all the items and close them`, () => {
131+
test(`should expand all the items and close them`, async () => {
129132
const el = document.createElement('div');
130-
accordion.api.registerItem().directives.itemDirective(el);
131-
accordion.api.registerItem().directives.itemDirective(el);
132-
accordion.api.registerItem().directives.itemDirective(el);
133+
const item1 = accordion.api.registerItem();
134+
const item2 = accordion.api.registerItem();
135+
const item3 = accordion.api.registerItem();
136+
item1.directives.itemDirective(el);
137+
item1.directives.bodyContainerDirective(el);
138+
item2.directives.itemDirective(el);
139+
item2.directives.bodyContainerDirective(el);
140+
item3.directives.itemDirective(el);
141+
item3.directives.bodyContainerDirective(el);
133142
expectOpenItems(state, [false, false, false]);
134-
accordion.api.expandAll();
143+
await accordion.api.expandAll();
135144
expectOpenItems(state, [true, true, true]);
136-
accordion.api.collapseAll();
145+
await accordion.api.collapseAll();
137146
expectOpenItems(state, [false, false, false]);
138147
});
139148

140-
test(`should toggle items from accordion api`, () => {
149+
test(`should toggle items from accordion api`, async () => {
141150
const items = createItems(accordion);
142151
const itemIds = items.map((i) => i.state$().id);
143152
expectOpenItems(state, [false, false, false]);
144-
accordion.api.expand(itemIds[0]);
145-
accordion.api.expand(itemIds[2]);
153+
await accordion.api.expand(itemIds[0]);
154+
await accordion.api.expand(itemIds[2]);
146155
expectOpenItems(state, [true, false, true]);
147-
accordion.api.toggle(itemIds[1]);
148-
accordion.api.collapse(itemIds[2]);
156+
await accordion.api.toggle(itemIds[1]);
157+
await accordion.api.collapse(itemIds[2]);
149158
expectOpenItems(state, [true, true, false]);
150159
});
151160

152-
test(`should toggle items with item api`, () => {
161+
test(`should toggle items with item api`, async () => {
153162
const items = createItems(accordion);
154163
expectOpenItems(state, [false, false, false]);
155-
items[0].api.expand();
156-
items[2].api.expand();
164+
await items[0].api.expand();
165+
await items[2].api.expand();
157166
expectOpenItems(state, [true, false, true]);
158-
items[1].api.toggle();
159-
items[2].api.collapse();
167+
await items[1].api.toggle();
168+
await items[2].api.collapse();
160169
expectOpenItems(state, [true, true, false]);
161170
});
162171

@@ -167,12 +176,12 @@ describe(`Accordion`, () => {
167176
i.directives.bodyContainerDirective(element);
168177
expectOpenItems(state, [false]);
169178
//calling it twice to ensure only one event is fired
170-
i.api.toggle();
171-
i.api.expand();
179+
void i.api.toggle();
180+
void i.api.expand();
172181
await promiseOnShownItem.promise;
173182
expectOpenItems(state, [true]);
174-
i.api.toggle();
175-
i.api.collapse();
183+
void i.api.toggle();
184+
void i.api.collapse();
176185
await promiseOnHiddenItem.promise;
177186
expectOpenItems(state, [false]);
178187
expect(itemShown).toBe(1);
@@ -188,10 +197,10 @@ describe(`Accordion`, () => {
188197
bodyContainerDirective(element);
189198
itemDirective(element);
190199
expectOpenItems(state, [false]);
191-
accordion.api.toggle(id$());
192-
accordion.api.expand(id$());
200+
void accordion.api.toggle(id$());
201+
void accordion.api.expand(id$());
193202
await promiseOnShown.promise;
194-
accordion.api.collapse(id$());
203+
void accordion.api.collapse(id$());
195204
await promiseOnHidden.promise;
196205
expect(showns).toMatchObject([id$()]);
197206
expect(hiddens).toMatchObject([id$()]);
@@ -208,7 +217,7 @@ describe(`Accordion`, () => {
208217
expectOpenItems(state, [true, true, false]);
209218
});
210219

211-
test(`should close the old item if closeOthers`, () => {
220+
test(`should close the old item if closeOthers`, async () => {
212221
const element = document.createElement('div');
213222
accordion.directives.accordionDirective(element);
214223
const items = createItems(accordion, 2);
@@ -220,11 +229,11 @@ describe(`Accordion`, () => {
220229
expectOpenItems(state, [true, false]);
221230

222231
// item api
223-
items[1].api.expand();
232+
await items[1].api.expand();
224233
expectOpenItems(state, [false, true]);
225234

226235
// accordion api
227-
accordion.api.expand(items[0].state$().id);
236+
await accordion.api.expand(items[0].state$().id);
228237
expectOpenItems(state, [true, false]);
229238
});
230239

@@ -241,40 +250,42 @@ describe(`Accordion`, () => {
241250
expectOpenItems(state, [false, true, false, false]);
242251
});
243252

244-
test(`should have correct value for shouldBeInDOM`, () => {
253+
test(`should have correct value for shouldBeInDOM`, async () => {
254+
const el = document.createElement('div');
245255
const i = accordion.api.registerItem({props: {visible: true}});
256+
i.directives.bodyContainerDirective(el);
246257
expect(i.state$().shouldBeInDOM).toBe(true);
247-
i.api.collapse();
258+
await i.api.collapse();
248259
expect(i.state$().shouldBeInDOM).toBe(false);
249260
i.patch({destroyOnHide: false});
250261
expect(i.state$().shouldBeInDOM).toBe(true);
251262
});
252263

253-
test(`should closeOthers work when oldOpen is undefined`, () => {
264+
test(`should closeOthers work when oldOpen is undefined`, async () => {
254265
const element = document.createElement('div');
255266
accordion.directives.accordionDirective(element);
256267
const items = createItems(accordion, 4);
257-
items[0].api.expand();
258-
items[1].api.expand();
268+
await items[0].api.expand();
269+
await items[1].api.expand();
259270
expectOpenItems(state, [true, true, false, false]);
260271
//oldOpenItem is undefined because initially openItems was [] and the first value of
261272
//oldOpenItem is openItems[0]
262273
accordion.patch({closeOthers: true});
263274
expectOpenItems(state, [false, true, false, false]);
264275
});
265276

266-
test(`should call initDone to enable the transition on item`, () => {
277+
test(`should call initDone to enable the transition on item`, async () => {
267278
const el = document.createElement('div');
268279
const transition = vi.fn();
269280
const itemWidget = accordion.api.registerItem({props: {transition}});
270281
itemWidget.directives.itemDirective(el);
271282
itemWidget.directives.bodyContainerDirective(el);
272283
expectOpenItems(state, [false]);
273-
itemWidget.api.expand();
284+
await itemWidget.api.expand();
274285
expectOpenItems(state, [true]);
275286
expect(transition.mock.calls[transition.mock.calls.length - 1].slice(1, 3)).toEqual(['show', false]);
276287
itemWidget.api.initDone();
277-
itemWidget.api.collapse();
288+
await itemWidget.api.collapse();
278289
expectOpenItems(state, [false]);
279290
expect(transition.mock.calls[transition.mock.calls.length - 1].slice(1, 3)).toEqual(['hide', true]);
280291
});

core/src/components/accordion/accordion.ts

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -160,34 +160,41 @@ export interface AccordionApi {
160160
* Given the itemId, will expand the corresponding accordion-item.
161161
*
162162
* If the itemId is not valid, nothing will happen.
163+
* @returns A promise that resolves when the expand operation is completed.
163164
*/
164-
expand(itemId: string): void;
165+
expand(itemId: string): Promise<void>;
165166

166167
/**
167168
* Given the itemId, will collapse the corresponding accordion-item.
168169
*
169170
* If the itemId is not valid, nothing will happen.
171+
* @returns A promise that resolves when the collapse operation is completed.
170172
*/
171-
collapse(itemId: string): void;
173+
collapse(itemId: string): Promise<void>;
172174

173175
/**
174176
* Given the itemId, will toggle the corresponding accordion-item.
175177
*
178+
* @returns A promise that resolves when the toggle operation is completed.
176179
* If the itemId is not valid, nothing will happen.
177180
*/
178-
toggle(itemId: string): void;
181+
toggle(itemId: string): Promise<void>;
179182

180183
/**
181184
* It will expand all the items in the accordion.
182185
*
183186
* If `closeOthers` is `true` it will expand only the last accordion-item.
187+
*
188+
* @returns A promise that resolves when all the expand operations are completed.
184189
*/
185-
expandAll(): void;
190+
expandAll(): Promise<void>;
186191

187192
/**
188193
* It will collapse all the accordion-items in the accordion.
194+
*
195+
* @returns A promise that resolves when all the collapse operations are completed.
189196
*/
190-
collapseAll(): void;
197+
collapseAll(): Promise<void>;
191198

192199
/**
193200
* Creates a new accordionItem.
@@ -216,18 +223,21 @@ export type AccordionWidget = Widget<AccordionProps, AccordionState, AccordionAp
216223
export interface AccordionItemApi {
217224
/**
218225
* It will collapse the accordion-item.
226+
* @returns A promise that resolves when the collapse operation is completed.
219227
*/
220-
collapse(): void;
228+
collapse(): Promise<void>;
221229

222230
/**
223231
* It will expand the accordion-item.
232+
* @returns A promise that resolves when the expand operation is completed.
224233
*/
225-
expand(): void;
234+
expand(): Promise<void>;
226235

227236
/**
228237
* It will toggle the accordion-item.
238+
* @returns A promise that resolves when the toggle operation is completed.
229239
*/
230-
toggle(): void;
240+
toggle(): Promise<void>;
231241

232242
/**
233243
* Method to be called after the initialization to allow animations.
@@ -498,7 +508,7 @@ export function createAccordionItem(config?: PropsConfig<AccordionItemProps>): A
498508
events: {
499509
click: () => {
500510
if (!disabled$()) {
501-
visible$.update((c: boolean) => !c);
511+
void transition.api.toggle();
502512
}
503513
},
504514
},
@@ -530,15 +540,9 @@ export function createAccordionItem(config?: PropsConfig<AccordionItemProps>): A
530540
initDone: () => {
531541
initDone$.set(true);
532542
},
533-
collapse: () => {
534-
visible$.set(false);
535-
},
536-
expand: () => {
537-
visible$.set(true);
538-
},
539-
toggle: () => {
540-
visible$.update((c: boolean) => !c);
541-
},
543+
collapse: transition.api.hide,
544+
expand: transition.api.show,
545+
toggle: transition.api.toggle,
542546
},
543547
directives: {
544548
toggleDirective,
@@ -610,20 +614,20 @@ export function factoryCreateAccordion(
610614
...stateStores({itemWidgets$, className$}),
611615
patch,
612616
api: {
613-
expand: (id: string) => {
614-
getItem(itemWidgets$(), id)?.api.expand();
617+
expand: async (id: string) => {
618+
await getItem(itemWidgets$(), id)?.api.expand();
615619
},
616-
collapse: (id: string) => {
617-
getItem(itemWidgets$(), id)?.api.collapse();
620+
collapse: async (id: string) => {
621+
await getItem(itemWidgets$(), id)?.api.collapse();
618622
},
619-
toggle: (id: string) => {
620-
getItem(itemWidgets$(), id)?.api.toggle();
623+
toggle: async (id: string) => {
624+
await getItem(itemWidgets$(), id)?.api.toggle();
621625
},
622-
expandAll: () => {
623-
itemWidgets$().forEach((i) => i.api.expand());
626+
expandAll: async () => {
627+
await Promise.all(itemWidgets$().map((i) => i.api.expand()));
624628
},
625-
collapseAll: () => {
626-
itemWidgets$().forEach((i) => i.api.collapse());
629+
collapseAll: async () => {
630+
await Promise.all(itemWidgets$().map((i) => i.api.collapse()));
627631
},
628632
registerItem: (propsConfig?: PropsConfig<AccordionItemProps>) => {
629633
const itemProps = accordionItemProps as (keyof AccordionItemProps)[];

react/demo/src/daisyui/samples/accordion/Accordion.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const AccordionItem = (
4141
useEffect(() => api.initDone(), [api]);
4242
const onEnter = (e: KeyboardEvent<HTMLDivElement>) => {
4343
if (e.key === 'Enter') {
44-
api.toggle();
44+
void api.toggle();
4545
}
4646
};
4747

svelte/demo/src/daisyui/samples/accordion/AccordionItem.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
4545
const onkeydown = (e: KeyboardEvent) => {
4646
if (e.key === 'Enter') {
47-
toggle();
47+
void toggle();
4848
}
4949
};
5050
onMount(widget.api.initDone);

0 commit comments

Comments
 (0)